use keleusma::Arena;
use keleusma::GenericValue;
use keleusma::compiler::compile_with_target;
use keleusma::lexer::tokenize;
use keleusma::parser::parse;
use keleusma::target::Target;
use keleusma::vm::{DEFAULT_ARENA_CAPACITY, GenericVm, GenericVmState};
type NarrowVm<'a, 'arena> = GenericVm<'a, 'arena, i16, u16, f32>;
fn main() {
println!("=== narrow runtime: Vm<i16, u16, f32> on embedded_16 bytecode ===");
plain_arithmetic();
wrapping_at_word_boundary();
host_function_truncation();
}
fn plain_arithmetic() {
let src = "fn main() -> Word { 1 + 2 }";
let module = {
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
compile_with_target(&program, &Target::embedded_16()).expect("compile")
};
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm: NarrowVm<'_, '_> = NarrowVm::new(module, &arena).expect("verify");
match vm.call(&[]).expect("call") {
GenericVmState::Finished(GenericValue::Int(n)) => {
assert_eq!(n, 3_i16);
println!(" plain: 1 + 2 = {}", n);
}
other => panic!("unexpected: {:?}", other),
}
}
fn wrapping_at_word_boundary() {
let src = "fn main() -> Word { 30000 + 10000 }";
let module = {
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
compile_with_target(&program, &Target::embedded_16()).expect("compile")
};
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm: NarrowVm<'_, '_> = NarrowVm::new(module, &arena).expect("verify");
match vm.call(&[]).expect("call") {
GenericVmState::Finished(GenericValue::Int(n)) => {
assert_eq!(n, -25_536_i16);
println!(" wrap : 30000 + 10000 = {} (wrapped at i16 boundary)", n);
}
other => panic!("unexpected: {:?}", other),
}
}
fn host_function_truncation() {
let src = "use host::triple\nfn main() -> Word { host::triple(7) }";
let module = {
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
compile_with_target(&program, &Target::embedded_16()).expect("compile")
};
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm: NarrowVm<'_, '_> = NarrowVm::new(module, &arena).expect("verify");
vm.register_fn("host::triple", |x: i64| -> i64 { x * 3 });
match vm.call(&[]).expect("call") {
GenericVmState::Finished(GenericValue::Int(n)) => {
assert_eq!(n, 21_i16);
println!(" host: triple(7) = {} (via i64 host closure)", n);
}
other => panic!("unexpected: {:?}", other),
}
}