Compare commits

...

2 commits

Author SHA1 Message Date
janis a90a01bc28
more comparison operators 2025-11-03 20:32:23 +01:00
janis 0e25f627a8
can codegen if/else 2025-11-03 20:07:51 +01:00
8 changed files with 636 additions and 70 deletions

View file

@ -4,11 +4,16 @@ default rel
%include "src/ast.inc"
section .rdata
PRECEDENCE_PIPE2 dw 10
PRECEDENCE_AMP2 dw 20
PRECEDENCE_PIPE dw 30
PRECEDENCE_CARET dw 40
PRECEDENCE_AMP dw 50
PRECEDENCE_EQ dw 60
PRECEDENCE_CMP dw 70
PRECEDENCE_SHIFT dw 80
PRECEDENCE_ADD dw 90
PRECEDENCE_SUB dw 90
PRECEDENCE_MUL dw 100
PRECEDENCE_DIV dw 100
PRECEDENCE_REM dw 100
section .text
extern vec_init_with
@ -42,6 +47,7 @@ global parse_args
global parse_expr
global parse_binary_expr
global parse_primary_expr
global parse_if_expr
global parse_statement
global parse_block
global ast_build_symtable
@ -446,11 +452,23 @@ parse_binary_expr:
cmp al, TOKEN_PLUS
cmove bx, word [rel PRECEDENCE_ADD]
cmp al, TOKEN_MINUS
cmove bx, word [rel PRECEDENCE_SUB]
cmove bx, word [rel PRECEDENCE_ADD]
cmp al, TOKEN_STAR
cmove bx, word [rel PRECEDENCE_MUL]
cmp al, TOKEN_SLASH
cmove bx, word [rel PRECEDENCE_DIV]
cmove bx, word [rel PRECEDENCE_MUL]
cmp al, TOKEN_EQEQ
cmove bx, word [rel PRECEDENCE_EQ]
cmp al, TOKEN_BANGEQ
cmove bx, word [rel PRECEDENCE_EQ]
cmp al, TOKEN_LT
cmove bx, word [rel PRECEDENCE_CMP]
cmp al, TOKEN_LTEQ
cmove bx, word [rel PRECEDENCE_CMP]
cmp al, TOKEN_GT
cmove bx, word [rel PRECEDENCE_CMP]
cmp al, TOKEN_GTEQ
cmove bx, word [rel PRECEDENCE_CMP]
cmp bx, -1
je .done
mov byte [rsp + 18], bl
@ -557,10 +575,20 @@ parse_statement:
call peek_expect_token ; parse_block expects lbrace to still be there
test rax, rax
jnz .block
mov dil, TOKEN_IF
call peek_expect_token
test rax, rax
jnz .if_expr
mov rdi, [rsp] ; Ast
call parse_expr
jmp .epilogue
.if_expr:
mov rdi, [rsp] ; Ast
call ast_parse_if_expr
; If expressions don't require a trailing semicolon
jmp .epilogue
.block:
mov rdi, [rsp] ; Ast
call parse_block
@ -576,6 +604,12 @@ parse_statement:
.return:
mov rdi, [rsp] ; Ast
call parse_expr
; return expression requires a value
mov rdi, [rsp] ; Ast
mov rsi, rax ; expr
call ast_place_to_value
mov byte [rsp + 8], AST_RETURN_STATEMENT ; AstNode.kind
mov [rsp + 16], rax ; AstNode.data
mov qword [rsp + 24], 0 ; AstNode.extra
@ -859,6 +893,116 @@ parse_assignment_expr:
pop rbp
ret
;; rdi: *mut Ast
;; define-fn: fn ast_parse_switch_expr(ast: *mut Ast) -> (u64, bool)
ast_parse_switch_expr:
push rbp
mov rbp, rsp
; start-structs
; struct AstSwitch {
; expr: u64,
; cases: *const u64,
; cases_len: usize,
; }
;
; struct AstSwitchCase {
; pattern: u64,
; expr: u64,
; }
; end-structs
pop rbp
ret
;; rdi: *mut Ast
;; define-fn: fn ast_parse_if_expr(ast: *mut Ast) -> (u64, bool)
ast_parse_if_expr:
push rbp
mov rbp, rsp
; start-structs
; struct AstIfExpr {
; condition: u64,
; then: u64,
; else_: u64,
; }
; end-structs
; ast [0..8]
sub rsp, 40
mov [rsp], rdi ; Ast
call tokeniser_get_cursor
mov [rsp + 32], rax ; span
mov dil, TOKEN_IF
call unwrap_token
mov dil, TOKEN_LPARENS
call unwrap_token
mov rdi, [rsp] ; Ast
call parse_expr
mov [rsp + 8], rax ; condition
mov dil, TOKEN_RPARENS
call unwrap_token
mov rdi, [rsp] ; Ast
call parse_block
mov [rsp + 16], rax ; then
mov dil, TOKEN_ELSE
call expect_token
test rax, rax
jz .no_else
mov dil, TOKEN_IF
call peek_expect_token
test rax, rax
jnz .else_if
mov rdi, [rsp] ; Ast
call parse_block
mov [rsp + 24], rax ; else
jmp .after_else
.else_if:
mov rdi, [rsp] ; Ast
call ast_parse_if_expr
mov [rsp + 24], rax ; else
jmp .after_else
.no_else:
mov qword [rsp + 24], -1 ; else = None
.after_else:
mov rdi, 24 ; size_of::<AstIfExpr>
mov rsi, 8 ; align_of::<AstIfExpr>
call bump_alloc
mov rdi, rax ; AstIfExpr ptr
lea rsi, [rsp + 8] ; &AstIfExpr
mov rdx, 24 ; size_of::<AstIfExpr>
call memcpy
mov qword [rsp + 8], AST_IF ; 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
add rsp, 40
pop rbp
ret
;; rdi: *mut Ast
;; define-fn: fn ast_parse_let(ast: *mut Ast) -> (u64, bool)
ast_parse_let:
@ -1441,6 +1585,8 @@ ast_walk_for_each:
je .address_of
cmp bl, AST_RETURN_STATEMENT
je .return_statement
cmp bl, AST_IF
je .if_expr
jmp .check_scope
.func:
@ -1496,6 +1642,19 @@ ast_walk_for_each:
push rdx ; push left index
jmp .check_scope
.if_expr:
mov rbx, [rax + 8] ; AstNode.data
mov rdx, [rbx + 16] ; else index
cmp rdx, -1
je .no_else
push rdx ; push else index
.no_else:
mov rdx, [rbx + 8] ; then index
push rdx ; push then index
mov rdx, [rbx + 0] ; condition index
push rdx ; push condition index
jmp .check_scope
.assignment:
mov rbx, [rax + 8] ; AstNode.data = dest
mov rdx, [rax + 16] ; AstNode.extra = source

