use crate::object::{BuiltinExit, Obj, StrObj}; use crate::vm::{error::RuntimeError, machine::MachineBuilder}; impl MachineBuilder { /// Registers all builtins for calling on the machine. pub(super) fn register_builtins(&mut self) { self.scope_stack.push_scope(); // // panic // self.register_builtin_fun("panic", |machine, _| { println!("!!! panic"); println!("!!! top of stack"); for (i, value) in machine.stack().iter().enumerate().rev() { println!("!!! {}. {:?}", i, value); } println!("!!! bottom of stack"); panic!(); }); /* // // if // self.register_builtin_fun("if", |machine, _| { let if_false = machine.stack_pop()?; let if_true = machine.stack_pop()?; let condition = machine.stack_pop()?; let value = if condition.is_truthy() { if_true } else { if_false }; if let Value::Quote(quote) = value { Ok(BuiltinExit::Call(quote)) } else { return Err(RuntimeError::CannotCall( "if statement requires quote value".to_string(), ) .into()); } }); */ // // print // self.register_builtin_fun("print", |machine, reentry| { const CALL_STR: usize = 1; if reentry == 0 { let obj = machine .stack_peek() .ok_or_else(|| RuntimeError::StackUnderflow)?; // Push the value's __str__ value, call it, and then print it. let str_fun = obj .get("__str__") .ok_or_else(|| RuntimeError::UnsetWord("__str__".to_string()))?; let call_site = machine.call_stack().last().unwrap().call_site().cloned(); str_fun.call(call_site, machine)?; Ok(BuiltinExit::Resume(CALL_STR)) } else if reentry == CALL_STR { let obj_ptr = machine.stack_pop()?; let str_obj: &(dyn Obj + 'static) = &*obj_ptr; if let Some(string) = str_obj.as_any().downcast_ref::() { print!("{}", string.value()); Ok(BuiltinExit::Return) } else { panic!( "expected StrObj from __str__ function but got {:?} instead", str_obj ); } } else { unreachable!() } }); // // println // self.register_builtin_fun("println", |machine, reentry| { const CALL_STR: usize = 1; if reentry == 0 { let obj = machine .stack_peek() .ok_or_else(|| RuntimeError::StackUnderflow)?; // Push the value's __str__ value, call it, and then print it. let str_fun = obj .get("__str__") .ok_or_else(|| RuntimeError::UnsetWord("__str__".to_string()))?; let call_site = machine.call_stack().last().unwrap().call_site().cloned(); str_fun.call(call_site, machine)?; Ok(BuiltinExit::Resume(CALL_STR)) } else if reentry == CALL_STR { let obj_ptr = machine.stack_pop()?; let str_obj: &(dyn Obj + 'static) = &*obj_ptr; if let Some(string) = str_obj.as_any().downcast_ref::() { println!("{}", string.value()); Ok(BuiltinExit::Return) } else { panic!( "expected StrObj from __str__ function but got {:?} instead", str_obj ); } } else { unreachable!() } }); /* // // == // self.register_builtin_fun("==", |machine, _| { let rhs = machine.stack_pop()?; let lhs = machine.stack_pop()?; machine.stack_push(Value::Int((lhs == rhs) as Int))?; Ok(BuiltinExit::Return) }); // // ~= // self.register_builtin_fun("~=", |machine, _| { let rhs = machine.stack_pop()?; let lhs = machine.stack_pop()?; machine.stack_push(Value::Int((lhs != rhs) as Int))?; Ok(BuiltinExit::Return) }); */ } }