jit: ops_ext delegation + M3 syntax scaffolding; unify BoxCall execution path

This commit is contained in:
Moe Charm
2025-09-02 17:12:51 +09:00
parent 5a5e09b69a
commit d52779dc10
33 changed files with 2499 additions and 423 deletions

View File

@ -663,3 +663,79 @@ bash tools/build_aot.sh examples/aot_min_string_len.nyash -o app
- 非基本コンストラクタの委譲徹底Math/Random/Sound/Debugなど
- 主要ビルトインの plugin 化nyash_box.toml 整備)
- CIに `NYASH_USE_PLUGIN_BUILTINS=1` / `NYASH_PLUGIN_OVERRIDE_TYPES` のスモークを追加
---
## 引き継ぎPhase 11.9 / 統一文法アーキテクチャ + JIT分割
現状サマリ(実装済み)
- 統一文法スキャフォールド
- build時コード生成: `build.rs` → `src/grammar/generated.rs`
- `KEYWORDS`(最小)と `OPERATORS_ADD_COERCION`, `OPERATORS_ADD_RULES` を生成
- TOML未整備でも add 既定規則を生成側で補完
- エンジン: `src/grammar/engine.rs``is_keyword_str`/`add_coercion_strategy`/`add_rules`/`decide_add_result`
- Tokenizerに非侵襲差分ログ`NYASH_GRAMMAR_DIFF=1`
- Add 規則の非侵襲導入
- JIT: `lower_binop(Add)` で grammar ヒントをイベント出力
- VM/Interpreter: 期待と実際の型を差分ログ(`NYASH_GRAMMAR_DIFF=1`
- オプトイン強制適用(挙動変更は未既定): `NYASH_GRAMMAR_ENFORCE_ADD=1`
- スナップショットテスト
- `tests/grammar_add_rules.rs`grammar 期待 と 現行セマンティクスの一致検証)→ 単体実行で緑
JIT分割 進捗(継続観点)
- 完了: builder分割`builder/cranelift.rs`、core 第一段階分割(`core_ops.rs`、`core/analysis.rs`、`core/cfg.rs`
- jit-direct スモーク緑debug: mir-branch-ret=1 / mir-phi-min=10 / mir-branch-multi=1
使い方(開発時)
- 差分ログ: `NYASH_GRAMMAR_DIFF=1`Tokenizer/VM/Interp/JIT各所
- 規則強制: `NYASH_GRAMMAR_ENFORCE_ADD=1`Add のみ、他は非侵襲)
- JITスモーク例: `NYASH_JIT_THRESHOLD=1 ./target/debug/nyash --jit-direct apps/tests/mir-branch-ret/main.nyash`
- テスト(本件のみ): `cargo test -q --test grammar_add_rules`
次のTODO優先順
1) JITロワラー分割の続き
- 大きい分岐Extern/PluginInvoke/BoxCallを `src/jit/lower/core/ops_ext.rs` へ抽出
- 各ステップごとに jit-direct スモーク確認
2) 統一文法の拡張
- operators: Sub/Mul/Div の `type_rules` を TOML → 生成 → VM/Interp/JIT に非侵襲ログ(必要なら `*_ENFORCE_*`を用意)
- keywords/alias/context の雛形を TOML 化(差分ログ継続)
3) スナップショット整備
- add 以外の演算子でも「grammar期待 vs 実際」の表テストを追加
- 将来、Tokenizer/Parser でも「grammar期待 vs 実際構文」のスナップショットを追加
注意
- 既存の他テストには未整備部分があり全体 `cargo test` は赤が出るため、当面は個別テスト/スモークを推奨
- Release の jit-direct 実行は `--features cranelift-jit` が必要
## Update: Phase 11.9 統一文法アーキテクチャMVP導入計画
目的: Tokenizer/Parser/Interpreter/MIR/VM/JIT の解釈差異を解消するため、単一の文法・意味・実行定義を導入(詳細は `docs/development/roadmap/phases/phase-11.9/unified-grammar-architecture.md` と `docs/development/roadmap/phases/phase-11.9/PLAN.md`)。
直近TODOM1/M2のMVP範囲
- [ ] scaffolding: `build.rs` + `src/grammar/{mod.rs,engine.rs}` + `src/grammar/generated.rs`codegen方式
- [ ] `grammar/unified-grammar.toml` 初期化keywords: `me`,`from`,`loop`; operators: `add`
- [ ] Tokenizer に `engine.is_keyword()` を差し込み(`NYASH_GRAMMAR_DIFF=1` で差分ログ)
- [ ] `ExecutionSemantics` に `operators.add` を実装し、Interpreter/VM/JIT へ薄く統合(既存実装はフォールバック)
- [ ] 予約語マッピングの一貫性テストと、加算セマンティクスの VM/JIT/Interpreter 一致テスト
備考
- ランタイム I/O は避け、TOML→生成コードに変換して起動/ホットパスへの影響を最小化
- プラグイン拡張は将来の統合対象(優先度・名前空間・競合検知を設計)
## Progress: JIT Lowering リファクタ状況11.8/12系
完了
- [x] builder 分割(`src/jit/lower/builder.rs` を薄いハブ化、`builder/cranelift.rs` へ移動)
- [x] jit-direct の最小スモーク安定debug
- apps/tests/mir-branch-ret → 1
- apps/tests/mir-phi-min → 10
- apps/tests/mir-branch-multi → 1
- [x] core.rs の第一段階分割:
- `src/jit/lower/core_ops.rs` にヘルパー移設push_value_if_known_or_param, cover_if_supported, BinOp/Compareなど
- - `src/jit/lower/core/analysis.rs` 追加Bool/PHI推論統計
- - `src/jit/lower/core/cfg.rs` 追加PHI受け口順序とCFGダンプ
次の分割候補
- [ ] Extern/PluginInvoke/BoxCall 周辺の肥大化した分岐を `core/ops_ext.rs` に整理
- [ ] `analysis`/`cfg` の補助関数succ_phi_inputs など)の関数化
- [ ] 分割ごとに jit-direct スモークの緑維持debug / release+feature