View file

@ -14,6 +14,10 @@ section .rdata
AST_VAR_DECL equ 12 ; :u8
AST_VAR_REF equ 13 ; :u8
AST_ARG equ 14 ; :u8
AST_SWITCH equ 15 ; :u8
AST_IF equ 16 ; :u8
AST_ELSE equ 17 ; :u8
AST_CALL equ 18 ; :u8
TYPE_VOID equ 1 ; :u8
TYPE_BOOL equ 2 ; :u8
@ -21,4 +25,4 @@ section .rdata
TYPE_U32 equ 4 ; :u8
TYPE_STR equ 5 ; :u8
TYPE_POINTER equ 6 ; :u8
;; end-consts
;; end-consts

View file

@ -1020,8 +1020,210 @@ codegen_expr:
je .deref
cmp bl, AST_ADDRESS_OF
je .address_of
cmp bl, AST_IF
je .if_expr
jmp .panic
.if_expr:
mov rbx, [rax + 8] ; AstNode.data = *AstIfExpr
mov [rsp + 16], rax ; scratch = AstNode
mov rdx, [rbx] ; AstIfExpr.cond
mov rdi, [rsp] ; ctx
mov rsi, [rsp + 8] ; &function_ctx
call codegen_expr
mov [rsp + 24], rax ; cond operand
mov [rsp + 32], rdx
; cmp cond, 0
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 24] ; left = cond
lea rdx, [rel OPERAND_ZERO] ; right = 0
mov rcx, 'cmp '
call codegen_binary_op_unchecked
; free cond
mov rdi, [rsp + 8] ; &function_ctx
lea rsi, [rsp + 24] ; cond operand
call codegen_free_operand
; je .branch_{else_}
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel JE_B]
mov rdx, JE_B_len
call vec_extend
mov rdi, [rbx + 16] ; AstIfExpr.else
lea rsi, [rsp + 24] ; scratch
mov rdx, 30
mov rcx, 16
call int_to_str2
mov byte [rax + rdx], 10
inc rdx
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
mov rsi, rax
call vec_extend
; codegen then branch
mov rdx, [rbx + 8] ; AstIfExpr.then
mov rdi, [rsp] ; ctx
mov rsi, [rsp + 8] ; &function_ctx
call codegen_expr
mov [rsp + 24], rax ; then
mov [rsp + 32], rdx
cmp rax, 0
je .if_skip_phi
; mov rax, then
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel OPERAND_RAX]
lea rdx, [rsp + 24] ; src
call codegen_move_dst_src
; free then
mov rdi, [rsp + 8] ; &function_ctx
lea rsi, [rsp + 24] ; then operand
call codegen_free_operand
.if_skip_phi:
; jmp .branch_{if}
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel JMP_PHI]
mov rdx, JMP_PHI_len
call vec_extend
mov rdi, [rbx + 0] ; AstIfExpr.cond
lea rsi, [rsp + 24] ; scratch
mov rdx, 30
mov rcx, 16
call int_to_str2
mov byte [rax + rdx], 10
inc rdx
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
mov rsi, rax
call vec_extend
; .branch_{else_}:
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel JE_B]
add rsi, 3
mov rdx, 2
call vec_extend
mov rdi, [rbx + 16] ; AstIfExpr.else
lea rsi, [rsp + 24] ; scratch
mov rdx, 30
mov rcx, 16
call int_to_str2
mov byte [rax + rdx], ':'
inc rdx
mov byte [rax + rdx], 10
inc rdx
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
mov rsi, rax
call vec_extend
; codegen else branch
mov rdx, [rbx + 16] ; AstIfExpr.else
mov rdi, [rsp] ; ctx
mov rsi, [rsp + 8] ; &function_ctx
call codegen_expr
mov [rsp + 24], rax ; else
mov [rsp + 32], rdx
cmp rax, 0
je .if_skip_phi2
; mov rax, else
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel OPERAND_RAX]
lea rdx, [rsp + 24] ; src
call codegen_move_dst_src
; free else
mov rdi, [rsp + 8] ; &function_ctx
lea rsi, [rsp + 24] ; else operand
call codegen_free_operand
.if_skip_phi2:
; .branch_{if}
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rel JMP_PHI]
add rsi, 4
mov rdx, 4
call vec_extend
mov rdi, [rbx + 0] ; AstIfExpr.cond
lea rsi, [rsp + 32] ; scratch
mov rdx, 30
mov rcx, 16
call int_to_str2
mov byte [rax + rdx], ':'
inc rdx
mov byte [rax + rdx], 10
inc rdx
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
mov rsi, rax
call vec_extend
mov rax, qword [rsp + 24]
cmp rax, 0
je .if_no_value
; dst = allocate_value
mov rdi, [rsp + 8] ; &function_ctx
mov rsi, 8 ; width
call codegen_allocate_value
mov [rsp + 40], rax
mov [rsp + 48], rdx
cmp byte [rsp + 24], OPERAND_LAST_VALUE
ja .if_phi_place
; preserve width of then/else value
mov ax, word [rsp + 24 + 2] ; Operand.width
mov word [rsp + 40 + 2], ax
jmp .if_value
.if_phi_place:
; turn dst into it's place equivalent
cmp byte [rsp + 40], OPERAND_REGISTER
cmove ax, word [rel OPERAND_REGISTER_PLACE]
cmp byte [rsp + 40], OPERAND_RBP_VALUE
cmove ax, word [rel OPERAND_RBP_PLACE]
mov byte [rsp + 40], al
.if_value:
; mov dst, rax
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 40] ; dst
lea rdx, [rel OPERAND_RAX] ; rax (phi)
call codegen_move_dst_src
mov rax, [rsp + 40]
mov rdx, [rsp + 48]
jmp .done
.if_no_value:
xor rax, rax
xor rdx, rdx
jmp .done
.block:
mov rbx, [rax + 8] ; AstNode.data
mov r15, [rax + 16] ; AstNode.extra
@ -1154,6 +1356,10 @@ codegen_expr:
cmove rbx, [rel SUB_]
cmp rbx, -1
jne .gen_op
cmp al, TOKEN_EQEQ
je .binop_cmp
cmp al, TOKEN_BANGEQ
je .binop_cmp
cmp al, TOKEN_STAR
cmove rbx, [rel MUL_]
cmp al, TOKEN_SLASH
@ -1161,7 +1367,73 @@ codegen_expr:
cmp al, TOKEN_PERCENT
cmove rbx, [rel DIV_]
cmp rbx, -1
je .panic ; unknown operator
jne .mul_div
jmp .panic ; unknown operator
.binop_cmp:
mov bl, al ; operator
mov rdi, [rsp + 8] ; &function_ctx
mov rsi, [rsp] ; ctx
lea rsi, [rsi + 8] ; &ctx.text
lea rdx, [rsp + 32] ; left operand
lea rcx, [rsp + 48] ; right operand
mov r8, 'cmp '
mov r9, 1
call codegen_binary_op_rm64_rm64
mov [rsp + 32], rax
mov [rsp + 40], rdx
; free operand
mov rdi, [rsp + 8] ; &function_ctx
lea rsi, [rsp + 32] ; left operand
call codegen_free_operand
; dst = allocate_value(1)
mov rdi, [rsp + 8] ; &function_ctx
mov rsi, 1 ; width
call codegen_allocate_value
mov [rsp + 32], rax
mov [rsp + 40], rdx
xor rax, rax
cmp bl, TOKEN_EQEQ
cmove rax, [rel SETE_]
cmp bl, TOKEN_BANGEQ
cmove rax, [rel SETNE_]
cmp bl, TOKEN_LEQ
cmove rax, [rel SETBE_]
cmp bl, TOKEN_LT
cmove rax, [rel SETB_]
cmp bl, TOKEN_GEQ
cmove rax, [rel SETAE_]
cmp bl, TOKEN_GT
cmove rax, [rel SETA_]
cmp rax, 0
je .panic ; unknown cmp operator
mov [rsp + 48], rax
; "{rax} dst\n"
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 48] ; op
mov rdx, 6
call vec_extend
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
lea rsi, [rsp + 32] ; dst
call codegen_write_operand
mov rdi, [rsp] ; ctx
lea rdi, [rdi + 8] ; &ctx.text
mov byte [rsp + 48], 10 ; newline
lea rsi, [rsp + 48]
call vec_push
mov rax, [rsp + 32]
mov rdx, [rsp + 40]
jmp .done
.mul_div:
; mul/div need to clobber rax:rdx
@ -1316,6 +1588,7 @@ codegen_expr:
lea rdx, [rsp + 32] ; left operand
lea rcx, [rsp + 48] ; right operand
mov r8, rbx ; operation
mov r9, 0
call codegen_binary_op_rm64_rm64
jmp .done
@ -1612,6 +1885,8 @@ section .rdata
OPERAND_RBP_V dq 0x0008_0002, 0
align 8
OPERAND_RBP_P dq 0x0008_0009, 0
align 8
OPERAND_ZERO dq 0x0001_000b, 0
section .text
@ -1836,19 +2111,23 @@ codegen_write_width:
;; rdx: lhs: *Operand
;; rcx: rhs: *Operand
;; r8: op: [u8; 8]
;; r9: discard_result
;; Generates: {op} {lhs}, {rhs} for a binary operation that has the encodings rN, rmN and rmN, rN
;; define-fn: fn codegen_binary_op_rm64_rm64(function_ctx: *mut FunctionCtx, text: *mut BlobVec, lhs: *const Operand, rhs: *const Operand, op: [u8; 8], discard_result: bool) -> *const Operand
codegen_binary_op_rm64_rm64:
push rbp
mov rbp, rsp
push rbx
; dst [32..48]
sub rsp, 56
; discard_result [56..57]
; dst [40..56]
sub rsp, 64
mov [rsp], rdi ; *function_ctx
mov [rsp + 8], rsi ; *text
mov [rsp + 16], rdx ; lhs
mov [rsp + 24], rcx ; rhs
mov [rsp + 32], r8 ; op
mov byte [rsp + 48], r9b ; discard_result
; match (lhs.kind, rhs.kind) {
cmp byte [rdx + 0], OPERAND_REGISTER
@ -1961,6 +2240,15 @@ codegen_binary_op_rm64_rm64:
mov rsi, [rsp + 16] ; lhs
call codegen_free_operand
cmp byte [rsp + 56], 0
je .rax_rhs_done
; mov rhs, rax
mov rdi, [rsp + 8] ; *text
mov rsi, [rsp + 24] ; rhs
lea rdx, [rel OPERAND_RAX]
call codegen_move_dst_src
.rax_rhs_done:
; ret rhs
mov rbx, [rsp + 24] ; rhs
mov rax, [rbx]
@ -2007,13 +2295,13 @@ codegen_binary_op_rm64_rm64:
call codegen_free_operand
; ret dst
mov rax, [rsp + 32] ; dst
mov rdx, [rsp + 40]
mov rax, [rsp + 40] ; dst
mov rdx, [rsp + 48]
; }
.epilogue:
add rsp, 56
add rsp, 64
pop rbx
pop rbp
ret
@ -2243,4 +2531,18 @@ section .rdata
SUB_ dq "sub "
MUL_ dq "mul "
DIV_ dq "div "
SETE_ dq "sete "
SETNE_ dq "setne "
SETA_ dq "seta "
SETAE_ dq "setae "
SETB_ dq "setb "
SETBE_ dq "setbe "
SETL_ dq "setl "
SETLE_ dq "setle "
SETG_ dq "setg "
SETGE_ dq "setge "
JE_B dq "je .B"
JE_B_len equ $ - JE_B
JMP_PHI dq "jmp .PHI"
JMP_PHI_len equ $ - JMP_PHI

