Add vm::builtins mod as a place for builtin functions to live
Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
83
src/vm/builtins.rs
Normal file
83
src/vm/builtins.rs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
use crate::object::{BuiltinExit, Int, Value};
|
||||||
|
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, _| {
|
||||||
|
let value = machine.stack_pop()?;
|
||||||
|
print!("{}", value);
|
||||||
|
Ok(BuiltinExit::Return)
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// println
|
||||||
|
//
|
||||||
|
self.register_builtin_fun("println", |machine, _| {
|
||||||
|
let value = machine.stack_pop()?;
|
||||||
|
println!("{}", value);
|
||||||
|
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)
|
||||||
|
});
|
||||||
|
|
||||||
|
//
|
||||||
|
// ~=
|
||||||
|
//
|
||||||
|
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)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -318,10 +318,10 @@ impl Machine {
|
|||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct MachineBuilder {
|
pub struct MachineBuilder {
|
||||||
globals: BTreeMap<Word, Value>,
|
pub(super) globals: BTreeMap<Word, Value>,
|
||||||
scope_stack: ScopeStack,
|
pub(super) scope_stack: ScopeStack,
|
||||||
max_stack_size: Option<usize>,
|
pub(super) max_stack_size: Option<usize>,
|
||||||
max_arena_objects: Option<usize>,
|
pub(super) max_arena_objects: Option<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MachineBuilder {
|
impl MachineBuilder {
|
||||||
@@ -335,53 +335,7 @@ impl MachineBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Registers all builtins for calling on the machine.
|
pub(super) fn register_builtin_fun(
|
||||||
fn register_builtins(&mut self) {
|
|
||||||
self.scope_stack.push_scope();
|
|
||||||
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!();
|
|
||||||
});
|
|
||||||
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
self.register_builtin_fun("print", |machine, _| {
|
|
||||||
let value = machine.stack_pop()?;
|
|
||||||
print!("{}", value);
|
|
||||||
Ok(BuiltinExit::Return)
|
|
||||||
});
|
|
||||||
|
|
||||||
self.register_builtin_fun("println", |machine, _| {
|
|
||||||
let value = machine.stack_pop()?;
|
|
||||||
println!("{}", value);
|
|
||||||
Ok(BuiltinExit::Return)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_builtin_fun(
|
|
||||||
&mut self,
|
&mut self,
|
||||||
name: &str,
|
name: &str,
|
||||||
fun: fn(&mut Machine, usize) -> Result<BuiltinExit>,
|
fun: fn(&mut Machine, usize) -> Result<BuiltinExit>,
|
||||||
@@ -392,7 +346,7 @@ impl MachineBuilder {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_global(&mut self, name: &str, value: Value) {
|
pub(super) fn register_global(&mut self, name: &str, value: Value) {
|
||||||
let word = self.scope_stack.insert_local(name);
|
let word = self.scope_stack.insert_local(name);
|
||||||
self.globals.insert(word, value);
|
self.globals.insert(word, value);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
mod builtins;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod inst;
|
pub mod inst;
|
||||||
pub mod machine;
|
pub mod machine;
|
||||||
|
|||||||
Reference in New Issue
Block a user