Skip to main content

struct_method_dispatch/
struct_method_dispatch.rs

1//! End-to-end demonstration of method dispatch on a generic struct
2//! field. `c.value.double()` where `c: Cell<i64>` and the struct's
3//! field type is the generic parameter `T`.
4//!
5//! Without struct monomorphization, `c.value` would have an opaque
6//! type and the method dispatch on `.double()` would fail. The
7//! generic struct specialization pass clones `Cell` to `Cell__i64`
8//! with the field type substituted, so `c.value` resolves to `i64`
9//! and the trait method dispatches to `Doubler::i64::double`.
10//!
11//! Run with: `cargo run --example struct_method_dispatch`
12
13use keleusma::compiler::compile;
14use keleusma::lexer::tokenize;
15use keleusma::parser::parse;
16use keleusma::vm::{DEFAULT_ARENA_CAPACITY, Vm, VmState};
17use keleusma::{Arena, Value};
18
19fn main() {
20    let src = r#"
21        trait Doubler { fn double(x: i64) -> i64; }
22        impl Doubler for i64 { fn double(x: i64) -> i64 { x + x } }
23        struct Cell<T> { value: T }
24        fn main() -> i64 {
25            let c = Cell { value: 21 };
26            c.value.double()
27        }
28    "#;
29    let tokens = tokenize(src).expect("lex");
30    let program = parse(&tokens).expect("parse");
31    let module = compile(&program).expect("compile");
32    let arena = Arena::with_capacity(DEFAULT_ARENA_CAPACITY);
33    let mut vm = Vm::new(module, &arena).expect("verify");
34    match vm.call(&[]) {
35        Ok(VmState::Finished(Value::Int(n))) => {
36            println!("Cell {{ value: 21 }}.value.double() = {}", n);
37            assert_eq!(n, 42);
38            println!("generic struct method dispatch executed end to end");
39        }
40        other => panic!("unexpected: {:?}", other),
41    }
42}