View file

@ -62,6 +62,11 @@ LEXEMES:
dq LEX_DOT2
dq LEX_DOT
dq LEX_BACKTICK
dq LEX_SWITCH
dq LEX_AS
dq LEX_MATCH
dq LEX_WHILE
dq LEX_FOR
align 8
TOKENS:
@ -126,6 +131,11 @@ TOKENS:
db TOKEN_DOT2 ;; 53
db TOKEN_DOT ;; 52
db TOKEN_BACKTICK ;; 55
db TOKEN_SWITCH
db TOKEN_AS
db TOKEN_MATCH
db TOKEN_WHILE
db TOKEN_FOR
align 8
LEXEME_LENS:
@ -190,9 +200,14 @@ LEXEME_LENS:
dq LEX_DOT2_len
dq LEX_DOT_len
dq LEX_BACKTICK_len
dq LEX_SWITCH_len
dq LEX_AS_len
dq LEX_MATCH_len
dq LEX_WHILE_len
dq LEX_FOR_len
align 8
NUM_LEXEMES: dq 61
NUM_LEXEMES: dq 66
LEX_NOT_A_LEXEME db "<not a lexeme>", 0
LEX_LET db "let"
@ -315,6 +330,16 @@ NUM_LEXEMES: dq 61
LEX_DOT_len equ $ - LEX_DOT
LEX_BACKTICK db "`"
LEX_BACKTICK_len equ $ - LEX_BACKTICK
LEX_SWITCH db "switch"
LEX_SWITCH_len equ $ - LEX_SWITCH
LEX_AS db "as"
LEX_AS_len equ $ - LEX_AS
LEX_MATCH db "match"
LEX_MATCH_len equ $ - LEX_MATCH
LEX_WHILE db "while"
LEX_WHILE_len equ $ - LEX_WHILE
LEX_FOR db "for"
LEX_FOR_len equ $ - LEX_FOR
LEX_IDENT db "<identifier>"
LEX_IDENT_len equ $ - LEX_IDENT
LEX_NUMBER db "<number>"
@ -386,8 +411,13 @@ NUM_LEXEMES: dq 61
TOKEN_DOT2 equ 58 ; :u8
TOKEN_DOT equ 59 ; :u8
TOKEN_BACKTICK equ 60 ; :u8
TOKEN_IDENT equ 61 ; :u8
TOKEN_NUMBER equ 62 ; :u8
TOKEN_STRING equ 63 ; :u8
TOKEN_COMMENT equ 64 ; :u8
TOKEN_SWITCH equ 61 ; :u8
TOKEN_AS equ 62 ; :u8
TOKEN_MATCH equ 63 ; :u8
TOKEN_WHILE equ 64 ; :u8
TOKEN_FOR equ 65 ; :u8
TOKEN_IDENT equ 66 ; :u8
TOKEN_NUMBER equ 67 ; :u8
TOKEN_STRING equ 68 ; :u8
TOKEN_COMMENT equ 69 ; :u8
;; end-consts