View File

@ -0,0 +1,48 @@
# Phase 11.9: 統一文法アーキテクチャ — 実装予定MVP〜段階移行
## 目的
- Tokenizer/Parser/Interpreter/MIR/VM/JIT の解釈差異を解消し、単一の「文法・意味・実行」定義から各層が参照する構造へ移行する。
- 変更や拡張(予約語/演算子/構文)のコストと不整合リスクを減らす。
## マイルストーンMVP→段階導入
### M1: 予約語レジストリの導入(最小)
- 追加: `src/grammar/engine.rs``UnifiedGrammarEngine``KeywordRegistry` の骨格)
- 追加: `grammar/unified-grammar.toml`(初期エントリ: `me`, `from`, `loop`, `+`
- 追加: `build.rs` で TOML → `src/grammar/generated.rs` をコード生成(ランタイム I/O 回避)
- Tokenizer 統合(非侵襲): 従来テーブルの後段に `engine.is_keyword()` を差し込み、`NYASH_GRAMMAR_DIFF=1` で差分ログ
- 成功条件: 既存テストを落とさず、差分ログが 0 or 想定内のみに収束
### M2: 演算子セマンティクスの統一(加算など最小)
- `ExecutionSemantics``operators.add` を定義(型規則/コアーション/エラー方針)
- Interpreter/VM/JIT で `execute_semantic("add", …)` による共通実装窓口を追加(従来実装はフォールバック)
- 既存 `hostcall_registry`/JIT ポリシーと接合するインターフェースを用意(型分類/シンボルの参照点を一本化)
- 成功条件: 文字列結合/整数加算/浮動小数加算の3系統で VM/JIT/Interpreter の一致を維持
### M3: 構文規則エンジンの段階導入
- `SyntaxRuleEngine` 追加、`statement`/`expr` の骨格ルールを TOML 側へ切り出し
- Parser 統合(段階的): 既存パーサ優先+新ルールでの検証を併走、差分ログで移行安全性を担保
- 成功条件: 代表サンプルで新旧の AST→MIR が一致(スナップショット)
### M4: 並行実行/差分検出・テスト整備
- 並行期間は新旧両系の結果を比較し、スナップショットとファズで回帰防止
- 収束後、旧ルートを段階的に縮退
## 実装順(詳細 TODO
1) `build.rs``src/grammar/mod.rs` の雛形追加(`generated.rs``include!`
2) `KeywordRegistry` の生成コードを実装、Tokenizer に差し込み(環境変数で切り替え)
3) `operators.add` の型規則を TOML 化し、`ExecutionSemantics` で解決
4) Interpreter/VM/JIT へ共通窓口の薄い統合(実行は従来実装と比較可能に)
5) 構文ルール最小セットstatement/exprを TOML へ移管し、解析の差分をログ化
6) スナップショット/ファズの整備と収束確認
## リスクと対策
- 競合/拡張: プラグイン由来の拡張を名前空間+優先度でマージ、競合は検知してビルド失敗で気付かせる
- 実行コスト: 生成コード方式でランタイム I/O を避け、起動時間・ホットパスへの影響をゼロに近づける
- 文脈依存: `contextual` のキー粒度を設計node_kind/context など)し、曖昧解釈を防ぐ
## 成功基準Exit Criteria
- 予約語解決の統一Tokenizer での差分 0
- 加算に関する VM/JIT/Interpreter のセマンティクス一致(型差分含む)
- 構文最小セットで新旧の AST→MIR が一致(代表ケース)

