diff --git a/lang/src/ast.asm b/lang/src/ast.asm index f8f98e6..bfca7e3 100644 --- a/lang/src/ast.asm +++ b/lang/src/ast.asm @@ -4,19 +4,20 @@ default rel section .rdata ;; start-consts - AST_FUNCTION equ 1 - AST_BLOCK equ 2 - AST_VARIABLE equ 3 - AST_NUMBER equ 4 - AST_BINARY_OP equ 5 - AST_RETURN_STATEMENT equ 6 - AST_VALUE_TO_PLACE equ 7 - AST_PLACE_TO_VALUE equ 8 - AST_ASSIGNMENT equ 9 - AST_DEREF equ 10 - AST_ADDRESS_OF equ 11 - AST_VAR_DECL equ 12 - AST_VAR_REF equ 13 + AST_FUNCTION equ 1 ; :u8 + AST_BLOCK equ 2 ; :u8 + AST_VARIABLE equ 3 ; :u8 + AST_NUMBER equ 4 ; :u8 + AST_BINARY_OP equ 5 ; :u8 + AST_RETURN_STATEMENT equ 6 ; :u8 + AST_VALUE_TO_PLACE equ 7 ; :u8 + AST_PLACE_TO_VALUE equ 8 ; :u8 + AST_ASSIGNMENT equ 9 ; :u8 + AST_DEREF equ 10 ; :u8 + AST_ADDRESS_OF equ 11 ; :u8 + AST_VAR_DECL equ 12 ; :u8 + AST_VAR_REF equ 13 ; :u8 + AST_ARG equ 14 ; :u8 TYPE_VOID equ 1 TYPE_BOOL equ 2 @@ -77,7 +78,7 @@ global parse_block ;; extra: usize, ;; } ;; -;; struct Argument { +;; struct AstArgument { ;; name: *const u8, ;; name_len: usize, ;; arg_type: Type, @@ -99,7 +100,7 @@ parse_func: ; struct AstFunction { ; name: *const u8, ; name_len: usize, - ; args: *const Argument, + ; args: *const u64, ; args_len: usize, ; return_type: Type, ; body: u64, @@ -172,15 +173,18 @@ parse_func: call panic ;; rdi: *mut Ast -;; define-fn: fn parse_args(ast: *mut Ast) -> (*const Argument, usize) +;; define-fn: fn parse_args(ast: *mut Ast) -> (*const u64, usize) parse_args: push rbp mov rbp, rsp - push rdi - sub rsp, 64 + ; vec: [32..72] + ; argument: [8..32] + ; ast [0..8] + sub rsp, 72 + mov [rsp], rdi ; Ast - lea rdi, [rsp + 24] ; vec - mov rsi, 24 ; size of Argument + lea rdi, [rsp + 32] ; vec + mov rsi, 8 ; size of AstArgument mov rdx, 0 ; drop = None mov rcx, 16 ; capacity call vec_init_with @@ -189,19 +193,39 @@ parse_args: mov dil, TOKEN_RPARENS call expect_token test rax, rax - jz .done_args + jnz .done_args mov dil, TOKEN_IDENT call unwrap_token - mov [rsp], rax ; arg name - mov [rsp + 8], rdx ; arg name length + mov [rsp + 8], rax ; AstArgument.name + mov [rsp + 16], rdx ; AstArgument.name_len mov dil, TOKEN_COLON call unwrap_token - mov rdi, [rsp + 64] ; Ast + mov rdi, [rsp] ; Ast call parse_type - mov [rsp + 16], rax ; arg type + mov [rsp + 24], rax ; AstArgument.arg_type - lea rdi, [rsp + 24] ; vec - lea rsi, [rsp] ; arg + mov rdi, 24 + mov rsi, 8 + call bump_alloc + mov rdi, rax + lea rsi, [rsp + 8] ; &AstArgument + mov rdx, 24 + call memcpy + + mov qword [rsp + 8], AST_ARG ; AstNode.kind + mov [rsp + 16], rdi ; AstNode.data + mov qword [rsp + 24], 0 ; AstNode.extra + + mov rdi, [rsp] ; Ast + lea rsi, [rsp + 8] ; &AstNode + call vec_push + mov rdi, [rsp] ; Ast + mov rax, [rdi + 8] ; Ast.nodes.len() + dec rax + + lea rdi, [rsp + 32] ; vec + mov [rsp + 8], rax ; argument + lea rsi, [rsp + 8] ; &argument call vec_push mov dil, TOKEN_COMMA @@ -213,10 +237,9 @@ parse_args: mov dil, TOKEN_RPARENS call unwrap_token .done_args: - mov rax, [rsp + 24] ; args_ptr - mov rdx, [rsp + 32] ; args_len - add rsp, 64 - pop rdi + mov rax, [rsp + 32] ; args_ptr + mov rdx, [rsp + 40] ; args_len + add rsp, 72 pop rbp ret @@ -280,6 +303,14 @@ parse_primary_expr: sub rsp, 32 mov [rsp], rdi ; Ast + ; start-structs + ; struct AstVarRef { + ; resolved: u64, + ; name: *const u8, + ; name_len: usize, + ; } + ; end-structs + mov dil, TOKEN_NUMBER call expect_token test rax, rax @@ -288,7 +319,35 @@ parse_primary_expr: call expect_token test rax, rax jnz .paren_expr + mov dil, TOKEN_IDENT + call expect_token + test rax, rax + jnz .var_ref jmp .panic +.var_ref: + mov qword [rsp + 8], 0 ; AstVarRef.resolved + mov [rsp + 16], rax ; AstVarRef.name + mov [rsp + 24], rdx ; AstVarRef.name_len + + mov rdi, 24 + mov rsi, 8 + call bump_alloc + mov rdi, rax + lea rsi, [rsp + 8] + mov rdx, 24 + call memcpy + + mov qword [rsp + 8], AST_VAR_REF ; AstNode.kind + mov [rsp + 16], rdi ; AstNode.data + mov qword [rsp + 24], 0 ; AstNode.extra + mov rdi, [rsp] ; Ast + lea rsi, [rsp + 8] ; &AstNode + call vec_push + mov rdi, [rsp] ; Ast + mov rax, [rdi + 8] ; return Ast.nodes.len() + dec rax + mov rdx, 1 ; placeness = true + jmp .epilogue .number: mov rdi, rax ; lexeme ptr mov rsi, rdx ; lexeme len diff --git a/lang/tests/ast.rs b/lang/tests/ast.rs index 5ae1a38..e920bed 100644 --- a/lang/tests/ast.rs +++ b/lang/tests/ast.rs @@ -28,40 +28,71 @@ fn main() { }; } - 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"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); + // }); + + // print_ast(b"fn main() -> void { let x: u32 = 4; }", |ast| unsafe { + // parse_func(ast); + // }); print_ast( - b"fn main() -> void { return (1 + (2 * 3)) / 4; }", + b"fn main(a: u32) -> void { let x: u32 = a + 4; }", |ast| unsafe { parse_func(ast); }, ); - print_ast(b"fn main() -> void { return 1 + 2 * 3; }", |ast| unsafe { - parse_func(ast); - }); - - print_ast(b"fn main() -> void { let x: u32 = 4; }", |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_ADDRESS_OF, AST_ASSIGNMENT, AST_BINARY_OP, AST_BLOCK, AST_DEREF, - AST_FUNCTION, AST_NUMBER, AST_RETURN_STATEMENT, AST_VAR_DECL, AST_VAR_REF, + BinaryExpr, AST_ADDRESS_OF, AST_ARG, AST_ASSIGNMENT, AST_BINARY_OP, AST_BLOCK, + AST_DEREF, AST_FUNCTION, AST_NUMBER, AST_PLACE_TO_VALUE, AST_RETURN_STATEMENT, + AST_VALUE_TO_PLACE, AST_VAR_DECL, AST_VAR_REF, }; - match self.kind as u32 { + match self.kind { AST_NUMBER => { write!(f, "Number({})", self.data as usize) } + AST_ARG => { + let arg = unsafe { self.data.cast::().read() }; + write!( + f, + "Arg(name: {:?}, arg_type: {:?})", + unsafe { + std::str::from_utf8(std::slice::from_raw_parts(arg.name, arg.name_len)) + }, + arg.arg_type, + ) + } + AST_VAR_REF => { + let var_ref = unsafe { self.data.cast::().read() }; + if var_ref.resolved != 0 { + write!(f, "VarRef({})", var_ref.resolved) + } else { + write!(f, "VarRef(name: {:?})", unsafe { + std::str::from_utf8(std::slice::from_raw_parts( + var_ref.name, + var_ref.name_len, + )) + },) + } + } AST_VAR_DECL => { let var_decl = unsafe { self.data.cast::().read() }; write!( @@ -103,10 +134,13 @@ impl std::fmt::Display for AstNode { let func = unsafe { self.data.cast::().read() }; write!( f, - "Function(name: {:?}, return_type: {:?}, body: {})", + "Function(name: {:?}, args: {:?}, return_type: {:?}, body: {})", unsafe { std::str::from_utf8(std::slice::from_raw_parts(func.name, func.name_len)) }, + unsafe { + std::slice::from_raw_parts(func.args.cast::(), func.args_len as usize) + }, func.return_type, func.body ) diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index aec2a0d..d775478 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -3,7 +3,7 @@ unsafe extern "C" { pub unsafe fn parse_func(ast: *mut Ast) -> u64; - pub unsafe fn parse_args(ast: *mut Ast) -> (*const Argument, usize); + pub unsafe fn parse_args(ast: *mut Ast) -> (*const u64, usize); pub unsafe fn parse_primary_expr(ast: *mut Ast) -> (u64, bool); pub unsafe fn parse_binary_expr(ast: *mut Ast, precedence: u8) -> (u64, bool); pub unsafe fn parse_expr(ast: *mut Ast) -> u64; @@ -15,19 +15,20 @@ unsafe extern "C" { pub unsafe fn ast_parse_let(ast: *mut Ast) -> (u64, bool); } -pub const AST_FUNCTION: u32 = 1; -pub const AST_BLOCK: u32 = 2; -pub const AST_VARIABLE: u32 = 3; -pub const AST_NUMBER: u32 = 4; -pub const AST_BINARY_OP: u32 = 5; -pub const AST_RETURN_STATEMENT: u32 = 6; -pub const AST_VALUE_TO_PLACE: u32 = 7; -pub const AST_PLACE_TO_VALUE: u32 = 8; -pub const AST_ASSIGNMENT: u32 = 9; -pub const AST_DEREF: u32 = 10; -pub const AST_ADDRESS_OF: u32 = 11; -pub const AST_VAR_DECL: u32 = 12; -pub const AST_VAR_REF: u32 = 13; +pub const AST_FUNCTION: u8 = 1; +pub const AST_BLOCK: u8 = 2; +pub const AST_VARIABLE: u8 = 3; +pub const AST_NUMBER: u8 = 4; +pub const AST_BINARY_OP: u8 = 5; +pub const AST_RETURN_STATEMENT: u8 = 6; +pub const AST_VALUE_TO_PLACE: u8 = 7; +pub const AST_PLACE_TO_VALUE: u8 = 8; +pub const AST_ASSIGNMENT: u8 = 9; +pub const AST_DEREF: u8 = 10; +pub const AST_ADDRESS_OF: u8 = 11; +pub const AST_VAR_DECL: u8 = 12; +pub const AST_VAR_REF: u8 = 13; +pub const AST_ARG: u8 = 14; pub const TYPE_VOID: u32 = 1; pub const TYPE_BOOL: u32 = 2; pub const TYPE_I32: u32 = 3; @@ -97,7 +98,7 @@ pub struct AstNode { #[repr(C)] #[derive(Debug)] -pub struct Argument { +pub struct AstArgument { pub name: *const u8, pub name_len: usize, pub arg_type: Type, @@ -114,12 +115,20 @@ pub struct Type { pub struct AstFunction { pub name: *const u8, pub name_len: usize, - pub args: *const Argument, + pub args: *const u64, pub args_len: usize, pub return_type: Type, pub body: u64, } +#[repr(C)] +#[derive(Debug)] +pub struct AstVarRef { + pub resolved: u64, + pub name: *const u8, + pub name_len: usize, +} + #[repr(C)] #[derive(Debug)] pub struct BinaryExpr {