View file

@ -12,7 +12,7 @@ unsafe extern "C" {
unsafe fn tokeniser_init_buf(bytes: *const u8, len: usize) -> ();
}
use util::defs::{parse_func, Ast};
use util::defs::{parse_expr, parse_func, Ast};
fn main() {
unsafe {
@ -58,57 +58,67 @@ fn main() {
};
}
// 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 * 4; }",
|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"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(a: u32) -> void { let x: u32 = a + 4; }",
// |ast| unsafe { parse_func(ast) },
// );
// print_ast(
// b"fn main(a: u32) -> void {
// let y: u32 = a + 4;
// let y: *u32 = &y;
// return *y;
// }",
// |ast| unsafe { parse_func(ast) },
// );
// print_ast(
// b"fn main(a: u32) -> void {
// let y: u32 = a + 4;
// {
// let y: u32 = 10;
// }
// let y: *u32 = &y;
// return *y;
// }",
// |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(a: u32) -> void { let x: u32 = a + 4; }",
|ast| unsafe { parse_func(ast) },
);
print_ast(
b"fn main(a: u32) -> void {
let y: u32 = a + 4;
let y: *u32 = &y;
return *y;
}",
|ast| unsafe { parse_func(ast) },
);
print_ast(
b"fn main(a: u32) -> void {
let y: u32 = a + 4;
{
let y: u32 = 10;
}
let y: *u32 = &y;
return *y;
}",
|ast| unsafe { parse_func(ast) },
);
print_ast(
b"fn main(a: *u32, b: u32) -> void {
*a = b;
a = &b;
}",
|ast| unsafe { parse_func(ast) },
);
print_ast(
b"fn main(a: u32) -> void {
if (a == 0) {
return 1;
} else {
return 0;
}
}",
|ast| unsafe { parse_func(ast) },
);

