jit: split CraneliftBuilder to builder/cranelift.rs and hub-ify builder.rs; stabilize jit-direct (seal/fb TLS/end_function); prep for core.rs split (no behavior change)

This commit is contained in:
Moe Charm
2025-09-02 13:30:04 +09:00
parent 2c795fa554
commit 5a5e09b69a
10 changed files with 2241 additions and 1920 deletions

View File

@ -4,12 +4,21 @@
Nyashの文法知識が分散している問題を解決し、AIがNyashコードを正しく書けるよう支援する包括的な文法統一化フェーズ。
## 🔥 核心的な問題
現在のNyashは各層Tokenizer/Parser/Interpreter/MIR/VM/JITで予約語・文法解釈がバラバラに実装されており、これが以下の問題を引き起こしている
- 同じ `me` キーワードが各層で独自解釈される
- `+` 演算子の動作がInterpreter/VM/JITで微妙に異なる
- 新しい予約語追加時に6箇所以上の修正が必要
- AIが正しいコードを書けないどの層の解釈に従うべきか不明
## 🎯 フェーズの目的
1. **文法の一元管理**: 分散した文法知識を統一
2. **AIエラー削減**: 文法間違いを90%以上削減
3. **開発効率向上**: 新構文追加を簡単に
4. **ANCP連携**: AI通信の効率化
1. **完全統一文法エンジン**: すべての層が単一の文法定義を参照
2. **セマンティクス一元化**: 演算子・型変換・実行規則の完全統一
3. **AIエラー削減**: 文法間違いを90%以上削減
4. **保守性革命**: 新機能追加が1箇所の修正で完了
## 📊 主要成果物
@ -66,7 +75,12 @@ keywords:
## 🔗 関連ドキュメント
- [統一文法アーキテクチャ設計書](unified-grammar-architecture.md) ← **🔥 核心設計**
- [統一予約語システム仕様](unified-keyword-system.md) ← **🎯 具体的実装**
- [AI深層考察: 統一文法アーキテクチャ](ai-deep-thoughts-unified-grammar.md) ← **💡 Gemini/Codex分析**
- [文法統一化詳細設計](grammar-unification.txt)
- [統一文法定義YAML](nyash-grammar-v1.yaml)
- [実装計画](implementation-plan.txt)
- [AI-Nyash Compact Notation Protocol](../../ideas/new-features/2025-08-29-ai-compact-notation-protocol.md)
- [Phase 12: プラグインシステム](../phase-12/)

View File

@ -0,0 +1,146 @@
# AI深層考察: Nyash統一文法アーキテクチャ
## 🎯 概要
GeminiとCodexに時間無制限で深く考えてもらった、Nyash統一文法アーキテクチャに関する洞察をまとめました。
## 🔥 Gemini先生の洞察
### 核心的提言: 宣言的文法定義 + ビルド時コード生成
```
[ grammar.toml ] ← 宣言的SSoTSingle Source of Truth
[ build.rs ] ← メタプログラミング層
├─ generated_tokens.rs
├─ generated_keywords.rs
├─ generated_rules.rs
└─ generated_opcodes.rs
```
### 重要ポイント
1. **真の分離**: `UnifiedKeyword`構造体は依然として各層を密結合させる。宣言的ファイルからコード生成する方が疎結合を保てる。
2. **ゼロコスト抽象化**:
- ビルド時生成により実行時オーバーヘッドなし
- `enum``match`文で高速ディスパッチ
- `#[inline(always)]`で関数呼び出しコストなし
3. **コンパイラ駆動開発**:
```rust
// 新機能追加時、全層でコンパイルエラー発生
// → 実装漏れがなくなる
match token {
TokenType::Async => // 新しく追加されたので実装必須
_ => // ...
}
```
4. **他言語からの学び**:
- **CPython**: `Grammar/Tokens`ファイルから生成
- **V8**: Ignition(インタプリタ)とTurboFan(JIT)の分離
- **rustc**: HIR→MIRという段階的表現
## 💡 Codex先生の洞察
### 核心的提言: MIRを中心とした統一セマンティクス基盤
```yaml
# grammar/nyash.yml
tokens:
- name: ME
literal: "me"
soft: true
contexts: ["expr", "pattern"]
deprecated_aliases: ["self"]
ai_hint: "Current object; not assignable."
operators:
- symbol: "+"
name: add
precedence: 110
associativity: left
overloads:
- types: ["i64","i64"] -> "i64"
lower: MIR.AddI64
- types: ["String","String"] -> "String"
lower: MIR.Concat
```
### 実装戦略
1. **単一仕様ファイル**: `grammar/nyash.yml`に全て定義
- キーワード、演算子、文法、型、強制変換
- MIRローリング、VMオペコード、JITパターン
- 非推奨、AIヒント
2. **コード生成クレート**: `crates/nygrammar-gen`
- Perfect hash関数でO(1)キーワード認識
- Pratt/PEGパーサーテーブル生成
- 型ディスパッチマトリックス生成
3. **MIRが真実の基盤**:
```rust
pub fn add(lhs: Value, rhs: Value) -> Result<MIRNode> {
// 生成されたfast-pathを使用
// 常にMIRードを返す
}
```
4. **性能最適化**:
- ビルド時にすべて決定(実行時検索なし)
- インラインキャッシュで呼び出しサイト最適化
- ソフトキーワードはパーサー状態で判定
### 段階的移行計画
- **Phase 0**: ベースラインテスト(現状記録)
- **Phase 1**: 正準MIR定義
- **Phase 2**: KeywordRegistry生成
- **Phase 3**: UnifiedSemantics導入
- **Phase 4**: パーサー統一
- **Phase 5**: バックエンドマッピング
- **Phase 6**: 非推奨警告
- **Phase 7**: ツール/ドキュメント生成
## 🎯 統合された知見
両AIの提言を統合すると
### 1. 宣言的定義 + コード生成が最強
- YAML/TOMLで文法を宣言的に定義
- build.rsでRustコードを生成
- 実行時オーバーヘッドゼロ
### 2. MIRを中心とした統一
- すべてのセマンティクスはMIRで表現
- 各バックエンドはMIRを実行/コンパイル
- 一貫性が自動的に保証される
### 3. AI友好的な設計
- 機械可読な仕様ファイル
- 豊富な例とエラーカタログ
- 自動生成されるドキュメント
### 4. 拡張性への配慮
- 新バックエンド追加が容易
- プラグインによる拡張可能
- 後方互換性の維持
## 📋 実装優先順位
1. **最優先**: `grammar/nyash.yml`の初版作成
2. **高優先**: `build.rs`によるトークン生成
3. **中優先**: MIR統一とUnifiedSemantics
4. **低優先**: JIT最適化ヒント
## 🚀 期待される効果
- **保守性**: 新機能追加が1箇所の修正で完了
- **一貫性**: 全層で同じセマンティクス保証
- **性能**: ビルド時最適化で実行時コストなし
- **AI対応**: LLMが正確にNyashコードを生成
これらの深い洞察により、Nyashの統一文法アーキテクチャは強固な基盤の上に構築されることになります。

