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