Skip to content

Commit e8a751a

Browse files
timfennisclaude
andcommitted
Fix: map default function called when key is missing
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
1 parent 89c7366 commit e8a751a

2 files changed

Lines changed: 22 additions & 6 deletions

File tree

ndc_stdlib/src/index.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use ndc_core::{FunctionRegistry, StaticType};
2+
use ndc_vm::Vm;
23
use ndc_vm::error::VmError;
34
use ndc_vm::value::{NativeFunc, NativeFunction, Object as VmObject, Value as VmValue};
45
use std::rc::Rc;
@@ -11,14 +12,14 @@ pub fn register(env: &mut FunctionRegistry<Rc<NativeFunction>>) {
1112
parameters: None,
1213
return_type: Box::new(StaticType::Any),
1314
},
14-
func: NativeFunc::Simple(Box::new(|args: &[VmValue]| {
15+
func: NativeFunc::WithVm(Box::new(|args: &[VmValue], vm: &mut Vm| {
1516
let [container, index_value] = args else {
1617
return Err(VmError::native(format!(
1718
"[] requires exactly 2 arguments, got {}",
1819
args.len()
1920
)));
2021
};
21-
vm_get_at_index(container, index_value)
22+
vm_get_at_index(container, index_value, vm)
2223
})),
2324
});
2425
env.declare_global_fn(get_native);
@@ -125,7 +126,11 @@ fn extract_vm_offset(index_value: &VmValue, size: usize) -> Result<VmOffset, VmE
125126
Ok(VmOffset::Element(to_forward_index(i, size, false)?))
126127
}
127128

128-
fn vm_get_at_index(container: &VmValue, index_value: &VmValue) -> Result<VmValue, VmError> {
129+
fn vm_get_at_index(
130+
container: &VmValue,
131+
index_value: &VmValue,
132+
vm: &mut Vm,
133+
) -> Result<VmValue, VmError> {
129134
let Some(size) = vm_sequence_length(container) else {
130135
return Err(VmError::native(format!(
131136
"cannot index into {}",
@@ -177,9 +182,12 @@ fn vm_get_at_index(container: &VmValue, index_value: &VmValue) -> Result<VmValue
177182
None => Err(VmError::native(format!("Key not found in map: {key}"))),
178183
Some(default_val) => match default_val {
179184
VmValue::Object(o) if matches!(o.as_ref(), VmObject::Function(_)) => {
180-
todo!(
181-
"map default functions require an environment and cannot be called from vm_native"
182-
)
185+
let VmObject::Function(f) = o.as_ref() else {
186+
unreachable!()
187+
};
188+
let result = vm.call_callback(f.clone(), vec![])?;
189+
entries.borrow_mut().insert(key, result.clone());
190+
Ok(result)
183191
}
184192
non_fn => {
185193
let v = non_fn.clone();
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
let dd = %{:fn() => []};
2+
dd["foo"].push(3);
3+
dd["bar"].push(4);
4+
5+
// expect-output: 1
6+
print(dd["foo"].len);
7+
// expect-output: 1
8+
print(dd["bar"].len);

0 commit comments

Comments
 (0)