255 lines
7.1 KiB
Markdown
255 lines
7.1 KiB
Markdown
# 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さんの指摘により、実装の潜在的リスクが明確になりました。
|
||
これらの対策を組み込むことで、より堅牢で実用的な統一文法アーキテクチャが実現できます。
|
||
|
||
「痛点直結」という評価に応えられる実装を目指しますにゃ!🚀 |