Add string literals, fix instruction encoding

This commit is contained in:
2026-05-06 14:33:23 +03:00
parent a9a67acdce
commit 43938dee3c
13 changed files with 500 additions and 202 deletions
+164
View File
@@ -0,0 +1,164 @@
use std::slice;
use crate::{
convert::{AnyFunction, TryFromValue},
util::IteratorExt,
vm::{
machine::{Machine, MachineError},
value::{Value, ValueString},
},
};
mod math;
pub(crate) use math::*;
pub fn load(vm: &mut Machine) {
// math
vm.defun_native("+", builtin_add);
vm.defun_native("-", builtin_sub);
vm.defun_native("*", builtin_mul);
vm.defun_native("%", builtin_mod);
vm.defun_native("/", builtin_div);
vm.defun_native("&&", builtin_and);
vm.defun_native("||", builtin_or);
vm.defun_native("&", builtin_bitwise_and);
vm.defun_native("|", builtin_bitwise_or);
vm.defun_native("^", builtin_bitwise_xor);
vm.defun_native(">", builtin_cmp_gt);
vm.defun_native("<", builtin_cmp_lt);
vm.defun_native("=", builtin_cmp_eq);
vm.defun_native("/=", builtin_cmp_ne);
vm.defun_native(">=", builtin_cmp_ge);
vm.defun_native("<=", builtin_cmp_le);
// conversion
vm.defun_native("string->int", |_vm, args| {
let [arg] = args else {
return Err(MachineError::InvalidArgument);
};
let arg = ValueString::try_from_value(arg)?;
let result = arg.parse::<i64>().map(Value::Integer).unwrap_or(Value::Nil);
Ok(result)
});
vm.defun_native("int->string", |_vm, args| {
let [arg] = args else {
return Err(MachineError::InvalidArgument);
};
let arg = i64::try_from_value(arg)?;
let result = Value::String(format!("{arg}").into());
Ok(result)
});
// lists
vm.defun_native("map", |vm, args| {
let [f, xs] = args else {
return Err(MachineError::InvalidArgument);
};
let f = AnyFunction::try_from_value(f)?;
let xs = xs.proper_iter(MachineError::InvalidArgument);
let out = Value::try_list_or_nil(xs.map(|v| f.invoke(vm, slice::from_ref(v?))))?;
Ok(out)
});
vm.defun_native("filter", |vm, args| {
let [f, xs] = args else {
return Err(MachineError::InvalidArgument);
};
let f = AnyFunction::try_from_value(f)?;
let xs = xs
.proper_iter(MachineError::InvalidArgument)
.map(|x| x.cloned());
let out = Value::try_list_or_nil(xs.try_filter(|v| {
let result = f.invoke(vm, slice::from_ref(v))?;
bool::try_from_value(&result)
}))?;
Ok(out)
});
vm.defun_native("list", |_, args| {
let out = Value::list_or_nil(args.iter().cloned());
Ok(out)
});
// functional
vm.defun_native("identity", |_, args| {
let [arg] = args else {
return Err(MachineError::InvalidArgument);
};
Ok(arg.clone())
});
// eval
vm.defun_native("apply", |vm, args| {
let [f, xs] = args else {
return Err(MachineError::InvalidArgument);
};
let f = AnyFunction::try_from_value(f)?;
let args = xs
.proper_iter(MachineError::InvalidArgument)
.map(|x| x.cloned())
.collect::<Result<Vec<_>, _>>()?;
f.invoke(vm, &args[..])
});
vm.defun_native("assert", |vm, args| match args {
[] => Err(MachineError::InvalidArgument),
[cond] => {
let cond = bool::try_from_value(cond)?;
if !cond {
let ip = vm.ip();
if let Some(ip) = ip {
eprintln!("Assertion failed at {ip}:");
eprintln!();
ip.module.dump(Some(ip.address), 8);
}
panic!("Assertion failed");
}
Ok(Value::Nil)
}
_ => todo!(),
});
vm.defun_native("assert-equal", |vm, args| match args {
[] | [_] => Err(MachineError::InvalidArgument),
[a, b] => {
if a != b {
let ip = vm.ip();
if let Some(ip) = ip {
eprintln!("Assertion failed at {ip}:");
eprintln!();
eprintln!(":: {a}{b}");
eprintln!();
ip.module.dump(Some(ip.address), 8);
}
panic!("Assertion failed");
}
Ok(Value::Nil)
}
[a, b, msg] => {
if a != b {
let ip = vm.ip();
if let Some(ip) = ip {
eprintln!("Assertion failed at {ip}: {msg}");
eprintln!();
eprintln!(":: {a}{b}");
eprintln!();
ip.module.dump(Some(ip.address), 8);
}
panic!("Assertion failed");
}
Ok(Value::Nil)
}
_ => todo!(),
});
// io
vm.defun_native("print", |_, args| {
for (i, arg) in args.iter().enumerate() {
if i != 0 {
print!(" ");
}
print!("{arg}");
}
println!();
Ok(Value::Nil)
});
}