Fix interface compatibility issues with Arc-based reference sharing
Co-authored-by: moe-charm <217100418+moe-charm@users.noreply.github.com>
This commit is contained in:
@ -61,21 +61,22 @@ impl NyashInterpreter {
|
|||||||
|
|
||||||
ASTNode::This { .. } => {
|
ASTNode::This { .. } => {
|
||||||
// 🌍 革命的this解決:local変数から取得
|
// 🌍 革命的this解決:local変数から取得
|
||||||
self.resolve_variable("me")
|
let shared_this = self.resolve_variable("me")
|
||||||
.map_err(|_| RuntimeError::InvalidOperation {
|
.map_err(|_| RuntimeError::InvalidOperation {
|
||||||
message: "'this' is only available inside methods".to_string(),
|
message: "'this' is only available inside methods".to_string(),
|
||||||
})
|
})?;
|
||||||
|
Ok((**shared_this).clone_box()) // Convert for external interface
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode::Me { .. } => {
|
ASTNode::Me { .. } => {
|
||||||
|
|
||||||
// 🌍 革命的me解決:local変数から取得(thisと同じ)
|
// 🌍 革命的me解決:local変数から取得(thisと同じ)
|
||||||
let result = self.resolve_variable("me")
|
let shared_me = self.resolve_variable("me")
|
||||||
.map_err(|_| RuntimeError::InvalidOperation {
|
.map_err(|_| RuntimeError::InvalidOperation {
|
||||||
message: "'me' is only available inside methods".to_string(),
|
message: "'me' is only available inside methods".to_string(),
|
||||||
});
|
})?;
|
||||||
|
|
||||||
result
|
Ok((**shared_me).clone_box()) // Convert for external interface
|
||||||
}
|
}
|
||||||
|
|
||||||
ASTNode::ThisField { field, .. } => {
|
ASTNode::ThisField { field, .. } => {
|
||||||
@ -85,11 +86,12 @@ impl NyashInterpreter {
|
|||||||
message: "'this' is not bound in the current context".to_string(),
|
message: "'this' is not bound in the current context".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = (**this_value).as_any().downcast_ref::<InstanceBox>() {
|
||||||
instance.get_field(field)
|
let shared_field = instance.get_field(field)
|
||||||
.ok_or_else(|| RuntimeError::InvalidOperation {
|
.ok_or_else(|| RuntimeError::InvalidOperation {
|
||||||
message: format!("Field '{}' not found on this", field)
|
message: format!("Field '{}' not found on this", field)
|
||||||
})
|
})?;
|
||||||
|
Ok((**shared_field).clone_box()) // Convert for external interface
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::TypeError {
|
Err(RuntimeError::TypeError {
|
||||||
message: "'this' is not an instance".to_string(),
|
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(),
|
message: "'this' is not bound in the current context".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = (**me_value).as_any().downcast_ref::<InstanceBox>() {
|
||||||
instance.get_field(field)
|
let shared_field = instance.get_field(field)
|
||||||
.ok_or_else(|| RuntimeError::InvalidOperation {
|
.ok_or_else(|| RuntimeError::InvalidOperation {
|
||||||
message: format!("Field '{}' not found on me", field)
|
message: format!("Field '{}' not found on me", field)
|
||||||
})
|
})?;
|
||||||
|
Ok((**shared_field).clone_box()) // Convert for external interface
|
||||||
} else {
|
} else {
|
||||||
Err(RuntimeError::TypeError {
|
Err(RuntimeError::TypeError {
|
||||||
message: "'this' is not an instance".to_string(),
|
message: "'this' is not an instance".to_string(),
|
||||||
@ -551,7 +554,7 @@ impl NyashInterpreter {
|
|||||||
if name == "me" {
|
if name == "me" {
|
||||||
// Get current instance to check if field is weak
|
// Get current instance to check if field is weak
|
||||||
if let Ok(current_me) = self.resolve_variable("me") {
|
if let Ok(current_me) = self.resolve_variable("me") {
|
||||||
if let Some(current_instance) = current_me.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(current_instance) = (**current_me).as_any().downcast_ref::<InstanceBox>() {
|
||||||
if current_instance.is_weak_field(field) {
|
if current_instance.is_weak_field(field) {
|
||||||
return Err(RuntimeError::InvalidOperation {
|
return Err(RuntimeError::InvalidOperation {
|
||||||
message: format!(
|
message: format!(
|
||||||
@ -862,7 +865,7 @@ impl NyashInterpreter {
|
|||||||
message: "'from' can only be used inside methods".to_string(),
|
message: "'from' can only be used inside methods".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let current_instance = current_instance_val.as_any().downcast_ref::<InstanceBox>()
|
let current_instance = (**current_instance_val).as_any().downcast_ref::<InstanceBox>()
|
||||||
.ok_or(RuntimeError::TypeError {
|
.ok_or(RuntimeError::TypeError {
|
||||||
message: "'from' requires current instance to be InstanceBox".to_string(),
|
message: "'from' requires current instance to be InstanceBox".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|||||||
@ -718,20 +718,21 @@ impl NyashInterpreter {
|
|||||||
.or_else(|| final_box_decl.constructors.get(&init_key))
|
.or_else(|| final_box_decl.constructors.get(&init_key))
|
||||||
.or_else(|| final_box_decl.constructors.get(&box_name_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() {
|
} else if !arguments.is_empty() {
|
||||||
return Err(RuntimeError::InvalidOperation {
|
return Err(RuntimeError::InvalidOperation {
|
||||||
message: format!("No constructor found for {} with {} arguments", class, arguments.len()),
|
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
|
/// コンストラクタを実行 - Constructor execution
|
||||||
pub(super) fn execute_constructor(
|
pub(super) fn execute_constructor(
|
||||||
&mut self,
|
&mut self,
|
||||||
instance: &Box<dyn NyashBox>,
|
instance: &SharedNyashBox,
|
||||||
constructor: &ASTNode,
|
constructor: &ASTNode,
|
||||||
arguments: &[ASTNode],
|
arguments: &[ASTNode],
|
||||||
box_decl: &BoxDeclaration
|
box_decl: &BoxDeclaration
|
||||||
|
|||||||
@ -321,7 +321,7 @@ impl NyashInterpreter {
|
|||||||
message: "'this' is not bound in the current context".to_string(),
|
message: "'this' is not bound in the current context".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = this_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = (**this_value).as_any().downcast_ref::<InstanceBox>() {
|
||||||
// 🔥 Usage prohibition guard - check if instance is finalized
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
if instance.is_finalized() {
|
if instance.is_finalized() {
|
||||||
return Err(RuntimeError::InvalidOperation {
|
return Err(RuntimeError::InvalidOperation {
|
||||||
@ -354,7 +354,7 @@ impl NyashInterpreter {
|
|||||||
message: "'this' is not bound in the current context".to_string(),
|
message: "'this' is not bound in the current context".to_string(),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
if let Some(instance) = me_value.as_any().downcast_ref::<InstanceBox>() {
|
if let Some(instance) = (**me_value).as_any().downcast_ref::<InstanceBox>() {
|
||||||
// 🔥 Usage prohibition guard - check if instance is finalized
|
// 🔥 Usage prohibition guard - check if instance is finalized
|
||||||
if instance.is_finalized() {
|
if instance.is_finalized() {
|
||||||
return Err(RuntimeError::InvalidOperation {
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
|||||||
33
test_complete_socketbox_fix.nyash
Normal file
33
test_complete_socketbox_fix.nyash
Normal file
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
40
test_multiple_stateful_boxes.nyash
Normal file
40
test_multiple_stateful_boxes.nyash
Normal file
@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user