diff --git a/stages/lisp0/lisp1.asm b/stages/lisp0/lisp1.asm index 62c66e5..a7851db 100644 --- a/stages/lisp0/lisp1.asm +++ b/stages/lisp0/lisp1.asm @@ -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 diff --git a/stages/lisp0/test.rs b/stages/lisp0/test.rs index f844da5..0a490ee 100644 --- a/stages/lisp0/test.rs +++ b/stages/lisp0/test.rs @@ -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:?}"); + } + } } diff --git a/stages/lisp0/tests/comment.l b/stages/lisp0/tests/comment.l new file mode 100644 index 0000000..9757d29 --- /dev/null +++ b/stages/lisp0/tests/comment.l @@ -0,0 +1,2 @@ +;; this is a comment +(define x 10) ; this is another comment