/*! * Nyash AST (Abstract Syntax Tree) - Rust Implementation * * Python版nyashc_v4.pyのAST構造をRustで完全再実装 * Everything is Box哲学に基づく型安全なAST設計 */ use crate::box_trait::NyashBox; use std::collections::HashMap; use std::fmt; mod span; pub use span::Span; mod nodes; mod utils; pub use nodes::*; // Span は src/ast/span.rs へ分離(re-export で後方互換維持) /// 🌟 AST分類システム - ChatGPTアドバイス統合による3層アーキテクチャ /// Structure/Expression/Statement の明確な分離による型安全性向上 /// ASTノードの種類分類 #[derive(Debug, Clone, PartialEq)] pub enum ASTNodeType { Structure, // 構造定義: box, function, if, loop, try/catch Expression, // 式: リテラル, 変数, 演算, 呼び出し Statement, // 文: 代入, return, break, include } /// 構造ノード - 言語の基本構造を定義 #[derive(Debug, Clone)] pub enum StructureNode { BoxDeclaration { name: String, fields: Vec, methods: Vec, constructors: Vec, init_fields: Vec, weak_fields: Vec, // 🔗 weak修飾子が付いたフィールドのリスト is_interface: bool, extends: Vec, // 🚀 Multi-delegation: Changed from Option to Vec implements: Vec, /// 🔥 ジェネリクス型パラメータ (例: ["T", "U"]) type_parameters: Vec, /// 🔥 Static boxかどうかのフラグ is_static: bool, /// 🔥 Static初期化ブロック (static { ... }) static_init: Option>, span: Span, }, FunctionDeclaration { name: String, params: Vec, body: Vec, is_static: bool, // 🔥 静的メソッドフラグ is_override: bool, // 🔥 オーバーライドフラグ span: Span, }, IfStructure { condition: Box, then_body: Vec, else_body: Option>, span: Span, }, LoopStructure { condition: Box, body: Vec, span: Span, }, TryCatchStructure { try_body: Vec, catch_clauses: Vec, finally_body: Option>, span: Span, }, } /// 式ノード - 値を生成する表現 #[derive(Debug, Clone)] pub enum ExpressionNode { Literal { value: LiteralValue, span: Span, }, Variable { name: String, span: Span, }, BinaryOperation { operator: BinaryOperator, left: Box, right: Box, span: Span, }, UnaryOperation { operator: UnaryOperator, operand: Box, span: Span, }, FunctionCall { name: String, arguments: Vec, span: Span, }, MethodCall { object: Box, method: String, arguments: Vec, span: Span, }, FieldAccess { object: Box, field: String, span: Span, }, NewExpression { class: String, arguments: Vec, /// 🔥 ジェネリクス型引数 (例: ["IntegerBox", "StringBox"]) type_arguments: Vec, span: Span, }, ThisExpression { span: Span, }, MeExpression { span: Span, }, /// match式: match { lit => expr, ... else => expr } MatchExpr { scrutinee: Box, arms: Vec<(LiteralValue, ASTNode)>, else_expr: Box, span: Span, }, // (Stage‑2 sugar for literals is represented in unified ASTNode, not here) } /// 文ノード - 実行可能なアクション #[derive(Debug, Clone)] pub enum StatementNode { Assignment { target: Box, value: Box, span: Span, }, Print { expression: Box, span: Span, }, Return { value: Option>, span: Span, }, Break { span: Span, }, Continue { span: Span, }, Include { filename: String, span: Span, }, Local { variables: Vec, span: Span, }, Throw { exception_type: String, message: Box, span: Span, }, Expression { expr: Box, span: Span, }, } /// Catch節の構造体 #[derive(Debug, Clone, PartialEq)] pub struct CatchClause { pub exception_type: Option, // None = catch-all pub variable_name: Option, // 例外を受け取る変数名 pub body: Vec, // catch本体 pub span: Span, // ソースコード位置 } /// リテラル値の型 (Clone可能) #[derive(Debug, Clone, PartialEq)] pub enum LiteralValue { String(String), Integer(i64), Float(f64), // 浮動小数点数サポート追加 Bool(bool), Null, // null値 Void, } impl LiteralValue { /// LiteralValueをNyashBoxに変換 pub fn to_nyash_box(&self) -> Box { use crate::box_trait::{BoolBox, IntegerBox, StringBox, VoidBox}; use crate::boxes::FloatBox; match self { LiteralValue::String(s) => Box::new(StringBox::new(s)), LiteralValue::Integer(i) => Box::new(IntegerBox::new(*i)), LiteralValue::Float(f) => Box::new(FloatBox::new(*f)), LiteralValue::Bool(b) => Box::new(BoolBox::new(*b)), LiteralValue::Null => Box::new(crate::boxes::null_box::NullBox::new()), LiteralValue::Void => Box::new(VoidBox::new()), } } /// NyashBoxからLiteralValueに変換 pub fn from_nyash_box(box_val: &dyn NyashBox) -> Option { use crate::box_trait::{BoolBox, IntegerBox, StringBox, VoidBox}; use crate::boxes::FloatBox; #[allow(unused_imports)] use std::any::Any; if let Some(string_box) = box_val.as_any().downcast_ref::() { Some(LiteralValue::String(string_box.value.clone())) } else if let Some(int_box) = box_val.as_any().downcast_ref::() { Some(LiteralValue::Integer(int_box.value)) } else if let Some(float_box) = box_val.as_any().downcast_ref::() { Some(LiteralValue::Float(float_box.value)) } else if let Some(bool_box) = box_val.as_any().downcast_ref::() { Some(LiteralValue::Bool(bool_box.value)) } else if box_val .as_any() .downcast_ref::() .is_some() { Some(LiteralValue::Null) } else if box_val.as_any().downcast_ref::().is_some() { Some(LiteralValue::Void) } else { None } } } impl fmt::Display for LiteralValue { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { LiteralValue::String(s) => write!(f, "\"{}\"", s), LiteralValue::Integer(i) => write!(f, "{}", i), LiteralValue::Float(fl) => write!(f, "{}", fl), LiteralValue::Bool(b) => write!(f, "{}", b), LiteralValue::Null => write!(f, "null"), LiteralValue::Void => write!(f, "void"), } } } /// 単項演算子の種類 #[derive(Debug, Clone, PartialEq)] pub enum UnaryOperator { Minus, // -x Not, // not x / !x BitNot, // ~x } /// 二項演算子の種類 #[derive(Debug, Clone, PartialEq)] pub enum BinaryOperator { Add, Subtract, Multiply, Divide, Modulo, BitAnd, BitOr, BitXor, Shl, // << shift-left (Phase 1) Shr, Equal, NotEqual, Less, Greater, LessEqual, GreaterEqual, And, Or, } impl fmt::Display for UnaryOperator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let symbol = match self { UnaryOperator::Minus => "-", UnaryOperator::Not => "not", UnaryOperator::BitNot => "~", }; write!(f, "{}", symbol) } } impl fmt::Display for BinaryOperator { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let symbol = match self { BinaryOperator::Add => "+", BinaryOperator::Subtract => "-", BinaryOperator::Multiply => "*", BinaryOperator::Divide => "/", BinaryOperator::Modulo => "%", BinaryOperator::BitAnd => "&", BinaryOperator::BitOr => "|", BinaryOperator::BitXor => "^", BinaryOperator::Shl => "<<", BinaryOperator::Shr => ">>", BinaryOperator::Equal => "==", BinaryOperator::NotEqual => "!=", BinaryOperator::Less => "<", BinaryOperator::Greater => ">", BinaryOperator::LessEqual => "<=", BinaryOperator::GreaterEqual => ">=", BinaryOperator::And => "&&", BinaryOperator::Or => "||", }; write!(f, "{}", symbol) } } /// AST Node - Everything is Box哲学に基づく統一構造 #[derive(Debug, Clone, PartialEq)] pub enum ASTNode { /// プログラム全体 - 文のリスト Program { statements: Vec, span: Span, }, // ===== 文 (Statements) ===== /// 代入文: target = value Assignment { target: Box, value: Box, span: Span, }, /// print文: print(expression) Print { expression: Box, span: Span, }, /// if文: if condition { then_body } else { else_body } If { condition: Box, then_body: Vec, else_body: Option>, span: Span, }, /// loop文: loop(condition) { body } のみ Loop { condition: Box, body: Vec, span: Span, }, /// Stage-3: while文: while condition { body } While { condition: Box, body: Vec, span: Span, }, /// Stage-3: for-range文: for ident in start..end { body } /// - 半開区間 [start, end) ForRange { var_name: String, start: Box, end: Box, body: Vec, span: Span, }, /// return文: return value Return { value: Option>, span: Span, }, /// break文 Break { span: Span }, /// continue文 Continue { span: Span }, /// using文: using namespace_name UsingStatement { namespace_name: String, span: Span }, /// import文: import "path" (as Alias)? ImportStatement { path: String, alias: Option, span: Span, }, /// nowait文: nowait variable = expression Nowait { variable: String, expression: Box, span: Span, }, /// await式: await expression AwaitExpression { expression: Box, span: Span, }, /// result伝播: expr? (ResultBoxなら isOk/getValue or 早期return) QMarkPropagate { expression: Box, span: Span, }, /// match式: match { lit => expr, ... else => expr } MatchExpr { scrutinee: Box, arms: Vec<(LiteralValue, ASTNode)>, else_expr: Box, span: Span, }, /// 配列リテラル(糖衣): [e1, e2, ...] ArrayLiteral { elements: Vec, span: Span }, /// マップリテラル(糖衣): { "k": v, ... } (Stage‑2: 文字列キー限定) MapLiteral { entries: Vec<(String, ASTNode)>, span: Span, }, /// 無名関数(最小P1: 値としてのみ。呼び出しは未対応) Lambda { params: Vec, body: Vec, span: Span, }, /// arrow文: (sender >> receiver).method(args) Arrow { sender: Box, receiver: Box, span: Span, }, /// try/catch/finally文: try { ... } catch (Type e) { ... } finally { ... } TryCatch { try_body: Vec, catch_clauses: Vec, finally_body: Option>, span: Span, }, /// throw文: throw expression Throw { expression: Box, span: Span, }, // ===== 宣言 (Declarations) ===== /// box宣言: box Name { fields... methods... } BoxDeclaration { name: String, fields: Vec, /// 公開フィールド(public { ... }) public_fields: Vec, /// 非公開フィールド(private { ... }) private_fields: Vec, methods: HashMap, // method_name -> FunctionDeclaration constructors: HashMap, // constructor_key -> FunctionDeclaration init_fields: Vec, // initブロック内のフィールド定義 weak_fields: Vec, // 🔗 weak修飾子が付いたフィールドのリスト is_interface: bool, // interface box かどうか extends: Vec, // 🚀 Multi-delegation: Changed from Option to Vec implements: Vec, // 実装するinterface名のリスト type_parameters: Vec, // 🔥 ジェネリクス型パラメータ (例: ["T", "U"]) /// 🔥 Static boxかどうかのフラグ is_static: bool, /// 🔥 Static初期化ブロック (static { ... }) static_init: Option>, span: Span, }, /// 関数宣言: functionName(params) { body } FunctionDeclaration { name: String, params: Vec, body: Vec, is_static: bool, // 🔥 静的メソッドフラグ is_override: bool, // 🔥 オーバーライドフラグ span: Span, }, /// グローバル変数: global name = value GlobalVar { name: String, value: Box, span: Span, }, // ===== 式 (Expressions) ===== /// リテラル値: "string", 42, true, etc Literal { value: LiteralValue, span: Span }, /// 変数参照: variableName Variable { name: String, span: Span }, /// 単項演算: operator operand UnaryOp { operator: UnaryOperator, operand: Box, span: Span, }, /// 二項演算: left operator right BinaryOp { operator: BinaryOperator, left: Box, right: Box, span: Span, }, /// Stage-3: 括弧付き代入式: (x = expr) - Phase 152-A /// 値・型は右辺と同じ、副作用として左辺に代入 /// 使用例: local y = (x = x + 1), if (x = next()) != null { } GroupedAssignmentExpr { lhs: String, // 変数名 rhs: Box, // 右辺式 span: Span, }, /// メソッド呼び出し: object.method(arguments) MethodCall { object: Box, method: String, arguments: Vec, span: Span, }, /// フィールドアクセス: object.field FieldAccess { object: Box, field: String, span: Span, }, /// 添字アクセス: target[index] Index { target: Box, index: Box, span: Span, }, /// コンストラクタ呼び出し: new ClassName(arguments) New { class: String, arguments: Vec, type_arguments: Vec, // 🔥 ジェネリクス型引数 (例: ["IntegerBox", "StringBox"]) span: Span, }, /// this参照 This { span: Span }, /// me参照 Me { span: Span }, /// 🔥 from呼び出し: from Parent.method(arguments) or from Parent.constructor(arguments) FromCall { parent: String, // Parent名 method: String, // method名またはconstructor arguments: Vec, // 引数 span: Span, }, /// thisフィールドアクセス: this.field ThisField { field: String, span: Span }, /// meフィールドアクセス: me.field MeField { field: String, span: Span }, /// ローカル変数宣言: local x, y, z Local { variables: Vec, /// 初期化値(変数と同じ順序、Noneは初期化なし) initial_values: Vec>>, span: Span, }, /// ScopeBox(オプション): 正規化で注入される明示的なレキシカルスコープ境界。 /// MIR ビルダは `{ ... }` と同様にブロックとして処理する(local のシャドウイング/寿命を分離)。 ScopeBox { body: Vec, span: Span }, /// Outbox変数宣言: outbox x, y, z (static関数内専用) Outbox { variables: Vec, /// 初期化値(変数と同じ順序、Noneは初期化なし) initial_values: Vec>>, span: Span, }, /// 関数呼び出し: functionName(arguments) FunctionCall { name: String, arguments: Vec, span: Span, }, /// 一般式呼び出し: (callee)(arguments) Call { callee: Box, arguments: Vec, span: Span, }, } // Tests moved to integration tests to keep this file lean