can syscall!
This commit is contained in:
parent
b66b4f6668
commit
927b8517c5
|
|
@ -3,7 +3,7 @@
|
||||||
section .bss
|
section .bss
|
||||||
buf resb 0x100
|
buf resb 0x100
|
||||||
align 8,db 0
|
align 8,db 0
|
||||||
atoms times 20 resb 8
|
atoms times 24 resb 8
|
||||||
global env
|
global env
|
||||||
env resq 1
|
env resq 1
|
||||||
env_tail resq 1
|
env_tail resq 1
|
||||||
|
|
@ -57,7 +57,7 @@ strcmp:
|
||||||
xor eax, eax
|
xor eax, eax
|
||||||
.strcmp_loop:
|
.strcmp_loop:
|
||||||
cmp rsi, rax
|
cmp rsi, rax
|
||||||
je .strcmp_equal
|
jz .strcmp_equal
|
||||||
movzx ecx, byte [rdx + rax]
|
movzx ecx, byte [rdx + rax]
|
||||||
cmp byte [rdi + rax], cl
|
cmp byte [rdi + rax], cl
|
||||||
lea rax, [rax + 1]
|
lea rax, [rax + 1]
|
||||||
|
|
@ -134,6 +134,10 @@ align 8,db 0
|
||||||
ATOM_IF equ 15
|
ATOM_IF equ 15
|
||||||
ATOM_LET equ 16
|
ATOM_LET equ 16
|
||||||
ATOM_LET_STAR equ 17
|
ATOM_LET_STAR equ 17
|
||||||
|
ATOM_STR_LEN equ 18
|
||||||
|
ATOM_LIST_LEN equ 19
|
||||||
|
ATOM_STR_PARTS equ 20
|
||||||
|
ATOM_SYSCALL equ 21
|
||||||
|
|
||||||
QUOTE_STR db "quote"
|
QUOTE_STR db "quote"
|
||||||
QUOTE_STR_LEN equ $ - QUOTE_STR
|
QUOTE_STR_LEN equ $ - QUOTE_STR
|
||||||
|
|
@ -171,6 +175,21 @@ align 8,db 0
|
||||||
LET_STR_LEN equ $ - LET_STR
|
LET_STR_LEN equ $ - LET_STR
|
||||||
LET_STAR_STR db "let*"
|
LET_STAR_STR db "let*"
|
||||||
LET_STAR_STR_LEN equ $ - LET_STAR_STR
|
LET_STAR_STR_LEN equ $ - LET_STAR_STR
|
||||||
|
STR_LEN_STR db "str-len"
|
||||||
|
STR_LEN_STR_LEN equ $ - STR_LEN_STR
|
||||||
|
LIST_LEN_STR db "list-len"
|
||||||
|
LIST_LEN_STR_LEN equ $ - LIST_LEN_STR
|
||||||
|
STR_PARTS_STR db "str-parts"
|
||||||
|
STR_PARTS_STR_LEN equ $ - STR_PARTS_STR
|
||||||
|
SYSCALL_STR db "syscall"
|
||||||
|
SYSCALL_STR_LEN equ $ - SYSCALL_STR
|
||||||
|
|
||||||
|
SPACE_CHAR db "\Space"
|
||||||
|
SPACE_CHAR_LEN equ $ - SPACE_CHAR
|
||||||
|
NL_CHAR db "\NL"
|
||||||
|
NL_CHAR_LEN equ $ - NL_CHAR
|
||||||
|
TAB_CHAR db "\Tab"
|
||||||
|
TAB_CHAR_LEN equ $ - TAB_CHAR
|
||||||
|
|
||||||
;; 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, Env) -> U, U) -> U
|
;; fn fold_list(List<T>, Env, (U, T, Env) -> U, U) -> U
|
||||||
|
|
@ -602,11 +621,11 @@ p_if:
|
||||||
call get_car
|
call get_car
|
||||||
mov rsi, rax
|
mov rsi, rax
|
||||||
call get_cdr
|
call get_cdr
|
||||||
|
mov rdi, rax
|
||||||
|
call get_car
|
||||||
test cl, cl
|
test cl, cl
|
||||||
cmovnz rsi, rax
|
cmovnz rsi, rax
|
||||||
mov rdi, rsi
|
mov rdi, rsi
|
||||||
call get_car
|
|
||||||
mov rdi, rax
|
|
||||||
mov rsi, qword [rsp + 8] ; restore $rsi = env
|
mov rsi, qword [rsp + 8] ; restore $rsi = env
|
||||||
call eval
|
call eval
|
||||||
add rsp, 16
|
add rsp, 16
|
||||||
|
|
@ -700,6 +719,219 @@ p_let_star:
|
||||||
ret
|
ret
|
||||||
; p_let_rec:
|
; p_let_rec:
|
||||||
|
|
||||||
|
;; returns the length of the input list as a number
|
||||||
|
p_list_len:
|
||||||
|
call eval_list
|
||||||
|
xor rcx, rcx ; acc = 0
|
||||||
|
.len_loop:
|
||||||
|
mov rdi, rax ; list
|
||||||
|
call is_nil
|
||||||
|
test al, al
|
||||||
|
jnz .len_done
|
||||||
|
inc rcx
|
||||||
|
call get_cdr
|
||||||
|
jmp .len_loop
|
||||||
|
.len_done:
|
||||||
|
push rcx
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov dword [rax], 1 ; refcount = 1
|
||||||
|
pop rcx
|
||||||
|
mov qword [rax + 8], rcx ; value = length
|
||||||
|
mov rdi, rax
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; concatenates a list of strings into a single string
|
||||||
|
;; (str_concat "Hello," " my" " name is" " Alice") -> "Hello, my name is Alice"
|
||||||
|
p_str_concat:
|
||||||
|
;; appends a list of chars to a string
|
||||||
|
;; (str_append "hello" \Space \w \o \r \l \d) -> "hello world"
|
||||||
|
p_str_append:
|
||||||
|
;; return the nth element of a string
|
||||||
|
p_str_nth:
|
||||||
|
;; returns a new string that is a substring from a a+b of the input string
|
||||||
|
;; (substr "hello world" 0 5) -> "hello"
|
||||||
|
p_str_substr:
|
||||||
|
;; returns 't if the haystack-string contains the needle-char , and nil otherwise
|
||||||
|
p_str_contains_char:
|
||||||
|
;; returns 't if the haystack-string contains the needle-string, and nil otherwise
|
||||||
|
;; (contains_str? "hello world" "lo wo") -> 't
|
||||||
|
p_str_contains_str:
|
||||||
|
|
||||||
|
;; returns the length of the input string as a number
|
||||||
|
p_str_len:
|
||||||
|
call eval_list
|
||||||
|
mov rdi, rax
|
||||||
|
call get_car
|
||||||
|
mov rdi, rax
|
||||||
|
call obj_tag_part
|
||||||
|
cmp al, OBJ_STR
|
||||||
|
jne do_panic_abort
|
||||||
|
call obj_addr_part
|
||||||
|
movzx rax, dword [rax + 4]
|
||||||
|
push rax
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov rdi, rax
|
||||||
|
mov dword [rdi], 1 ; refcount = 1
|
||||||
|
pop rax
|
||||||
|
mov qword [rdi + 8], rax ; value = string length
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; returns the pointer and length part of the string object as a pair of numbers
|
||||||
|
p_str_decompose:
|
||||||
|
call eval_list
|
||||||
|
mov rdi, rax
|
||||||
|
call get_car
|
||||||
|
mov rdi, rax
|
||||||
|
call obj_tag_part
|
||||||
|
cmp al, OBJ_STR
|
||||||
|
jne do_panic_abort
|
||||||
|
sub rsp, 16
|
||||||
|
call obj_addr_part
|
||||||
|
mov edi, dword [rax + 4] ; length
|
||||||
|
mov rsi, qword [rax + 8] ; ptr
|
||||||
|
mov dword [rsp], edi
|
||||||
|
mov qword [rsp + 8], rsi
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov rdi, rax
|
||||||
|
mov dword [rdi], 1 ; refcount = 1
|
||||||
|
movzx rax, dword [rsp] ; length
|
||||||
|
mov qword [rdi + 8], rax ; value = length
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
mov qword [rsp], rax ; length number
|
||||||
|
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov rdi, rax
|
||||||
|
mov dword [rdi], 1 ; refcount = 1
|
||||||
|
mov rax, qword [rsp + 8] ; ptr
|
||||||
|
mov qword [rdi + 8], rax ; value = ptr
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
mov rdi, rax
|
||||||
|
mov rsi, qword [rsp] ; length number
|
||||||
|
call cons
|
||||||
|
add rsp, 16
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
;; returns the ascii value of the char
|
||||||
|
p_char_code:
|
||||||
|
call eval_list
|
||||||
|
mov rdi, rax
|
||||||
|
call get_car
|
||||||
|
mov rdi, rax
|
||||||
|
call obj_tag_part
|
||||||
|
cmp al, OBJ_BYTE
|
||||||
|
jne do_panic_abort
|
||||||
|
shr rax, 8
|
||||||
|
and rax, 0xFF
|
||||||
|
push rax
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov dword [rax], 1 ; refcount = 1
|
||||||
|
mov rdi, rax
|
||||||
|
pop rax
|
||||||
|
mov qword [rdi + 8], rax ; value = char code
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; returns a char object representing the ascii value
|
||||||
|
p_make_char:
|
||||||
|
call eval_list
|
||||||
|
mov rdi, rax
|
||||||
|
call get_car
|
||||||
|
mov rdi, rax
|
||||||
|
call obj_tag_part
|
||||||
|
cmp al, OBJ_NUM
|
||||||
|
jne do_panic_abort
|
||||||
|
call obj_addr_part
|
||||||
|
mov rcx, qword [rax + 8] ; char code
|
||||||
|
xor rax, rax
|
||||||
|
mov ah, cl
|
||||||
|
mov al, 0 ; OBJ_BYTE
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; performs a system call, returning the result as a number
|
||||||
|
;; (syscall num arg1 arg2 arg3) -> syscall(num, arg1, arg2, arg3)
|
||||||
|
p_syscall:
|
||||||
|
push r12
|
||||||
|
call eval_list
|
||||||
|
mov rdi, rax
|
||||||
|
; r11 = syscall num
|
||||||
|
; r12 = arg0
|
||||||
|
xor r11, r11
|
||||||
|
xor r12, r12
|
||||||
|
call ._next_arg ; syacall num
|
||||||
|
jnz .do_syscall
|
||||||
|
mov r11, rcx
|
||||||
|
call ._next_arg ; arg0
|
||||||
|
jnz .do_syscall
|
||||||
|
mov r12, rcx
|
||||||
|
call ._next_arg ; arg1
|
||||||
|
jnz .do_syscall
|
||||||
|
mov rsi, rcx
|
||||||
|
call ._next_arg ; arg2
|
||||||
|
jnz .do_syscall
|
||||||
|
mov rdx, rcx
|
||||||
|
call ._next_arg ; arg3
|
||||||
|
jz .do_syscall
|
||||||
|
mov r10, rcx
|
||||||
|
call ._next_arg ; arg4
|
||||||
|
jz .do_syscall
|
||||||
|
mov r8, rcx
|
||||||
|
call ._next_arg ; arg5
|
||||||
|
jz .do_syscall
|
||||||
|
mov r9, rcx
|
||||||
|
.do_syscall:
|
||||||
|
mov rax, r11 ; syscall num
|
||||||
|
mov rdi, r12 ; arg0
|
||||||
|
syscall
|
||||||
|
push rax
|
||||||
|
mov rdi, 16
|
||||||
|
mov rsi, 8
|
||||||
|
call alloc
|
||||||
|
mov rdi, rax
|
||||||
|
mov dword [rdi], 1 ; refcount = 1
|
||||||
|
pop rax
|
||||||
|
mov qword [rdi + 8], rax ; value = syscall result
|
||||||
|
mov rsi, OBJ_NUM
|
||||||
|
call obj_set_tag
|
||||||
|
pop r12
|
||||||
|
ret
|
||||||
|
;; fn _next_arg(list) -> ($rcx=arg, $rdi=rest)
|
||||||
|
._next_arg:
|
||||||
|
call is_nil
|
||||||
|
test al, al
|
||||||
|
jnz ._next_arg_done
|
||||||
|
call get_car
|
||||||
|
mov rcx, rax ; arg
|
||||||
|
call get_cdr
|
||||||
|
mov rdi, rax ; rest
|
||||||
|
xchg rdi, rcx
|
||||||
|
call obj_tag_part
|
||||||
|
cmp al, OBJ_NUM
|
||||||
|
jne do_panic_abort
|
||||||
|
call obj_addr_part
|
||||||
|
mov rdi, qword [rax + 8] ; arg value
|
||||||
|
xchg rdi, rcx
|
||||||
|
mov al, 0
|
||||||
|
test al, al
|
||||||
|
._next_arg_done:
|
||||||
|
ret
|
||||||
|
|
||||||
global init_env
|
global init_env
|
||||||
;; appends var=$rdi bound to val=$rsi to the global environment
|
;; appends var=$rdi bound to val=$rsi to the global environment
|
||||||
|
|
@ -809,6 +1041,22 @@ init_env:
|
||||||
lea rsi, [rel p_let_star]
|
lea rsi, [rel p_let_star]
|
||||||
call genv_append_atom_prim_by_idx
|
call genv_append_atom_prim_by_idx
|
||||||
|
|
||||||
|
mov rdi, ATOM_STR_LEN
|
||||||
|
lea rsi, [rel p_str_len]
|
||||||
|
call genv_append_atom_prim_by_idx
|
||||||
|
|
||||||
|
mov rdi, ATOM_LIST_LEN
|
||||||
|
lea rsi, [rel p_list_len]
|
||||||
|
call genv_append_atom_prim_by_idx
|
||||||
|
|
||||||
|
mov rdi, ATOM_STR_PARTS
|
||||||
|
lea rsi, [rel p_str_decompose]
|
||||||
|
call genv_append_atom_prim_by_idx
|
||||||
|
|
||||||
|
mov rdi, ATOM_SYSCALL
|
||||||
|
lea rsi, [rel p_syscall]
|
||||||
|
call genv_append_atom_prim_by_idx
|
||||||
|
|
||||||
mov rax, qword [rel env]
|
mov rax, qword [rel env]
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
@ -957,6 +1205,30 @@ init_atoms:
|
||||||
lea rcx, [rel atoms]
|
lea rcx, [rel atoms]
|
||||||
mov qword [rcx + ATOM_LET_STAR * 8], rax ; atoms[17] = "let*"
|
mov qword [rcx + ATOM_LET_STAR * 8], rax ; atoms[17] = "let*"
|
||||||
|
|
||||||
|
mov rdi, STR_LEN_STR
|
||||||
|
mov rsi, STR_LEN_STR_LEN
|
||||||
|
call make_atom
|
||||||
|
lea rcx, [rel atoms]
|
||||||
|
mov qword [rcx + ATOM_STR_LEN * 8], rax ; atoms[18] = "str-len"
|
||||||
|
|
||||||
|
mov rdi, LIST_LEN_STR
|
||||||
|
mov rsi, LIST_LEN_STR_LEN
|
||||||
|
call make_atom
|
||||||
|
lea rcx, [rel atoms]
|
||||||
|
mov qword [rcx + ATOM_LIST_LEN * 8], rax ; atoms[21] = "list-len"
|
||||||
|
|
||||||
|
mov rdi, STR_PARTS_STR
|
||||||
|
mov rsi, STR_PARTS_STR_LEN
|
||||||
|
call make_atom
|
||||||
|
lea rcx, [rel atoms]
|
||||||
|
mov qword [rcx + ATOM_STR_PARTS * 8], rax ; atoms[19] = "str-parts"
|
||||||
|
|
||||||
|
mov rdi, SYSCALL_STR
|
||||||
|
mov rsi, SYSCALL_STR_LEN
|
||||||
|
call make_atom
|
||||||
|
lea rcx, [rel atoms]
|
||||||
|
mov qword [rcx + ATOM_SYSCALL * 8], rax ; atoms[20] = "syscall"
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -964,6 +1236,8 @@ init_atoms:
|
||||||
;; returns 0 if the objects pointed at by $rdi and $rsi are equal, and 1 otherwise.
|
;; returns 0 if the objects pointed at by $rdi and $rsi are equal, and 1 otherwise.
|
||||||
obj_eq:
|
obj_eq:
|
||||||
sub rsp, 24
|
sub rsp, 24
|
||||||
|
cmp rdi, rsi
|
||||||
|
je .equal
|
||||||
mov qword [rsp], rdi ; save obj1
|
mov qword [rsp], rdi ; save obj1
|
||||||
mov qword [rsp + 8], rsi ; save obj2
|
mov qword [rsp + 8], rsi ; save obj2
|
||||||
call obj_tag_part
|
call obj_tag_part
|
||||||
|
|
@ -972,6 +1246,8 @@ obj_eq:
|
||||||
call obj_tag_part
|
call obj_tag_part
|
||||||
cmp al, byte [rsp + 16] ; compare tag2 with tag1
|
cmp al, byte [rsp + 16] ; compare tag2 with tag1
|
||||||
jne .not_equal
|
jne .not_equal
|
||||||
|
cmp al, OBJ_BYTE
|
||||||
|
je .compare_bytes
|
||||||
cmp al, OBJ_ATOM
|
cmp al, OBJ_ATOM
|
||||||
je .compare_atoms
|
je .compare_atoms
|
||||||
cmp al, OBJ_STR
|
cmp al, OBJ_STR
|
||||||
|
|
@ -985,6 +1261,8 @@ obj_eq:
|
||||||
cmp al, OBJ_PRIM
|
cmp al, OBJ_PRIM
|
||||||
je .compare_prims
|
je .compare_prims
|
||||||
jmp .equal
|
jmp .equal
|
||||||
|
.compare_bytes:
|
||||||
|
jmp do_panic_abort
|
||||||
.compare_atoms:
|
.compare_atoms:
|
||||||
.compare_strs:
|
.compare_strs:
|
||||||
call obj_addr_part
|
call obj_addr_part
|
||||||
|
|
@ -1257,8 +1535,10 @@ is_ch:
|
||||||
|
|
||||||
next_token:
|
next_token:
|
||||||
push r14
|
push r14
|
||||||
push rdi
|
|
||||||
xor r14, r14
|
xor r14, r14
|
||||||
|
sub rsp, 16
|
||||||
|
mov qword [rsp + 8], 0 ; flags
|
||||||
|
mov qword [rsp], rdi ; source iterator
|
||||||
.skip_spaces:
|
.skip_spaces:
|
||||||
mov rsi, ' '
|
mov rsi, ' '
|
||||||
call is_ch
|
call is_ch
|
||||||
|
|
@ -1275,7 +1555,11 @@ next_token:
|
||||||
cmp al, ')'
|
cmp al, ')'
|
||||||
je .leading_kw
|
je .leading_kw
|
||||||
cmp al, "'"
|
cmp al, "'"
|
||||||
jne .eat
|
je .leading_kw
|
||||||
|
cmp al, `"`
|
||||||
|
sete al
|
||||||
|
mov byte [rsp + 8], al ; set string-ness if the next char is a quote
|
||||||
|
jmp .eat
|
||||||
.leading_kw:
|
.leading_kw:
|
||||||
mov rdi, qword [rsp]
|
mov rdi, qword [rsp]
|
||||||
call getc
|
call getc
|
||||||
|
|
@ -1287,11 +1571,46 @@ next_token:
|
||||||
.eat:
|
.eat:
|
||||||
mov rdi, qword [rsp]
|
mov rdi, qword [rsp]
|
||||||
call getc
|
call getc
|
||||||
|
; handle escapes if we're in an escape sequence
|
||||||
|
cmp byte [rsp + 9], 1
|
||||||
|
jne .skip_escape
|
||||||
|
movzx ecx, al
|
||||||
|
cmp al, `n`
|
||||||
|
mov edi, `\n`
|
||||||
|
cmove ecx, edi
|
||||||
|
cmp al, `t`
|
||||||
|
mov edi, `\t`
|
||||||
|
cmove ecx, edi
|
||||||
|
cmp al, `r`
|
||||||
|
mov edi, `\r`
|
||||||
|
cmove ecx, edi
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
mov byte [rdi + r14], cl
|
||||||
|
mov byte [rsp + 9], 0
|
||||||
|
inc r14
|
||||||
|
jmp .eat
|
||||||
|
.skip_escape:
|
||||||
|
cmp al, `\\`
|
||||||
|
sete cl
|
||||||
|
mov byte [rsp + 9], cl
|
||||||
|
je .eat
|
||||||
|
|
||||||
lea rcx, [rel buf]
|
lea rcx, [rel buf]
|
||||||
lea rcx, [rcx + r14]
|
lea rcx, [rcx + r14]
|
||||||
mov byte [rcx], al
|
mov byte [rcx], al
|
||||||
inc r14
|
inc r14
|
||||||
|
|
||||||
|
cmp al, `"`
|
||||||
|
sete dl
|
||||||
|
mov cl, byte [rsp + 8] ; get string-ness
|
||||||
|
xchg cl, dl
|
||||||
|
shl dl, cl ; string-ness = 2^(num_quotes_eaten)
|
||||||
|
mov byte [rsp + 8], dl
|
||||||
|
cmp dl, 2
|
||||||
|
jg .done
|
||||||
|
cmp dl, 0
|
||||||
|
jne .eat
|
||||||
|
|
||||||
mov rdi, qword [rsp]
|
mov rdi, qword [rsp]
|
||||||
mov rsi, ' '
|
mov rsi, ' '
|
||||||
call is_ch
|
call is_ch
|
||||||
|
|
@ -1315,7 +1634,7 @@ next_token:
|
||||||
lea rcx, [rel buf]
|
lea rcx, [rel buf]
|
||||||
lea rax, [rcx + r14]
|
lea rax, [rcx + r14]
|
||||||
mov byte [rax], 0
|
mov byte [rax], 0
|
||||||
pop rdi
|
add rsp, 16
|
||||||
pop r14
|
pop r14
|
||||||
mov al, byte [rel buf]
|
mov al, byte [rel buf]
|
||||||
ret
|
ret
|
||||||
|
|
@ -1328,6 +1647,8 @@ parse_cur_token:
|
||||||
je .quote
|
je .quote
|
||||||
cmp byte [rel buf], `"`
|
cmp byte [rel buf], `"`
|
||||||
je .string
|
je .string
|
||||||
|
cmp byte [rel buf], `\\`
|
||||||
|
je .char
|
||||||
pop rdi
|
pop rdi
|
||||||
call parse_atom
|
call parse_atom
|
||||||
ret
|
ret
|
||||||
|
|
@ -1340,7 +1661,56 @@ parse_cur_token:
|
||||||
call parse_quote
|
call parse_quote
|
||||||
ret
|
ret
|
||||||
.string:
|
.string:
|
||||||
|
pop rdi
|
||||||
|
call parse_string
|
||||||
ret
|
ret
|
||||||
|
.char:
|
||||||
|
pop rdi
|
||||||
|
call parse_char
|
||||||
|
ret
|
||||||
|
|
||||||
|
;; fn parse_string(&mut iter) -> Char
|
||||||
|
parse_char:
|
||||||
|
sub rsp, 8
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
call strlen
|
||||||
|
mov qword [rsp], rax ; len
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
mov rsi, rax
|
||||||
|
lea rdx, [rel SPACE_CHAR]
|
||||||
|
mov rcx, SPACE_CHAR_LEN
|
||||||
|
call strcmp
|
||||||
|
test al, al
|
||||||
|
je .is_space
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
mov rsi, qword [rsp] ; len
|
||||||
|
lea rdx, [rel NL_CHAR]
|
||||||
|
mov rcx, NL_CHAR_LEN
|
||||||
|
call strcmp
|
||||||
|
test al, al
|
||||||
|
je .is_newline
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
mov rsi, qword [rsp] ; len
|
||||||
|
lea rdx, [rel TAB_CHAR]
|
||||||
|
mov rcx, TAB_CHAR_LEN
|
||||||
|
call strcmp
|
||||||
|
test al, al
|
||||||
|
je .is_tab
|
||||||
|
lea rdi, [rel buf]
|
||||||
|
mov ah, byte [rdi + 1] ; get the char after the backslash
|
||||||
|
.done:
|
||||||
|
add rsp, 8
|
||||||
|
mov al, 0 ; OBJ_BYTE
|
||||||
|
ret
|
||||||
|
.is_space:
|
||||||
|
mov ah, ' '
|
||||||
|
jmp .done
|
||||||
|
.is_newline:
|
||||||
|
mov ah, `\n`
|
||||||
|
jmp .done
|
||||||
|
.is_tab:
|
||||||
|
mov ah, `\t`
|
||||||
|
jmp .done
|
||||||
|
|
||||||
;; fn parse_string(&mut iter) -> Box<[u8]>
|
;; fn parse_string(&mut iter) -> Box<[u8]>
|
||||||
parse_string:
|
parse_string:
|
||||||
|
|
@ -1349,7 +1719,7 @@ parse_string:
|
||||||
.loop:
|
.loop:
|
||||||
; scan for closing quote
|
; scan for closing quote
|
||||||
lea rax, [rel buf]
|
lea rax, [rel buf]
|
||||||
mov al, byte [rax + r12]
|
mov al, byte [rax + r12 + 1]
|
||||||
; cmp al, `\\`
|
; cmp al, `\\`
|
||||||
; je .escape
|
; je .escape
|
||||||
cmp al, `"`
|
cmp al, `"`
|
||||||
|
|
@ -1363,10 +1733,11 @@ parse_string:
|
||||||
mov rsi, 1
|
mov rsi, 1
|
||||||
call alloc
|
call alloc
|
||||||
lea rdi, [rel buf]
|
lea rdi, [rel buf]
|
||||||
|
inc rdi
|
||||||
mov rsi, rax
|
mov rsi, rax
|
||||||
mov rdx, r12
|
mov rdx, r12
|
||||||
call memcpy
|
|
||||||
push rax
|
push rax
|
||||||
|
call memcpy
|
||||||
mov rdi, 16
|
mov rdi, 16
|
||||||
mov rsi, 8
|
mov rsi, 8
|
||||||
call alloc
|
call alloc
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ impl fmt::Debug for Object {
|
||||||
return write!(f, "nil");
|
return write!(f, "nil");
|
||||||
}
|
}
|
||||||
match self.tag() {
|
match self.tag() {
|
||||||
|
0 => write!(f, "'{}'", (self.0.addr() >> 8) as u8 as char),
|
||||||
1 => unsafe {
|
1 => unsafe {
|
||||||
let car = self.ptr().byte_add(8).cast::<Object>().read();
|
let car = self.ptr().byte_add(8).cast::<Object>().read();
|
||||||
let cdr = self.ptr().byte_add(16).cast::<Object>().read();
|
let cdr = self.ptr().byte_add(16).cast::<Object>().read();
|
||||||
|
|
@ -154,7 +155,15 @@ fn test_parse_list() {
|
||||||
let env = unsafe { *ENV_INIT };
|
let env = unsafe { *ENV_INIT };
|
||||||
println!("env: {:?}\n", env);
|
println!("env: {:?}\n", env);
|
||||||
|
|
||||||
let input = b"(let ((x 10) (y 20)) (+ x y))";
|
// let input = b"(let ((x 10) (y 20)) (+ x y))";
|
||||||
|
let input = b"(if () 1 2)";
|
||||||
|
// let hello_world = b"(let* (
|
||||||
|
// (msg \"hello world\\n\")
|
||||||
|
// (msg-parts (str-parts msg))
|
||||||
|
// (ptr (car msg-parts))
|
||||||
|
// (len (cdr msg-parts))
|
||||||
|
// (fd 1))
|
||||||
|
// (syscall 1 fd ptr len))";
|
||||||
let mut src = Source::from(&input[..]);
|
let mut src = Source::from(&input[..]);
|
||||||
let sexp = unsafe { parse_next_token(&raw mut src) };
|
let sexp = unsafe { parse_next_token(&raw mut src) };
|
||||||
println!("> {:?}", sexp);
|
println!("> {:?}", sexp);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue