-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinterp.asm
More file actions
192 lines (176 loc) · 3.36 KB
/
Copy pathinterp.asm
File metadata and controls
192 lines (176 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
;; Copyright (C) 2025 Florian Marrero Liestmann
;;
;; This program is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;
;; Author: Florian Marrero Liestmann <f.m.liestmann@fx-ttr.de>
;; File: interp.asm
[BITS 16]
HEAP equ 0x8400 ; first cons cell; names must stay below
start_interp:
mov si, __prompt_sym
call printer
call parse_expr
call eval
call print_val
jmp start_interp
cons:
push di
mov di, [__heap_ptr]
push di
stosw
xchg ax, dx
stosw
mov [__heap_ptr], di
pop ax
pop di
ret
eval:
or ax, ax
jz .ret ; nil
cmp ax, HEAP
jae .combo
mov bx, [__env] ; symbol: unbound evaluates to itself
.look:
or bx, bx
jz .ret
mov di, [bx] ; binding (symbol . value)
cmp ax, [di]
je .hit
mov bx, [bx+2]
jmp .look
.hit:
mov ax, [di+2]
.ret:
ret
.combo:
xchg ax, di ; DI = the cell
mov ax, [di]
cmp ax, __quote_sym
je .quote
cmp ax, __if_sym
je .if
cmp ax, __lambda_sym
jne .app
xchg ax, di ; a lambda evaluates to itself
ret
.quote:
mov di, [di+2]
mov ax, [di]
ret
.if:
mov di, [di+2] ; (cond then [else])
push di
mov ax, [di]
call eval
pop di
mov di, [di+2] ; (then [else])
or ax, ax
jnz .sel
mov di, [di+2] ; ([else])
.sel:
or di, di ; missing branch: nil (AX is 0 here)
jz .ret
mov ax, [di]
jmp eval ; tail position
.app: ; (fn arg...)
push di
call eval ; AX still holds the operator expression
pop di
push ax
mov di, [di+2]
call _evlis
xchg ax, di ; DI = argument list
pop ax ; AX = function
apply:
cmp ax, HEAP
jae .closure
cmp ax, __car_sym
je .car
cmp ax, __cdr_sym
je .cdr
cmp ax, __cons_sym
je .cons
cmp ax, __eq_sym
jne .nil ; not applicable -> ()
mov ax, [di] ; eq
mov di, [di+2]
cmp ax, [di]
mov ax, __t_sym
je .ret
.nil:
xor ax, ax
.ret:
ret
.car:
mov bx, [di]
mov ax, [bx]
ret
.cdr:
mov bx, [di]
mov ax, [bx+2]
ret
.cons:
mov ax, [di]
mov di, [di+2]
mov dx, [di]
jmp cons
.closure: ; AX = (lambda param body), DI = args
xchg ax, di ; DI = lambda, AX = args
mov si, [di+2] ; (param body)
push si
xchg ax, bx ; BX = args
mov ax, [si] ; the parameter symbol
mov dx, [bx] ; the first argument
call _bind
pop di
mov di, [di+2] ; (body)
mov ax, [di]
jmp eval ; bindings stay: dynamic scope, no cleanup
_evlis:
or di, di
jnz .go
xor ax, ax
ret
.go:
push word [di+2]
mov ax, [di]
call eval
pop di
push ax
call _evlis
mov dx, ax
pop ax
jmp cons
_bind:
call cons ; (symbol . value)
mov dx, [__env]
call cons
mov [__env], ax
ret
%include "print.asm"
%include "read.asm"
__prompt_sym: db 0x0D, 0x0A, "> ", 0x00
__env: dw 0x00
__heap_ptr: dw HEAP
__names_ptr: dw __names_end
__names:
__quote_sym: db "quote", 0x00
__if_sym: db "if", 0x00
__lambda_sym: db "lambda", 0x00
__car_sym: db "car", 0x00
__cdr_sym: db "cdr", 0x00
__cons_sym: db "cons", 0x00
__eq_sym: db "eq", 0x00
__t_sym: db "t", 0x00
__names_end: