args, var-ref

This commit is contained in:
janis 2025-10-30 13:48:08 +01:00
parent 84e87824ba
commit e54313b6a2
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 170 additions and 68 deletions

View file

@ -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

View file

@ -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::<util::defs::AstArgument>().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::<util::defs::AstVarRef>().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::<util::defs::AstVarDecl>().read() };
write!(
@ -103,10 +134,13 @@ impl std::fmt::Display for AstNode {
let func = unsafe { self.data.cast::<util::defs::AstFunction>().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::<u64>(), func.args_len as usize)
},
func.return_type,
func.body
)

View file

@ -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 {