View File

@ -75,12 +75,28 @@ 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)
### 📌 まず読むべき資料
- **[統一セマンティクス実装設計](unified-semantics-implementation.txt)****🎯 最新の実装方針**
- **[統一文法設計総合まとめ](UNIFIED-GRAMMAR-DESIGN-SUMMARY.md)**設計思想の理解
### 🔥 核心設計ドキュメント
- [統一文法アーキテクチャ設計書](unified-grammar-architecture.md) - 基本設計
- [統一予約語システム仕様](unified-keyword-system.md) - 具体的実装
- [AI深層考察: 統一文法アーキテクチャ](ai-deep-thoughts-unified-grammar.md) - Gemini/Codex分析
### 📚 発展的設計(参考)
- [発展的設計集](advanced-designs/) - より深い設計思想
- box-first-grammar-architecture.md - 箱化アプローチ
- root-cutting-architecture.md - 疎結合設計
- zero-knowledge-architecture.md - 究極の分離
### 🔧 実装資料
- [アーカイブ](archive/) - 過去の詳細設計ドキュメント
- grammar-unification.txt - 初期の文法統一化詳細設計
- nyash-grammar-v1.yaml - 統一文法定義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,107 @@
# Phase 11.9 統一文法設計 - 総合まとめ
## 📋 概要
Nyashの各実行層Tokenizer/Parser/Interpreter/MIR/VM/JITで予約語・文法解釈がバラバラに実装されている問題を解決する統一文法アーキテクチャ設計のまとめです。
## 🎯 核心的な問題
```rust
// 現在: 同じ "me" が6箇所で別々に定義
Tokenizer: "me" TokenType::ME
Parser: 独自のme処理ロジック
Interpreter: 独自のself参照実装
MIR Builder: LoadLocal(0)への変換
VM: OP_LOAD_MEの実行
JIT: LoadFirstParamの生成
```
## 💡 提案された解決策
### 1. 基本アプローチ: 統一文法エンジン
- 単一の文法定義YAML/TOML
- 各層が参照する統一API
- UnifiedSemantics による一貫した実行
### 2. AI提案: ビルド時コード生成
- **Gemini**: 宣言的定義 + build.rs によるコード生成
- **Codex**: MIR中心の統一セマンティクス基盤
- 実行時オーバーヘッドゼロ
### 3. 箱化による疎結合設計
- 各層を独立した「箱」として実装
- 変換箱TransformerBoxパターン
- パイプライン方式での連結
## 📊 実装アプローチの比較
| アプローチ | 利点 | 欠点 | 推奨度 |
|---------|------|------|-------|
| 統一エンジン | シンプル、理解しやすい | 実行時オーバーヘッド | ★★★ |
| コード生成 | 高性能、型安全 | ビルド複雑化 | ★★★★★ |
| 完全箱化 | 究極の疎結合 | 実装複雑度高 | ★★★★ |
## 🚀 推奨実装計画
### Phase 1: 文法定義ファイル作成
```yaml
# grammar/nyash.yml
tokens:
me: { id: 1, category: self_reference }
from: { id: 2, category: delegation }
loop: { id: 3, category: control_flow }
operators:
"+": { precedence: 10, associativity: left }
```
### Phase 2: コード生成基盤
```rust
// build.rs
fn generate_from_grammar() {
// grammar.yml → generated/*.rs
}
```
### Phase 3: 段階的移行
1. Tokenizer を生成コードに移行
2. Parser を統一文法に移行
3. Semantics を一元化
4. MIR/VM/JIT を統合
## 🎯 期待される効果
1. **保守性向上**: 新機能追加が1箇所で完了
2. **一貫性確保**: 全層で同じセマンティクス
3. **AI対応改善**: LLMが正確なコードを生成
4. **性能維持**: ビルド時最適化でオーバーヘッドなし
## 📁 作成されたドキュメント
### 必須ドキュメント(実装に必要)
1. **[統一文法アーキテクチャ設計書](unified-grammar-architecture.md)** - 基本設計
2. **[統一予約語システム仕様](unified-keyword-system.md)** - 具体的実装仕様
3. **[AI深層考察](ai-deep-thoughts-unified-grammar.md)** - Gemini/Codex分析
### 発展的ドキュメント(参考資料)
4. **[Box-First文法アーキテクチャ](box-first-grammar-architecture.md)** - 箱化アプローチ
5. **[根切り文法アーキテクチャ](root-cutting-architecture.md)** - 完全疎結合設計
6. **[ゼロ知識文法アーキテクチャ](zero-knowledge-architecture.md)** - 究極の分離設計
### 既存ドキュメント
- [文法統一化詳細設計](grammar-unification.txt)
- [統一文法定義YAML](nyash-grammar-v1.yaml)
- [実装計画](implementation-plan.txt)
## 🔧 次のステップ
1. `grammar/nyash.yml` の初版作成
2. `crates/nygrammar-gen` の実装開始
3. Tokenizer の移行から着手
4. 段階的に全層を統一
## 📝 結論
コード生成アプローチGemini/Codex推奨を採用し、`grammar/nyash.yml` を単一の真実の源として、build.rs で各層向けのコードを生成する方式が最も実用的です。
これにより、Nyashの文法が完全に統一され、保守性・一貫性・AI対応すべてが改善されます。