View file

@ -91,10 +91,23 @@ fn main() {
};
}
// print_ast(
// b"fn main(a: u32) -> void {
// let b: *u32 = &a;
// return 5 + *b;
// }",
// |ast| unsafe { parse_func(ast) },
// );
print_ast(
b"fn main(a: u32) -> void {
let b: *u32 = &a;
return 5 + *b;
let x: u32 = 10;
if (a == 42) {
x = 7;
} else {
x = 8;
}
return x;
}",
|ast| unsafe { parse_func(ast) },
);

View file

@ -4,7 +4,7 @@ impl core::fmt::Display for util::defs::AstNode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
use util::defs::{
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_DEREF, AST_FUNCTION, AST_IF, AST_NUMBER, AST_PLACE_TO_VALUE, AST_RETURN_STATEMENT,
AST_VALUE_TO_PLACE, AST_VAR_DECL, AST_VAR_REF,
};
match self.kind {
@ -98,6 +98,19 @@ impl core::fmt::Display for util::defs::AstNode {
std::slice::from_raw_parts(self.data.cast::<u64>(), self.extra as usize)
})
}
AST_IF => {
let if_node = unsafe { self.data.cast::<util::defs::AstIfExpr>().read() };
write!(
f,
"If(cond: {}, then_branch: {}, else_branch: {:?})",
if_node.condition,
if_node.then,
match if_node.else_ {
u64::MAX => None,
v => Some(v),
}
)
}
AST_PLACE_TO_VALUE => {
write!(f, "PlaceToValue(place: {})", self.data as usize)
}

