From 192c1233730c551e2bf39c64fe9e493d91a8b64a Mon Sep 17 00:00:00 2001 From: janis Date: Tue, 4 Nov 2025 16:51:59 +0100 Subject: [PATCH] as expression ( as ), more types in ast --- lang/src/ast.asm | 130 ++++++++++++++++++++++++++++++++- lang/src/ast.inc | 19 ++++- lang/tests/ast.rs | 7 ++ lang/tests/shared/ast_debug.rs | 6 +- lang/tests/shared/defs.rs | 27 ++++++- lang/tests/shared/shared.rs | 46 ++++++++++-- 6 files changed, 217 insertions(+), 18 deletions(-) diff --git a/lang/src/ast.asm b/lang/src/ast.asm index 460f3eb..5d773cc 100644 --- a/lang/src/ast.asm +++ b/lang/src/ast.asm @@ -315,6 +315,80 @@ parse_number: .panic: call panic +;; rdi: *mut Ast +;; define-fn: fn parse_as_expr(ast: *mut Ast) -> (u64, bool) +parse_as_expr: + push rbp + mov rbp, rsp + + ; start-structs + ; struct AstAsExpr { + ; expr: u64, + ; ty: Type, + ; } + ; end-structs + + ; Type [32..48] + ; prefix_expr [16..32] + ; span [8..16] + ; ast [0..8] + sub rsp, 48 + mov [rsp], rdi ; Ast + call parse_prefix_expr + mov [rsp + 16], rax ; prefix_expr + mov [rsp + 24], rdx ; placeness + + call tokeniser_get_cursor + mov [rsp + 8], rax ; span + + mov dil, TOKEN_AS + call expect_token + test rax, rax + jz .done + + ; convert prefix_expr to value +.as_expr: + mov rdi, [rsp] ; Ast + mov rsi, [rsp + 16] ; prefix_expr + mov dl, [rsp + 24] ; placeness + call ast_place_to_value + mov [rsp + 24], rax ; AstAsExpr.expr + + ; parse type + mov rdi, [rsp] ; Ast + call parse_type + mov [rsp + 32], rax ; AstAsExpr.Type.kind + mov [rsp + 40], rdx ; AstAsExpr.Type.data + + mov rdi, 16 ; size_of:: + mov rsi, 8 ; align_of:: + call bump_alloc + mov rdi, rax ; dst + lea rsi, [rsp + 24] ; &AstAsExpr + mov rdx, 16 ; size_of:: + call memcpy + + mov qword [rsp + 16], AST_AS ; AstNode.kind + mov [rsp + 24], rdi ; AstNode.data + mov qword [rsp + 32], 0 ; AstNode.extra + mov rdi, [rsp + 8] ; span + mov [rsp + 40], rdi ; AstNode.span + + mov rdi, [rsp] ; Ast + lea rsi, [rsp + 16] ; &AstNode + call vec_push + ; rax = index of pushed node + mov rdx, 0 ; placeness = false + jmp .epilogue + +.done: + mov rax, [rsp + 16] ; prefix_expr + mov rdx, [rsp + 24] ; placeness +.epilogue: + add rsp, 48 + pop rbp + ret + ;; rdi: *mut Ast ;; define-fn: fn parse_postfix_expr(ast: *mut Ast) -> (u64, bool) parse_postfix_expr: @@ -551,7 +625,7 @@ parse_binary_expr: call tokeniser_get_cursor mov [rsp + 56], rax ; span - call parse_prefix_expr + call parse_as_expr mov [rsp + 8], rax ; left mov [rsp + 19], dl ; left_placeness @@ -834,13 +908,63 @@ parse_type: je .bool_type cmp al, TOKEN_STAR je .pointer_type + cmp al, TOKEN_U8 + je .u8_type + cmp al, TOKEN_I8 + je .i8_type + cmp al, TOKEN_U16 + je .u16_type + cmp al, TOKEN_I16 + je .i16_type + cmp al, TOKEN_U64 + je .u64_type + cmp al, TOKEN_I64 + je .i64_type + cmp al, TOKEN_F32 + je .f32_type + cmp al, TOKEN_F64 + je .f64_type + cmp al, TOKEN_USIZE + je .usize_type + cmp al, TOKEN_ISIZE + je .isize_type jmp .panic -.i32_type: - mov rax, TYPE_I32 +.u8_type: + mov rax, TYPE_U8 + jmp .epilogue +.i8_type: + mov rax, TYPE_I8 + jmp .epilogue +.u16_type: + mov rax, TYPE_U16 + jmp .epilogue +.i16_type: + mov rax, TYPE_I16 jmp .epilogue .u32_type: mov rax, TYPE_U32 jmp .epilogue +.i32_type: + mov rax, TYPE_I32 + jmp .epilogue +.u64_type: + mov rax, TYPE_U64 + jmp .epilogue +.i64_type: + mov rax, TYPE_I64 + jmp .epilogue +.usize_type: + mov rax, TYPE_USIZE + jmp .epilogue +.isize_type: + mov rax, TYPE_ISIZE + jmp .epilogue +.f32_type: + mov rax, TYPE_F32 + jmp .epilogue +.f64_type: + mov rax, TYPE_F64 + jmp .epilogue .void_type: mov rax, TYPE_VOID jmp .epilogue diff --git a/lang/src/ast.inc b/lang/src/ast.inc index fe8cfda..37ebab5 100644 --- a/lang/src/ast.inc +++ b/lang/src/ast.inc @@ -18,11 +18,22 @@ section .rdata AST_IF equ 16 ; :u8 AST_ELSE equ 17 ; :u8 AST_CALL equ 18 ; :u8 + AST_AS equ 19 ; :u8 TYPE_VOID equ 1 ; :u8 TYPE_BOOL equ 2 ; :u8 - TYPE_I32 equ 3 ; :u8 - TYPE_U32 equ 4 ; :u8 - TYPE_STR equ 5 ; :u8 - TYPE_POINTER equ 6 ; :u8 + TYPE_U8 equ 3 ; :u8 + TYPE_U16 equ 4 ; :u8 + TYPE_U32 equ 5 ; :u8 + TYPE_U64 equ 6 ; :u8 + TYPE_USIZE equ 7 ; :u8 + TYPE_I8 equ 8 ; :u8 + TYPE_I16 equ 9 ; :u8 + TYPE_I32 equ 10 ; :u8 + TYPE_I64 equ 11 ; :u8 + TYPE_ISIZE equ 12 ; :u8 + TYPE_STR equ 13 ; :u8 + TYPE_POINTER equ 14 ; :u8 + TYPE_F32 equ 15 ; :u8 + TYPE_F64 equ 16 ; :u8 ;; end-consts diff --git a/lang/tests/ast.rs b/lang/tests/ast.rs index 4e841c3..2ae9155 100644 --- a/lang/tests/ast.rs +++ b/lang/tests/ast.rs @@ -127,6 +127,13 @@ fn main() { print_ast( b"fn main(a: u32) -> void { return main(1); +}", + |ast| unsafe { parse_func(ast) }, + ); + + print_ast( + b"fn main(a: u32) -> void { +return 1 as u8; }", |ast| unsafe { parse_func(ast) }, ); diff --git a/lang/tests/shared/ast_debug.rs b/lang/tests/shared/ast_debug.rs index 7a81968..b6e3061 100644 --- a/lang/tests/shared/ast_debug.rs +++ b/lang/tests/shared/ast_debug.rs @@ -3,7 +3,7 @@ use super::util; 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, + BinaryExpr, AST_ADDRESS_OF, AST_ARG, AST_AS, AST_ASSIGNMENT, AST_BINARY_OP, AST_BLOCK, AST_CALL, 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, }; @@ -23,6 +23,10 @@ impl core::fmt::Display for util::defs::AstNode { std::slice::from_raw_parts(call.params.cast::(), call.params_len as usize) },) } + AST_AS => { + let as_expr = unsafe { self.data.cast::().read() }; + write!(f, "As(expr: {}, target_type: {})", as_expr.expr, as_expr.ty) + } AST_ARG => { let arg = unsafe { self.data.cast::().read() }; write!( diff --git a/lang/tests/shared/defs.rs b/lang/tests/shared/defs.rs index cd498d2..6e27d4f 100644 --- a/lang/tests/shared/defs.rs +++ b/lang/tests/shared/defs.rs @@ -6,6 +6,7 @@ unsafe extern "C" { pub unsafe fn bump_alloc(size: usize, alignment: usize) -> *mut u8; pub unsafe fn parse_func(ast: *mut Ast) -> u64; pub unsafe fn parse_args(ast: *mut Ast) -> (*const u64, usize); + pub unsafe fn parse_as_expr(ast: *mut Ast) -> (u64, bool); pub unsafe fn parse_postfix_expr(ast: *mut Ast) -> (u64, bool); pub unsafe fn parse_primary_expr(ast: *mut Ast) -> (u64, bool); pub unsafe fn parse_binary_expr(ast: *mut Ast, precedence: u8) -> (u64, bool); @@ -64,12 +65,23 @@ 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 AST_AS: u8 = 19; pub const TYPE_VOID: u8 = 1; pub const TYPE_BOOL: u8 = 2; -pub const TYPE_I32: u8 = 3; -pub const TYPE_U32: u8 = 4; -pub const TYPE_STR: u8 = 5; -pub const TYPE_POINTER: u8 = 6; +pub const TYPE_U8: u8 = 3; +pub const TYPE_U16: u8 = 4; +pub const TYPE_U32: u8 = 5; +pub const TYPE_U64: u8 = 6; +pub const TYPE_USIZE: u8 = 7; +pub const TYPE_I8: u8 = 8; +pub const TYPE_I16: u8 = 9; +pub const TYPE_I32: u8 = 10; +pub const TYPE_I64: u8 = 11; +pub const TYPE_ISIZE: u8 = 12; +pub const TYPE_STR: u8 = 13; +pub const TYPE_POINTER: u8 = 14; +pub const TYPE_F32: u8 = 15; +pub const TYPE_F64: u8 = 16; pub const OPERAND_REGISTER: u32 = 1; pub const OPERAND_RBP_VALUE: u32 = 2; pub const OPERAND_RBP_PVALUE: u32 = 3; @@ -195,6 +207,13 @@ pub struct AstFunction { pub body: u64, } +#[repr(C)] +#[derive(Debug)] +pub struct AstAsExpr { + pub expr: u64, + pub ty: Type, +} + #[repr(C)] #[derive(Debug)] pub struct AstCallExpr { diff --git a/lang/tests/shared/shared.rs b/lang/tests/shared/shared.rs index bf937db..4c394b1 100644 --- a/lang/tests/shared/shared.rs +++ b/lang/tests/shared/shared.rs @@ -373,26 +373,60 @@ impl<'a, T: core::fmt::Display> core::fmt::Display for DisplaySlice<'a, T> { impl core::fmt::Display for defs::Type { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + use defs::{ + TYPE_BOOL, TYPE_F32, TYPE_F64, TYPE_I16, TYPE_I32, TYPE_I64, TYPE_I8, TYPE_ISIZE, + TYPE_POINTER, TYPE_STR, TYPE_U16, TYPE_U32, TYPE_U64, TYPE_U8, TYPE_USIZE, TYPE_VOID, + }; match self.kind { - defs::TYPE_VOID => { + TYPE_VOID => { write!(f, "void") } - defs::TYPE_BOOL => { + TYPE_BOOL => { write!(f, "bool") } - defs::TYPE_I32 => { + TYPE_I32 => { write!(f, "i32") } - defs::TYPE_U32 => { + TYPE_U32 => { write!(f, "u32") } - defs::TYPE_STR => { + TYPE_STR => { write!(f, "str") } - defs::TYPE_POINTER => { + TYPE_POINTER => { let pointee = unsafe { (self.data as *const defs::Type).read() }; write!(f, "*{pointee}",) } + TYPE_I8 => { + write!(f, "i8") + } + TYPE_U8 => { + write!(f, "u8") + } + TYPE_I16 => { + write!(f, "i16") + } + TYPE_U16 => { + write!(f, "u16") + } + TYPE_I64 => { + write!(f, "i64") + } + TYPE_U64 => { + write!(f, "u64") + } + TYPE_F32 => { + write!(f, "f32") + } + TYPE_F64 => { + write!(f, "f64") + } + TYPE_USIZE => { + write!(f, "usize") + } + TYPE_ISIZE => { + write!(f, "isize") + } _ => { write!(f, "UnknownType") }