View File

@ -0,0 +1,304 @@
# ゼロ知識文法アーキテクチャ - 究極の疎結合
## 🔍 さらに深い問題: 暗黙知識の漏洩
### 現在の設計でもまだ残る問題
```rust
// 🚨 TokenToASTBoxがTokenの意味を知っている
transform(tokens: TokenStream) -> AST {
if token == Token::Me { // Tokenの意味を知っている
return AST::SelfReference
}
}
// 🚨 ASTToMIRBoxがASTの構造を知っている
transform(ast: AST) -> MIR {
match ast {
AST::BinaryOp(op, left, right) => { // AST構造を知っている
// ...
}
}
}
```
## 🎯 ゼロ知識原則: 「箱は変換ルールだけを知る」
### 純粋な変換テーブル駆動設計
```rust
// 各箱は変換テーブルだけを持つ
box TokenClassifierBox {
init { table: Map<String, u32> } // 文字列→数値のマッピングのみ
classify(word: String) -> u32 {
return me.table.get(word).unwrapOr(0) // 0 = unknown
}
}
// ビルド時に生成される純粋なマッピング
const TOKEN_TABLE: Map<String, u32> = {
"me" => 1,
"from" => 2,
"loop" => 3,
// ...
}
```
## 📊 統一中間表現UIR: Unified Intermediate Representation
### すべての層が数値タグで通信
```
Source Code UIR Tags Execution
----------- -------- ---------
"me" → [1] → LoadLocal(0)
"+" → [100] → Add
"loop" → [200] → Branch
1 + 2 → [300,1,300,2,100] → Const(1), Const(2), Add
```
### UIRTag: 意味を持たない純粋な識別子
```rust
box UIRTag {
init { id: u32, children: Array<UIRTag> }
// タグは意味を持たない、ただの番号
isLeaf() { return me.children.isEmpty() }
getChildren() { return me.children }
}
```
## 🔄 完全分離された変換パイプライン
### 1. 字句解析: 文字列→UIRタグ
```rust
box LexicalTransformerBox {
init { charTable: Array<u32> } // 文字→タグのテーブル
transform(text: String) -> Array<UIRTag> {
local tags = []
local chars = text.chars()
loop(chars.hasNext()) {
local ch = chars.next()
local tag = me.charTable[ch.code()]
if tag == TAG_LETTER {
local word = me.collectWhile(chars, TAG_LETTER)
tags.push(me.lookupWord(word))
} else if tag == TAG_DIGIT {
local num = me.collectWhile(chars, TAG_DIGIT)
tags.push(UIRTag(TAG_NUMBER, num))
}
// ...
}
return tags
}
// 単語検索も純粋なハッシュ値
lookupWord(word: String) -> UIRTag {
local hash = me.perfectHash(word)
return UIRTag(hash, [])
}
}
```
### 2. 構文解析: UIRタグ→UIRツリー
```rust
box SyntaxTransformerBox {
init {
// 優先順位テーブル(タグ→優先度)
precedence: Map<u32, u32>,
// 結合性テーブル(タグ→左/右)
associativity: Map<u32, u8>
}
transform(tags: Array<UIRTag>) -> UIRTag {
// Prattパーサーだが、意味を知らない
return me.parseExpression(tags, 0)
}
parseExpression(tags: Array<UIRTag>, minPrec: u32) -> UIRTag {
local left = me.parsePrimary(tags)
loop(tags.hasNext()) {
local op = tags.peek()
local prec = me.precedence.get(op.id).unwrapOr(0)
if prec < minPrec { break }
tags.next() // consume operator
local assoc = me.associativity.get(op.id).unwrapOr(LEFT)
local nextPrec = if assoc == LEFT { prec + 1 } else { prec }
local right = me.parseExpression(tags, nextPrec)
// 構造だけ作る、意味は知らない
left = UIRTag(op.id, [left, right])
}
return left
}
}
```
### 3. 意味解析: UIRツリー→実行可能形式
```rust
box SemanticTransformerBox {
init {
// タグ→実行アクションのテーブル
actions: Map<u32, ExecutionAction>
}
transform(tree: UIRTag) -> ExecutableCode {
local action = me.actions.get(tree.id)
if action {
return action.generate(tree.children.map(child => {
me.transform(child)
}))
}
return ExecutableCode.Noop()
}
}
```
## 📐 ビルド時の統一: マスターテーブル生成
### grammar.yaml → 各種テーブル生成
```yaml
# grammar.yaml - 真の単一情報源
tokens:
me: { id: 1, type: self_reference }
from: { id: 2, type: delegation }
loop: { id: 3, type: control_flow }
operators:
"+": { id: 100, precedence: 10, associativity: left }
"*": { id: 101, precedence: 20, associativity: left }
semantics:
1: { action: load_self }
2: { action: delegate_call }
3: { action: loop_construct }
100: { action: add_operation }
```
### ビルド時生成
```rust
// build.rs
fn generate_tables(grammar: GrammarDef) {
// 1. 完全ハッシュ関数生成
generate_perfect_hash(grammar.tokens)
// 2. 優先順位テーブル生成
generate_precedence_table(grammar.operators)
// 3. セマンティクステーブル生成
generate_semantic_table(grammar.semantics)
// 4. 各層の定数生成
generate_constants(grammar)
}
```
## 🎯 究極の利点: 完全な知識分離
### 1. 各箱が知っていること
- **LexicalTransformer**: 文字の分類とハッシュ計算のみ
- **SyntaxTransformer**: 優先順位と結合性のみ
- **SemanticTransformer**: タグとアクションの対応のみ
### 2. 各箱が知らないこと
- **すべての箱**: 他の層の存在、Nyashという言語名すら知らない
- **すべての箱**: キーワードの意味、演算子の意味
- **すべての箱**: 最終的な実行形式
### 3. テストの単純化
```rust
test "lexical transformer" {
local table = { "hello" => 42 }
local box = LexicalTransformerBox(table)
assert box.transform("hello") == [UIRTag(42)]
}
test "syntax transformer" {
local prec = { 100 => 10, 101 => 20 }
local box = SyntaxTransformerBox(prec, {})
// 1 + 2 * 3
local tags = [UIRTag(1), UIRTag(100), UIRTag(2), UIRTag(101), UIRTag(3)]
local tree = box.transform(tags)
// 期待: (+ 1 (* 2 3))
assert tree == UIRTag(100, [
UIRTag(1),
UIRTag(101, [UIRTag(2), UIRTag(3)])
])
}
```
## 🔧 動的拡張: プラグインテーブル
### 実行時のテーブル拡張
```rust
box PluginLoaderBox {
init { transformers: Map<String, TransformerBox> }
loadPlugin(path: String) {
local plugin = Plugin.load(path)
// プラグインは新しいタグを登録
local newTags = plugin.getTags()
// 各変換器のテーブルを拡張
me.transformers.get("lexical").extendTable(newTags.lexical)
me.transformers.get("syntax").extendTable(newTags.syntax)
me.transformers.get("semantic").extendTable(newTags.semantic)
}
}
```
## 📊 性能特性
### 1. キャッシュ効率
- 各テーブルは連続メモリに配置
- CPUキャッシュに収まるサイズ
- ランダムアクセスなし
### 2. 並列化可能
- 各変換は状態を持たない
- 入力を分割して並列処理可能
- ロックフリー実装
### 3. 最適化の余地
- テーブルのコンパクト化
- SIMDによる並列検索
- JITによるテーブル特化
## 🚀 最終形: 言語に依存しない変換エンジン
```rust
// このエンジンはNyashを知らない
box UniversalTransformEngine {
init {
pipeline: Array<TransformerBox>,
tables: Map<String, Table>
}
execute(input: String) -> Output {
local data = input
// 各変換を順番に適用
me.pipeline.forEach(transformer => {
data = transformer.transform(data)
})
return data
}
}
// Nyash = 特定のテーブルセット
const NYASH_TABLES = load_tables("nyash-grammar.yaml")
local engine = UniversalTransformEngine(STANDARD_PIPELINE, NYASH_TABLES)
```
これが究極の「根を切った」設計です。各箱は純粋な変換器であり、Nyashという言語の存在すら知りません。

