#[path = "shared/shared.rs"] mod util; unsafe extern "C" { unsafe fn bump_init(); unsafe fn tokeniser_init_buf(bytes: *const u8, len: usize) -> (); } use util::defs::{parse_expr, parse_func, Ast, AstNode}; fn main() { unsafe { bump_init(); } println!("Bump allocator initialized."); let src = b"3 + 4"; fn print_ast(src: &[u8], parser: impl FnOnce(&mut Ast)) { unsafe { tokeniser_init_buf(src.as_ptr(), src.len()); let mut ast = Ast { nodes: util::vec::Vec::new(), }; let expr_id = parser(&mut ast); println!("{:#}", &ast); }; } print_ast(b"3 + 4", |ast| unsafe { parse_expr(ast); }); print_ast(b"fn main() -> void { return 1 + 2; }", |ast| unsafe { parse_func(ast); }); print_ast(b"fn main() -> void { return (1 + (2)); }", |ast| unsafe { parse_func(ast); }); print_ast( b"fn main() -> void { return (1 + (2 * 3)) / 4; }", |ast| unsafe { parse_func(ast); }, ); print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe { parse_func(ast); }); } impl std::fmt::Display for AstNode { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use util::defs::{ BinaryExpr, AST_BINARY_OP, AST_BLOCK, AST_FUNCTION, AST_NUMBER, AST_RETURN_STATEMENT, }; match self.kind as u32 { AST_NUMBER => { write!(f, "Number({})", self.data as usize) } AST_BINARY_OP => { let BinaryExpr { left, operator, right, } = unsafe { self.data.cast::().read() }; write!( f, "BinaryOp(op: {}, left: {}, right: {})", operator, left, right ) } AST_RETURN_STATEMENT => { let return_expr_id = self.data as usize; write!(f, "ReturnStatement(expr: {})", return_expr_id) } AST_FUNCTION => { let func = unsafe { self.data.cast::().read() }; write!( f, "Function(name: {:?}, return_type: {:?}, body: {})", unsafe { std::str::from_utf8(std::slice::from_raw_parts(func.name, func.name_len)) }, func.return_type, func.body ) } AST_BLOCK => { write!(f, "Block(statements: {:?})", unsafe { std::slice::from_raw_parts(self.data.cast::(), self.extra as usize) }) } _ => write!(f, "UnknownNode"), } } } impl core::fmt::Display for Ast { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { writeln!(f, "[")?; for (i, item) in self.nodes.as_slice().iter().enumerate() { if i > 0 { writeln!(f, ", ")?; } write!(f, "\t{i}: {}", item)?; } writeln!(f, "\n]") } }