This commit is contained in:
janis 2026-07-05 04:50:03 +02:00
parent e287ace328
commit 26c219a2f7
Signed by: janis
SSH key fingerprint: SHA256:bB1qbbqmDXZNT0KKD5c2Dfjg53JGhj7B3CFcLIzSqq8
3 changed files with 113 additions and 13 deletions

View file

@ -165,6 +165,11 @@ panic_abort:
mov rax, 60
syscall
exit:
xor edi, edi
mov rax, 60
syscall
;; rdi: *u8
strlen:
xor rax, rax
@ -276,6 +281,7 @@ getc_inner:
xor dl, dl ; peeked_some = false
ret
;; returns the next byte from the input without advancing the cursor. returns 1 or 0 in dl depending on EOF
peekc:
call getc_inner
lea rdi, [rel ifile]
@ -288,6 +294,7 @@ peekc:
mov word [rdi + 4], cx ; peeked = Some(Some(c))
ret
;; returns the next byte from the input. returns 1 or 0 in dl depending on EOF
getc:
call getc_inner
lea rdi, [rel ifile]
@ -295,6 +302,12 @@ getc:
and eax, 0xff
ret
is_eof:
call peekc
test dl, dl
setz al
ret
;; Allocator
;; allocates $rdi bytes worth of pages via mmap
@ -500,6 +513,8 @@ heap_dealloc:
is_ch:
push rdi
call peekc
test dl, dl
je .eof
pop rdi
mov dl, al ; cl = peekc()
cmp al, ' '
@ -511,6 +526,9 @@ is_ch:
cmp al, dil
setz al ; al = (al == dil)
ret
.eof:
xor eax, eax
ret
;; converts char $dil to a digit with radix $rsi, returning it in $edx. $al is set to 1 if the char is a valid digit, and 0 otherwise.
to_digit:
@ -534,21 +552,42 @@ to_digit:
xor eax, eax
ret
skip_whitespaces:
call peekc
cmp al, ' '
ja .done
call getc
jmp skip_whitespaces
.done:
ret
skip_comment:
call peekc
cmp al, `;`
jne .done
.loop:
call getc
cmp al, 10
jne .loop
call skip_whitespaces
jmp skip_comment
.done:
ret
;; reads the next token from ifile into buf
next_token:
push r14
xor r14, r14
sub rsp, 8
mov qword [rsp], 0 ; flags
.skip_whitespaces:
mov rdi, ' '
call is_ch
test al, al
jz .test_kw
call getc
jmp .skip_whitespaces
.test_kw:
call skip_whitespaces
call skip_comment
call peekc
test dl, dl
jz .done
movzx ecx, al
sub cl, `'`
cmp cl, `)` - `'`
@ -643,15 +682,18 @@ global parse_next_token
parse_next_token:
call next_token
parse_cur_token:
cmp byte [rel buf], `(`
cmp al, `(`
je parse_list
cmp byte [rel buf], `'`
cmp al, `'`
je parse_quote
cmp byte [rel buf], `"`
cmp al, `"`
je parse_string
cmp byte [rel buf], `\\`
cmp al, `\\`
je parse_char
jmp parse_atom
cmp al, 0
jne parse_atom
xor eax, eax
ret
parse_list:
@ -3283,3 +3325,45 @@ p_typeof:
mov rax, qword [rsp] ; result
add rsp, 8
ret
;; Entry
open_file:
mov rax, 2 ; syscall: open
mov rsi, 0 ; flags: O_RDONLY
mov rdx, 0 ; mode
syscall
ret
init_ifile:
mov esi, edi
lea rdi, [rel ifile]
jmp init_source
global _interp_entry
_interp_entry:
mov eax, dword [rsp]
lea rbx, [rsp + 8]
mov edi, 1
cmp eax, 2
jle .init_ifile
mov rdi, qword [rbx + 8] ; argv[1]
call open_file
mov edi, eax ; fd
.init_ifile:
call init_ifile
call init_env
sub rsp, 8
mov qword [rsp], rsi ; env
.loop:
call parse_next_token
test eax, eax
jz .done
mov rdi, rax
mov rsp, qword [rsp] ; env
call eval
jmp .loop
.done:
call exit

View file

@ -499,4 +499,18 @@ mod tests {
eprintln!("{result:?}");
}
}
#[test]
fn eval_comment() {
let file = ManuallyDrop::new(File::open("tests/comment.l").unwrap());
unsafe {
init_source(&raw mut IFILE, file.as_raw_fd());
let expr = parse_next_token();
eprintln!("parsed: {:?}", expr);
let env = unsafe { *ENV_INIT };
let result = eval(expr, env);
eprint!("done: ");
eprintln!("{result:?}");
}
}
}

View file

@ -0,0 +1,2 @@
;; this is a comment
(define x 10) ; this is another comment