View File

@ -0,0 +1,255 @@
# ChatGPT5フィードバック統合 - 統一文法アーキテクチャ改善
## 📋 ChatGPT5からの評価
> 「Grammar as THE Source of Truth で各層の乖離を一元化する狙いは現状の痛点に直結しており、有効です」
## 🎯 指摘されたリスクへの対応策
### 1. ランタイム依存過多への対応
#### 問題
```rust
// ❌ 悪い例実行時にTOMLパース
let grammar = toml::from_str(&fs::read_to_string("grammar.toml")?)?;
```
#### 解決策build.rs による完全コード生成
```rust
// build.rs
fn main() {
println!("cargo:rerun-if-changed=grammar/nyash.yml");
let grammar = load_grammar_definition();
// Rust定数として生成
generate_keyword_constants(&grammar);
generate_perfect_hash_function(&grammar);
generate_semantic_tables(&grammar);
generate_mir_mappings(&grammar);
}
// 生成されるコード例
// generated/keywords.rs
pub const KEYWORD_ME: u32 = 1;
pub const KEYWORD_FROM: u32 = 2;
pub const KEYWORD_LOOP: u32 = 3;
#[inline(always)]
pub fn classify_keyword(s: &str) -> Option<u32> {
match s {
"me" => Some(KEYWORD_ME),
"from" => Some(KEYWORD_FROM),
"loop" => Some(KEYWORD_LOOP),
_ => None,
}
}
```
### 2. プラグイン拡張性と競合への対応
#### マージ戦略の定義
```yaml
# grammar/nyash.yml
version: "1.0"
namespace: "core"
# プラグイン拡張ポイント
extension_points:
operators:
merge_strategy: "priority" # 優先順位ベース
conflict_resolution: "namespace" # 名前空間で分離
# プラグイン例
# plugins/custom/grammar.yml
namespace: "custom"
extends: "core"
operators:
"++": # 新しい演算子
priority: 100
precedence: 15
semantics: increment
```
#### 実装時の名前空間解決
```rust
pub struct GrammarRegistry {
core: CoreGrammar,
plugins: HashMap<String, PluginGrammar>,
}
impl GrammarRegistry {
pub fn resolve_operator(&self, op: &str, context: &Context) -> OperatorDef {
// 1. 現在の名前空間で検索
if let Some(def) = context.namespace.find_operator(op) {
return def;
}
// 2. インポートされた名前空間を優先順位順に検索
for imported in &context.imports {
if let Some(def) = self.plugins.get(imported)?.find_operator(op) {
return def;
}
}
// 3. コア名前空間にフォールバック
self.core.find_operator(op).unwrap_or_else(|| {
panic!("Unknown operator: {}", op)
})
}
}
```
### 3. 文脈依存キーワードの曖昧性解決
#### fromキーワードの文脈解決ルール
```yaml
# grammar/nyash.yml
contextual_keywords:
from:
contexts:
- name: "box_delegation"
pattern: "box IDENT from"
priority: 100
- name: "method_delegation"
pattern: "from IDENT.IDENT"
priority: 90
- name: "variable_name"
pattern: "IDENT = from" # 変数名として使用
priority: 10
resolution: "longest_match_first" # 最長一致優先
```
#### パーサーでの実装
```rust
impl Parser {
fn parse_from(&mut self) -> Result<Node> {
let start_pos = self.current_pos();
// 最長一致を試みる
if let Ok(delegation) = self.try_parse_delegation() {
return Ok(delegation);
}
// フォールバック:通常の識別子として扱う
self.reset_to(start_pos);
Ok(Node::Identifier("from".to_string()))
}
}
```
### 4. 二重実装期間の管理
#### 自動差分検出テスト
```rust
#[cfg(test)]
mod migration_tests {
use super::*;
#[test]
fn test_unified_vs_legacy_semantics() {
let test_cases = load_test_cases("tests/semantics/*.nyash");
for case in test_cases {
let legacy_result = legacy_interpreter.execute(&case);
let unified_result = unified_interpreter.execute(&case);
// スナップショットテスト
assert_snapshot!(
format!("{}_unified", case.name),
unified_result
);
// 差分検出
if legacy_result != unified_result {
// 意図的な変更か確認
assert!(
is_expected_difference(&case, &legacy_result, &unified_result),
"Unexpected difference in {}: {:?} vs {:?}",
case.name, legacy_result, unified_result
);
}
}
}
}
```
#### 段階的移行フラグ
```rust
pub struct ExecutionConfig {
pub use_unified_grammar: bool,
pub log_differences: bool,
pub fail_on_difference: bool,
}
impl Interpreter {
pub fn execute_with_migration(&mut self, expr: &Expression) -> Result<Value> {
if self.config.use_unified_grammar {
let result = self.unified_execute(expr)?;
if self.config.log_differences {
let legacy_result = self.legacy_execute(expr)?;
if result != legacy_result {
log::warn!(
"Semantic difference detected: {:?} -> unified: {:?}, legacy: {:?}",
expr, result, legacy_result
);
if self.config.fail_on_difference {
panic!("Unexpected semantic difference");
}
}
}
Ok(result)
} else {
self.legacy_execute(expr)
}
}
}
```
## 📊 改善された実装計画
### Phase 0: 準備1週間
- ベースラインテストスイート作成
- 現在のセマンティクスのスナップショット記録
- 差分検出フレームワーク構築
### Phase 1: コード生成基盤1週間
- build.rs による完全静的生成
- ゼロランタイムコスト実現
- CI/CDでの生成コード検証
### Phase 2: 名前空間とプラグイン1週間
- 名前空間解決システム
- プラグインマージ戦略実装
- 競合検出と報告
### Phase 3: 文脈依存解決1週間
- fromキーワードの文脈ルール実装
- 最長一致パーサー
- 曖昧性テストケース
### Phase 4: 段階的移行2週間
- フィーチャーフラグ実装
- 並行実行と差分ログ
- 本番環境での検証
## 🎯 期待される成果
1. **ゼロコスト抽象化**: 実行時オーバーヘッドなし
2. **安全な拡張性**: プラグイン競合の自動解決
3. **明確な文脈解決**: 曖昧性のない文法
4. **リスクフリー移行**: 自動検証による安全な移行
## 📝 まとめ
ChatGPT5さんの指摘により、実装の潜在的リスクが明確になりました。
これらの対策を組み込むことで、より堅牢で実用的な統一文法アーキテクチャが実現できます。
「痛点直結」という評価に応えられる実装を目指しますにゃ!🚀

