ast: placeness, assignment, var decl, deref, address-of
This commit is contained in:
parent
4491df79a2
commit
84e87824ba
242
lang/src/ast.asm
242
lang/src/ast.asm
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in a new issue