ast: placeness, assignment, var decl, deref, address-of

This commit is contained in:
janis 2025-10-30 01:41:01 +01:00
parent 4491df79a2
commit 84e87824ba
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
4 changed files with 303 additions and 7 deletions

View file

@ -12,6 +12,11 @@ section .rdata
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
TYPE_VOID equ 1
TYPE_BOOL equ 2
@ -44,6 +49,9 @@ extern expect_token
extern unwrap_token
extern peek_expect_token
extern tokeniser_get_cursor
extern tokeniser_set_cursor
extern str_to_int
global parse_func
@ -342,7 +350,7 @@ parse_binary_expr:
mov byte [rsp + 17], sil ; upper_precedence
mov byte [rsp + 16], 0
call parse_primary_expr
call parse_prefix_expr
mov [rsp + 8], rax ; left
mov [rsp + 19], dl ; left_placeness
@ -404,12 +412,14 @@ parse_binary_expr:
mov dl, [rsp + 19] ; left_placeness
call ast_place_to_value
mov [rsp + 8], rax ; left
mov byte [rsp + 19], 0 ; left_placeness = false
mov rdi, [rsp] ; Ast
mov rsi, [rsp + 24] ; right
mov dl, [rsp + 20] ; right_placeness
call ast_place_to_value
mov [rsp + 24], rax ; right
mov byte [rsp + 20], 0 ; right_placeness = false
mov rdi, 24
mov rsi, 8
@ -431,10 +441,12 @@ parse_binary_expr:
mov rax, [rdi + 8] ; Ast.nodes.len()
dec rax
mov [rsp + 8], rax ; left
mov byte [rsp + 19], 0 ; left_placeness = false
jmp .loop
.done:
mov rax, [rsp + 8] ; left
movzx rdx, byte [rsp + 19] ; left_placeness
add rsp, 64
pop rbp
ret
@ -448,7 +460,7 @@ parse_expr:
sub rsp, 8
mov [rsp], rdi ; Ast
mov sil, 0
call parse_binary_expr
call parse_assignment_expr
add rsp, 8
pop rbp
ret
@ -468,8 +480,18 @@ parse_statement:
call expect_token
test rax, rax
jnz .return
mov dil, TOKEN_LET
call expect_token
test rax, rax
jnz .let
jmp .panic
.let:
mov rdi, [rsp + 24] ; Ast
call ast_parse_let
mov [rsp], rax ; statement
jmp .semi
.return:
mov rdi, [rsp + 24] ; Ast
call parse_expr
@ -484,6 +506,7 @@ parse_statement:
dec rax
mov [rsp], rax
.semi:
mov dil, TOKEN_SEMI
call unwrap_token
mov rax, [rsp] ; expression
@ -583,6 +606,213 @@ parse_type:
.panic:
call panic
;; rdi: *mut Ast
;; define-fn: fn parse_prefix_expr(ast: *mut Ast) -> (u64, bool)
parse_prefix_expr:
push rbp
mov rbp, rsp
; ast [0..8]
sub rsp, 32
mov [rsp], rdi ; Ast
mov dil, TOKEN_STAR
call expect_token
test rax, rax
jnz .dereference
mov dil, TOKEN_AMP
call expect_token
test rax, rax
jnz .address_of
mov rdi, [rsp] ; Ast
call parse_primary_expr
jmp .done
.dereference:
mov rdi, [rsp] ; Ast
call parse_prefix_expr
mov qword [rsp + 8], AST_DEREF ; AstNode.kind
mov [rsp + 16], rax ; 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
mov rdx, 1 ; placeness = true
jmp .done
.address_of:
; address-of must be applied to a place
; so we convert the inner expression to a place first
mov rdi, [rsp] ; Ast
call parse_prefix_expr
mov rdi, [rsp] ; Ast
mov rsi, rax ; expr
; mov rdx, rdx ; placeness
call ast_value_to_place
mov qword [rsp + 8], AST_ADDRESS_OF ; AstNode.kind
mov [rsp + 16], rax ; 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
xor rdx, rdx ; placeness = false
jmp .done
.done:
add rsp, 32
pop rbp
ret
;; rdi: *mut Ast
;; define-fn: fn parse_assignment(ast: *mut Ast) -> (u64, bool)
parse_assignment_expr:
push rbp
mov rbp, rsp
; source [24..32]
; dest [16..24]
; dest_placeness [8..9]
; ast [0..8]
sub rsp, 32
mov [rsp], rdi ; Ast
mov rdi, [rsp] ; Ast
call parse_binary_expr
mov [rsp + 16], rax ; dest
mov [rsp + 8], dl ; placeness
mov dil, TOKEN_EQUALS
call expect_token
test rax, rax
jnz .assignment
jmp .done
.assignment:
mov rdi, [rsp] ; Ast
mov rsi, [rsp + 16] ; dest
movzx rdx, byte [rsp + 8] ; placeness
call ast_value_to_place
mov [rsp + 16], rax ; source
mov rdi, [rsp] ; Ast
call parse_expr
mov rdi, [rsp] ; Ast
mov rsi, rax ; expr
; mov rdx, rdx ; placeness
call ast_place_to_value
mov [rsp + 24], rax ; source
mov qword [rsp + 8], AST_ASSIGNMENT ; AstNode.kind
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
mov [rsp + 16], rax ; dest
mov byte [rsp + 8], 0 ; placeness = false
.done:
mov rax, [rsp + 16] ; dest
movzx rdx, byte [rsp + 8] ; placeness
add rsp, 32
pop rbp
ret
;; rdi: *mut Ast
;; define-fn: fn ast_parse_let(ast: *mut Ast) -> (u64, bool)
ast_parse_let:
push rbp
mov rbp, rsp
; start-structs
; struct AstVarDecl {
; name: *const u8,
; name_len: usize,
; var_type: Type,
; }
;
; struct AstAssignment {
; variable: u64,
; expr: u64,
; }
; end-structs
sub rsp, 64
mov [rsp], rdi ; Ast
; skipped in parse_statement
; mov dil, TOKEN_LET
; call unwrap_token
mov dil, TOKEN_IDENT
call unwrap_token
mov [rsp + 8], rax ; variable name
mov [rsp + 16], rdx ; variable name length
mov dil, TOKEN_COLON
call unwrap_token
mov rdi, [rsp] ; Ast
call parse_type
mov [rsp + 24], rax ; variable type
mov rdi, 24
mov rsi, 8
call bump_alloc
mov rdi, rax ; AstVariable ptr
lea rsi, [rsp + 8] ; &AstVariable
mov rdx, 24
call memcpy
mov qword [rsp + 32], AST_VAR_DECL ; AstNode.kind
mov [rsp + 40], rdi ; AstNode.data
mov qword [rsp + 48], 0 ; AstNode.extra
mov rdi, [rsp] ; Ast
lea rsi, [rsp + 32] ; &AstNode
call vec_push
; variable is already a place
mov rdi, [rsp] ; Ast
mov rax, [rdi + 8] ; Ast.nodes.len()
dec rax
mov qword [rsp + 32], AST_ASSIGNMENT ; AstNode.kind
mov [rsp + 40], rax ; AstNode.data (variable index)
mov dil, TOKEN_EQUALS
call unwrap_token
mov rdi, [rsp] ; Ast
call parse_expr
mov rdi, [rsp] ; Ast
mov rsi, rax ; expr
; mov rdx, rdx ; is_placeness
call ast_place_to_value
mov [rsp + 48], rax ; AstNode.extra (expr index)
mov rdi, [rsp] ; Ast
lea rsi, [rsp + 32] ; &AstNode
call vec_push
mov rdi, [rsp] ; Ast
mov rax, [rdi + 8] ; Ast.nodes.len()
dec rax
add rsp, 64
xor rdx, rdx ; placeness = false
pop rbp
ret
;; rdi: *mut Ast
;; rsi: index of node
;; rdx: is_placeness
@ -591,8 +821,8 @@ ast_value_to_place:
push rbp
mov rbp, rsp
cmp dl, 0
xor rax, rax
cmp dl, 1
mov rax, rsi
je .done
; create new AST node
sub rsp, 32
@ -618,8 +848,8 @@ ast_place_to_value:
push rbp
mov rbp, rsp
cmp dl, 1
xor rax, rax
cmp dl, 0
mov rax, rsi
je .done
; create new AST node
sub rsp, 32

