# 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, // { field1, field2, .. } span: Span, }, // 配列パターン ArrayPattern { elements: Vec, // [first, second, ...] rest: Option, // ...rest span: Span, }, // OR パターン OrPattern { patterns: Vec, // pattern1 | pattern2 span: Span, }, // バインドパターン BindPattern { name: String, // @variable pattern: Box, // @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, // match対象 pub arms: Vec, // マッチアーム pub span: Span, } #[derive(Debug, Clone)] pub struct MatchArm { pub pattern: PatternAst, // パターン pub guard: Option>, // if guard pub body: Vec, // 実行文 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 { 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 { // パターン実装... } } ``` #### **PatternMatcher** ```rust pub struct PatternMatcher { bindings: HashMap, } 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, // テンプレート pub span: Span, } #[derive(Debug, Clone)] pub struct UnquoteExpression { pub template: Box, // 展開するテンプレート pub substitutions: HashMap, // 置換マップ 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, } impl TemplateEngine { /// テンプレート展開 pub fn expand_template(&self, template: &QuoteExpression) -> Result, 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 { 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>, attribute_macros: HashMap>, function_macros: HashMap>, } impl MacroRegistry { pub fn register_derive(&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, 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, 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, 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 { 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 { // 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, 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), } ``` ### **エラーメッセージ** ```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マクロシステムを実装する!** 🌟