stage3: unify to cleanup; MIR return-defer; docs+smokes updated; LLVM(harness): finalize_phis ownership, ret.py simplified, uses-predeclare; cleanup return override green; method-postfix cleanup return WIP (PHI head)

This commit is contained in:
Selfhosting Dev
2025-09-19 02:07:38 +09:00
parent 951a050592
commit 5e818eeb7e
205 changed files with 9671 additions and 1849 deletions

View File

@ -0,0 +1,140 @@
//! Evaluation entry points: execute program and nodes
use super::{ControlFlow, NyashInterpreter, RuntimeError};
use crate::ast::ASTNode;
use crate::box_trait::{NyashBox, VoidBox};
impl NyashInterpreter {
/// ASTを実行
pub fn execute(&mut self, ast: ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
super::core::debug_log("=== NYASH EXECUTION START ===");
let result = self.execute_node(&ast);
if let Err(ref e) = result {
eprintln!("❌ Interpreter error: {}", e);
}
super::core::debug_log("=== NYASH EXECUTION END ===");
result
}
/// ノードを実行
fn execute_node(&mut self, node: &ASTNode) -> Result<Box<dyn NyashBox>, RuntimeError> {
match node {
ASTNode::Program { statements, .. } => {
let mut result: Box<dyn NyashBox> = Box::new(VoidBox::new());
let last = statements.len().saturating_sub(1);
for (i, statement) in statements.iter().enumerate() {
let prev = self.discard_context;
self.discard_context = i != last; // 最終文以外は値が破棄される
result = self.execute_statement(statement)?;
self.discard_context = prev;
// 制御フローチェック
match &self.control_flow {
ControlFlow::Break => {
return Err(RuntimeError::BreakOutsideLoop);
}
ControlFlow::Continue => {
return Err(RuntimeError::BreakOutsideLoop);
}
ControlFlow::Return(_) => {
return Err(RuntimeError::ReturnOutsideFunction);
}
ControlFlow::Throw(_) => {
return Err(RuntimeError::UncaughtException);
}
ControlFlow::None => {}
}
}
// 🎯 Static Box Main パターン - main()メソッドの自動実行
let has_main_method = {
if let Ok(definitions) = self.shared.static_box_definitions.read() {
if let Some(main_definition) = definitions.get("Main") {
main_definition.methods.contains_key("main")
} else {
false
}
} else {
false
}
};
if has_main_method {
// Main static boxを初期化
self.ensure_static_box_initialized("Main")?;
// Main.main(args?) を呼び出し引数が1つならデフォルトで args を注入)
let mut default_args: Vec<ASTNode> = Vec::new();
if let Ok(defs) = self.shared.static_box_definitions.read() {
if let Some(main_def) = defs.get("Main") {
if let Some(m) = main_def.methods.get("main") {
if let ASTNode::FunctionDeclaration { params, .. } = m {
if params.len() == 1 {
// Try to read script args from env (JSON array); fallback to empty ArrayBox
if let Ok(json) = std::env::var("NYASH_SCRIPT_ARGS_JSON") {
if let Ok(vals) =
serde_json::from_str::<Vec<String>>(&json)
{
let mut str_nodes: Vec<ASTNode> =
Vec::with_capacity(vals.len());
for s in vals {
str_nodes.push(ASTNode::Literal {
value: crate::ast::LiteralValue::String(s),
span: crate::ast::Span::unknown(),
});
}
default_args.push(ASTNode::MethodCall {
object: Box::new(ASTNode::Variable {
name: "ArrayBox".to_string(),
span: crate::ast::Span::unknown(),
}),
method: "of".to_string(),
arguments: str_nodes,
span: crate::ast::Span::unknown(),
});
} else {
default_args.push(ASTNode::New {
class: "ArrayBox".to_string(),
arguments: vec![],
type_arguments: vec![],
span: crate::ast::Span::unknown(),
});
}
} else {
default_args.push(ASTNode::New {
class: "ArrayBox".to_string(),
arguments: vec![],
type_arguments: vec![],
span: crate::ast::Span::unknown(),
});
}
}
}
}
}
}
let main_call_ast = ASTNode::MethodCall {
object: Box::new(ASTNode::FieldAccess {
object: Box::new(ASTNode::Variable {
name: "statics".to_string(),
span: crate::ast::Span::unknown(),
}),
field: "Main".to_string(),
span: crate::ast::Span::unknown(),
}),
method: "main".to_string(),
arguments: default_args,
span: crate::ast::Span::unknown(),
};
// main()の戻り値を最終結果として使用
result = self.execute_statement(&main_call_ast)?;
}
Ok(result)
}
_ => self.execute_statement(node),
}
}
}