from-scratch/lang/tests/ast.rs
2025-10-30 00:22:24 +01:00

110 lines
3.2 KiB
Rust

#[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::<util::defs::BinaryExpr>().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::<util::defs::AstFunction>().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::<u64>(), 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]")
}
}