freeze: macro platform complete; default ON with profiles; env consolidation; docs + smokes\n\n- Profiles: --profile {lite|dev|ci|strict} (dev-like default for macros)\n- Macro paths: prefer NYASH_MACRO_PATHS (legacy envs deprecated with warnings)\n- Selfhost pre-expand: auto mode, PyVM-only, add smokes (array/map)\n- Docs: user-macros updated; new macro-profiles guide; AGENTS freeze note; CURRENT_TASK freeze\n- Compat: non-breaking; legacy envs print deprecation notices\n

This commit is contained in:
Selfhosting Dev
2025-09-19 22:27:59 +09:00
parent 811e3eb3f8
commit da32455afc
192 changed files with 6454 additions and 2973 deletions

View File

@ -1,32 +1,75 @@
# Phase 10.7 - True Python Native via Plugin Boxes
# Phase 10.7 - Python→Nyash革命Phase 16マクロ統合版
## 🎯 概要
## 🚀 **Phase 16マクロ革命による劇的変化**
PythonコードをNyashで**本当にネイティブ実行**する。CPythonへの依存なしに、Pythonコードが完全にNyash MIR/JIT経由で機械語として実行される。
**Before Phase 16**: 手動transpiler2-3ヶ月
**After Phase 16**: マクロボックス自動変換1-2週間
### 現状 vs 理想
**現状Phase 10.6**: PyRuntimeBox → libpython呼び出し
**理想Phase 10.7**: Python → Nyashスクリプト → MIR → ネイティブ
## 🏗️ アーキテクチャ:トランスパイル方式
### 🎯 新戦略MacroBox-Driven Python Transpilation
```
Python AST → CorePy IR → Nyash AST → Nyashスクリプト
Python AST → MacroBox Pattern Match → Nyash AST (自動生成)
```
### なぜトランスパイル?
**革命的変化**:
-**旧**: 手動コード変換地獄2000行実装
-**新**: マクロパターンで自動変換200行実装
1. **透明性**: 生成コードが見える・デバッグできる・手を加えられる
2. **既存資産活用**: Nyashコンパイラの最適化を自動享受
3. **教育的価値**: PythonとNyashの対応が学習価値を持つ
4. **段階的改善**: 生成コードの品質を徐々に向上
## 🧠 **核心アイデアEverything is Box + Macro = 言語統合**
### プラグインBox群
### **マクロボックス群(新設計)**
- **PythonParserBox**: Python → AST変換
- **PythonCompilerBox**: AST → Nyashスクリプト生成
- **py_runtime.ny**: Pythonセマンティクス保持ライブラリ
```rust
// src/macro/python_transpiler.rs新規
@macro_box("python_dataclass")
@macro_box("python_property")
@macro_box("python_listcomp")
@macro_box("python_contextmgr")
@macro_box("python_decorator")
```
### **実装例Python @dataclass**
#### **Before手動地獄**:
```python
@dataclass
class User:
name: str
age: int
```
→ 手動変換(数時間) → Nyashコード
#### **Afterマクロ天国**:
```nyash
// @python_dataclass マクロが自動処理!
@python_dataclass
box UserBox {
name: StringBox
age: IntegerBox
}
// ↓ 自動展開 ↓
@derive(Equals, ToString, Clone)
box UserBox {
name: StringBox
age: IntegerBox
}
```
### **実装例Python List Comprehension**
#### **Python**:
```python
result = [x * 2 for x in numbers if x > 0]
```
#### **マクロ展開Nyash**:
```nyash
// @python_listcomp マクロが自動生成
local result = numbers
.filter(|x| x > 0)
.map(|x| x * 2)
.toArray()
```
## ⚠️ All or Nothing設計フォールバックなし
@ -48,27 +91,35 @@ if result.isOk() {
理由:開発時と本番時で挙動が変わるのは最悪の設計
## 📋 実装フェーズ
## 📋 **新実装フェーズPhase 16統合版**
### Phase 10.7a - Parser Plugin1週間
- PythonParserBoxの実装
- Python AST → ASTBox変換
- テレメトリー基盤
### **Phase 10.7-A: MacroBox基盤3日**
```rust
// src/macro/python_transpiler.rs 作成
pub fn register_python_macros() {
register_macro_box("python_dataclass", PythonDataclassTranspiler);
register_macro_box("python_property", PythonPropertyTranspiler);
register_macro_box("python_listcomp", PythonListCompTranspiler);
}
```
### Phase 10.7b - Compiler Core2週間)
**Phase 1機能(必須**
- 関数定義、条件分岐、ループ
- 演算子、関数呼び出し
- Python固有LEGB、デフォルト引数、for/else
### **Phase 10.7-B: コア変換パターン1週間)**
**必須マクロ(Phase 1**:
- `@python_dataclass``@derive(Equals,ToString)`
- `@python_property``computed property`
- `@python_listcomp``.filter().map()`
- `@python_function` → Nyash関数+LEGB
### Phase 10.7c - Validation & Testing1週間
- コンパイル可能性の事前検証
- Differential testingCPythonと比較
- 明確なエラーメッセージ
### **Phase 10.7-C: テスト・検証3日**
- マクロ展開結果の差分テスト
- `nyash --expand` でPython→Nyash変換可視化
- エラー時の明確な診断メッセージ
### Phase 10.7d - Coverage拡大3-4週間)
**Phase 2**: 例外処理、with文、comprehensions
**Phase 3**: async/await、デコレータ、ジェネレータ
### **Phase 10.7-D: 高度パターン1週間)**
**拡張マクロ(Phase 2**:
- `@python_contextmgr` → try/finally自動展開
- `@python_decorator` → マクロ適用チェーン
- `@python_async` → async/await変換
## 🧪 py_runtime設計
@ -93,56 +144,143 @@ box PyRuntime {
}
```
## 📊 成功指標
## 📊 **新成功指標(マクロ革命版)**
### Phase 1完了時
### **Phase 1完了時2週間後**
```
Compilable files: 15/100 (15%)
Performance (numeric): 10x faster than CPython
Correctness: 100% (differential testing)
実装コスト: 2000行 → 200 (90%削減)
開発時間: 2-3ヶ月 → 1-2週間 (85%短縮)
マクロパターン: 5個実装完了
Python→Nyash変換率: 80%+ (基本構文)
```
### 最終目標(Phase 3
### **最終目標(1ヶ月後**
```
Coverage: 95%+ of common patterns
Performance: 5-20x faster
Distribution: Single binary, no CPython
マクロパターン: 15個+ (全主要Python構文)
変換精度: 95%+ (property/dataclass/listcomp)
パフォーマンス: 10-50x faster (LLVM最適化)
統合性: Property System完全対応
```
## 🚀 クイックスタート
## 🚀 **クイックスタート(マクロ版)**
```bash
# プラグイン作成
cd plugins/
cargo new nyash-python-parser-plugin --lib
# Phase 16マクロ基盤活用
cd src/macro/
touch python_transpiler.rs
# 最小実装
# 最小マクロボックス実装
[dependencies]
pyo3 = { version = "0.22", features = ["auto-initialize"] }
nyash-plugin-sdk = { path = "../../crates/plugin-sdk" }
nyash-rust = { path = "../../" }
serde_json = "1.0"
# テスト実行
cargo build --release
../../target/release/nyash test_parser.nyash
# テスト実行(マクロ展開確認)
NYASH_MACRO_ENABLE=1 ./target/release/nyash --expand python_test.ny
```
## 💡 創造的可能性
## 🎯 **Property System統合戦略**
### ハイブリッドプログラミング
### **Python @property → Nyash computed**
```python
@nyash.vectorize # PythonデコレータがNyashのSIMD生成
def matrix_multiply(a, b):
return a @ b
class Circle:
@property
def area(self):
return 3.14 * self.radius ** 2
```
### 言語の共進化
- Nyashが「Pythonで最も使われるイディオム」から学習
- Pythonに「Nyash-aware」コーディングスタイル誕生
**マクロ自動変換**:
```nyash
@python_property // マクロが自動処理
box CircleBox {
radius: FloatBox
// computed property自動生成
area: FloatBox { 3.14 * me.radius * me.radius }
}
```
### 教育的インパクト
左にPython、右にリアルタイムNyash変換のPlayground
### **Python @cached_property → Nyash once**
```python
@cached_property
def expensive_calculation(self):
return heavy_computation()
```
## 📚 参考資料
**マクロ自動変換**:
```nyash
// once property自動生成
once expensive_calculation: ResultBox {
heavyComputation()
}
```
## 💡 **創造的可能性(マクロ革命版)**
### **🎪 ハイブリッドプログラミング**
```python
@nyash.vectorize # PythonデコレータがNyashマクロ展開
@nyash.config_schema # 環境変数自動読み込み
@nyash.api_client("https://api.example.com/swagger.json")
class DataProcessor:
def process(self, data):
return self.api.process_batch(data)
```
**マクロ展開後**:
```nyash
@vectorize @config_schema @api_client("...")
box DataProcessorBox {
// 全てマクロで自動生成!
api_client: HttpBox { /* 自動生成 */ }
config: ConfigBox { /* 環境変数から自動読み込み */ }
method process(data: ArrayBox) -> ResultBox {
me.api.processBatch(data) // SIMD最適化済み
}
}
```
### **🌍 言語統合プラットフォーム**
**Phase 16マクロシステムにより実現**:
- 🐍 **Python** → 🦀 **Nyash**: 自動変換
-**Java** → 🦀 **Nyash**: `@java_class`マクロで
- 🟦 **TypeScript** → 🦀 **Nyash**: `@ts_interface`マクロで
- 🔷 **C#** → 🦀 **Nyash**: `@csharp_property`マクロで
### **🎓 教育革命**
**リアルタイム変換Playground**:
```
┌─ Python Input ─────┐ ┌─ Nyash Output ────┐
│ @dataclass │ → │ @derive(...) │
│ class User: │ │ box UserBox { │
│ name: str │ │ name: StringBox │
│ age: int │ │ age: IntegerBox │
└────────────────────┘ └────────────────────┘
```
**学習効果**:
- プログラミング学習時間: **10分の1**
- 言語間移植理解: **瞬時**
- 最適化理解: **可視化**
## 📚 **参考資料(更新版)**
### **Phase 16統合ドキュメント**
- **[Phase 16 Macro Revolution](../phase-16-macro-revolution/README.md)** - マクロシステム全体
- **[docs/guides/macro-system.md](../../../../guides/macro-system.md)** - マクロ使用方法
- **[Macro Examples](../phase-16-macro-revolution/macro-examples.md)** - 実装例集
### **従来資料**
- **archive/gemini-analysis-transpile-beauty.md** - 創造性分析
- **archive/codex-analysis-technical-implementation.md** - 技術分析
- **archive/codex-analysis-technical-implementation.md** - 技術分析
---
## 🏆 **結論Phase 10.7の革命的変化**
**Before Phase 16**: Python実装 = 地獄の手動transpiler
**After Phase 16**: Python実装 = 楽しいマクロパターン作成
**Phase 16マクロシステムにより、Phase 10.7は「Python実装」から「言語統合革命」へと進化した**
**実装コスト90%削減、開発時間85%短縮で、10倍の表現力を実現する新時代の到来** 🚀✨

View File

@ -131,6 +131,44 @@ Imports/Namespace plan15.3late
---
## ♻ 再計画Macro駆動リファクタ
強化されたマクロ基盤AST JSON v0 / PyVMサンドボックス / strict / timeout / goldenを前提に、Phase15 のセルフホスティング工程を **「前段AST正規化 → 正式MIR生成」** の二段型にリフレームする。
### ポイント(運用)
- すべてのフロント側変換構文糖衣・derive相当・軽微なリライト・静的検証**MacroBoxSpec**Nyash/PyVMで実行1パス固定点
- Rust側は **最小のコア**(パース/AST JSON生成、MIRビルド、バックエンドに収束。
- 決定性担保: strict=1既定、capabilitiesは全OFFio/net/env=falseの純粋展開。
- 観測: `--dump-expanded-ast-json` と golden 比較で安定性を担保。
### 実行順序(改定)
1) Parse → AST
2) Macro expand1パス固定点: Builtin(Rust)→User (Nyash/PyVM)
3) Using/解決 → MIR → BackendVM/LLVM/AOT
### 直近タスクリストPhase15用
1. Macro 前段の正式導入完了PoC→実運用
- `NYASH_MACRO_BOX_NY=1` → PyVMランナー経由既定推奨
- strict=1/timeout=2000ms既定
- `--dump-expanded-ast-json` を golden として活用
2. Selfhost フロントの簡素化
- Nyash 製パーサは **最小構文**のみサポートStage2サブセット
- 糖衣や軽いリライトは **MacroBox** に寄せる
3. Golden セットの拡充
- `apps/tests/*``tools/test/golden/*` で展開後JSONの一致
- timeout/strict/失敗cap の負例テストを追加
4. nyash.toml 設計の雛形capabilities
- `[macros] paths=[…]` + `[macro_caps."path"] io/net/env=false` をドキュメント化
### 受け入れ基準Phase15
- `--dump-expanded-ast-json` の golden が緑MacroON/OFF差分は無いまたは期待通り
- PyVM ランナー経由で `MacroBoxSpec.expand(json)` を呼べるstrict/timeout遵守
- MIR/LLVM/VM の後段は、Macro展開済み入力で恒常緑
関連: [planning/macro_driven_replan.md](planning/macro_driven_replan.md)
---
補足: JSON v0 の扱い(互換)
- Phase15: Bridge で PHI を生成(現行継続)。
- MIR18LoopForm以降: PHI 自動化後、JSON 側の PHI は非必須(将来は除外方向)。

View File

@ -0,0 +1,39 @@
# Phase15 MacroDriven Replan
Status: Adopted (202509). This plan reframes Phase15 selfhosting to leverage the new macro system (AST JSON v0 / PyVM sandbox / strict / timeout / golden).
## Goals
- Consolidate all frontend, sugar, and light rewrites into user macros (Nyash/PyVM)
- Keep Rust core minimal: parse/AST emit/MIR build/backend only
- Deterministic expansion with strict failure and timeouts; golden testing as acceptance
## Execution Pipeline
1) Parse (Rust) → AST
2) Macro Expansion (fixedpoint, 1 pass): Builtin (Rust) → User Macros (Nyash/PyVM)
3) Using/resolve → MIR → Backend (VM/LLVM/WASM/AOT)
## Guardrails
- strict=1 (default): child error/timeout aborts the build
- timeout: `NYASH_NY_COMPILER_TIMEOUT_MS=2000` (default)
- capabilities: all OFF (io/net/env=false) for Phase15
- observability: `--dump-expanded-ast-json` + JSONL trace (`NYASH_MACRO_TRACE_JSONL`)
## Work Items
1) Enable PyVM runner route for macros (done)
- `NYASH_MACRO_BOX_CHILD_RUNNER=1` → runner includes macro + calls `MacroBoxSpec.expand(json)`
2) Identity + upper_string templates (done)
- Examples under `apps/macros/examples/`
3) Golden tests
- identity/upper cases (done)
- add 12 more (array/map literal touch) [next]
4) Selfhost compiler refactor (front)
- Limit Ny parser to Stage2 subset; sugar via macros
- Keep resolver in runner (Phase15 policy)
5) nyash.toml sketch for macro registration and caps
- `[macros]` + `[macro_caps."path"]` io/net/env=false (docs only in Phase15)
## Acceptance
- Expanded AST JSON matches goldens for sample programs
- Macro runner path green under strict=1, timeout=2000ms
- MIR/LLVM/VM paths stable with expanded inputs

View File

@ -0,0 +1,742 @@
# Phase 16 Implementation Guide: Box-Based Macro System
Date: 2025-09-19
Version: 0.1.0
Status: **READY** - 実装開始準備完了
## 🚀 **実装開始チェックリスト**
### **前提条件確認**
- [x] CLI統合完了--expand, --run-tests既に実装済み
- [x] 環境変数対応NYASH_MACRO_ENABLE等
- [x] AST基盤既存のASTNode構造体
- [x] パーサー基盤NyashParser実装済み
- [ ] **開始準備**: Phase 1実装開始
## 🎯 **Phase 1: AST Pattern Matching 実装**
### **Step 1.1: AST構造体拡張**
#### **ファイル**: `src/ast.rs`
```rust
// 既存のASTNodeに追加
#[derive(Debug, Clone)]
pub enum ASTNode {
// ... 既存のVariant ...
// 新規追加: パターンマッチング
Match {
target: Box<ASTNode>,
arms: Vec<MatchArm>,
span: Span,
},
// パターン表現
Pattern(PatternAst),
}
// 新規追加: パターンAST
#[derive(Debug, Clone)]
pub enum PatternAst {
// 基本パターン
Wildcard { span: Span },
Identifier { name: String, span: Span },
Literal { value: LiteralValue, span: Span },
// 構造パターン
BoxPattern {
name: String,
fields: Vec<FieldPattern>,
rest: Option<String>, // ..rest
span: Span,
},
// 配列パターン
ArrayPattern {
elements: Vec<PatternAst>,
rest: Option<String>, // ...rest
span: Span,
},
// OR パターン
OrPattern {
patterns: Vec<PatternAst>,
span: Span,
},
// バインドパターン
BindPattern {
name: String, // @variable
pattern: Box<PatternAst>,
span: Span,
},
}
#[derive(Debug, Clone)]
pub struct MatchArm {
pub pattern: PatternAst,
pub guard: Option<Box<ASTNode>>,
pub body: Vec<ASTNode>,
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct FieldPattern {
pub name: String,
pub pattern: PatternAst,
pub span: Span,
}
```
**実装タスク**:
```bash
# 1. ast.rsに上記の定義を追加
# 2. 既存のコンパイルエラーを修正
# 3. 基本的なDebug traitの動作確認
```
### **Step 1.2: Tokenizer拡張**
#### **ファイル**: `src/tokenizer.rs`
```rust
// TokenTypeに追加
#[derive(Debug, Clone, PartialEq)]
pub enum TokenType {
// ... 既存のToken ...
// パターンマッチング用
MATCH, // match
PIPE, // |
AT, // @
DOTDOT, // ..
DOTDOTDOT, // ...
}
// Tokenizerに追加
impl Tokenizer {
fn read_word(&mut self) -> TokenType {
match word.as_str() {
// ... 既存のキーワード ...
"match" => TokenType::MATCH,
_ => TokenType::IDENTIFIER(word),
}
}
fn read_symbol(&mut self) -> TokenType {
match self.current_char() {
// ... 既存のシンボル ...
'|' => TokenType::PIPE,
'@' => TokenType::AT,
'.' => {
if self.peek_char() == Some('.') {
self.advance(); // consume second '.'
if self.peek_char() == Some('.') {
self.advance(); // consume third '.'
TokenType::DOTDOTDOT
} else {
TokenType::DOTDOT
}
} else {
TokenType::DOT
}
}
_ => // ... 既存の処理 ...
}
}
}
```
**実装タスク**:
```bash
# 1. TokenTypeに新しいトークンを追加
# 2. Tokenizerの辞書登録
# 3. 基本的なトークン化テスト
```
### **Step 1.3: Parser拡張match式**
#### **ファイル**: `src/parser/expressions.rs` (新規作成)
```rust
use crate::ast::{ASTNode, PatternAst, MatchArm, FieldPattern};
use crate::parser::{NyashParser, ParseError};
use crate::tokenizer::TokenType;
impl NyashParser {
/// match式のパース
pub fn parse_match_expression(&mut self) -> Result<ASTNode, ParseError> {
let start_line = self.current_token().line;
self.consume(TokenType::MATCH)?;
// match対象の式
let target = Box::new(self.parse_expression()?);
self.consume(TokenType::LBRACE)?;
self.skip_newlines();
// match arms
let mut arms = Vec::new();
while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() {
arms.push(self.parse_match_arm()?);
self.skip_newlines();
}
if arms.is_empty() {
return Err(ParseError::UnexpectedToken {
expected: "at least one match arm".to_string(),
found: self.current_token().token_type.clone(),
line: start_line,
});
}
self.consume(TokenType::RBRACE)?;
Ok(ASTNode::Match {
target,
arms,
span: crate::ast::Span::unknown(),
})
}
/// マッチアームのパース
fn parse_match_arm(&mut self) -> Result<MatchArm, ParseError> {
// パターン
let pattern = self.parse_pattern()?;
// ガードif condition
let guard = if self.match_token(&TokenType::IF) {
self.advance(); // consume 'if'
Some(Box::new(self.parse_expression()?))
} else {
None
};
self.consume(TokenType::ARROW)?; // =>
// ボディ
let body = if self.match_token(&TokenType::LBRACE) {
self.parse_block_statements()?
} else {
vec![self.parse_statement()?]
};
Ok(MatchArm {
pattern,
guard,
body,
span: crate::ast::Span::unknown(),
})
}
/// パターンのパース
pub fn parse_pattern(&mut self) -> Result<PatternAst, ParseError> {
self.parse_or_pattern()
}
/// ORパターン最低優先度
fn parse_or_pattern(&mut self) -> Result<PatternAst, ParseError> {
let mut pattern = self.parse_bind_pattern()?;
if self.match_token(&TokenType::PIPE) {
let mut patterns = vec![pattern];
while self.match_token(&TokenType::PIPE) {
self.advance(); // consume '|'
patterns.push(self.parse_bind_pattern()?);
}
pattern = PatternAst::OrPattern {
patterns,
span: crate::ast::Span::unknown(),
};
}
Ok(pattern)
}
/// バインドパターン(@variable pattern
fn parse_bind_pattern(&mut self) -> Result<PatternAst, ParseError> {
if self.match_token(&TokenType::AT) {
self.advance(); // consume '@'
let name = if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
let name = name.clone();
self.advance();
name
} else {
return Err(ParseError::UnexpectedToken {
expected: "identifier after '@'".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
};
let pattern = Box::new(self.parse_primary_pattern()?);
Ok(PatternAst::BindPattern {
name,
pattern,
span: crate::ast::Span::unknown(),
})
} else {
self.parse_primary_pattern()
}
}
/// 基本パターン
fn parse_primary_pattern(&mut self) -> Result<PatternAst, ParseError> {
match &self.current_token().token_type {
// ワイルドカード
TokenType::UNDERSCORE => {
self.advance();
Ok(PatternAst::Wildcard {
span: crate::ast::Span::unknown(),
})
}
// 識別子(変数バインドまたは構造体パターン)
TokenType::IDENTIFIER(name) => {
let name = name.clone();
self.advance();
if self.match_token(&TokenType::LBRACE) {
// 構造パターン: TypeName { field1, field2, .. }
self.parse_box_pattern(name)
} else {
// 変数バインド
Ok(PatternAst::Identifier {
name,
span: crate::ast::Span::unknown(),
})
}
}
// リテラル
TokenType::INTEGER(value) => {
let value = *value;
self.advance();
Ok(PatternAst::Literal {
value: crate::ast::LiteralValue::Integer(value),
span: crate::ast::Span::unknown(),
})
}
TokenType::STRING(value) => {
let value = value.clone();
self.advance();
Ok(PatternAst::Literal {
value: crate::ast::LiteralValue::String(value),
span: crate::ast::Span::unknown(),
})
}
// 配列パターン
TokenType::LBRACKET => self.parse_array_pattern(),
_ => Err(ParseError::UnexpectedToken {
expected: "pattern".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
}),
}
}
/// Box構造パターン: TypeName { field1, field2, .. }
fn parse_box_pattern(&mut self, type_name: String) -> Result<PatternAst, ParseError> {
self.consume(TokenType::LBRACE)?;
self.skip_newlines();
let mut fields = Vec::new();
let mut rest = None;
while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() {
// rest pattern: ..rest
if self.match_token(&TokenType::DOTDOT) {
self.advance(); // consume '..'
if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
rest = Some(name.clone());
self.advance();
} else {
return Err(ParseError::UnexpectedToken {
expected: "identifier after '..'".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
}
break; // rest patternは最後でなければならない
}
// フィールドパターン
let field_name = if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
let name = name.clone();
self.advance();
name
} else {
return Err(ParseError::UnexpectedToken {
expected: "field name".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
};
let pattern = if self.match_token(&TokenType::COLON) {
self.advance(); // consume ':'
self.parse_pattern()?
} else {
// 短縮形: field は field: field と同じ
PatternAst::Identifier {
name: field_name.clone(),
span: crate::ast::Span::unknown(),
}
};
fields.push(FieldPattern {
name: field_name,
pattern,
span: crate::ast::Span::unknown(),
});
if self.match_token(&TokenType::COMMA) {
self.advance();
self.skip_newlines();
} else if !self.match_token(&TokenType::RBRACE) {
return Err(ParseError::UnexpectedToken {
expected: "',' or '}'".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
}
}
self.consume(TokenType::RBRACE)?;
Ok(PatternAst::BoxPattern {
name: type_name,
fields,
rest,
span: crate::ast::Span::unknown(),
})
}
/// 配列パターン: [first, second, ...rest]
fn parse_array_pattern(&mut self) -> Result<PatternAst, ParseError> {
self.consume(TokenType::LBRACKET)?;
self.skip_newlines();
let mut elements = Vec::new();
let mut rest = None;
while !self.match_token(&TokenType::RBRACKET) && !self.is_at_end() {
// rest pattern: ...rest
if self.match_token(&TokenType::DOTDOTDOT) {
self.advance(); // consume '...'
if let TokenType::IDENTIFIER(name) = &self.current_token().token_type {
rest = Some(name.clone());
self.advance();
} else {
return Err(ParseError::UnexpectedToken {
expected: "identifier after '...'".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
}
break; // rest patternは最後でなければならない
}
elements.push(self.parse_pattern()?);
if self.match_token(&TokenType::COMMA) {
self.advance();
self.skip_newlines();
} else if !self.match_token(&TokenType::RBRACKET) {
return Err(ParseError::UnexpectedToken {
expected: "',' or ']'".to_string(),
found: self.current_token().token_type.clone(),
line: self.current_token().line,
});
}
}
self.consume(TokenType::RBRACKET)?;
Ok(PatternAst::ArrayPattern {
elements,
rest,
span: crate::ast::Span::unknown(),
})
}
}
```
**実装タスク**:
```bash
# 1. src/parser/expressions.rs を作成
# 2. src/parser/mod.rs に追加
# 3. 基本的なmatch式のパーステスト
```
### **Step 1.4: パターンマッチング実行エンジン**
#### **ファイル**: `src/macro_system/pattern_matcher.rs` (新規作成)
```rust
use crate::ast::{ASTNode, PatternAst, FieldPattern, LiteralValue};
use std::collections::HashMap;
#[derive(Debug)]
pub struct PatternMatcher {
bindings: HashMap<String, ASTNode>,
}
#[derive(Debug)]
pub enum MatchResult {
Success,
Failure,
}
impl PatternMatcher {
pub fn new() -> Self {
Self {
bindings: HashMap::new(),
}
}
/// パターンマッチング実行
pub fn match_pattern(&mut self, pattern: &PatternAst, value: &ASTNode) -> MatchResult {
match (pattern, value) {
// ワイルドカード: 常に成功
(PatternAst::Wildcard { .. }, _) => MatchResult::Success,
// 識別子: 変数バインド
(PatternAst::Identifier { name, .. }, _) => {
self.bindings.insert(name.clone(), value.clone());
MatchResult::Success
}
// リテラル: 値比較
(PatternAst::Literal { value: pattern_val, .. },
ASTNode::Literal { value: node_val, .. }) => {
if self.literal_equals(pattern_val, node_val) {
MatchResult::Success
} else {
MatchResult::Failure
}
}
// Box構造パターン
(PatternAst::BoxPattern { name: pattern_name, fields: pattern_fields, rest, .. },
ASTNode::BoxDeclaration { name: box_name, fields: box_fields, .. }) => {
if pattern_name == box_name {
self.match_box_fields(pattern_fields, box_fields, rest)
} else {
MatchResult::Failure
}
}
// 配列パターン
(PatternAst::ArrayPattern { elements, rest, .. },
ASTNode::Array { elements: array_elements, .. }) => {
self.match_array_elements(elements, array_elements, rest)
}
// ORパターン: いずれかが成功すれば成功
(PatternAst::OrPattern { patterns, .. }, value) => {
for pattern in patterns {
let mut temp_matcher = PatternMatcher::new();
if let MatchResult::Success = temp_matcher.match_pattern(pattern, value) {
// 成功したバインディングをマージ
self.bindings.extend(temp_matcher.bindings);
return MatchResult::Success;
}
}
MatchResult::Failure
}
// バインドパターン: 内部パターンマッチ + 変数バインド
(PatternAst::BindPattern { name, pattern, .. }, value) => {
if let MatchResult::Success = self.match_pattern(pattern, value) {
self.bindings.insert(name.clone(), value.clone());
MatchResult::Success
} else {
MatchResult::Failure
}
}
// その他: 失敗
_ => MatchResult::Failure,
}
}
/// リテラル値の比較
fn literal_equals(&self, a: &LiteralValue, b: &LiteralValue) -> bool {
match (a, b) {
(LiteralValue::Integer(a), LiteralValue::Integer(b)) => a == b,
(LiteralValue::String(a), LiteralValue::String(b)) => a == b,
(LiteralValue::Bool(a), LiteralValue::Bool(b)) => a == b,
(LiteralValue::Null, LiteralValue::Null) => true,
_ => false,
}
}
/// Boxフィールドのマッチング
fn match_box_fields(
&mut self,
pattern_fields: &[FieldPattern],
box_fields: &[String],
rest: &Option<String>,
) -> MatchResult {
// TODO: 実装
// 現在は簡単のため、フィールド名のマッチングのみ
if pattern_fields.len() <= box_fields.len() {
MatchResult::Success
} else {
MatchResult::Failure
}
}
/// 配列要素のマッチング
fn match_array_elements(
&mut self,
pattern_elements: &[PatternAst],
array_elements: &[ASTNode],
rest: &Option<String>,
) -> MatchResult {
// TODO: 実装
// 現在は簡単のため、要素数のチェックのみ
if pattern_elements.len() <= array_elements.len() {
MatchResult::Success
} else {
MatchResult::Failure
}
}
/// バインディング取得
pub fn get_binding(&self, name: &str) -> Option<&ASTNode> {
self.bindings.get(name)
}
/// すべてのバインディング取得
pub fn bindings(&self) -> &HashMap<String, ASTNode> {
&self.bindings
}
}
```
**実装タスク**:
```bash
# 1. src/macro_system ディレクトリ作成
# 2. pattern_matcher.rs 作成
# 3. src/lib.rs にmacro_systemモジュール追加
# 4. 基本的なパターンマッチテスト
```
### **Step 1.5: 基本テスト**
#### **ファイル**: `src/tests/pattern_matching_tests.rs` (新規作成)
```rust
#[cfg(test)]
mod tests {
use super::*;
use crate::ast::{ASTNode, PatternAst, LiteralValue};
use crate::macro_system::pattern_matcher::{PatternMatcher, MatchResult};
#[test]
fn test_wildcard_pattern() {
let mut matcher = PatternMatcher::new();
let pattern = PatternAst::Wildcard { span: crate::ast::Span::unknown() };
let value = ASTNode::Literal {
value: LiteralValue::Integer(42),
span: crate::ast::Span::unknown(),
};
let result = matcher.match_pattern(&pattern, &value);
assert!(matches!(result, MatchResult::Success));
}
#[test]
fn test_identifier_pattern() {
let mut matcher = PatternMatcher::new();
let pattern = PatternAst::Identifier {
name: "x".to_string(),
span: crate::ast::Span::unknown(),
};
let value = ASTNode::Literal {
value: LiteralValue::Integer(42),
span: crate::ast::Span::unknown(),
};
let result = matcher.match_pattern(&pattern, &value);
assert!(matches!(result, MatchResult::Success));
// バインディング確認
let binding = matcher.get_binding("x");
assert!(binding.is_some());
}
#[test]
fn test_literal_pattern_success() {
let mut matcher = PatternMatcher::new();
let pattern = PatternAst::Literal {
value: LiteralValue::Integer(42),
span: crate::ast::Span::unknown(),
};
let value = ASTNode::Literal {
value: LiteralValue::Integer(42),
span: crate::ast::Span::unknown(),
};
let result = matcher.match_pattern(&pattern, &value);
assert!(matches!(result, MatchResult::Success));
}
#[test]
fn test_literal_pattern_failure() {
let mut matcher = PatternMatcher::new();
let pattern = PatternAst::Literal {
value: LiteralValue::Integer(42),
span: crate::ast::Span::unknown(),
};
let value = ASTNode::Literal {
value: LiteralValue::Integer(99),
span: crate::ast::Span::unknown(),
};
let result = matcher.match_pattern(&pattern, &value);
assert!(matches!(result, MatchResult::Failure));
}
}
```
**実装タスク**:
```bash
# 1. テストファイル作成
# 2. cargo test で動作確認
# 3. CI通過確認
```
## 🎯 **Phase 1 完成目標**
### **動作する最小例**
```nyash
// パース可能なmatch式
match some_value {
42 => print("Found answer")
x => print("Found: " + x.toString())
_ => print("Unknown")
}
// パース可能なパターン
BoxDeclaration { name: "Person", fields: [first, ...rest] }
```
### **Phase 1 完了条件**
- [ ] すべてのパターン構文がパース可能
- [ ] 基本的なパターンマッチングが動作
- [ ] テストが緑色(通過)
- [ ] 既存機能に影響なし(回帰テスト通過)
---
**Phase 1が完了したら、Phase 2Quote/Unquoteの実装に進む** 🚀
**Next**: [Phase 2実装ガイド](./PHASE2_IMPLEMENTATION.md) | [テスト戦略](./TESTING_STRATEGY.md)

View File

@ -114,10 +114,10 @@ method __generated_equals_1234(other: UserBox) -> BoolBox {
```
#### 完了条件
- [ ] @derive(Equals)の動作確認
- [ ] @derive(ToString)の動作確認
- [ ] HIRパッチエンジンの安定動作
- [ ] 4つの必須テストケース通過
- [x] @derive(Equals)の動作確認AST展開→MIRで実行
- [x] @derive(ToString)の動作確認
- [x] HIRパッチエンジンの安定動作MVP: noop/derive注入
- [x] 初期スモークにてgreen追加テスト拡充中
## 🛡️ Phase 16.4: @validate統合1週間
@ -187,11 +187,11 @@ static method load() -> Result<AppConfig, ConfigError> {
### 品質保証とデモンストレーション
#### ChatGPT推奨の必須テスト
1. **derive等価性**: `UserBox("a",1) == UserBox("a",1)` → 真
2. **validation**: `age=200``ValidationError`
3. **config**: `DATABASE_URL`未設定 → `Err`
4. **hygiene**: 手書き`equals`と生成コードが衝突しない
#### ChatGPT推奨の必須テスト(進捗: 部分達成)
1. **derive等価性**: `UserBox("a",1) == UserBox("a",1)` → 真(達成)
2. **validation**: `age=200``ValidationError`(未)
3. **config**: `DATABASE_URL`未設定 → `Err`(未)
4. **hygiene**: 手書き`equals`と生成コードが衝突しないMVPでは上書き回避で担保
#### デバッグツール
- `nyash --expand`: マクロ展開結果の可視化
@ -297,22 +297,22 @@ local request = HttpRequestBox.builder()
- **学習コスト**: 充実したドキュメントとサンプル
- **既存影響**: MIR14不変でリスク最小化
## 🎯 次のアクション
## 🎯 次のアクション(進捗反映)
### 即座着手(今週)
1. **Pattern Matching最小実装**開始
2. **AST操作基盤API設計**確定
3. **HIRパッチエンジン設計**詳細化
4. **@derive(Equals)実装計画**策定
1. **Pattern/Quote最小実装**$name / $...name / OrPattern完了
2. **AST操作基盤API設計**MVP完了
3. **HIRパッチエンジン**MVP完了
4. **@derive(Equals/ToString)** 実装済みMVP
### 2週間後
1. **Pattern Matching完成**
2. **@derive(Equals)スモーク動作**
3. **マクロ展開デバッグツール**完成
4. **実用アプリ適用**開始
1. **Test Runner拡張**Box内/entry policy/args JSON
2. **Pattern強化**(配列/マップ/中間可変)
3. **Macro debug CLI**(展開ステップの可視化の拡張)
4. **実用アプリ適用**derive/test導入
---
**Phase 16 Macro Revolution**により、Nyashは世界最強のマクロ言語への道を確実に歩む。
*全AI賢者の叡智を統合した、実現可能かつ革新的な実装戦略。*
*全AI賢者の叡智を統合した、実現可能かつ革新的な実装戦略。*

View File

@ -1,132 +1,255 @@
# Phase 16: Macro Revolution - 世界最強マクロ言語への道
# Phase 16: Macro Revolution - 世界最強マクロシステムの構築
**開始日**: 2025-09-18
**ステータス**: 計画中
**目標**: Box-Based Macro Systemにより、Lisp/Rust/C++/Nim/Juliaを超越する
Date: 2025-09-19
Status: **ACTIVE** - AST Pattern Matching実装中
Target: 2025年12月完了
## 🔥 革命の発端
## 🎯 **革命の概要**
2025年9月18日、Nyashの調査中に**マクロ機能が存在しない**ことが判明。これを「第4の革命」の機会と捉え、世界最強のマクロ言語を目指すPhase 16が誕生。
**Everything is Box** 設計の究極進化形として、世界初の **Box-Based Macro System** を実装。
Lisp、Rust、C++、Nim、Juliaを超越する次世代マクロ言語を目指す。
### 🌟 これまでの革命
1. **Property System革命**: stored/computed/once/birth_once統一構文
2. **Python統合革命**: @property/@cached_property完全マッピング
3. **Pattern Matching革命**: ChatGPT提案実装予定
4. **🆕 Macro System革命**: 今回のPhase 16
## 🔥 **なぜ革命的か**
## 🎯 目標5つの最強言語を超越
### **従来のマクロシステム**
```rust
// Rust: 型ごとに別実装が必要
#[derive(Debug)] struct A {} // struct用実装
#[derive(Debug)] enum B {} // enum用実装
#[derive(Debug)] union C {} // union用実装
```
| 言語 | 強み | Nyashでの超越方法 |
|------|------|-------------------|
| **Lisp** | homoiconicity | BoxがAST表現 → コード=Box |
| **Rust** | 型安全derive | Property System + 型情報 |
| **C++** | 零オーバーヘッド | LLVM最適化 + Box統一 |
| **Nim** | 読みやすさ | Box記法 → より直感的 |
| **Julia** | 科学計算特化 | Python統合 → ライブラリ活用 |
## 🌟 Box-Based Macro の革新性
### 世界初の特徴
### **Nyash: Box-Based Macro**
```nyash
// 🚀 マクロが一等市民のBox
box CustomMacroBox {
template: StringBox
// computed: Property SystemとMacro Systemの融合
expanded_code: StringBox { expand(me.template) }
// once: 重いコンパイル処理をキャッシュ
once compiled_ast: ASTBox { compile(me.expanded_code) }
// birth_once: マクロライブラリの事前読み込み
birth_once macro_lib: MacroLibBox { load_stdlib() }
// すべてがBoxなので、1つの実装で全対応
@derive(Debug) box A {} // 同じ実装
@derive(Debug) box B {} // 同じ実装
@derive(Debug) box C {} // 同じ実装
```
**複雑度**: `O(型の種類 × マクロの種類)``O(マクロの種類)`
## 🏗️ **アーキテクチャ設計**
### **Phase 1: AST Pattern Matching基盤**
```nyash
// 安全なASTパターンマッチング
match ast_node {
BoxDeclaration { name, fields, methods, .. } => {
// 型安全な変換処理
}
FunctionDeclaration { name: @fname, params: [first, ...rest] } => {
// 束縛とワイルドカード対応
}
}
```
### 独自の革新要素
- **Everything is Box**: マクロもBoxとして統一
- **Property System統合**: リアルタイム展開 + キャッシュ
- **型安全性**: `MacroBox<InputAst, OutputAst>`
- **Visual debugging**: 展開ステップの可視化
- **Live macro**: ファイル変更でリアルタイム更新
## 📋 実装ロードマップ
### **Phase A: AST基盤構築**1週間
- AST Pattern/Unifier変数/ワイルドカード)
- Quasi-quote/unquote、AST Builder
- Rewriter停止条件/置換)
### **Phase B: 最小マクロシステム**1-2週間
- マクロ定義/登録/解決(関数風)
- 簡易衛生gensym+ 再帰上限
- エラー設計Span指向
### **Phase C: Box-Based Macro完成**1-2週間
- 属性マクロ(宣言/プロパティ)
- MacroBox型付きAPI
- デシュガpattern matching等
### **Phase D: 高機能化**(以降)
- 本格衛生SyntaxContext
- 外部手続きマクロJSON AST
- AI支援マクロ生成
## 🤖 AI協働の成果
### Gemini洞察言語設計
- Property×Macro統合の合理性確認
- MacroBox一等市民化の革新性評価
- Pattern Matching優先実装の推奨
### Codex洞察実装戦略
- 技術的実現可能性の確認
- 段階的実装ロードマップ
- 工数見積もり最小2-3週間、充実4-6週間
## 🎯 成功指標
### Phase A完了時
- AST操作ツールのユニットテスト通過
- Span一貫性の確保
### Phase B完了時
- マクロ→通常構文→MIR14が既存スモークと一致
- PyVM/LLVM両方で差分なし
### Phase C完了時
- 属性マクロでProperty宣言の糖衣実装
- MacroBoxで実例1つ動作
### 最終目標
### **Phase 2: Quote/Unquote システム**
```nyash
// 🎯 世界最強マクロの証明
@live_derive(Equals, ToString, Clone)
@python_bridge(numpy, pandas)
@visual_debug(expand_steps=true)
box RevolutionaryBox {
// Property System + Macro System完全融合
once ai_methods: MethodBox { AI.generate(me.type()) }
computed quality: QualityBox { analyze(me.generated_code) }
// 安全なコード生成
let template = quote! {
$(method_name)(other) {
return $(field_comparison_logic)
}
}
// 型安全な展開
let generated = unquote! {
template with {
method_name: "equals",
field_comparison_logic: generate_field_comparisons(box_fields)
}
}
```
## 📚 関連ドキュメント
### **Phase 3: HIRパッチ式マクロエンジン**
```nyash
// MIR命令は増やさないHIRレベルで変換
box MacroEngineBox {
expand_derive(input_box: BoxAst) -> Vec<MethodAst> {
// HIRレベルでパッチ適用
// 既存MIR14命令セットで実行
}
}
```
### 🎯 実装計画
- **[統合実装ロードマップ](IMPLEMENTATION_ROADMAP.md)** - 全AI相談結果を統合した実装戦略
- **[Pattern Matching基盤計画](PATTERN_MATCHING_FOUNDATION.md)** - マクロ実装の必須前提条件
## 🎯 **実装する実マクロ**
### 🤖 AI相談結果
- **[ChatGPT最強思考モード分析](CHATGPT_CONSULTATION.md)** - 6つのマクロタイプ評価と実装優先度
- **[Gemini哲学的検討](GEMINI_CONSULTATION.md)** - Property×Macro統合の合理性検証
- **[Codex技術分析](CODEX_CONSULTATION.md)** - 実装可能性と技術的制約
### **@derive マクロファミリー**
```nyash
@derive(Equals, ToString, Clone, Debug)
box Person {
name: StringBox
age: IntegerBox
address: AddressBox // ネストしたBoxも自動対応
}
### 🌟 設計ドキュメント
- **[マクロ実例集](macro-examples.md)** - 6つの革命的マクロタイプの具体例
// 自動生成される:
// - equals(other) メソッド
// - toString() メソッド
// - clone() メソッド
// - debug() メソッド
```
### **@test マクロ + ランナー**
```nyash
@test
test_person_creation() {
local person = new Person("Alice", 25, new AddressBox("Tokyo"))
assert_equals(person.name, "Alice")
assert_equals(person.age, 25)
}
@test
test_person_equals() {
local p1 = new Person("Bob", 30, new AddressBox("Osaka"))
local p2 = new Person("Bob", 30, new AddressBox("Osaka"))
assert_equals(p1.equals(p2), true)
}
```
```bash
# テスト実行
nyash --run-tests my_program.nyash
# [TEST] test_person_creation ... OK
# [TEST] test_person_equals ... OK
# Tests: 2 passed, 0 failed
```
## 🛡️ **ガードレール(安全性保証)**
### **1. Hygiene名前衝突回避**
```nyash
macro generate_counter() {
local temp = gensym("counter_temp") // 自動でユニーク名生成
quote! {
local $(temp) = 0
$(temp).increment()
}
}
```
### **2. 循環検出・再帰制限**
```nyash
// マクロ展開時に自動チェック
macro recursive_macro(depth) {
if macro_depth() > 100 {
compile_error!("Macro recursion limit exceeded")
}
}
```
### **3. 決定性・副作用なし**
```nyash
// ✅ 決定的なマクロ(推奨)
macro pure_derive(box_name, trait_name) {
// 同じ入力なら常に同じ出力
return generate_method(box_name, trait_name)
}
// ❌ 副作用のあるマクロ(禁止)
macro bad_macro() {
println!("This is forbidden!") // コンパイル時IO禁止
}
```
## 🎨 **開発者体験**
### **マクロ展開の可視化**
```bash
# マクロ展開結果を表示
nyash --expand my_program.nyash
# 詳細トレース
NYASH_MACRO_TRACE=1 nyash my_program.nyash
# [MACRO] @derive(Equals) -> generating equals() method for Person
# [MACRO] @test -> collecting test_person_creation()
# [MACRO] Expansion complete: 2 macros processed, 0 errors
```
### **エラーメッセージの親切さ**
```nyash
@derive(UnknownTrait)
box Person {}
// エラー例:
// error: Unknown derive trait 'UnknownTrait'
// --> person.nyash:1:9
// |
// 1 | @derive(UnknownTrait)
// | ^^^^^^^^^^^^
// |
// = help: Available traits: Equals, ToString, Clone, Debug
// = note: Did you mean 'ToString'?
```
## 📊 **他言語との比較優位性**
| 言語 | 型安全性 | 学習コスト | デバッグ性 | 実行性能 | 表現力 |
|------|----------|------------|------------|----------|--------|
| **Nyash** | ✅ | 🟢 Low | 🟢 High | 🟢 High | 🟢 High |
| Rust | ✅ | 🔴 High | 🔴 Low | 🟢 High | 🟡 Medium |
| Lisp | ❌ | 🔴 High | 🔴 Low | 🟡 Medium | 🟢 High |
| C++ | ❌ | 🔴 Very High | 🔴 Very Low | 🟢 High | 🟢 High |
| Nim | 🟡 | 🟡 Medium | 🟡 Medium | 🟢 High | 🟢 High |
## 🚀 **実装スケジュール**
### **Week 1-2: AST Pattern Matching基盤**
- [x] AST定義の拡張パターン用
- [ ] パターンマッチング構文の実装
- [ ] 束縛・ワイルドカードサポート
- [ ] 基本テストケース
### **Week 3-4: Quote/Unquote システム**
- [ ] Quote構文の実装
- [ ] Unquote展開エンジン
- [ ] スパン情報伝播
- [ ] エラー処理強化
### **Week 5-6: HIRパッチ式エンジン**
- [ ] マクロエンジンコア実装
- [ ] HIRレベル変換処理
- [ ] MIR14命令互換性確保
- [ ] パフォーマンス最適化
### **Week 7-8: 実マクロ実装**
- [ ] @derive(Equals, ToString)
- [ ] @test マクロ + ランナー
- [ ] CLI統合--expand, --run-tests
- [ ] ドキュメント・例示
### **Week 9-12: 安定化・拡張**
- [ ] ガードレール強化
- [ ] エラーメッセージ改善
- [ ] 性能最適化・メモリ効率
- [ ] 実用アプリでの検証
## 🎯 **成功指標**
### **技術指標**
- [ ] @derive マクロで100行→5行の圧縮達成
- [ ] マクロ展開時間 < 100ms中規模プロジェクト
- [ ] 型エラー100%コンパイル時検出
- [ ] メモリ使用量増加 < 20%
### **開発者体験指標**
- [ ] 学習コスト: 30分でマクロ作成可能
- [ ] デバッグ時間: --expand で即座に問題特定
- [ ] エラー理解率: 初学者でも90%理解
## 🏆 **世界制覇への道**
この実装完了によりNyashは
1. **Lisp超越**: 型安全性と構造化でパワーアップ
2. **Rust超越**: 学習コストとデバッグ性で圧勝
3. **C++超越**: 安全性と開発効率で完全勝利
4. **Nim超越**: Box統一でさらに直感的
5. **Julia超越**: Python統合で科学計算も制覇
**世界最強マクロ言語**の地位を確立する!🌟
---
**🚀 Nyash Macro Revolution - Everything is Box, Everything is Macro!**
*目標3週間で世界最強のマクロ言語を実現する*
**Next**: [実装詳細](./IMPLEMENTATION.md) | [技術仕様](./TECHNICAL_SPEC.md)

View File

@ -0,0 +1,606 @@
# Phase 16 Technical Specification: Box-Based Macro System
Date: 2025-09-19
Version: 0.1.0
Status: **DRAFT** - 実装前仕様
## 🏗️ **アーキテクチャ概要**
### **システム構成**
```
Nyash Source Code
Lexer/Parser
Raw AST
┌─────────────────────┐
│ Macro Expansion │ ← 新規実装部分
│ ┌───────────────┐ │
│ │ AST Pattern │ │ ← Phase 1
│ │ Matching │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ Quote/Unquote │ │ ← Phase 2
│ │ System │ │
│ └───────────────┘ │
│ ┌───────────────┐ │
│ │ HIR Patch │ │ ← Phase 3
│ │ Engine │ │
│ └───────────────┘ │
└─────────────────────┘
Expanded AST
MIR Lowering ← 既存システム(無変更)
MIR14 Instructions
VM/JIT/AOT Execution
```
## 🎯 **Phase 1: AST Pattern Matching**
### **新規AST構造体**
#### **PatternAst**
```rust
#[derive(Debug, Clone)]
pub enum PatternAst {
// 基本パターン
Wildcard { span: Span }, // _
Identifier { name: String, span: Span }, // variable
Literal { value: LiteralValue, span: Span }, // 42, "hello"
// 構造パターン
BoxPattern {
name: String, // BoxDeclaration
fields: Vec<FieldPattern>, // { field1, field2, .. }
span: Span,
},
// 配列パターン
ArrayPattern {
elements: Vec<PatternAst>, // [first, second, ...]
rest: Option<String>, // ...rest
span: Span,
},
// OR パターン
OrPattern {
patterns: Vec<PatternAst>, // pattern1 | pattern2
span: Span,
},
// バインドパターン
BindPattern {
name: String, // @variable
pattern: Box<PatternAst>, // @var pattern
span: Span,
},
}
#[derive(Debug, Clone)]
pub struct FieldPattern {
pub name: String,
pub pattern: PatternAst,
pub span: Span,
}
```
#### **MatchExpression**
```rust
#[derive(Debug, Clone)]
pub struct MatchExpression {
pub target: Box<ASTNode>, // match対象
pub arms: Vec<MatchArm>, // マッチアーム
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct MatchArm {
pub pattern: PatternAst, // パターン
pub guard: Option<Box<ASTNode>>, // if guard
pub body: Vec<ASTNode>, // 実行文
pub span: Span,
}
```
### **パターンマッチング構文**
#### **基本構文**
```nyash
match ast_node {
BoxDeclaration { name, fields, .. } => {
// Box宣言の処理
}
FunctionDeclaration { name: "main", .. } => {
// main関数の特別処理
}
_ => {
// その他
}
}
```
#### **高度なパターン**
```nyash
match ast_node {
// 束縛パターン
BoxDeclaration { name: @box_name, fields: [first, ...rest] } => {
// box_nameにnameをバインド
// firstに最初のフィールド、restに残り
}
// ORパターン
Literal { value: IntegerValue | StringValue } => {
// 整数または文字列リテラル
}
// ガード
BoxDeclaration { fields } if fields.length > 5 => {
// フィールドが5個より多いBox
}
}
```
### **実装詳細**
#### **Parser拡張**
```rust
impl NyashParser {
/// match式のパース
pub fn parse_match_expression(&mut self) -> Result<MatchExpression, ParseError> {
self.consume(TokenType::MATCH)?;
let target = self.parse_expression()?;
self.consume(TokenType::LBRACE)?;
let mut arms = Vec::new();
while !self.match_token(&TokenType::RBRACE) {
arms.push(self.parse_match_arm()?);
}
self.consume(TokenType::RBRACE)?;
Ok(MatchExpression { target: Box::new(target), arms, span: Span::unknown() })
}
/// パターンのパース
pub fn parse_pattern(&mut self) -> Result<PatternAst, ParseError> {
// パターン実装...
}
}
```
#### **PatternMatcher**
```rust
pub struct PatternMatcher {
bindings: HashMap<String, ASTNode>,
}
impl PatternMatcher {
/// パターンマッチング実行
pub fn match_pattern(&mut self, pattern: &PatternAst, value: &ASTNode) -> bool {
match (pattern, value) {
(PatternAst::Wildcard { .. }, _) => true,
(PatternAst::Identifier { name, .. }, value) => {
self.bindings.insert(name.clone(), value.clone());
true
}
(PatternAst::BoxPattern { name, fields, .. },
ASTNode::BoxDeclaration { name: box_name, fields: box_fields, .. }) => {
if name == box_name {
self.match_fields(fields, box_fields)
} else {
false
}
}
// その他のパターン...
_ => false,
}
}
}
```
## 🎯 **Phase 2: Quote/Unquote System**
### **新規AST構造体**
#### **QuoteExpression**
```rust
#[derive(Debug, Clone)]
pub struct QuoteExpression {
pub template: Vec<ASTNode>, // テンプレート
pub span: Span,
}
#[derive(Debug, Clone)]
pub struct UnquoteExpression {
pub template: Box<QuoteExpression>, // 展開するテンプレート
pub substitutions: HashMap<String, ASTNode>, // 置換マップ
pub span: Span,
}
// テンプレート内の変数展開
#[derive(Debug, Clone)]
pub struct TemplateVariable {
pub name: String, // $(variable_name)
pub span: Span,
}
```
### **Quote/Unquote構文**
#### **基本構文**
```nyash
// コードテンプレート作成
let template = quote! {
$(method_name)(other) {
return me.$(field_name).equals(other.$(field_name))
}
}
// テンプレート展開
let generated = unquote! {
template with {
method_name: "equals",
field_name: "name"
}
}
```
#### **高度な展開**
```nyash
// リスト展開
let field_comparisons = quote! {
$(for field in fields) {
me.$(field.name).equals(other.$(field.name))
}
}
// 条件展開
let method_body = quote! {
$(if has_fields) {
return $(field_comparisons)
} else {
return true
}
}
```
### **実装詳細**
#### **TemplateEngine**
```rust
pub struct TemplateEngine {
substitutions: HashMap<String, ASTNode>,
}
impl TemplateEngine {
/// テンプレート展開
pub fn expand_template(&self, template: &QuoteExpression) -> Result<Vec<ASTNode>, MacroError> {
let mut result = Vec::new();
for node in &template.template {
match self.expand_node(node)? {
ExpandResult::Single(n) => result.push(n),
ExpandResult::Multiple(nodes) => result.extend(nodes),
}
}
Ok(result)
}
/// 単一ノード展開
fn expand_node(&self, node: &ASTNode) -> Result<ExpandResult, MacroError> {
match node {
ASTNode::TemplateVariable { name, .. } => {
if let Some(substitution) = self.substitutions.get(name) {
Ok(ExpandResult::Single(substitution.clone()))
} else {
Err(MacroError::UnboundVariable(name.clone()))
}
}
// 再帰的展開
_ => self.expand_node_recursive(node),
}
}
}
```
## 🎯 **Phase 3: HIRパッチ式マクロエンジン**
### **MacroEngine Core**
#### **MacroRegistry**
```rust
pub struct MacroRegistry {
derive_macros: HashMap<String, Box<dyn DeriveMacro>>,
attribute_macros: HashMap<String, Box<dyn AttributeMacro>>,
function_macros: HashMap<String, Box<dyn FunctionMacro>>,
}
impl MacroRegistry {
pub fn register_derive<T: DeriveMacro + 'static>(&mut self, name: &str, macro_impl: T) {
self.derive_macros.insert(name.to_string(), Box::new(macro_impl));
}
pub fn expand_derive(&self, name: &str, input: &BoxDeclaration) -> Result<Vec<ASTNode>, MacroError> {
if let Some(macro_impl) = self.derive_macros.get(name) {
macro_impl.expand(input)
} else {
Err(MacroError::UnknownDeriveMacro(name.to_string()))
}
}
}
```
#### **DeriveMacro Trait**
```rust
pub trait DeriveMacro {
/// derive マクロ展開
fn expand(&self, input: &BoxDeclaration) -> Result<Vec<ASTNode>, MacroError>;
/// サポートする型チェック
fn supports_box(&self, box_decl: &BoxDeclaration) -> bool {
true // デフォルトすべてのBoxをサポート
}
}
```
### **@derive実装例**
#### **EqualsDeriveMacro**
```rust
pub struct EqualsDeriveMacro;
impl DeriveMacro for EqualsDeriveMacro {
fn expand(&self, input: &BoxDeclaration) -> Result<Vec<ASTNode>, MacroError> {
let method_name = "equals";
let param_name = "other";
// フィールド比較の生成
let field_comparisons = self.generate_field_comparisons(&input.fields)?;
// equals メソッドの生成
let equals_method = ASTNode::FunctionDeclaration {
name: method_name.to_string(),
params: vec![param_name.to_string()],
body: vec![
ASTNode::Return {
value: Some(Box::new(field_comparisons)),
span: Span::unknown(),
}
],
is_static: false,
is_override: false,
span: Span::unknown(),
};
Ok(vec![equals_method])
}
fn generate_field_comparisons(&self, fields: &[String]) -> Result<ASTNode, MacroError> {
if fields.is_empty() {
// フィールドなし常にtrue
return Ok(ASTNode::Literal {
value: LiteralValue::Bool(true),
span: Span::unknown(),
});
}
// フィールド比較の連鎖
let mut comparison = self.generate_single_field_comparison(&fields[0])?;
for field in &fields[1..] {
let field_comp = self.generate_single_field_comparison(field)?;
comparison = ASTNode::BinaryOp {
operator: BinaryOperator::And,
left: Box::new(comparison),
right: Box::new(field_comp),
span: Span::unknown(),
};
}
Ok(comparison)
}
fn generate_single_field_comparison(&self, field: &str) -> Result<ASTNode, MacroError> {
// me.field.equals(other.field)
Ok(ASTNode::MethodCall {
object: Box::new(ASTNode::FieldAccess {
object: Box::new(ASTNode::Me { span: Span::unknown() }),
field: field.to_string(),
span: Span::unknown(),
}),
method: "equals".to_string(),
arguments: vec![
ASTNode::FieldAccess {
object: Box::new(ASTNode::Variable {
name: "other".to_string(),
span: Span::unknown(),
}),
field: field.to_string(),
span: Span::unknown(),
}
],
span: Span::unknown(),
})
}
}
```
#### **TestMacro**
```rust
pub struct TestMacro;
impl AttributeMacro for TestMacro {
fn expand(&self, input: &FunctionDeclaration) -> Result<Vec<ASTNode>, MacroError> {
// テスト関数をテストレジストリに登録
let register_call = ASTNode::MethodCall {
object: Box::new(ASTNode::Variable {
name: "TestRegistry".to_string(),
span: Span::unknown(),
}),
method: "register".to_string(),
arguments: vec![
ASTNode::Literal {
value: LiteralValue::String(input.name.clone()),
span: Span::unknown(),
},
ASTNode::Variable {
name: input.name.clone(),
span: Span::unknown(),
}
],
span: Span::unknown(),
};
Ok(vec![
register_call,
ASTNode::FunctionDeclaration {
name: input.name.clone(),
params: input.params.clone(),
body: input.body.clone(),
is_static: input.is_static,
is_override: input.is_override,
span: input.span.clone(),
}
])
}
}
```
## 🛡️ **エラーハンドリング**
### **MacroError定義**
```rust
#[derive(Debug, Clone)]
pub enum MacroError {
// パターンマッチングエラー
PatternMismatch { expected: String, found: String },
UnboundVariable(String),
// Quote/Unquoteエラー
TemplateExpansionFailed(String),
InvalidSubstitution { variable: String, reason: String },
// Deriveマクロエラー
UnknownDeriveMacro(String),
UnsupportedBoxType { derive_name: String, box_name: String },
// 一般エラー
RecursionLimitExceeded,
CircularDependency(Vec<String>),
}
```
### **エラーメッセージ**
```rust
impl MacroError {
pub fn user_message(&self) -> String {
match self {
MacroError::UnknownDeriveMacro(name) => {
format!("Unknown derive trait '{}'
Available traits: Equals, ToString, Clone, Debug
Did you mean 'ToString'?", name)
}
MacroError::PatternMismatch { expected, found } => {
format!("Pattern mismatch: expected {}, found {}", expected, found)
}
_ => format!("Macro error: {:?}", self),
}
}
}
```
## 🎨 **CLI統合**
### **新規コマンドオプション**
既に実装済み:
```rust
// src/cli.rs で確認済み
.arg(
Arg::new("expand")
.long("expand")
.help("Macro: enable macro engine and dump expansion traces")
.action(clap::ArgAction::SetTrue)
)
.arg(
Arg::new("run-tests")
.long("run-tests")
.help("Run tests: enable macro engine and inject test harness")
.action(clap::ArgAction::SetTrue)
)
.arg(
Arg::new("test-filter")
.long("test-filter")
.value_name("SUBSTR")
.help("Only run tests whose name contains SUBSTR")
)
```
### **環境変数**
```rust
// マクロエンジン有効化
NYASH_MACRO_ENABLE=1
// マクロ展開トレース
NYASH_MACRO_TRACE=1
// テスト実行
NYASH_TEST_RUN=1
// テストフィルタ
NYASH_TEST_FILTER="substring"
```
## 📊 **パフォーマンス要件**
### **目標指標**
- **展開時間**: < 100ms中規模プロジェクト
- **メモリ使用量**: < 20% 増加ベースコンパイラ比
- **型チェック**: 100% コンパイル時
- **エラー検出**: 100% コンパイル時
### **最適化戦略**
1. **遅延展開**: 必要な時のみマクロ展開
2. **キャッシュ**: 同一パターンの結果をキャッシュ
3. **並列処理**: 独立なマクロの並列展開
4. **メモリプール**: AST ノードの効率的割り当て
## 🚀 **実装順序**
### **Week 1-2: AST Pattern Matching**
1. PatternAst構造体定義
2. Parser拡張match式
3. PatternMatcher実装
4. 基本テストケース
### **Week 3-4: Quote/Unquote**
1. QuoteExpression定義
2. TemplateEngine実装
3. 変数置換システム
4. エラーハンドリング
### **Week 5-6: HIRパッチエンジン**
1. MacroRegistry実装
2. DeriveMacro trait定義
3. EqualsDeriveMacro実装
4. TestMacro実装
### **Week 7-8: 統合・最適化**
1. CLI統合
2. エラーメッセージ改善
3. パフォーマンス最適化
4. ドキュメント作成
---
**この仕様に基づいて、世界最強のBox-Basedマクロシステムを実装する** 🌟