diff --git a/src/ast/vm.rs b/src/ast/vm.rs index 343c867..f9ad455 100644 --- a/src/ast/vm.rs +++ b/src/ast/vm.rs @@ -128,141 +128,6 @@ pub struct VM { frames: Vec, } -macro_rules! dispatch_eval { - ($self:ident, $node:ident, $eval_method:ident $(, $observer:ident)?) => { - match &$node.kind { - BoundKind::Nop => Ok(Value::Void), - BoundKind::Constant(v) => Ok(v.clone()), - BoundKind::Parameter { .. } => Ok(Value::Void), - BoundKind::DefGlobal { global_index, value, .. } => { - let val = $self.$eval_method($($observer,)? value)?; - let idx = *global_index as usize; - let mut globals = $self.globals.borrow_mut(); - if idx >= globals.len() { globals.resize(idx + 1, Value::Void); } - globals[idx] = val.clone(); - Ok(val) - }, - BoundKind::Get { addr, .. } => $self.get_value(*addr), - BoundKind::Set { addr, value } => { - let val = $self.$eval_method($($observer,)? value)?; - $self.set_value(*addr, val.clone())?; - Ok(val) - }, - BoundKind::DefLocal { slot, value, captured_by, .. } => { - let val = $self.$eval_method($($observer,)? value)?; - let final_val = if !captured_by.is_empty() { Value::Cell(Rc::new(RefCell::new(val))) } else { val }; - let frame = $self.frames.last().ok_or("No call frame")?; - let abs_index = frame.stack_base + (*slot as usize); - if abs_index == $self.stack.len() { $self.stack.push(final_val.clone()); } - else if abs_index < $self.stack.len() { $self.stack[abs_index] = final_val.clone(); } - else { return Err(format!("Stack gap at local {}", slot)); } - Ok(final_val) - }, - BoundKind::If { cond, then_br, else_br } => { - let c = $self.$eval_method($($observer,)? cond)?; - if c.is_truthy() { $self.$eval_method($($observer,)? then_br) } - else if let Some(e) = else_br { $self.$eval_method($($observer,)? e) } - else { Ok(Value::Void) } - }, - BoundKind::Block { exprs } => { - let mut last = Value::Void; - for e in exprs { last = $self.$eval_method($($observer,)? e)?; } - Ok(last) - }, - BoundKind::Lambda { params, upvalues, body, positional_count } => { - let mut captured = Vec::with_capacity(upvalues.len()); - for addr in upvalues { captured.push($self.capture_upvalue(*addr)?); } - let closure = Closure::new( - params.ty.original.clone(), - body.ty.original.clone(), - body.clone(), - captured, - *positional_count - ); - Ok(Value::Object(Rc::new(closure))) - }, - BoundKind::Call { callee, args } => { - let mut func_val = $self.$eval_method($($observer,)? callee)?; - - macro_rules! get_arg_vals { - ($s:ident, $a:ident) => { $s.prepare_args($a)? }; - ($s:ident, $o:ident, $a:ident) => { $s.prepare_args_observed($o, $a)? }; - } - - let mut arg_vals = match &args.kind { - BoundKind::Tuple { elements } => { - let mut vals = Vec::with_capacity(elements.len()); - let mut is_complex = false; - for e in elements { - if matches!(e.kind, BoundKind::Tuple { .. }) { is_complex = true; break; } - vals.push($self.$eval_method($($observer,)? e)?); - } - if is_complex { get_arg_vals!($self, $($observer,)? args) } else { vals } - } - _ => { get_arg_vals!($self, $($observer,)? args) } - }; - - if $node.ty.is_tail { - match func_val { - Value::Object(obj) => return Ok(Value::TailCallRequest(Box::new((obj, arg_vals)))), - Value::Function(f) => return Ok((f.func)(arg_vals)), - _ => return Err(format!("Tail call target is not a function: {}", func_val)), - } - } - - loop { - match func_val { - Value::Function(f) => break Ok((f.func)(arg_vals)), - Value::Object(obj) => { - if let Some(closure) = obj.as_any().downcast_ref::() { - let old_stack_top = $self.stack.len(); - let closure_rc = Rc::new(closure.clone()); - $self.frames.push(CallFrame { stack_base: old_stack_top, closure: Some(closure_rc.clone()) }); - if let Some(count) = closure.positional_count && arg_vals.len() == count as usize { - $self.stack.extend(arg_vals); - } else { - $self.unpack(&closure.parameter_node, &arg_vals, &mut 0)?; - } - let result = $self.$eval_method($($observer,)? &closure.exec_node); - $self.frames.pop(); - $self.stack.truncate(old_stack_top); - match result { - Ok(Value::TailCallRequest(payload)) => { - let (next_obj, next_args) = *payload; - func_val = Value::Object(next_obj); - arg_vals = next_args; - continue; - }, - res => break res, - } - } else { break Err(format!("Object is not a closure: {}", obj.type_name())); } - }, - _ => break Err(format!("Attempt to call non-function: {}", func_val)), - } - } - }, - BoundKind::Tuple { elements } => { - let mut vals = Vec::with_capacity(elements.len()); - for e in elements { vals.push($self.$eval_method($($observer,)? e)?); } - Ok(Value::make_tuple(vals)) - }, - BoundKind::Record { fields } => { - let mut keys = Vec::with_capacity(fields.len()); - let mut values = Vec::with_capacity(fields.len()); - for (k, v) in fields { - let key = $self.$eval_method($($observer,)? k)?; - let val = $self.$eval_method($($observer,)? v)?; - if let Value::Keyword(kw) = key { keys.push(kw); values.push(val); } - else { return Err(format!("Record key must be keyword, got {}", key)); } - } - Ok(Value::make_record(keys, values)) - }, - BoundKind::Expansion { bound_expanded, .. } => { $self.$eval_method($($observer,)? bound_expanded) } - BoundKind::Extension(ext) => { Err(format!("Execution of extension '{}' not implemented yet", ext.display_name())) } - } - }; -} - impl VM { pub fn new(globals: Rc>>) -> Self { Self { @@ -369,9 +234,236 @@ impl VM { #[inline(always)] fn eval(&mut self, node: &ExecNode) -> Result { - dispatch_eval!(self, node, eval) + self.eval_internal(&mut NoOpObserver, node) } + fn eval_observed( + &mut self, + observer: &mut O, + node: &ExecNode, + ) -> Result { + self.eval_internal(observer, node) + } + + #[inline(always)] + fn eval_internal( + &mut self, + obs: &mut O, + node: &ExecNode, + ) -> Result { + if O::ACTIVE { + obs.before_eval(self, node); + let result = self.eval_core(obs, node); + obs.after_eval(self, node, &result); + result + } else { + self.eval_core(obs, node) + } + } + + #[inline(always)] + fn eval_core( + &mut self, + obs: &mut O, + node: &ExecNode, + ) -> Result { + match &node.kind { + BoundKind::Nop => Ok(Value::Void), + BoundKind::Constant(v) => Ok(v.clone()), + BoundKind::Parameter { .. } => Ok(Value::Void), + BoundKind::DefGlobal { + global_index, + value, + .. + } => { + let val = self.eval_internal(obs, value)?; + let idx = *global_index as usize; + let mut globals = self.globals.borrow_mut(); + if idx >= globals.len() { + globals.resize(idx + 1, Value::Void); + } + globals[idx] = val.clone(); + Ok(val) + } + BoundKind::Get { addr, .. } => self.get_value(*addr), + BoundKind::Set { addr, value } => { + let val = self.eval_internal(obs, value)?; + self.set_value(*addr, val.clone())?; + Ok(val) + } + BoundKind::DefLocal { + slot, + value, + captured_by, + .. + } => { + let val = self.eval_internal(obs, value)?; + let final_val = if !captured_by.is_empty() { + Value::Cell(Rc::new(RefCell::new(val))) + } else { + val + }; + let frame = self.frames.last().ok_or("No call frame")?; + let abs_index = frame.stack_base + (*slot as usize); + if abs_index == self.stack.len() { + self.stack.push(final_val.clone()); + } else if abs_index < self.stack.len() { + self.stack[abs_index] = final_val.clone(); + } else { + return Err(format!("Stack gap at local {}", slot)); + } + Ok(final_val) + } + BoundKind::If { + cond, + then_br, + else_br, + } => { + let c = self.eval_internal(obs, cond)?; + if c.is_truthy() { + self.eval_internal(obs, then_br) + } else if let Some(e) = else_br { + self.eval_internal(obs, e) + } else { + Ok(Value::Void) + } + } + BoundKind::Block { exprs } => { + let mut last = Value::Void; + for e in exprs { + last = self.eval_internal(obs, e)?; + } + Ok(last) + } + BoundKind::Lambda { + params, + upvalues, + body, + positional_count, + } => { + let mut captured = Vec::with_capacity(upvalues.len()); + for addr in upvalues { + captured.push(self.capture_upvalue(*addr)?); + } + let closure = Closure::new( + params.ty.original.clone(), + body.ty.original.clone(), + body.clone(), + captured, + *positional_count, + ); + Ok(Value::Object(Rc::new(closure))) + } + BoundKind::Call { callee, args } => { + let mut func_val = self.eval_internal(obs, callee)?; + + let mut arg_vals = match &args.kind { + BoundKind::Tuple { elements } => { + let mut vals = Vec::with_capacity(elements.len()); + let mut is_complex = false; + for e in elements { + if matches!(e.kind, BoundKind::Tuple { .. }) { + is_complex = true; + break; + } + vals.push(self.eval_internal(obs, e)?); + } + if is_complex { + self.prepare_args_internal(obs, args)? + } else { + vals + } + } + _ => self.prepare_args_internal(obs, args)?, + }; + + if node.ty.is_tail { + match func_val { + Value::Object(obj) => { + return Ok(Value::TailCallRequest(Box::new((obj, arg_vals)))) + } + Value::Function(f) => return Ok((f.func)(arg_vals)), + _ => { + return Err(format!( + "Tail call target is not a function: {}", + func_val + )) + } + } + } + + loop { + match func_val { + Value::Function(f) => break Ok((f.func)(arg_vals)), + Value::Object(obj) => { + if let Some(closure) = obj.as_any().downcast_ref::() { + let old_stack_top = self.stack.len(); + let closure_rc = Rc::new(closure.clone()); + self.frames.push(CallFrame { + stack_base: old_stack_top, + closure: Some(closure_rc.clone()), + }); + if let Some(count) = closure.positional_count + && arg_vals.len() == count as usize + { + self.stack.extend(arg_vals); + } else { + self.unpack(&closure.parameter_node, &arg_vals, &mut 0)?; + } + let result = self.eval_internal(obs, &closure.exec_node); + self.frames.pop(); + self.stack.truncate(old_stack_top); + match result { + Ok(Value::TailCallRequest(payload)) => { + let (next_obj, next_args) = *payload; + func_val = Value::Object(next_obj); + arg_vals = next_args; + continue; + } + res => break res, + } + } else { + break Err(format!( + "Object is not a closure: {}", + obj.type_name() + )); + } + } + _ => break Err(format!("Attempt to call non-function: {}", func_val)), + } + } + } + BoundKind::Tuple { elements } => { + let mut vals = Vec::with_capacity(elements.len()); + for e in elements { + vals.push(self.eval_internal(obs, e)?); + } + Ok(Value::make_tuple(vals)) + } + BoundKind::Record { fields } => { + let mut keys = Vec::with_capacity(fields.len()); + let mut values = Vec::with_capacity(fields.len()); + for (k, v) in fields { + let key = self.eval_internal(obs, k)?; + let val = self.eval_internal(obs, v)?; + if let Value::Keyword(kw) = key { + keys.push(kw); + values.push(val); + } else { + return Err(format!("Record key must be keyword, got {}", key)); + } + } + Ok(Value::make_record(keys, values)) + } + BoundKind::Expansion { bound_expanded, .. } => self.eval_internal(obs, bound_expanded), + BoundKind::Extension(ext) => Err(format!( + "Execution of extension '{}' not implemented yet", + ext.display_name() + )), + } + } + + pub fn resolve_tail_calls(&mut self, mut result: Value) -> Value { while let Value::TailCallRequest(payload) = result { let (next_obj, next_args) = *payload; @@ -390,20 +482,6 @@ impl VM { result } - fn eval_observed( - &mut self, - observer: &mut O, - node: &ExecNode, - ) -> Result { - observer.before_eval(self, node); - let wrapper = |vm: &mut Self, obs: &mut O| -> Result { - dispatch_eval!(vm, node, eval_observed, obs) - }; - let result = wrapper(self, observer); - observer.after_eval(self, node, &result); - result - } - fn capture_upvalue(&mut self, addr: Address) -> Result>, String> { match addr { Address::Local(idx) => { @@ -532,62 +610,35 @@ impl VM { } } - fn prepare_args(&mut self, args: &ExecNode) -> Result, String> { - let mut arg_vals = Vec::new(); - match &args.kind { - BoundKind::Tuple { elements } => { - self.eval_and_flatten(elements, &mut arg_vals)?; - } - _ => { - VM::flatten_value(self.eval(args)?, &mut arg_vals); - } - } - Ok(arg_vals) - } - - fn prepare_args_observed( + fn prepare_args_internal( &mut self, - observer: &mut O, + obs: &mut O, args: &ExecNode, ) -> Result, String> { let mut arg_vals = Vec::new(); match &args.kind { BoundKind::Tuple { elements } => { - self.eval_observed_and_flatten(observer, elements, &mut arg_vals)?; + self.eval_and_flatten_internal(obs, elements, &mut arg_vals)?; } _ => { - VM::flatten_value(self.eval_observed(observer, args)?, &mut arg_vals); + VM::flatten_value(self.eval_internal(obs, args)?, &mut arg_vals); } } Ok(arg_vals) } - fn eval_and_flatten( + fn eval_and_flatten_internal( &mut self, - elements: &[ExecNode], - into: &mut Vec, - ) -> Result<(), String> { - for e in elements { - match &e.kind { - BoundKind::Tuple { elements: sub } => self.eval_and_flatten(sub, into)?, - _ => into.push(self.eval(e)?), - } - } - Ok(()) - } - - fn eval_observed_and_flatten( - &mut self, - observer: &mut O, + obs: &mut O, elements: &[ExecNode], into: &mut Vec, ) -> Result<(), String> { for e in elements { match &e.kind { BoundKind::Tuple { elements: sub } => { - self.eval_observed_and_flatten(observer, sub, into)? + self.eval_and_flatten_internal(obs, sub, into)? } - _ => into.push(self.eval_observed(observer, e)?), + _ => into.push(self.eval_internal(obs, e)?), } } Ok(())