View File

@ -0,0 +1,339 @@
# Box-First統一文法アーキテクチャ再設計
## 🚨 現在の設計の問題点
### 1. 密結合の罠
```rust
// ❌ 現在の設計: 各層がUnifiedGrammarEngineに直接依存
impl Tokenizer {
fn tokenize(&mut self) {
self.engine.is_keyword() // 直接参照!
}
}
```
### 2. 根が這う実装
```rust
// ❌ UnifiedKeyword構造体が全層の情報を持つ
struct UnifiedKeyword {
token_type: TokenType, // Tokenizer層
semantic_action: Action, // Parser層
mir_instruction: MirOp, // MIR層
vm_opcode: VmOp, // VM層
jit_pattern: JitPattern, // JIT層
// すべてが絡み合っている!
}
```
### 3. 巨大な神オブジェクト
```rust
// ❌ UnifiedGrammarEngineが全てを知っている
struct UnifiedGrammarEngine {
keywords: KeywordRegistry,
syntax: SyntaxRules,
semantics: SemanticRules,
execution: ExecutionSemantics,
// 責任が多すぎる!
}
```
## 🎯 Box-First再設計
### 核心思想: 「箱に入れて、箱同士をつなぐ」
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ GrammarBox │ │ TokenBox │ │ ParserBox │
│ (定義のみ) │ --> │ (Token化) │ --> │ (構文解析) │
└─────────────┘ └─────────────┘ └─────────────┘
| |
v v
┌─────────────┐ ┌─────────────┐
│ SemanticBox │ <---------------------- │ ASTBox │
│ (意味解釈) │ │ (構文木) │
└─────────────┘ └─────────────┘
|
v
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ MIRBox │ --> │ VMBox │ │ JITBox │
│ (中間表現) │ │ (実行) │ │ (コンパイル) │
└─────────────┘ └─────────────┘ └─────────────┘
```
## 📦 各箱の責任と境界
### 1. GrammarBox - 純粋な定義の箱
```rust
// 定義だけを持つ、実装を持たない
box GrammarBox {
init { definitions }
// キーワード定義を返すだけ
getKeywordDef(word) {
return me.definitions.keywords.get(word)
}
// 演算子定義を返すだけ
getOperatorDef(symbol) {
return me.definitions.operators.get(symbol)
}
}
// キーワード定義は純粋なデータ
box KeywordDef {
init { literal, category, aliases }
// 実装なし、データのみ
}
```
### 2. TokenBox - トークン化だけの責任
```rust
box TokenBox {
init { grammarBox } // 定義への参照のみ
tokenize(text) {
local tokens = []
// GrammarBoxに聞くだけ、自分では判断しない
loop(text.hasMore()) {
local word = text.readWord()
local def = me.grammarBox.getKeywordDef(word)
if def {
tokens.push(new Token(def.category, word))
} else {
tokens.push(new Token("IDENTIFIER", word))
}
}
return tokens
}
}
```
### 3. SemanticBox - 意味解釈の箱
```rust
box SemanticBox {
init { } // 他の箱に依存しない!
// 純粋関数として実装
add(left, right) {
// String + String
if left.isString() and right.isString() {
return new StringBox(left.value + right.value)
}
// Number + Number
if left.isNumber() and right.isNumber() {
return new IntegerBox(left.value + right.value)
}
// エラー
return new ErrorBox("Type mismatch")
}
coerceToString(value) {
// 各型の変換ロジック
if value.isString() { return value }
if value.isNumber() { return new StringBox(value.toString()) }
// ...
}
}
```
### 4. MIRBuilderBox - AST→MIR変換の箱
```rust
box MIRBuilderBox {
init { semanticBox } // セマンティクスへの参照のみ
buildFromAST(ast) {
// ASTの種類に応じてMIRを生成
if ast.type == "BinaryOp" {
return me.buildBinaryOp(ast)
}
// ...
}
buildBinaryOp(ast) {
local left = me.buildFromAST(ast.left)
local right = me.buildFromAST(ast.right)
// セマンティクスに聞いて、適切なMIR命令を選択
if ast.op == "+" {
// SemanticBoxに型情報を聞く
local mirOp = me.selectAddInstruction(left.type, right.type)
return new MIRNode(mirOp, left, right)
}
}
}
```
## 🔄 疎結合の実現方法
### 1. インターフェース(契約)による結合
```rust
// 各箱は最小限のインターフェースだけを公開
trait TokenProvider {
fn next_token(&mut self) -> Option<Token>;
}
trait SemanticProvider {
fn apply_operator(&self, op: &str, args: &[Value]) -> Result<Value>;
}
trait MIRProvider {
fn get_instruction(&self, index: usize) -> &MIRInstruction;
}
```
### 2. メッセージパッシング
```rust
// 箱同士は直接呼び出さず、メッセージで通信
box ParserBox {
parseExpression() {
// TokenBoxにメッセージを送る
local token = me.sendMessage(me.tokenBox, "nextToken")
// 結果を処理
if token.type == "NUMBER" {
return new NumberNode(token.value)
}
}
}
```
### 3. イベント駆動
```rust
// 文法変更時の通知システム
box GrammarBox {
updateKeyword(word, newDef) {
me.definitions.keywords.set(word, newDef)
// 変更を通知(購読者に伝える)
me.notify("keyword_changed", word)
}
}
box TokenBox {
init { grammarBox }
constructor() {
// 文法変更を購読
me.grammarBox.subscribe("keyword_changed", me.onKeywordChanged)
}
onKeywordChanged(word) {
// キャッシュをクリア
me.clearCache()
}
}
```
## 📐 ビルド時生成の箱化
### GeneratorBox - コード生成も箱
```rust
box GeneratorBox {
init { grammarBox, outputPath }
generate() {
local grammar = me.grammarBox.getDefinitions()
// 各層向けのコードを生成
me.generateTokens(grammar.keywords)
me.generateParseTables(grammar.syntax)
me.generateSemanticTables(grammar.operators)
}
generateTokens(keywords) {
local code = "pub enum Token {\n"
keywords.forEach((name, def) => {
code += " " + name + ",\n"
})
code += "}\n"
me.writeFile("generated/tokens.rs", code)
}
}
```
## 🎯 密結合を避ける設計原則
### 1. 単一責任の原則
- GrammarBox: 定義の管理のみ
- TokenBox: トークン化のみ
- ParserBox: 構文解析のみ
- SemanticBox: 意味解釈のみ
### 2. 依存関係の逆転
```rust
// ❌ 悪い例: 具象に依存
box VMBox {
init { mirBuilder: MIRBuilderBox } // 具象型に依存
}
// ✅ 良い例: 抽象に依存
box VMBox {
init { mirProvider: MIRProvider } // インターフェースに依存
}
```
### 3. Open/Closed原則
```rust
// 新しい演算子の追加が既存コードを変更しない
box OperatorRegistry {
init { operators }
register(symbol, handler) {
me.operators.set(symbol, handler)
}
apply(symbol, args) {
local handler = me.operators.get(symbol)
if handler {
return handler.apply(args)
}
return new ErrorBox("Unknown operator")
}
}
```
## 🔧 段階的移行(箱単位)
### Phase 1: GrammarBox導入
- grammar.yamlをGrammarBoxでラップ
- 既存コードはGrammarBox経由でアクセス
### Phase 2: TokenBox分離
- Tokenizerの機能をTokenBoxに移動
- GrammarBoxへの依存を最小化
### Phase 3: SemanticBox独立
- 演算子実装をSemanticBoxに集約
- 純粋関数として実装
### Phase 4: 箱間通信の確立
- メッセージパッシング導入
- イベントシステム構築
## 📊 疎結合度の測定
### 1. 依存関係グラフ
```
GrammarBox (依存なし)
TokenBox → GrammarBox (1依存)
ParserBox → TokenBox (1依存)
SemanticBox (依存なし)
MIRBox → SemanticBox (1依存)
VMBox → MIRBox (1依存)
JITBox → MIRBox (1依存)
```
### 2. 変更影響範囲
- 新キーワード追加: GrammarBoxのみ
- 新演算子追加: GrammarBox + SemanticBoxのみ
- 新バックエンド追加: 既存箱への変更なし
## 🚀 期待される効果
1. **真の疎結合**: 各箱が独立して開発・テスト可能
2. **容易な拡張**: 新しい箱の追加が既存を壊さない
3. **明確な境界**: 責任の所在が明確
4. **並行開発**: チームが独立して各箱を開発可能
これで「Everything is Box」哲学に忠実な、真に疎結合な統一文法アーキテクチャが実現されます。

View File

@ -0,0 +1,297 @@
# 根切り文法アーキテクチャ - 真の疎結合設計
## 🌳 「根が這う」問題の本質
### 現在の設計の根本的な問題
```rust
// 🌳 根が這っている例: 一つの変更が全体に波及
struct Keyword {
name: String,
token_type: TokenType, // Tokenizer層の型
parser_rule: ParserRule, // Parser層の型
mir_op: MIROpcode, // MIR層の型
vm_handler: VMHandler, // VM層の型
// → 一つのstructが全層の型を知っている
}
```
## 🎯 根切り設計: レイヤー完全分離
### 核心思想: 「各層は自分の関心事だけを知る」
```
【Tokenizer層】 【Parser層】 【Semantic層】
"me" → Token::Me → SelfReference
知識:文字列のみ 知識:トークンのみ 知識:意味のみ
【MIR層】 【VM層】 【JIT層】
LoadLocal(0) → OP_LOAD_0 → mov rax, [rbp]
知識:MIRのみ 知識:オペコードのみ 知識:機械語のみ
```
## 📦 真の箱化: 変換箱TransformerBoxパターン
### 1. 各層は純粋な箱
```rust
// Tokenizer層: 文字列→トークンの変換のみ
box StringToTokenBox {
init { } // 依存なし!
transform(text: String) -> TokenStream {
// 純粋な文字列処理
local tokens = []
local chars = text.chars()
loop(chars.hasNext()) {
local ch = chars.next()
if ch.isLetter() {
local word = me.readWord(chars, ch)
tokens.push(me.classifyWord(word))
}
// ...
}
return TokenStream(tokens)
}
classifyWord(word: String) -> Token {
// ローカルな判定のみ
match word {
"me" => Token::Me,
"from" => Token::From,
"loop" => Token::Loop,
_ => Token::Identifier(word)
}
}
}
```
### 2. 層間の変換も箱
```rust
// Token→AST変換箱
box TokenToASTBox {
init { } // 依存なし!
transform(tokens: TokenStream) -> AST {
local parser = PrattParser()
return parser.parse(tokens)
}
}
// AST→MIR変換箱
box ASTToMIRBox {
init { } // 依存なし!
transform(ast: AST) -> MIR {
match ast {
AST::BinaryOp(op, left, right) => {
local leftMIR = me.transform(left)
local rightMIR = me.transform(right)
return me.selectMIROp(op, leftMIR, rightMIR)
}
// ...
}
}
selectMIROp(op: String, left: MIR, right: MIR) -> MIR {
// ローカルな判断のみ
if op == "+" {
if left.type == "String" and right.type == "String" {
return MIR::StringConcat(left, right)
}
if left.type == "Integer" and right.type == "Integer" {
return MIR::AddI64(left, right)
}
}
// ...
}
}
```
## 🔄 パイプライン: 箱の連鎖
### 純粋関数的パイプライン
```rust
// 各箱は前の箱の出力を入力として受け取るだけ
box NyashPipeline {
init { }
compile(source: String) -> ExecutableCode {
// 各変換箱を順番に適用
local tokens = StringToTokenBox().transform(source)
local ast = TokenToASTBox().transform(tokens)
local mir = ASTToMIRBox().transform(ast)
local bytecode = MIRToVMBox().transform(mir)
return bytecode
}
}
```
## 📐 設定の分離: ConfigBox
### 文法定義も実行時から分離
```rust
// ビルド時のみ使用される設定箱
box GrammarConfigBox {
init { yamlPath }
load() -> GrammarConfig {
// YAMLを読み込んで設定オブジェクトを返す
return YAML.parse(File.read(me.yamlPath))
}
}
// ビルド時コード生成箱
box CodeGeneratorBox {
init { config }
generate() {
// 設定から各層のコードを生成
me.generateTokenizerTable(me.config.keywords)
me.generateParserTable(me.config.syntax)
me.generateMIRTable(me.config.semantics)
}
generateTokenizerTable(keywords) {
// キーワードマッチング用の完全ハッシュ関数生成
local code = "fn classify_keyword(s: &str) -> Token {\n"
code += " match s {\n"
keywords.forEach((word, info) => {
code += ' "' + word + '" => Token::' + info.token + ',\n'
})
code += " _ => Token::Identifier(s.to_string())\n"
code += " }\n"
code += "}\n"
File.write("src/generated/keywords.rs", code)
}
}
```
## 🎯 セマンティクスの分離
### セマンティクスも変換箱として実装
```rust
// 型強制変換箱
box TypeCoercionBox {
init { } // 依存なし!
coerceToString(value: Value) -> StringValue {
match value {
Value::String(s) => StringValue(s),
Value::Integer(i) => StringValue(i.toString()),
Value::Float(f) => StringValue(f.toString()),
Value::Bool(b) => StringValue(b ? "true" : "false"),
_ => panic("Cannot coerce to string")
}
}
}
// 演算子実行箱
box OperatorExecutorBox {
init { coercionBox }
executeAdd(left: Value, right: Value) -> Value {
// ローカルな判断
match (left, right) {
(Value::String(s1), Value::String(s2)) => {
Value::String(s1 + s2)
}
(Value::String(s), other) => {
local s2 = me.coercionBox.coerceToString(other)
Value::String(s + s2.value)
}
(Value::Integer(i1), Value::Integer(i2)) => {
Value::Integer(i1 + i2)
}
// ...
}
}
}
```
## 🔧 テスト可能性の向上
### 各箱が独立してテスト可能
```rust
// StringToTokenBoxのテスト
test "tokenize keywords" {
local box = StringToTokenBox()
local tokens = box.transform("me loop from")
assert tokens == [Token::Me, Token::Loop, Token::From]
}
// ASTToMIRBoxのテスト
test "binary op to MIR" {
local box = ASTToMIRBox()
local ast = AST::BinaryOp("+",
AST::Literal(Value::Integer(1)),
AST::Literal(Value::Integer(2))
)
local mir = box.transform(ast)
assert mir == MIR::AddI64(
MIR::Const(Value::Integer(1)),
MIR::Const(Value::Integer(2))
)
}
```
## 📊 依存グラフ: 完全なDAG有向非巡環グラフ
```
StringToTokenBox (依存: 0)
TokenToASTBox (依存: 0)
ASTToMIRBox (依存: 0)
↓ ↓
MIRToVMBox (依存: 0) MIRToJITBox (依存: 0)
TypeCoercionBox (依存: 0)
OperatorExecutorBox (依存: 1)
```
## 🚀 この設計の利点
### 1. 真の疎結合
- 各箱は入力と出力の型だけを知る
- 他の箱の実装を一切知らない
- インターフェースすら不要(型だけで十分)
### 2. 並行開発可能
- チームAがTokenizer開発
- チームBがParser開発
- チームCがMIR開発
- 全員が独立して作業可能
### 3. 差し替え可能
```rust
// 別実装への差し替えが容易
local pipeline = NyashPipeline()
pipeline.tokenizer = OptimizedStringToTokenBox() // 高速版
pipeline.parser = ErrorRecoveringTokenToASTBox() // エラー回復版
```
### 4. 段階的最適化
```rust
// 最適化も箱として追加
box MIROptimizerBox {
transform(mir: MIR) -> MIR {
// 定数畳み込み、死んだコード除去など
return optimized
}
}
// パイプラインに挿入
local mir = ASTToMIRBox().transform(ast)
mir = MIROptimizerBox().transform(mir) // 追加
local bytecode = MIRToVMBox().transform(mir)
```
## 🎯 まとめ: 根を完全に切る
1. **データ中心設計**: 各層は入力データを出力データに変換するだけ
2. **状態を持たない**: すべての箱が純粋関数的
3. **設定と実装の分離**: ビルド時と実行時を明確に分離
4. **変換の連鎖**: パイプラインで箱をつなぐ
これにより、真に「根が這わない」アーキテクチャが実現されます。

View File

@ -0,0 +1,344 @@
# Phase 11.9: 統一文法アーキテクチャ設計書
## 🔴 現在の根本的問題
現在のNyashは、各層で予約語・文法解釈がバラバラに実装されている
### 1. Tokenizer層での分散
```rust
// src/tokenizer.rs
match word.as_str() {
"me" => TokenType::ME, // ハードコード
"from" => TokenType::FROM, // ハードコード
"loop" => TokenType::LOOP, // ハードコード
// ... 各予約語が個別定義
}
```
### 2. Parser層での独自解釈
```rust
// src/parser/mod.rs
fn parse_loop(&mut self) {
// loop構文の独自解釈
// while/forとの混同を個別チェック
}
```
### 3. Interpreter層での独自実行
```rust
// src/interpreter/expressions.rs
fn execute_from_call(&mut self) {
// fromの独自解釈
// デリゲーションロジックが埋め込み
}
```
### 4. MIR Builder層での独自変換
```rust
// src/mir/builder.rs
fn build_loop(&mut self) {
// loop → MIRへの独自変換
// セーフポイント挿入も個別判断
}
```
### 5. VM/JIT層での独自実行
- VM: 独自のセマンティクス実装
- JIT: 独自のコード生成戦略
## 🎯 統一文法アーキテクチャの設計
### 核心コンセプト: "Grammar as THE Source of Truth"
```
┌─────────────────────────────────────────────┐
│ Unified Grammar Engine │
│ (単一の文法定義・解釈・実行エンジン) │
├─────────────────────────────────────────────┤
│ - Keyword Registry (予約語レジストリ) │
│ - Syntax Rules (構文規則) │
│ - Semantic Rules (意味規則) │
│ - Execution Semantics (実行セマンティクス) │
└─────────────────────────────────────────────┘
┌──────────┬──────────┬──────────┬──────────┐
│Tokenizer │ Parser │Interpreter│MIR/VM/JIT│
│ (利用) │ (利用) │ (利用) │ (利用) │
└──────────┴──────────┴──────────┴──────────┘
```
## 📐 統一文法エンジンの実装設計
### 1. コア構造体
```rust
// src/grammar/engine.rs
pub struct UnifiedGrammarEngine {
// 予約語の統一定義
keywords: KeywordRegistry,
// 構文規則の統一定義
syntax: SyntaxRuleEngine,
// 意味規則の統一定義
semantics: SemanticRuleEngine,
// 実行セマンティクスの統一定義
execution: ExecutionSemantics,
}
impl UnifiedGrammarEngine {
/// 単一のソースから全情報を読み込み
pub fn load() -> Self {
// YAML/TOML/Rustコードから読み込み
let config = include_str!("../../../grammar/unified-grammar.toml");
Self::from_config(config)
}
/// Tokenizerが使う統一API
pub fn is_keyword(&self, word: &str) -> Option<TokenType> {
self.keywords.lookup(word)
}
/// Parserが使う統一API
pub fn parse_rule(&self, rule_name: &str) -> &SyntaxRule {
self.syntax.get_rule(rule_name)
}
/// Interpreter/VM/JITが使う統一API
pub fn execute_semantic(&self, op: &str, args: &[Value]) -> Value {
self.execution.apply(op, args)
}
}
```
### 2. 予約語レジストリ
```rust
pub struct KeywordRegistry {
// 正規形マップ
canonical: HashMap<String, KeywordDef>,
// エイリアスマップ(非推奨含む)
aliases: HashMap<String, String>,
// コンテキスト別解釈
contextual: HashMap<(String, Context), KeywordDef>,
}
pub struct KeywordDef {
pub token: TokenType,
pub category: KeywordCategory,
pub semantic_action: SemanticAction,
pub mir_opcode: Option<MirOpcode>,
pub vm_handler: Option<VmHandler>,
pub jit_lowering: Option<JitLowering>,
}
```
### 3. 構文規則エンジン
```rust
pub struct SyntaxRuleEngine {
rules: HashMap<String, SyntaxRule>,
}
pub struct SyntaxRule {
pub pattern: Pattern,
pub precedence: i32,
pub associativity: Associativity,
pub semantic_transform: Box<dyn Fn(&AST) -> MIR>,
}
```
### 4. 実行セマンティクス統一
```rust
pub struct ExecutionSemantics {
// 演算子の統一実装
operators: HashMap<String, OperatorSemantics>,
// 型変換の統一ルール
coercions: CoercionRules,
// エラー処理の統一
error_handling: ErrorSemantics,
}
impl ExecutionSemantics {
/// すべてのバックエンドが使う統一演算
pub fn add(&self, left: Value, right: Value) -> Value {
// Interpreter/VM/JIT すべて同じロジック
match (&left, &right) {
(Value::String(s1), Value::String(s2)) => {
Value::String(s1.clone() + s2)
}
(Value::Integer(i1), Value::Integer(i2)) => {
Value::Integer(i1 + i2)
}
_ => self.coerce_and_add(left, right)
}
}
}
```
## 🔄 統一化の実装手順
### Phase 1: 基盤構築
1. `src/grammar/engine.rs` - 統一エンジン本体
2. `grammar/unified-grammar.toml` - 統一定義ファイル
3. 既存コードとの並行実行(デバッグ用)
### Phase 2: Tokenizer統合
```rust
impl NyashTokenizer {
fn new() -> Self {
Self {
engine: UnifiedGrammarEngine::load(),
// ...
}
}
fn read_keyword_or_identifier(&mut self) -> TokenType {
let word = self.read_word();
// 統一エンジンに委譲
self.engine.is_keyword(&word)
.unwrap_or(TokenType::IDENTIFIER(word))
}
}
```
### Phase 3: Parser統合
```rust
impl Parser {
fn parse_statement(&mut self) -> Result<ASTNode> {
// 統一エンジンから構文規則を取得
let rule = self.engine.get_syntax_rule("statement");
rule.parse(self)
}
}
```
### Phase 4: セマンティクス統合
```rust
// Interpreter
impl Interpreter {
fn execute_binop(&mut self, op: &str, left: Value, right: Value) -> Value {
// 統一エンジンに委譲
self.engine.execute_semantic(op, &[left, right])
}
}
// VM
impl VM {
fn execute_add(&mut self) -> Result<()> {
let right = self.pop()?;
let left = self.pop()?;
// 統一エンジンに委譲
let result = self.engine.execute_semantic("add", &[left, right]);
self.push(result)
}
}
// JIT
impl JitBuilder {
fn lower_add(&mut self, left: Value, right: Value) {
// 統一エンジンから最適化ヒントを取得
let strategy = self.engine.get_jit_strategy("add", &left, &right);
strategy.emit(self, left, right)
}
}
```
## 🎯 統一定義ファイルの例
```toml
# grammar/unified-grammar.toml
[keywords.me]
token = "ME"
category = "self_reference"
deprecated_aliases = ["this", "self", "@"]
semantic_action = "load_self"
mir_opcode = "LoadSelf"
vm_handler = "OP_LOAD_ME"
jit_lowering = "emit_load_local(0)"
[keywords.from]
token = "FROM"
category = "delegation"
contexts = [
{ context = "class_decl", meaning = "inheritance" },
{ context = "method_call", meaning = "delegation_call" }
]
semantic_action = "delegate"
mir_opcode = "DelegateCall"
[keywords.loop]
token = "LOOP"
category = "control_flow"
deprecated_aliases = ["while", "for"]
semantic_action = "loop_construct"
mir_opcode = "Loop"
safepoint_insertion = true
[operators.add]
symbol = "+"
precedence = 10
associativity = "left"
type_rules = [
{ left = "String", right = "String", result = "String", action = "concat" },
{ left = "Integer", right = "Integer", result = "Integer", action = "add_i64" },
{ left = "Float", right = "Float", result = "Float", action = "add_f64" },
]
coercion_strategy = "string_priority" # String + anything = String
[semantics.string_concat]
interpreter = "rust:concatenate_strings"
vm = "CONCAT_STRINGS"
jit = "call @nyash.string.concat_hh"
```
## 🚀 期待される効果
1. **完全な一貫性**
- すべての層が同じ予約語定義を使用
- すべての層が同じ文法解釈を実行
- すべての層が同じセマンティクスを適用
2. **保守性の劇的向上**
- 新しい予約語/演算子の追加が1箇所
- 文法変更が全層に自動反映
- バグの削減(解釈の不一致がなくなる)
3. **AI開発の簡素化**
- 単一の文法定義をAIに学習させる
- 正しいNyashコードの生成率向上
- エラーメッセージの一貫性
4. **性能最適化の余地**
- 統一エンジンでの最適化が全層に効果
- JITヒントの統一管理
- キャッシュ戦略の一元化
## 📊 実装優先度
1. **最優先**: 予約語レジストリ(すぐ効果が出る)
2. **高優先**: セマンティクス統一(バグ削減効果大)
3. **中優先**: 構文規則エンジン(段階的移行可能)
4. **低優先**: JIT最適化ヒント性能向上は後回し
## 🔧 移行戦略
1. **並行実行期間**
- 新旧両方の実装を維持
- デバッグモードで差分検出
- 段階的に新実装に切り替え
2. **テスト駆動**
- 各層の動作一致を自動テスト
- スナップショットテストで回帰防止
- ファズテストで edge case 発見
3. **ドキュメント駆動**
- 統一文法仕様書を先に作成
- 実装は仕様書に従う
- AIトレーニングデータも同時生成
これにより、Nyashの全層で完全に統一された文法解釈と実行が実現される。

View File

@ -0,0 +1,321 @@
# Nyash統一予約語システム仕様
## 🎯 目的
Nyashの全実行層Script/MIR/VM/JITで完全に同一の予約語・文法解釈を実現する。
## 📊 現状の予約語分散状況
### Tokenizer層 (src/tokenizer.rs)
```rust
// 現在: ハードコードされた予約語
match word.as_str() {
"box" => TokenType::BOX,
"me" => TokenType::ME,
"from" => TokenType::FROM,
"loop" => TokenType::LOOP,
"if" => TokenType::IF,
"else" => TokenType::ELSE,
"local" => TokenType::LOCAL,
"return" => TokenType::RETURN,
"new" => TokenType::NEW,
"static" => TokenType::STATIC,
"init" => TokenType::INIT,
"birth" => TokenType::BIRTH,
"pack" => TokenType::PACK,
"override" => TokenType::OVERRIDE,
"and" => TokenType::AND,
"or" => TokenType::OR,
"not" => TokenType::NOT,
_ => TokenType::IDENTIFIER(word)
}
```
### MIR Builder層での独自解釈
```rust
// 現在: MIR生成時の独自判断
fn build_from_call(&mut self) {
// "from"の解釈がTokenizerと異なる可能性
}
```
### VM/JIT層での実行差異
```rust
// VM: 文字列連結の独自実装
VMValue::String(s1) + VMValue::String(s2) => concat
// JIT: 異なる最適化戦略
emit_call("nyash.string.concat_hh")
```
## 🏗️ 統一予約語システムの設計
### 1. 中央予約語レジストリ
```rust
// src/grammar/keyword_registry.rs
pub struct UnifiedKeywordRegistry {
keywords: HashMap<&'static str, UnifiedKeyword>,
}
pub struct UnifiedKeyword {
// トークン情報
pub token_type: TokenType,
pub literal: &'static str,
// 文法情報
pub category: KeywordCategory,
pub precedence: Option<i32>,
// セマンティクス情報
pub semantic_action: SemanticAction,
pub mir_instruction: Option<MirInstruction>,
pub vm_opcode: Option<VmOpcode>,
pub jit_pattern: Option<JitPattern>,
// メタ情報
pub deprecated_aliases: Vec<&'static str>,
pub ai_hint: &'static str,
}
// 静的に初期化される単一インスタンス
pub static KEYWORDS: Lazy<UnifiedKeywordRegistry> = Lazy::new(|| {
let mut registry = UnifiedKeywordRegistry::new();
// "me" - 自己参照
registry.register(UnifiedKeyword {
token_type: TokenType::ME,
literal: "me",
category: KeywordCategory::SelfReference,
semantic_action: SemanticAction::LoadSelf,
mir_instruction: Some(MirInstruction::LoadLocal(0)),
vm_opcode: Some(VmOpcode::LOAD_ME),
jit_pattern: Some(JitPattern::LoadFirstParam),
deprecated_aliases: vec!["this", "self", "@"],
ai_hint: "Always use 'me' for self-reference",
precedence: None,
});
// "from" - デリゲーション
registry.register(UnifiedKeyword {
token_type: TokenType::FROM,
literal: "from",
category: KeywordCategory::Delegation,
semantic_action: SemanticAction::DelegateCall,
mir_instruction: Some(MirInstruction::Call),
vm_opcode: Some(VmOpcode::DELEGATE_CALL),
jit_pattern: Some(JitPattern::VirtualCall),
deprecated_aliases: vec!["super", "parent", "base"],
ai_hint: "Use 'from' for parent method calls",
precedence: None,
});
// "loop" - 制御フロー
registry.register(UnifiedKeyword {
token_type: TokenType::LOOP,
literal: "loop",
category: KeywordCategory::ControlFlow,
semantic_action: SemanticAction::Loop,
mir_instruction: Some(MirInstruction::Branch),
vm_opcode: Some(VmOpcode::LOOP_START),
jit_pattern: Some(JitPattern::LoopWithSafepoint),
deprecated_aliases: vec!["while", "for", "repeat"],
ai_hint: "Only 'loop' exists for iteration",
precedence: None,
});
// 演算子も統一管理
registry.register(UnifiedKeyword {
token_type: TokenType::PLUS,
literal: "+",
category: KeywordCategory::BinaryOperator,
precedence: Some(10),
semantic_action: SemanticAction::Add,
mir_instruction: Some(MirInstruction::BinOp(BinOpKind::Add)),
vm_opcode: Some(VmOpcode::ADD),
jit_pattern: Some(JitPattern::PolymorphicAdd),
deprecated_aliases: vec![],
ai_hint: "String + String = concat, Number + Number = add",
});
registry
});
```
### 2. 各層での統一API使用
#### Tokenizer統合
```rust
impl NyashTokenizer {
fn tokenize_word(&mut self, word: String) -> TokenType {
// 統一レジストリを参照
KEYWORDS.lookup(&word)
.map(|kw| kw.token_type.clone())
.unwrap_or(TokenType::IDENTIFIER(word))
}
}
```
#### Parser統合
```rust
impl Parser {
fn parse_keyword(&mut self, token: &Token) -> Result<ASTNode> {
if let Some(keyword) = KEYWORDS.get_by_token(&token.token_type) {
// 統一されたセマンティクスアクションを実行
match keyword.semantic_action {
SemanticAction::Loop => self.parse_loop_unified(keyword),
SemanticAction::DelegateCall => self.parse_from_unified(keyword),
// ...
}
}
}
}
```
#### MIR Builder統合
```rust
impl MirBuilder {
fn build_keyword(&mut self, keyword: &UnifiedKeyword, args: Vec<MirValue>) -> MirValue {
// 統一されたMIR命令を生成
if let Some(mir_inst) = &keyword.mir_instruction {
self.emit_unified(mir_inst.clone(), args)
}
}
}
```
#### VM統合
```rust
impl VM {
fn execute_keyword(&mut self, keyword: &UnifiedKeyword) -> Result<()> {
// 統一されたVMオペコードを実行
if let Some(opcode) = &keyword.vm_opcode {
self.execute_unified_opcode(opcode)
}
}
}
```
#### JIT統合
```rust
impl JitBuilder {
fn compile_keyword(&mut self, keyword: &UnifiedKeyword, args: &[Value]) {
// 統一されたJITパターンを適用
if let Some(pattern) = &keyword.jit_pattern {
self.emit_unified_pattern(pattern, args)
}
}
}
```
## 🔄 セマンティクス統一の例
### 現在の問題: "+" 演算子の挙動差異
```rust
// Interpreter: 独自の型変換ロジック
fn execute_add(&mut self, left: Value, right: Value) -> Value {
// 複雑な型変換ロジック
}
// VM: 異なる型変換ロジック
fn vm_add(&mut self) {
// 別の型変換ロジック
}
// JIT: さらに異なる最適化
fn jit_add(&mut self) {
// JIT独自の最適化
}
```
### 統一後: 単一のセマンティクス定義
```rust
// src/grammar/unified_semantics.rs
pub struct UnifiedSemantics;
impl UnifiedSemantics {
/// すべての層が使用する統一Add実装
pub fn add(left: &Value, right: &Value) -> Result<Value> {
use Value::*;
match (left, right) {
// String優先Nyashの仕様
(String(s1), String(s2)) => Ok(String(s1.clone() + s2)),
(String(s), other) | (other, String(s)) => {
Ok(String(s.clone() + &Self::coerce_to_string(other)?))
}
// 数値演算
(Integer(i1), Integer(i2)) => Ok(Integer(i1 + i2)),
(Float(f1), Float(f2)) => Ok(Float(f1 + f2)),
(Integer(i), Float(f)) | (Float(f), Integer(i)) => {
Ok(Float(*i as f64 + f))
}
// その他はエラー
_ => Err(Error::TypeMismatch)
}
}
/// 統一された文字列変換
pub fn coerce_to_string(value: &Value) -> Result<String> {
match value {
Value::String(s) => Ok(s.clone()),
Value::Integer(i) => Ok(i.to_string()),
Value::Float(f) => Ok(f.to_string()),
Value::Bool(b) => Ok(b.to_string()),
Value::Null => Ok("null".to_string()),
_ => Err(Error::CannotCoerceToString)
}
}
}
// 各層での使用
// Interpreter
left_value = UnifiedSemantics::add(&left, &right)?;
// VM
let result = UnifiedSemantics::add(&self.pop()?, &self.pop()?)?;
self.push(result);
// JIT
self.emit_call("UnifiedSemantics::add", args);
```
## 📋 実装チェックリスト
- [ ] `src/grammar/keyword_registry.rs` - 統一予約語レジストリ
- [ ] `src/grammar/unified_semantics.rs` - 統一セマンティクス
- [ ] `src/grammar/mod.rs` - モジュール統合
- [ ] Tokenizer修正 - 統一レジストリ参照
- [ ] Parser修正 - 統一セマンティクス使用
- [ ] MIR Builder修正 - 統一MIR生成
- [ ] VM修正 - 統一実行
- [ ] JIT修正 - 統一コード生成
- [ ] テストスイート - 全層の一致確認
- [ ] ドキュメント - 統一仕様書
## 🎯 成功基準
1. **完全一致**: すべての層で同じ入力が同じ出力を生成
2. **単一修正**: 新予約語追加が1ファイルの修正で完了
3. **AI正確性**: AIが生成するコードのエラー率90%削減
4. **性能維持**: 統一化による性能劣化5%以内
## 🚀 移行計画
### Phase 1: 基盤構築1週間
- 統一レジストリ実装
- 既存コードとの並行動作
### Phase 2: Tokenizer/Parser統合1週間
- 段階的切り替え
- 差分検出とログ
### Phase 3: 実行層統合2週間
- MIR/VM/JIT の統一
- 包括的テスト
### Phase 4: 完全移行1週間
- 旧コード削除
- ドキュメント完成
これにより、Nyashのすべての層で完全に統一された予約語・文法解釈が実現される。