View file

@ -12,6 +12,8 @@ unsafe extern "C" {
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_switch_expr(ast: *mut Ast) -> (u64, bool);
pub unsafe fn ast_parse_if_expr(ast: *mut Ast) -> (u64, bool);
pub unsafe fn ast_parse_let(ast: *mut Ast) -> (u64, bool);
pub unsafe fn symkey_cmp(a: *const SymKey, b: *const SymKey) -> i32;
pub unsafe fn ast_build_symtable(ast: *mut Ast, root_index: u64, symtable: *mut core::mem::MaybeUninit<SymbolTable>);
@ -27,6 +29,7 @@ unsafe extern "C" {
pub unsafe fn codegen_function(ast: *const CodegenCtx, func_idx: u64) -> ();
pub unsafe fn codegen_push_pop_used_registers(text: *mut Vec<u8>, function_ctx: &FunctionCtx, pop: bool) -> u8;
pub unsafe fn codegen_expr(ctx: *const CodegenCtx, function_ctx: &FunctionCtx, expr_idx: u64) -> (u64, bool);
pub unsafe fn codegen_binary_op_rm64_rm64(function_ctx: *mut FunctionCtx, text: *mut BlobVec, lhs: *const Operand, rhs: *const Operand, op: [u8; 8], discard_result: bool) -> *const Operand;
pub unsafe fn vec_insert_many(vec: *mut BlobVec, index: usize, data: *const u8, count: usize);
pub unsafe fn vec_extend(vec: *mut BlobVec, elements: *const u8, count: usize) -> ();
}
@ -52,6 +55,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 AST_SWITCH: u8 = 15;
pub const AST_IF: u8 = 16;
pub const AST_ELSE: u8 = 17;
pub const AST_CALL: u8 = 18;
pub const TYPE_VOID: u8 = 1;
pub const TYPE_BOOL: u8 = 2;
pub const TYPE_I32: u8 = 3;
@ -132,10 +139,15 @@ pub const TOKEN_DOT3: u8 = 57;
pub const TOKEN_DOT2: u8 = 58;
pub const TOKEN_DOT: u8 = 59;
pub const TOKEN_BACKTICK: u8 = 60;
pub const TOKEN_IDENT: u8 = 61;
pub const TOKEN_NUMBER: u8 = 62;
pub const TOKEN_STRING: u8 = 63;
pub const TOKEN_COMMENT: u8 = 64;
pub const TOKEN_SWITCH: u8 = 61;
pub const TOKEN_AS: u8 = 62;
pub const TOKEN_MATCH: u8 = 63;
pub const TOKEN_WHILE: u8 = 64;
pub const TOKEN_FOR: u8 = 65;
pub const TOKEN_IDENT: u8 = 66;
pub const TOKEN_NUMBER: u8 = 67;
pub const TOKEN_STRING: u8 = 68;
pub const TOKEN_COMMENT: u8 = 69;
#[repr(C)]
#[derive(Debug)]
@ -194,6 +206,29 @@ pub struct BinaryExpr {
pub right: u64,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstSwitch {
pub expr: u64,
pub cases: *const u64,
pub cases_len: usize,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstSwitchCase {
pub pattern: u64,
pub expr: u64,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstIfExpr {
pub condition: u64,
pub then: u64,
pub else_: u64,
}
#[repr(C)]
#[derive(Debug)]
pub struct AstVarDecl {