2022-01-18 14:39:06 -08:00
|
|
|
use crate::object::{BuiltinExit, Obj, StrObj};
|
2022-01-16 19:22:02 -08:00
|
|
|
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!();
|
|
|
|
|
});
|
|
|
|
|
|
2022-01-18 14:39:06 -08:00
|
|
|
/*
|
2022-01-16 19:22:02 -08:00
|
|
|
//
|
|
|
|
|
// if
|
|
|
|
|
//
|
|
|
|
|
self.register_builtin_fun("if", |machine, _| {
|
|
|
|
|
let if_false = machine.stack_pop()?;
|
|
|
|
|
let if_true = machine.stack_pop()?;
|
|
|
|
|
let condition = machine.stack_pop()?;
|
2022-01-18 14:39:06 -08:00
|
|
|
|
2022-01-16 19:22:02 -08:00
|
|
|
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());
|
|
|
|
|
}
|
|
|
|
|
});
|
2022-01-18 14:39:06 -08:00
|
|
|
*/
|
2022-01-16 19:22:02 -08:00
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// print
|
|
|
|
|
//
|
2022-01-18 14:39:06 -08:00
|
|
|
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::<StrObj>() {
|
|
|
|
|
print!("{}", string.value());
|
|
|
|
|
Ok(BuiltinExit::Return)
|
|
|
|
|
} else {
|
|
|
|
|
panic!(
|
|
|
|
|
"expected StrObj from __str__ function but got {:?} instead",
|
|
|
|
|
str_obj
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
unreachable!()
|
|
|
|
|
}
|
2022-01-16 19:22:02 -08:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
//
|
|
|
|
|
// println
|
|
|
|
|
//
|
2022-01-18 14:39:06 -08:00
|
|
|
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::<StrObj>() {
|
|
|
|
|
println!("{}", string.value());
|
|
|
|
|
Ok(BuiltinExit::Return)
|
|
|
|
|
} else {
|
|
|
|
|
panic!(
|
|
|
|
|
"expected StrObj from __str__ function but got {:?} instead",
|
|
|
|
|
str_obj
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
unreachable!()
|
|
|
|
|
}
|
2022-01-16 19:22:02 -08:00
|
|
|
});
|
|
|
|
|
|
2022-01-18 14:39:06 -08:00
|
|
|
/*
|
2022-01-16 19:22:02 -08:00
|
|
|
//
|
|
|
|
|
// ==
|
|
|
|
|
//
|
|
|
|
|
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)
|
|
|
|
|
});
|
2022-01-18 14:39:06 -08:00
|
|
|
*/
|
2022-01-16 19:22:02 -08:00
|
|
|
}
|
|
|
|
|
}
|