string parsing/remove nil tag in favour of constant pointer/add char tag

This commit is contained in:
janis 2026-06-11 17:30:43 +02:00
parent 6df1d2ac9b
commit 13f4e2bfe4
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8

View file

@ -98,13 +98,14 @@ extern dealloc
align 8,db 0 align 8,db 0
nil dq 1 ; the nil object, with refcount = 1 nil dq 1 ; the nil object, with refcount = 1
OBJ_NIL equ 0 OBJ_BYTE equ 0
OBJ_CONS equ 1 OBJ_CONS equ 1
OBJ_CLOS equ 2 OBJ_CLOS equ 2
OBJ_ATOM equ 3 OBJ_ATOM equ 3
OBJ_NUM equ 4 OBJ_NUM equ 4
OBJ_PRIM equ 5 OBJ_PRIM equ 5
OBJ_STR equ 6 OBJ_STR equ 6
OBJ_ARR equ 7
ATOM_QUOTE equ 0 ATOM_QUOTE equ 0
ATOM_TRUE equ 1 ATOM_TRUE equ 1
@ -145,7 +146,7 @@ extern dealloc
NOT_STR_LEN equ $ - NOT_STR NOT_STR_LEN equ $ - NOT_STR
;; folds all elements in the list $rdi using the binary function $rdx in the environment $rsi with an accumulator value of $rcx, returning the result in $rax ;; folds all elements in the list $rdi using the binary function $rdx in the environment $rsi with an accumulator value of $rcx, returning the result in $rax
;; fn fold_list(List<T>, Env, (U, T) -> U, U) -> U ;; fn fold_list(List<T>, Env, (U, T, Env) -> U, U) -> U
fold_list: fold_list:
sub rsp, 32 sub rsp, 32
mov qword [rsp], rdi ; rest mov qword [rsp], rdi ; rest
@ -172,7 +173,7 @@ fold_list:
ret ret
;; like fold_list, but requires that the list is non-empty ;; like fold_list, but requires that the list is non-empty
;; fn reduce_list(List<T>, Env, (T, T) -> T) -> T ;; fn reduce_list(List<T>, Env, (T, T, Env) -> T) -> T
reduce_list: reduce_list:
call get_car call get_car
mov rcx, rax ; acc = car(list) mov rcx, rax ; acc = car(list)
@ -188,6 +189,7 @@ reduce_list:
ret ret
;; like reduce_list, calls a predicate instead of a binary function, and returns "t" if the predicate returns non-zero for any pair of adjacent elements, and nil otherwise ;; like reduce_list, calls a predicate instead of a binary function, and returns "t" if the predicate returns non-zero for any pair of adjacent elements, and nil otherwise
;; predicate: fn (T, T, Env) -> bool
any2_list: any2_list:
sub rsp, 24 sub rsp, 24
mov qword [rsp], rdi ; rest mov qword [rsp], rdi ; rest
@ -843,12 +845,12 @@ obj_eq:
dtor_table: dtor_table:
dd dtor_table - dtor_nil dd 0
dd dtor_table - dtor_cons dd dtor_table - dtor_cons
dd dtor_table - dtor_clos dd dtor_table - dtor_clos
dd dtor_table - dtor_atom dd dtor_table - dtor_atom
dd dtor_table - dtor_num dd dtor_table - dtor_num
dd dtor_table - dtor_prim dd 0
dd dtor_table - dtor_str dd dtor_table - dtor_str
dd 0 dd 0
@ -884,26 +886,30 @@ dtor_num:
call dealloc call dealloc
ret ret
obj_inc_ref: obj_inc_ref:
call obj_tag_part call is_nil
cmp al, OBJ_NIL test al, al
je .done ; nil is immortal, so we're done jnz .done ; nil is immortal, so we're done
call obj_addr_part call obj_addr_part
inc dword [rax] ; increment the refcount inc dword [rax] ; increment the refcount
.done: .done:
ret ret
obj_dec_ref: obj_dec_ref:
call is_nil
test al, al
jnz .done ; nil is immortal, so we're done
call obj_tag_part call obj_tag_part
cmp al, OBJ_NIL
je .done ; nil is immortal, so we're done
mov rsi, rax mov rsi, rax
call obj_addr_part call obj_addr_part
dec dword [rax] ; decrement the refcount dec dword [rax] ; decrement the refcount
jnz .done ; if refcount != 0, we're done jnz .done ; if refcount != 0, we're done
lea rcx, qword [rel dtor_table] lea rcx, qword [rel dtor_table]
movsxd rsi, [rcx + rsi * 4] ; get the offset of the destructor movsxd rsi, [rcx + rsi * 4] ; get the offset of the destructor
add rcx, rsi ; calculate the address of the destructor test rsi, rsi
jz .done ; if there's no destructor, we're done
add rcx, rsi ; p_dtor = &dtor_table + dtor_table[tag]
mov rdi, rax ; set the argument for the destructor (the object pointer) mov rdi, rax ; set the argument for the destructor (the object pointer)
call rcx ; call the destructor call rcx ; call the destructor
.done: .done:
@ -928,6 +934,18 @@ obj_set_tag:
or rax, rsi ; set the new tag bits or rax, rsi ; set the new tag bits
ret ret
;; construcst a closure object with params $rdi, body $rsi, and env $rdx
clos:
push rdx
call cons
mov rdi, rax
pop rsi
call cons
mov rdi, rax
mov rsi, OBJ_CLOS
call obj_set_tag
ret
;; constructs a cons cell ($rdi . $rsi) and returns an object pointer to it ;; constructs a cons cell ($rdi . $rsi) and returns an object pointer to it
cons: cons:
push rdi push rdi
@ -1080,6 +1098,50 @@ parse_cur_token:
pop rdi pop rdi
call parse_quote call parse_quote
ret ret
.string:
ret
;; fn parse_string(&mut iter) -> Box<[u8]>
parse_string:
push r12
xor r12, r12
.loop:
; scan for closing quote
mov al, byte [rel buf + r12]
; cmp al, `\\`
; je .escape
cmp al, `"`
je .done
test al, al
jz .invalid
inc r12
jmp .loop
.done:
mov rdi, r12
mov rsi, 1
call alloc
lea rdi, [rel buf]
mov rsi, rax
mov rdx, r12
call memcpy
push rax
mov rdi, 16
mov rsi, 8
call alloc
mov dword [rax], 1 ; refcount = 1
mov dword [rax + 4], r12w ; length of string
pop rdi
mov qword [rax + 8], rdi ; pointer to string
mov rdi, rax
mov rsi, OBJ_STR
call obj_set_tag
pop r12
ret
.invalid:
xor rdi, rdi
call panic_abort
parse_num: parse_num:
push r12 push r12
@ -1307,8 +1369,9 @@ eval_list:
mov rdi, qword [rsp + 24] ; $rdi = cdr($rdi) mov rdi, qword [rsp + 24] ; $rdi = cdr($rdi)
jmp .tailcall jmp .tailcall
.not_cons: .not_cons:
cmp al, OBJ_NIL call is_nil
je .nil test al, al
jnz .nil
mov rsi, qword [rsp] ; $rsi = environment mov rsi, qword [rsp] ; $rsi = environment
call eval call eval
mov rsi, rax mov rsi, rax