diff --git a/src/interpreter/expressions.rs b/src/interpreter/expressions.rs index 5ccb1061..42e513d1 100644 --- a/src/interpreter/expressions.rs +++ b/src/interpreter/expressions.rs @@ -61,21 +61,22 @@ impl NyashInterpreter { ASTNode::This { .. } => { // 🌍 革命的this解決:local変数から取得 - self.resolve_variable("me") + let shared_this = self.resolve_variable("me") .map_err(|_| RuntimeError::InvalidOperation { message: "'this' is only available inside methods".to_string(), - }) + })?; + Ok((**shared_this).clone_box()) // Convert for external interface } ASTNode::Me { .. } => { // 🌍 革命的me解決:local変数から取得(thisと同じ) - let result = self.resolve_variable("me") + let shared_me = self.resolve_variable("me") .map_err(|_| RuntimeError::InvalidOperation { message: "'me' is only available inside methods".to_string(), - }); + })?; - result + Ok((**shared_me).clone_box()) // Convert for external interface } ASTNode::ThisField { field, .. } => { @@ -85,11 +86,12 @@ impl NyashInterpreter { message: "'this' is not bound in the current context".to_string(), })?; - if let Some(instance) = this_value.as_any().downcast_ref::() { - instance.get_field(field) + if let Some(instance) = (**this_value).as_any().downcast_ref::() { + let shared_field = instance.get_field(field) .ok_or_else(|| RuntimeError::InvalidOperation { message: format!("Field '{}' not found on this", field) - }) + })?; + Ok((**shared_field).clone_box()) // Convert for external interface } else { Err(RuntimeError::TypeError { message: "'this' is not an instance".to_string(), @@ -104,11 +106,12 @@ impl NyashInterpreter { message: "'this' is not bound in the current context".to_string(), })?; - if let Some(instance) = me_value.as_any().downcast_ref::() { - instance.get_field(field) + if let Some(instance) = (**me_value).as_any().downcast_ref::() { + let shared_field = instance.get_field(field) .ok_or_else(|| RuntimeError::InvalidOperation { message: format!("Field '{}' not found on me", field) - }) + })?; + Ok((**shared_field).clone_box()) // Convert for external interface } else { Err(RuntimeError::TypeError { message: "'this' is not an instance".to_string(), @@ -551,7 +554,7 @@ impl NyashInterpreter { if name == "me" { // Get current instance to check if field is weak if let Ok(current_me) = self.resolve_variable("me") { - if let Some(current_instance) = current_me.as_any().downcast_ref::() { + if let Some(current_instance) = (**current_me).as_any().downcast_ref::() { if current_instance.is_weak_field(field) { return Err(RuntimeError::InvalidOperation { message: format!( @@ -862,7 +865,7 @@ impl NyashInterpreter { message: "'from' can only be used inside methods".to_string(), })?; - let current_instance = current_instance_val.as_any().downcast_ref::() + let current_instance = (**current_instance_val).as_any().downcast_ref::() .ok_or(RuntimeError::TypeError { message: "'from' requires current instance to be InstanceBox".to_string(), })?; diff --git a/src/interpreter/objects.rs b/src/interpreter/objects.rs index fada4003..0133cdb3 100644 --- a/src/interpreter/objects.rs +++ b/src/interpreter/objects.rs @@ -718,20 +718,21 @@ impl NyashInterpreter { .or_else(|| final_box_decl.constructors.get(&init_key)) .or_else(|| final_box_decl.constructors.get(&box_name_key)) { // コンストラクタを実行 - self.execute_constructor(&instance_box, constructor, arguments, &final_box_decl)?; + let instance_arc = Arc::from(instance_box); + self.execute_constructor(&instance_arc, constructor, arguments, &final_box_decl)?; } else if !arguments.is_empty() { return Err(RuntimeError::InvalidOperation { message: format!("No constructor found for {} with {} arguments", class, arguments.len()), }); } - Ok(instance_box) + Ok((*instance_arc).clone_box()) // Convert Arc back to Box for external interface } /// コンストラクタを実行 - Constructor execution pub(super) fn execute_constructor( &mut self, - instance: &Box, + instance: &SharedNyashBox, constructor: &ASTNode, arguments: &[ASTNode], box_decl: &BoxDeclaration diff --git a/src/interpreter/statements.rs b/src/interpreter/statements.rs index ad8c6067..aed7cd23 100644 --- a/src/interpreter/statements.rs +++ b/src/interpreter/statements.rs @@ -321,7 +321,7 @@ impl NyashInterpreter { message: "'this' is not bound in the current context".to_string(), })?; - if let Some(instance) = this_value.as_any().downcast_ref::() { + if let Some(instance) = (**this_value).as_any().downcast_ref::() { // 🔥 Usage prohibition guard - check if instance is finalized if instance.is_finalized() { return Err(RuntimeError::InvalidOperation { @@ -354,7 +354,7 @@ impl NyashInterpreter { message: "'this' is not bound in the current context".to_string(), })?; - if let Some(instance) = me_value.as_any().downcast_ref::() { + if let Some(instance) = (**me_value).as_any().downcast_ref::() { // 🔥 Usage prohibition guard - check if instance is finalized if instance.is_finalized() { return Err(RuntimeError::InvalidOperation { diff --git a/test_complete_socketbox_fix.nyash b/test_complete_socketbox_fix.nyash new file mode 100644 index 00000000..797b623c --- /dev/null +++ b/test_complete_socketbox_fix.nyash @@ -0,0 +1,33 @@ +// Complete test for the SocketBox state preservation fix +static box Main { + init { server } + + main() { + print("=== SocketBox State Preservation Test ===") + + // 1. Create new SocketBox + me.server = new SocketBox() + + print("=== Before bind ===") + print("isServer: " + me.server.isServer()) + + // 2. Call bind() which should set is_server=true + me.server.bind("127.0.0.1", 8080) + + print("=== After bind ===") + print("isServer: " + me.server.isServer()) + + // 3. Test multiple accesses + print("=== Multiple access test ===") + local temp1 + temp1 = me.server + print("temp1.isServer(): " + temp1.isServer()) + + local temp2 + temp2 = me.server + print("temp2.isServer(): " + temp2.isServer()) + + // If the fix works, all should return true + return me.server.isServer() + } +} \ No newline at end of file diff --git a/test_multiple_stateful_boxes.nyash b/test_multiple_stateful_boxes.nyash new file mode 100644 index 00000000..316f8da2 --- /dev/null +++ b/test_multiple_stateful_boxes.nyash @@ -0,0 +1,40 @@ +// Comprehensive test for multiple stateful boxes +static box Main { + init { socket, debug_tracker } + + main() { + print("=== Comprehensive Stateful Box Test ===") + + // Test 1: SocketBox (the main issue) + print("=== Test 1: SocketBox ===") + me.socket = new SocketBox() + print("Before bind - isServer: " + me.socket.isServer()) + me.socket.bind("127.0.0.1", 8080) + print("After bind - isServer: " + me.socket.isServer()) + + // Test multiple field accesses + local socket1 + socket1 = me.socket + local socket2 + socket2 = me.socket + print("socket1.isServer(): " + socket1.isServer()) + print("socket2.isServer(): " + socket2.isServer()) + + // Test 2: DebugBox (should already work) + print("=== Test 2: DebugBox ===") + me.debug_tracker = new DebugBox() + me.debug_tracker.enableTracking() + print("Tracking enabled: " + me.debug_tracker.isTrackingEnabled()) + + // Test multiple accesses + local debug1 + debug1 = me.debug_tracker + local debug2 + debug2 = me.debug_tracker + print("debug1.isTrackingEnabled(): " + debug1.isTrackingEnabled()) + print("debug2.isTrackingEnabled(): " + debug2.isTrackingEnabled()) + + print("=== All tests completed ===") + return me.socket.isServer() + } +} \ No newline at end of file