2025-09-02 17:12:51 +09:00
|
|
|
|
# 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() {
|
2025-11-06 15:41:52 +09:00
|
|
|
|
let test_cases = load_test_cases("tests/semantics/*.hako");
|
2025-09-02 17:12:51 +09:00
|
|
|
|
|
|
|
|
|
|
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さんの指摘により、実装の潜在的リスクが明確になりました。
|
|
|
|
|
|
これらの対策を組み込むことで、より堅牢で実用的な統一文法アーキテクチャが実現できます。
|
|
|
|
|
|
|
|
|
|
|
|
「痛点直結」という評価に応えられる実装を目指しますにゃ!🚀
|