View File

@ -0,0 +1,255 @@
# Nyash統一セマンティクス実装設計
# 作成日: 2025-09-02
# 目的: Interpreter/VM/JIT全層での予約語・文法解釈の完全統一
## 概要
すべての実行層が同じセマンティクスに従うよう、MIR正規化層を中心とした統一実装を行う。
## 核心的な問題
現在、同じ式が各層で異なる解釈をされている:
- "hello" + 123
- Interpreter: エラーを出す
- VM: 型変換してから連結
- JIT: 数値を文字列化してから連結
## 解決策MIR統一セマンティクス + 軽量UIRタグ
### 1. 統一セマンティクス定義grammar/semantics.yml
```yaml
# すべての層が従う唯一の定義
version: "1.0"
semantics:
add:
- pattern: [String, String]
action: concat
mir: StringConcat
vm: OP_STR_CONCAT
- pattern: [String, Any]
action: coerce_concat
steps:
- ToString($2)
- StringConcat($1, $2)
- pattern: [Integer, Integer]
action: add_i64
mir: AddI64
vm: OP_ADD_I64
toString:
- pattern: [String]
action: identity
- pattern: [Integer]
action: int_to_string
- pattern: [Float]
action: float_to_string
- pattern: [Bool]
action: bool_to_string
- pattern: [Null]
action: const_null_string
```
### 2. UIRタグシステム層間通信
```rust
// generated/uir_tags.rs (build.rsで生成)
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum UIRTag {
// 予約語
ME = 1,
FROM = 2,
LOOP = 3,
BOX = 4,
INIT = 5,
// 演算子
ADD = 100,
SUB = 101,
MUL = 102,
DIV = 103,
// セマンティクスアクション
STRING_CONCAT = 200,
TO_STRING = 201,
ADD_I64 = 202,
ADD_F64 = 203,
}
```
### 3. MIR正規化層真実の基盤
```rust
// src/mir/normalizer.rs
pub struct MIRNormalizer {
semantics_table: SemanticRuleTable,
}
impl MIRNormalizer {
pub fn normalize(&self, expr: &Expression) -> MIR {
match expr {
Expression::BinaryOp(op, left, right) => {
let left_type = self.infer_type(left);
let right_type = self.infer_type(right);
// 統一ルールを適用
let rule = self.semantics_table.lookup(op, &[left_type, right_type]);
match rule.action {
Action::Concat => {
MIR::StringConcat(
Box::new(self.normalize(left)),
Box::new(self.normalize(right))
)
}
Action::CoerceConcat => {
// 右辺を文字列に変換してから連結
MIR::Sequence(vec![
self.normalize(left),
MIR::ToString(Box::new(self.normalize(right))),
MIR::StringConcat
])
}
Action::AddI64 => {
MIR::AddI64(
Box::new(self.normalize(left)),
Box::new(self.normalize(right))
)
}
}
}
}
}
}
```
### 4. 各層の統一実装
#### Interpreter層
```rust
impl Interpreter {
fn execute_expression(&mut self, expr: &Expression) -> Result<Value> {
// すべてMIR経由で実行
let mir = self.mir_normalizer.normalize(expr);
self.execute_mir(&mir)
}
fn execute_mir(&mut self, mir: &MIR) -> Result<Value> {
match mir {
MIR::StringConcat(left, right) => {
let left_val = self.execute_mir(left)?;
let right_val = self.execute_mir(right)?;
Ok(Value::String(format!("{}{}", left_val, right_val)))
}
MIR::ToString(expr) => {
let val = self.execute_mir(expr)?;
Ok(Value::String(self.value_to_string(&val)))
}
MIR::AddI64(left, right) => {
let left_val = self.execute_mir(left)?;
let right_val = self.execute_mir(right)?;
Ok(Value::Integer(left_val.as_i64()? + right_val.as_i64()?))
}
}
}
}
```
#### VM層
```rust
impl VM {
fn compile_mir(&mut self, mir: &MIR) -> Vec<Opcode> {
// MIRから機械的にバイトコード生成
match mir {
MIR::StringConcat(left, right) => {
let mut code = vec![];
code.extend(self.compile_mir(left));
code.extend(self.compile_mir(right));
code.push(Opcode::StringConcat);
code
}
MIR::ToString(expr) => {
let mut code = self.compile_mir(expr);
code.push(Opcode::ToString);
code
}
MIR::AddI64(left, right) => {
let mut code = vec![];
code.extend(self.compile_mir(left));
code.extend(self.compile_mir(right));
code.push(Opcode::AddI64);
code
}
}
}
}
```
#### JIT層
```rust
impl JITCompiler {
fn compile_mir(&mut self, mir: &MIR) {
// MIRから最適化されたネイティブコード生成
match mir {
MIR::StringConcat(left, right) => {
self.compile_mir(left);
self.compile_mir(right);
// 高速な文字列連結関数を呼び出し
self.emit_call(fast_string_concat);
}
MIR::ToString(expr) => {
self.compile_mir(expr);
// 型に応じた最適な変換
self.emit_call(optimized_to_string);
}
MIR::AddI64(left, right) => {
self.compile_mir(left);
self.compile_mir(right);
// ネイティブな加算命令
self.emit_add_i64();
}
}
}
}
```
## 実装手順
### Phase 1: 基盤構築1週間
1. grammar/semantics.yml 作成
2. UIRTag定義とbuild.rs生成
3. SemanticRuleTable実装
### Phase 2: MIR正規化層1週間
1. MIRNormalizer実装
2. 型推論システム構築
3. セマンティクステーブル連携
### Phase 3: 各層統合2週間
1. Interpreterを MIR経由に変更
2. VMのMIRコンパイラ実装
3. JITのMIRコンパイラ実装
### Phase 4: テストと検証1週間
1. 統一セマンティクステスト作成
2. 各層での一貫性検証
3. パフォーマンス測定
## 期待される効果
1. **完全な一貫性**: すべての層が同じ動作
2. **保守性向上**: セマンティクス変更が1箇所
3. **拡張性**: 新しい演算子の追加が容易
4. **AI対応**: 単一の仕様から学習可能
5. **デバッグ容易性**: MIRレベルでの統一デバッグ
## 注意事項
- 既存のコードとの互換性を保つため、フィーチャーフラグで段階的移行
- パフォーマンスへの影響を最小限にするため、ビルド時最適化を活用
- テストカバレッジを十分に確保してから本番移行
## 関連ファイル
- grammar/semantics.yml - セマンティクス定義
- src/mir/normalizer.rs - MIR正規化実装
- build.rs - コード生成
- tests/unified_semantics.rs - 統一テスト