/*! * Nyash Interpreter - Rust Implementation * * Python版nyashc_v4.pyのインタープリターをRustで完全再実装 * Everything is Box哲学に基づくAST実行エンジン */ use crate::ast::{ASTNode, Span}; use crate::box_trait::{NyashBox, StringBox, IntegerBox, BoolBox, VoidBox}; use crate::instance::InstanceBox; use crate::parser::ParseError; use std::sync::{Arc, Mutex, RwLock}; use std::collections::{HashMap, HashSet}; use thiserror::Error; use super::{ControlFlow, BoxDeclaration, ConstructorContext, StaticBoxDefinition, StaticBoxState}; /// 実行時エラー #[derive(Error, Debug)] pub enum RuntimeError { #[error("Undefined variable '{name}'")] UndefinedVariable { name: String }, #[error("Undefined function '{name}'")] UndefinedFunction { name: String }, #[error("Undefined class '{name}'")] UndefinedClass { name: String }, #[error("Type error: {message}")] TypeError { message: String }, #[error("Invalid operation: {message}")] InvalidOperation { message: String }, #[error("Break outside of loop")] BreakOutsideLoop, #[error("Return outside of function")] ReturnOutsideFunction, #[error("Uncaught exception")] UncaughtException, #[error("Parse error: {0}")] ParseError(#[from] ParseError), #[error("Environment error: {0}")] EnvironmentError(String), // === 🔥 Enhanced Errors with Span Information === #[error("Undefined variable '{name}' at {span}")] UndefinedVariableAt { name: String, span: Span }, #[error("Type error: {message} at {span}")] TypeErrorAt { message: String, span: Span }, #[error("Invalid operation: {message} at {span}")] InvalidOperationAt { message: String, span: Span }, #[error("Break outside of loop at {span}")] BreakOutsideLoopAt { span: Span }, #[error("Return outside of function at {span}")] ReturnOutsideFunctionAt { span: Span }, #[error("Runtime failure: {message}")] RuntimeFailure { message: String }, } impl RuntimeError { /// エラーの詳細な文脈付きメッセージを生成 pub fn detailed_message(&self, source: Option<&str>) -> String { match self { // Enhanced errors with span information RuntimeError::UndefinedVariableAt { name, span } => { let mut msg = format!("⚠️ Undefined variable '{}'", name); if let Some(src) = source { msg.push('\n'); msg.push_str(&span.error_context(src)); } else { msg.push_str(&format!(" at {}", span)); } msg } RuntimeError::TypeErrorAt { message, span } => { let mut msg = format!("⚠️ Type error: {}", message); if let Some(src) = source { msg.push('\n'); msg.push_str(&span.error_context(src)); } else { msg.push_str(&format!(" at {}", span)); } msg } RuntimeError::InvalidOperationAt { message, span } => { let mut msg = format!("⚠️ Invalid operation: {}", message); if let Some(src) = source { msg.push('\n'); msg.push_str(&span.error_context(src)); } else { msg.push_str(&format!(" at {}", span)); } msg } RuntimeError::BreakOutsideLoopAt { span } => { let mut msg = "⚠️ Break statement outside of loop".to_string(); if let Some(src) = source { msg.push('\n'); msg.push_str(&span.error_context(src)); } else { msg.push_str(&format!(" at {}", span)); } msg } RuntimeError::ReturnOutsideFunctionAt { span } => { let mut msg = "⚠️ Return statement outside of function".to_string(); if let Some(src) = source { msg.push('\n'); msg.push_str(&span.error_context(src)); } else { msg.push_str(&format!(" at {}", span)); } msg } // Fallback for old error variants without span _ => format!("⚠️ {}", self), } } } /// スレッド間で共有される状態 #[derive(Clone)] pub struct SharedState { /// 🌍 GlobalBox - すべてのトップレベル関数とグローバル変数を管理 pub global_box: Arc>, /// Box宣言のレジストリ(読み込みが多いのでRwLock) pub box_declarations: Arc>>, /// 🔥 静的関数のレジストリ(読み込みが多いのでRwLock) pub static_functions: Arc>>>, /// 🔥 Static Box定義レジストリ(遅延初期化用) pub static_box_definitions: Arc>>, /// 読み込み済みファイル(重複防止) pub included_files: Arc>>, } impl SharedState { /// 新しい共有状態を作成 pub fn new() -> Self { let global_box = InstanceBox::new( "Global".to_string(), vec![], // フィールド名(空から始める) HashMap::new(), // メソッド(グローバル関数) ); Self { global_box: Arc::new(Mutex::new(global_box)), box_declarations: Arc::new(RwLock::new(HashMap::new())), static_functions: Arc::new(RwLock::new(HashMap::new())), static_box_definitions: Arc::new(RwLock::new(HashMap::new())), included_files: Arc::new(Mutex::new(HashSet::new())), } } } /// Nyashインタープリター - AST実行エンジン pub struct NyashInterpreter { /// 共有状態(スレッド間で共有) pub(super) shared: SharedState, /// 📦 local変数スタック(関数呼び出し時の一時変数) pub(super) local_vars: HashMap>, /// 📤 outbox変数スタック(static関数内の所有権移転変数) pub(super) outbox_vars: HashMap>, /// 制御フロー状態 pub(super) control_flow: ControlFlow, /// 現在実行中のコンストラクタ情報 pub(super) current_constructor_context: Option, } impl NyashInterpreter { /// 新しいインタープリターを作成 pub fn new() -> Self { let shared = SharedState::new(); Self { shared, local_vars: HashMap::new(), outbox_vars: HashMap::new(), control_flow: ControlFlow::None, current_constructor_context: None, } } /// 共有状態から新しいインタープリターを作成(非同期実行用) pub fn with_shared(shared: SharedState) -> Self { Self { shared, local_vars: HashMap::new(), outbox_vars: HashMap::new(), control_flow: ControlFlow::None, current_constructor_context: None, } } /// ASTを実行 pub fn execute(&mut self, ast: ASTNode) -> Result, RuntimeError> { self.execute_node(&ast) } /// ノードを実行 fn execute_node(&mut self, node: &ASTNode) -> Result, RuntimeError> { match node { ASTNode::Program { statements, .. } => { let mut result: Box = Box::new(VoidBox::new()); for statement in statements { result = self.execute_statement(statement)?; // 制御フローチェック match &self.control_flow { ControlFlow::Break => { 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() を呼び出し 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: vec![], span: crate::ast::Span::unknown(), }; // main()の戻り値を最終結果として使用 result = self.execute_statement(&main_call_ast)?; } Ok(result) } _ => self.execute_statement(node), } } // ========== 🌍 GlobalBox変数解決システム ========== /// 革命的変数解決: local変数 → GlobalBoxフィールド → エラー pub(super) fn resolve_variable(&self, name: &str) -> Result, RuntimeError> { // 1. outbox変数を最初にチェック(static関数内で優先) if let Some(outbox_value) = self.outbox_vars.get(name) { return Ok(outbox_value.clone_box()); } // 2. local変数をチェック if let Some(local_value) = self.local_vars.get(name) { return Ok(local_value.clone_box()); } // 3. GlobalBoxのフィールドをチェック let global_box = self.shared.global_box.lock().unwrap(); if let Some(field_value) = global_box.get_field(name) { return Ok(field_value); } // 4. エラー:見つからない Err(RuntimeError::UndefinedVariable { name: name.to_string(), }) } /// 🔥 厳密変数設定: 明示的宣言のみ許可 - Everything is Box哲学 pub(super) fn set_variable(&mut self, name: &str, value: Box) -> Result<(), RuntimeError> { // 1. outbox変数が存在する場合は更新 if self.outbox_vars.contains_key(name) { self.outbox_vars.insert(name.to_string(), value); return Ok(()); } // 2. local変数が存在する場合は更新 if self.local_vars.contains_key(name) { self.local_vars.insert(name.to_string(), value); return Ok(()); } // 3. GlobalBoxのフィールドが既に存在する場合は更新 { let global_box = self.shared.global_box.lock().unwrap(); if global_box.get_field(name).is_some() { drop(global_box); // lockを解放 let mut global_box = self.shared.global_box.lock().unwrap(); global_box.set_field_dynamic(name.to_string(), value); return Ok(()); } } // 4. 🚨 未宣言変数への代入は厳密にエラー Err(RuntimeError::UndefinedVariable { name: format!( "{}\n💡 Suggestion: Declare the variable first:\n • For fields: Add '{}' to 'init {{ }}' block\n • For local variables: Use 'local {}'\n • For field access: Use 'me.{}'", name, name, name, name ), }) } /// local変数を宣言(関数内でのみ有効) pub(super) fn declare_local_variable(&mut self, name: &str, value: Box) { self.local_vars.insert(name.to_string(), value); } /// outbox変数を宣言(static関数内で所有権移転) pub(super) fn declare_outbox_variable(&mut self, name: &str, value: Box) { self.outbox_vars.insert(name.to_string(), value); } /// local変数スタックを保存・復元(関数呼び出し時) pub(super) fn save_local_vars(&self) -> HashMap> { self.local_vars.iter() .map(|(k, v)| (k.clone(), v.clone_box())) .collect() } pub(super) fn restore_local_vars(&mut self, saved: HashMap>) { self.local_vars = saved; } /// outbox変数スタックを保存・復元(static関数呼び出し時) pub(super) fn save_outbox_vars(&self) -> HashMap> { self.outbox_vars.iter() .map(|(k, v)| (k.clone(), v.clone_box())) .collect() } pub(super) fn restore_outbox_vars(&mut self, saved: HashMap>) { self.outbox_vars = saved; } /// トップレベル関数をGlobalBoxのメソッドとして登録 pub(super) fn register_global_function(&mut self, name: String, func_ast: ASTNode) -> Result<(), RuntimeError> { let mut global_box = self.shared.global_box.lock().unwrap(); global_box.add_method(name, func_ast); Ok(()) } /// 値が真と評価されるかチェック pub(super) fn is_truthy(&self, value: &Box) -> bool { #[allow(unused_imports)] use std::any::Any; if let Some(bool_box) = value.as_any().downcast_ref::() { bool_box.value } else if let Some(int_box) = value.as_any().downcast_ref::() { int_box.value != 0 } else if let Some(string_box) = value.as_any().downcast_ref::() { !string_box.value.is_empty() } else if value.as_any().downcast_ref::().is_some() { false } else { true // 他のBoxは真とみなす } } /// 🌍 革命的変数取得(テスト用):GlobalBoxのフィールドから取得 pub fn get_variable(&self, name: &str) -> Result, RuntimeError> { self.resolve_variable(name) } } // ===== Tests ===== #[cfg(test)] mod tests { use super::*; use crate::parser::NyashParser; #[test] fn test_simple_execution() { let code = r#" x = 42 print(x) "#; let ast = NyashParser::parse_from_string(code).unwrap(); let mut interpreter = NyashInterpreter::new(); let result = interpreter.execute(ast); assert!(result.is_ok()); } #[test] fn test_arithmetic() { let code = r#" result = 10 + 32 "#; let ast = NyashParser::parse_from_string(code).unwrap(); let mut interpreter = NyashInterpreter::new(); interpreter.execute(ast).unwrap(); // 🌍 革命的変数取得:GlobalBoxから let result = interpreter.get_variable("result").unwrap(); assert_eq!(result.to_string_box().value, "42"); } #[test] fn test_if_statement() { let code = r#" x = true if x { y = "success" } else { y = "failure" } "#; let ast = NyashParser::parse_from_string(code).unwrap(); let mut interpreter = NyashInterpreter::new(); interpreter.execute(ast).unwrap(); // 🌍 革命的変数取得:GlobalBoxから let result = interpreter.get_variable("y").unwrap(); assert_eq!(result.to_string_box().value, "success"); } #[test] fn test_box_instance_creation() { let code = r#" box TestBox { value getValue() { return this.value } setValue(newValue) { this.value = newValue } } obj = new TestBox() obj.value = "test123" result = obj.getValue() "#; let ast = NyashParser::parse_from_string(code).unwrap(); let mut interpreter = NyashInterpreter::new(); interpreter.execute(ast).unwrap(); // 🌍 革命的変数取得:インスタンス作成確認 let obj = interpreter.get_variable("obj").unwrap(); assert!(obj.as_any().downcast_ref::().is_some()); // 🌍 革命的変数取得:メソッド呼び出し結果確認 let result = interpreter.get_variable("result").unwrap(); assert_eq!(result.to_string_box().value, "test123"); } } // ===== 🔥 Static Box管理システム ===== impl NyashInterpreter { /// Static Box定義を登録 pub fn register_static_box(&mut self, definition: StaticBoxDefinition) -> Result<(), RuntimeError> { let mut definitions = self.shared.static_box_definitions.write() .map_err(|_| RuntimeError::RuntimeFailure { message: "Failed to acquire write lock for static box definitions".to_string() })?; definitions.insert(definition.name.clone(), definition); Ok(()) } /// Static Box宣言を登録(AST処理から呼ばれる) pub fn register_static_box_declaration( &mut self, name: String, fields: Vec, methods: HashMap, init_fields: Vec, static_init: Option>, extends: Option, implements: Vec, type_parameters: Vec ) -> Result<(), RuntimeError> { // 🌍 Static Box定義時にstatics名前空間を確実に作成 self.ensure_statics_namespace()?; let definition = StaticBoxDefinition { name: name.clone(), fields, methods, init_fields, static_init, extends, implements, type_parameters, initialization_state: StaticBoxState::NotInitialized, }; eprintln!("🔥 Static Box '{}' definition registered in statics namespace", name); self.register_static_box(definition) } /// Static Boxの初期化を実行(遅延初期化) pub fn ensure_static_box_initialized(&mut self, name: &str) -> Result<(), RuntimeError> { // 1. 定義を取得 let definition = { let definitions = self.shared.static_box_definitions.read() .map_err(|_| RuntimeError::RuntimeFailure { message: "Failed to acquire read lock for static box definitions".to_string() })?; match definitions.get(name) { Some(def) => def.clone(), None => return Err(RuntimeError::UndefinedClass { name: name.to_string() }), } }; // 2. 初期化状態をチェック if definition.initialization_state == StaticBoxState::Initialized { return Ok(()); // 既に初期化済み } if definition.initialization_state == StaticBoxState::Initializing { return Err(RuntimeError::RuntimeFailure { message: format!("Circular dependency detected during initialization of static box '{}'", name) }); } // 3. 初期化開始をマーク self.set_static_box_state(name, StaticBoxState::Initializing)?; // 4. 「statics」名前空間をGlobalBoxに作成(未存在の場合) self.ensure_statics_namespace()?; // 5. シングルトンインスタンスを作成(メソッドも含む) let singleton = InstanceBox::new( format!("{}_singleton", name), definition.init_fields.clone(), definition.methods.clone(), // ★ メソッドを正しく設定 ); // 6. GlobalBox.staticsに登録 self.set_static_instance(name, singleton)?; // 7. static初期化ブロックを実行(me変数をバインドして) if let Some(ref init_statements) = definition.static_init { // statics名前空間からシングルトンインスタンスを取得 let static_instance = { let global_box = self.shared.global_box.lock().unwrap(); let statics_box = global_box.get_field("statics").unwrap(); let statics_instance = statics_box.as_any().downcast_ref::().unwrap(); statics_instance.get_field(name).unwrap() }; // 🌍 this変数をバインドしてstatic初期化実行(me構文のため) self.declare_local_variable("me", static_instance); for stmt in init_statements { self.execute_statement(stmt)?; } // 🌍 this変数をクリーンアップ self.local_vars.remove("me"); } // 8. 初期化完了をマーク self.set_static_box_state(name, StaticBoxState::Initialized)?; Ok(()) } /// Static Box初期化状態を設定 fn set_static_box_state(&mut self, name: &str, state: StaticBoxState) -> Result<(), RuntimeError> { let mut definitions = self.shared.static_box_definitions.write() .map_err(|_| RuntimeError::RuntimeFailure { message: "Failed to acquire write lock for static box definitions".to_string() })?; if let Some(definition) = definitions.get_mut(name) { definition.initialization_state = state; } Ok(()) } /// 「statics」名前空間をGlobalBoxに作成 fn ensure_statics_namespace(&mut self) -> Result<(), RuntimeError> { let global_box = self.shared.global_box.lock() .map_err(|_| RuntimeError::RuntimeFailure { message: "Failed to acquire global box lock".to_string() })?; // 既に存在する場合はスキップ if global_box.get_field("statics").is_some() { eprintln!("🌍 statics namespace already exists - skipping creation"); return Ok(()); } // 「statics」用のInstanceBoxを作成 let statics_box = InstanceBox::new( "statics".to_string(), vec![], HashMap::new(), ); // GlobalBoxのfieldsに直接挿入 { let mut fields = global_box.fields.lock().unwrap(); fields.insert("statics".to_string(), Box::new(statics_box)); } eprintln!("🌍 statics namespace created in GlobalBox successfully"); Ok(()) } /// Static Boxシングルトンインスタンスを設定 fn set_static_instance(&mut self, name: &str, instance: InstanceBox) -> Result<(), RuntimeError> { let global_box = self.shared.global_box.lock() .map_err(|_| RuntimeError::RuntimeFailure { message: "Failed to acquire global box lock".to_string() })?; // statics名前空間を取得 let statics_box = global_box.get_field("statics") .ok_or(RuntimeError::TypeError { message: "statics namespace not found in GlobalBox".to_string() })?; let statics_instance = statics_box.as_any() .downcast_ref::() .ok_or(RuntimeError::TypeError { message: "statics field is not an InstanceBox".to_string() })?; // statics InstanceBoxのfieldsに直接挿入(動的フィールド追加) { let mut fields = statics_instance.fields.lock().unwrap(); fields.insert(name.to_string(), Box::new(instance)); } eprintln!("🔥 Static box '{}' instance registered in statics namespace", name); Ok(()) } /// 🔥 Static Boxかどうかをチェック pub(super) fn is_static_box(&self, name: &str) -> bool { if let Ok(definitions) = self.shared.static_box_definitions.read() { definitions.contains_key(name) } else { false } } }