#![cfg(all(feature = "compile", feature = "verify"))]
extern crate alloc;
use alloc::string::String;
use alloc::sync::Arc;
use keleusma::compiler::compile;
use keleusma::lexer::tokenize;
use keleusma::parser::parse;
use keleusma::vm::{DEFAULT_ARENA_CAPACITY, Vm, VmState};
use keleusma::{Arena, HostOpaque, KeleusmaType, Value, host_arc};
#[derive(KeleusmaType)]
struct Greeting {
msg: String,
n: i64,
}
#[test]
fn decode_flat_struct_with_text_field() {
let src = "struct Greeting { msg: Text, n: Word }\n\
fn main() -> Greeting { Greeting { msg: \"hi\", n: 5 } }";
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
let module = compile(&program).expect("compile");
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm = Vm::new(module, &arena).expect("verify");
let val = match vm.call(&[]).expect("call") {
VmState::Finished(v) => v,
other => panic!("expected finished, got {:?}", other),
};
let g: Greeting = vm.decode(&val).expect("decode");
assert_eq!(g.msg, "hi");
assert_eq!(g.n, 5);
}
struct Handle {
label: String,
}
impl HostOpaque for Handle {
fn type_name(&self) -> &'static str {
"Handle"
}
}
#[derive(KeleusmaType)]
struct Carrier {
h: Arc<dyn HostOpaque>,
n: i64,
}
#[test]
fn decode_flat_struct_with_opaque_field() {
let src = "use make_handle\n\
struct Carrier { h: Handle, n: Word }\n\
fn main() -> Carrier { Carrier { h: make_handle(), n: 9 } }";
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
let module = compile(&program).expect("compile");
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm = Vm::new(module, &arena).expect("verify");
vm.register_native("make_handle", |_args| {
Ok(Value::Opaque(host_arc(Handle {
label: "decoded".into(),
})))
});
let val = match vm.call(&[]).expect("call") {
VmState::Finished(v) => v,
other => panic!("expected finished, got {:?}", other),
};
let c: Carrier = vm.decode(&val).expect("decode");
assert_eq!(c.n, 9);
let typed: &Handle = c.h.as_ref().downcast_ref::<Handle>().expect("downcast");
assert_eq!(typed.label, "decoded");
}
#[derive(KeleusmaType, PartialEq, Debug)]
struct Pair {
a: i64,
b: i64,
}
#[test]
fn decode_arena_resident_flat_struct() {
use keleusma::bytecode::{GenericValue, StructBody};
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let v = Value::struct_value(
"Pair".into(),
vec![
("a".into(), GenericValue::Int(3)),
("b".into(), GenericValue::Int(4)),
],
);
let v = v
.into_arena_canonical(8, 8, &arena)
.expect("canonicalise into arena");
assert!(
matches!(&v, GenericValue::Struct(StructBody::Flat(_))),
"expected a flat struct body"
);
let ctx = keleusma::RefContext {
arena: &arena,
opaques: &[],
word_bytes: 8,
float_bytes: 8,
ref_epoch: arena.epoch(),
};
let p = Pair::from_value_ctx(&v, &ctx).expect("decode arena-resident flat struct");
assert_eq!(p, Pair { a: 3, b: 4 });
}
#[test]
fn native_receives_struct_with_text_field() {
let src = "use greet_len\n\
struct Greeting { msg: Text, n: Word }\n\
fn main() -> Word { greet_len(Greeting { msg: \"hello\", n: 2 }) }";
let tokens = tokenize(src).expect("lex");
let program = parse(&tokens).expect("parse");
let module = compile(&program).expect("compile");
let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
let mut vm = Vm::new(module, &arena).expect("verify");
vm.register_fn("greet_len", |g: Greeting| -> i64 {
g.msg.len() as i64 + g.n
});
match vm.call(&[]).expect("call") {
VmState::Finished(Value::Int(n)) => assert_eq!(n, 7),
other => panic!("expected Int(7), got {:?}", other),
}
}