View file

@ -27,6 +27,9 @@ global unwrap_token
global peek_expect_token
global peek_lexeme
global tokeniser_get_cursor
global tokeniser_set_cursor
;; =============================
;; Tokeniser functions
;; =============================
@ -583,3 +586,11 @@ peek_lexeme:
pop rax
pop rbp
ret
tokeniser_get_cursor:
mov rax, [rel cursor]
ret
tokeniser_set_cursor:
mov [rel cursor], rdi
ret

View file

@ -46,17 +46,43 @@ fn main() {
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_BINARY_OP, AST_BLOCK, AST_FUNCTION, AST_NUMBER, AST_RETURN_STATEMENT,
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,
};
match self.kind as u32 {
AST_NUMBER => {
write!(f, "Number({})", self.data as usize)
}
AST_VAR_DECL => {
let var_decl = unsafe { self.data.cast::<util::defs::AstVarDecl>().read() };
write!(
f,
"VarDecl(name: {:?}, var_type: {:?})",
unsafe {
std::str::from_utf8(std::slice::from_raw_parts(
var_decl.name,
var_decl.name_len,
))
},
var_decl.var_type,
)
}
AST_ASSIGNMENT => {
write!(
f,
"Assignment(dest: {}, src: {})",
self.data as usize, self.extra
)
}
AST_BINARY_OP => {
let BinaryExpr {
left,
@ -90,6 +116,12 @@ impl std::fmt::Display for AstNode {
std::slice::from_raw_parts(self.data.cast::<u64>(), self.extra as usize)
})
}
AST_PLACE_TO_VALUE => {
write!(f, "PlaceToValue(place: {})", self.data as usize)
}
AST_VALUE_TO_PLACE => {
write!(f, "ValueToPlace(value: {})", self.data as usize)
}
_ => write!(f, "UnknownNode"),
}
}

View file

@ -10,6 +10,9 @@ unsafe extern "C" {
pub unsafe fn parse_statement(ast: *mut Ast) -> u64;
pub unsafe fn parse_block(ast: *mut Ast) -> u64;
pub unsafe fn parse_type(ast: *mut Ast) -> Type;
pub unsafe fn parse_prefix_expr(ast: *mut Ast) -> (u64, bool);
pub unsafe fn parse_assignment(ast: *mut Ast) -> (u64, bool);
pub unsafe fn ast_parse_let(ast: *mut Ast) -> (u64, bool);
}
pub const AST_FUNCTION: u32 = 1;
@ -20,6 +23,11 @@ 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 TYPE_VOID: u32 = 1;
pub const TYPE_BOOL: u32 = 2;
pub const TYPE_I32: u32 = 3;
@ -120,4 +128,19 @@ pub struct BinaryExpr {
pub right: u64,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstVarDecl {
pub name: *const u8,
pub name_len: usize,
pub var_type: Type,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstAssignment {
pub variable: u64,
pub expr: u64,
}
use super::vec::Vec;