- Fix condition_fn resolution: Value call path + dev safety + stub injection - VM bridge: handle Method::birth via BoxCall; ArrayBox push/get/length/set direct bridge - Receiver safety: pin receiver in method_call_handlers to avoid undefined use across blocks - Local vars: materialize on declaration (use init ValueId; void for uninit) - Prefer legacy BoxCall for Array/Map/String/user boxes in emit_box_or_plugin_call (stability-first) - Test runner: update LLVM hint to llvmlite harness (remove LLVM_SYS_180_PREFIX guidance) - Docs/roadmap: update CURRENT_TASK with unified default-ON + guards Note: NYASH_DEV_BIRTH_INJECT_BUILTINS=1 can re-enable builtin birth() injection during migration.
71 lines
3.5 KiB
Rust
71 lines
3.5 KiB
Rust
#![cfg(feature = "interpreter-legacy")]
|
|
|
|
use crate::interpreter::NyashInterpreter;
|
|
use crate::ast::{ASTNode, LiteralValue};
|
|
use crate::box_trait::{NyashBox, IntegerBox};
|
|
|
|
#[test]
|
|
fn assign_updates_refcell_variable_inner() {
|
|
let mut interp = NyashInterpreter::new();
|
|
// x = RefCell(1)
|
|
let rc = crate::boxes::ref_cell_box::RefCellBox::new(Box::new(IntegerBox::new(1)));
|
|
interp.declare_local_variable("x", Box::new(rc));
|
|
|
|
// Execute: x = 42
|
|
let target = ASTNode::Variable { name: "x".to_string(), span: crate::ast::Span::unknown() };
|
|
let value = ASTNode::Literal { value: LiteralValue::Integer(42), span: crate::ast::Span::unknown() };
|
|
let _ = interp.execute_assignment(&target, &value).expect("assign ok");
|
|
|
|
// Verify x is still RefCell and inner == 42
|
|
let xv = interp.resolve_variable("x").expect("x exists");
|
|
let rc = xv.as_any().downcast_ref::<crate::boxes::ref_cell_box::RefCellBox>().expect("x is RefCellBox");
|
|
let inner = rc.borrow();
|
|
let ib = inner.as_any().downcast_ref::<IntegerBox>().expect("inner integer");
|
|
assert_eq!(ib.value, 42);
|
|
}
|
|
|
|
#[test]
|
|
fn assign_updates_refcell_field_inner() {
|
|
let mut interp = NyashInterpreter::new();
|
|
// obj with field v = RefCell(5)
|
|
let inst = crate::instance_v2::InstanceBox::from_declaration("Test".to_string(), vec!["v".to_string()], std::collections::HashMap::new());
|
|
let rc = crate::boxes::ref_cell_box::RefCellBox::new(Box::new(IntegerBox::new(5)));
|
|
let _ = inst.set_field("v", std::sync::Arc::from(Box::new(rc) as Box<dyn NyashBox>));
|
|
// bind obj into local
|
|
interp.declare_local_variable("obj", Box::new(inst.clone()));
|
|
|
|
// Execute: obj.v = 7
|
|
let target = ASTNode::FieldAccess { object: Box::new(ASTNode::Variable { name: "obj".to_string(), span: crate::ast::Span::unknown() }), field: "v".to_string(), span: crate::ast::Span::unknown() };
|
|
let value = ASTNode::Literal { value: LiteralValue::Integer(7), span: crate::ast::Span::unknown() };
|
|
let _ = interp.execute_assignment(&target, &value).expect("assign ok");
|
|
|
|
// Verify obj.v inner == 7
|
|
let sv = inst.get_field("v").expect("field exists");
|
|
let rc = sv.as_any().downcast_ref::<crate::boxes::ref_cell_box::RefCellBox>().expect("v is RefCellBox");
|
|
let inner = rc.borrow();
|
|
let ib = inner.as_any().downcast_ref::<IntegerBox>().expect("inner integer");
|
|
assert_eq!(ib.value, 7);
|
|
}
|
|
|
|
#[test]
|
|
fn closure_reads_updated_refcell_capture() {
|
|
let mut interp = NyashInterpreter::new();
|
|
// local x = 10
|
|
interp.declare_local_variable("x", Box::new(IntegerBox::new(10)));
|
|
// Build lambda: () { x }
|
|
let lam = ASTNode::Lambda { params: vec![], body: vec![
|
|
ASTNode::Return { value: Some(Box::new(ASTNode::Variable { name: "x".to_string(), span: crate::ast::Span::unknown() })), span: crate::ast::Span::unknown() }
|
|
], span: crate::ast::Span::unknown() };
|
|
// Evaluate lambda to FunctionBox
|
|
let f = interp.execute_expression(&lam).expect("lambda eval");
|
|
// x = 20 (should update RefCell capture)
|
|
let target = ASTNode::Variable { name: "x".to_string(), span: crate::ast::Span::unknown() };
|
|
let value = ASTNode::Literal { value: LiteralValue::Integer(20), span: crate::ast::Span::unknown() };
|
|
let _ = interp.execute_assignment(&target, &value).expect("assign ok");
|
|
// Call f()
|
|
let call = ASTNode::Call { callee: Box::new(lam.clone()), arguments: vec![], span: crate::ast::Span::unknown() };
|
|
let out = interp.execute_expression(&call).expect("call ok");
|
|
let ib = out.as_any().downcast_ref::<IntegerBox>().expect("integer ret");
|
|
assert_eq!(ib.value, 20);
|
|
}
|