1
1
mirror of https://github.com/kanaka/mal.git synced 2024-09-21 10:37:58 +03:00

Bug fix in list and vector eval

If a value was returned from an expression then
it would be modified by being inserted into
the list or vector. If this value was the result of a symbol
lookup then this would modify the symbol value.

let* form now takes either vectors or lists

All stage 3 tests now pass
This commit is contained in:
Ben Dudson 2017-11-03 22:57:19 +00:00
parent c301f1c4ca
commit ef1d930428
2 changed files with 63 additions and 14 deletions

View File

@ -39,7 +39,7 @@ section .data
static let_missing_bindings_string, db "let* missing bindings",10
static let_bindings_list_string, db "let* expected a list of bindings",10
static let_bindings_list_string, db "let* expected a list or vector of bindings",10
static let_bind_symbol_string, db "let* expected a symbol in bindings list",10
@ -259,7 +259,8 @@ eval_ast:
cmp ah, content_pointer
je .list_pointer
; A value, so copy
; A value in RSI, so copy
call alloc_cons
mov bl, BYTE [rsi]
and bl, content_mask
@ -290,7 +291,7 @@ eval_ast:
mov bh, bl
and bh, (block_mask + container_mask)
cmp bh, (block_cons + container_value)
je .list_append
je .list_eval_value
; Not a value, so need a pointer to it
push rax
@ -298,8 +299,29 @@ eval_ast:
mov [rax], BYTE (block_cons + container_list + content_pointer)
pop rbx ; Address to point to
mov [rax + Cons.car], rbx
; Fall through to .list_append
jmp .list_append
.list_eval_value:
; Got value in RAX, so copy
push rax
call alloc_cons ; Copy in RAX
pop rbx ; Value to copy in RBX
mov cl, BYTE [rbx]
and cl, content_mask
or cl, (block_cons + container_list)
mov [rax], BYTE cl ; set type
mov rcx, [rbx + Cons.car]
mov [rax + Cons.car], rcx ; copy value
; Release the value in RBX
push rsi
push rax
mov rsi, rbx
call release_cons
pop rax
pop rsi
; Fall through to .list_append
.list_append:
; In RAX
@ -510,7 +532,7 @@ eval_ast:
mov bh, bl
and bh, (block_mask + container_mask)
cmp bh, (block_cons + container_value)
je .vector_append_value
je .vector_eval_value
; Not a value, so need a pointer to it
push rax
@ -520,9 +542,25 @@ eval_ast:
mov [rax + Cons.car], rbx
jmp .vector_append
.vector_append_value:
or bl, container_vector
mov [rax], BYTE bl
.vector_eval_value:
; Got value in RAX, so copy
push rax
call alloc_cons ; Copy in RAX
pop rbx ; Value to copy in RBX
mov cl, BYTE [rbx]
and cl, content_mask
or cl, (block_cons + container_vector)
mov [rax], BYTE cl ; set type
mov rcx, [rbx + Cons.car]
mov [rax + Cons.car], rcx ; copy value
; Release the value in RBX
push rsi
push rax
mov rsi, rbx
call release_cons
pop rax
pop rsi
.vector_append:
; In RAX
@ -745,14 +783,19 @@ eval:
mov r12, [r11 + Cons.car] ; should be bindings list
mov al, BYTE [r12]
and al, (block_mask + container_mask)
; Can be either a list or vector
cmp al, block_cons + container_list
jne .let_error_bindings_list
je .let_bind_loop
cmp al, block_cons + container_vector
je .let_bind_loop
; Not a list or vector
jmp .let_error_bindings_list
.let_bind_loop:
; R12 now contains a list with an even number of items
; The first should be a symbol, then a value to evaluate
.let_bind_loop:
; Get the symbol
mov al, BYTE [r12]
and al, content_mask
@ -851,7 +894,7 @@ eval:
.body_pointer:
; Evaluate using new environment
mov rsi, r11
mov rsi, [r11 + Cons.car] ; Object pointed to
mov rdi, r14 ; New environment
push r14
call eval
@ -870,7 +913,7 @@ eval:
mov rdx, let_missing_bindings_string.len
jmp .let_handle_error
.let_error_bindings_list: ; expected a list, got something else
.let_error_bindings_list: ; expected a list or vector, got something else
mov rsi, let_bindings_list_string
mov rdx, let_bindings_list_string.len
jmp .let_handle_error

View File

@ -302,6 +302,12 @@ alloc_cons:
;; Decrements the reference count of the cons in RSI
;; If the count reaches zero then push the cons
;; onto the free list
;;
;; Modifies registers:
;; RAX
;; RBX
;; RCX
;;
release_cons:
mov ax, WORD [rsi + Cons.refcount]
dec ax