#![feature(offset_of_enum)]
use nearest::{Flat, Near, Region, near};
#[derive(Flat, Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u8)]
enum Op {
Add,
Sub,
Mul,
}
#[derive(Flat, Debug)]
#[repr(C, u8)]
#[expect(dead_code, reason = "variants constructed via emitters")]
enum Expr {
Lit(i64),
Bin { op: Op, lhs: Near<Expr>, rhs: Near<Expr> },
}
fn eval(expr: &Expr) -> i64 {
match expr {
Expr::Lit(n) => *n,
Expr::Bin { op, lhs, rhs } => {
let l = eval(lhs);
let r = eval(rhs);
match op {
Op::Add => l + r,
Op::Sub => l - r,
Op::Mul => l * r,
}
}
}
}
fn pretty(expr: &Expr) -> String {
match expr {
Expr::Lit(n) => n.to_string(),
Expr::Bin { op, lhs, rhs } => {
let sym = match op {
Op::Add => "+",
Op::Sub => "-",
Op::Mul => "*",
};
format!("({} {} {})", pretty(lhs), sym, pretty(rhs))
}
}
}
fn main() {
let region = Region::new(Expr::make_bin(
Op::Mul,
near(Expr::make_bin(Op::Add, near(Expr::make_lit(2)), near(Expr::make_lit(3)))),
near(Expr::make_bin(Op::Sub, near(Expr::make_lit(10)), near(Expr::make_lit(4)))),
));
println!("expr: {}", pretty(®ion));
println!("value: {}", eval(®ion));
assert_eq!(eval(®ion), 30);
let mut cloned = region.clone();
assert_eq!(eval(&cloned), eval(®ion));
println!("\nclone matches: {}", eval(&cloned) == eval(®ion));
cloned.session(|s| {
let rhs_of_sub = s.nav(s.root(), |e| match e {
Expr::Bin { rhs, .. } => match &**rhs {
Expr::Bin { rhs: inner_rhs, .. } => inner_rhs,
Expr::Lit(_) => panic!("expected Bin"),
},
Expr::Lit(_) => panic!("expected Bin"),
});
s.splice(rhs_of_sub, Expr::make_lit(1));
});
println!("\nmutated: {}", pretty(&cloned));
println!("value: {}", eval(&cloned));
assert_eq!(eval(&cloned), 45);
let before = cloned.byte_len();
cloned.trim();
println!("\ntrim: {} -> {} bytes", before, cloned.byte_len());
assert_eq!(eval(&cloned), 45);
}