Basic: add step3, vector/hash-map evaluation.
[jackhill/mal.git] / basic / step2_eval.in.bas
CommitLineData
b7b1787f
JM
1GOTO MAIN
2
3REM $INCLUDE: 'readline.in.bas'
4REM $INCLUDE: 'types.in.bas'
5REM $INCLUDE: 'reader.in.bas'
6REM $INCLUDE: 'printer.in.bas'
7
8REM READ(A$) -> R%
9MAL_READ:
10 GOSUB READ_STR
11 RETURN
12
13REM EVAL_AST(A%, E%) -> R%
14EVAL_AST:
15 ZL%=ZL%+2: ZZ%(ZL%-1)=E%: ZZ%(ZL%)=A%
16 IF ER%=1 THEN GOTO EVAL_AST_RETURN
17
18 REM AZ%=A%: GOSUB PR_STR
19 REM PRINT "EVAL_AST: " + R$ + "(" + STR$(R%) + ")"
20
21 T%=Z%(A%,0)
22 IF T%=5 THEN EVAL_AST_SYMBOL
0cb556e0
JM
23 IF T%=6 THEN EVAL_AST_SEQ
24 IF T%=8 THEN EVAL_AST_SEQ
25 IF T%=10 THEN EVAL_AST_SEQ
b7b1787f
JM
26 R%=A%
27 GOTO EVAL_AST_RETURN
28
29 EVAL_AST_SYMBOL:
30 HM%=E%: K%=A%: GOSUB HASHMAP_GET
31 IF T3%=0 THEN ER%=1: ER$="'" + ZS$(Z%(A%,1)) + "' not found"
32 GOTO EVAL_AST_RETURN
33
0cb556e0
JM
34 EVAL_AST_SEQ:
35 REM push type of sequence
36 ZL%=ZL%+1
37 ZZ%(ZL%)=T%
38 REM push sequence index
39 ZL%=ZL%+1
40 ZZ%(ZL%)=-1
41 REM push future return value (new sequence)
b7b1787f
JM
42 ZL%=ZL%+1
43 ZZ%(ZL%)=ZI%
0cb556e0 44 REM push previous new sequence entry
b7b1787f
JM
45 ZL%=ZL%+1
46 ZZ%(ZL%)=ZI%
47
0cb556e0
JM
48 EVAL_AST_SEQ_LOOP:
49 REM create new sequence entry
50 Z%(ZI%,0)=ZZ%(ZL%-3)
b7b1787f
JM
51 Z%(ZI%,1)=0
52 ZI%=ZI%+1
53
0cb556e0
JM
54 REM update index
55 ZZ%(ZL%-2)=ZZ%(ZL%-2)+1
56
57 REM check if we are done evaluating the sequence
58 IF Z%(A%,1)=0 THEN GOTO EVAL_AST_SEQ_LOOP_DONE
b7b1787f
JM
59
60 REM create value ptr placeholder
61 Z%(ZI%,0)=15
62 Z%(ZI%,1)=0
63 ZI%=ZI%+1
64
0cb556e0
JM
65 REM if hashmap, skip eval of even entries (keys)
66 R%=A%+1
67 IF (ZZ%(ZL%-3)=10) AND ((ZZ%(ZL%-2) AND 1)=0) THEN GOTO EVAL_AST_SEQ_SKIP
68
b7b1787f
JM
69 REM call EVAL for each entry
70 A%=A%+1: GOSUB EVAL
71 A%=A%-1
72
0cb556e0
JM
73 EVAL_AST_SEQ_SKIP:
74
75 REM update previous sequence entry to point to current entry
b7b1787f
JM
76 Z%(ZZ%(ZL%),1)=ZI%
77 REM update previous value pointer to evaluated entry
78 Z%(ZZ%(ZL%)+1,1)=R%
79 REM update previous ptr to current entry
80 ZZ%(ZL%)=ZI%
81
0cb556e0 82 REM process the next sequence entry
b7b1787f
JM
83 A%=Z%(A%,1)
84
0cb556e0
JM
85 GOTO EVAL_AST_SEQ_LOOP
86 EVAL_AST_SEQ_LOOP_DONE:
87 REM pop previous new sequence entry value
b7b1787f 88 ZL%=ZL%-1
0cb556e0 89 REM pop return value (new seq), index, and seq type
b7b1787f 90 R%=ZZ%(ZL%)
0cb556e0 91 ZL%=ZL%-3
b7b1787f
JM
92 GOTO EVAL_AST_RETURN
93
94 EVAL_AST_RETURN:
95 E%=ZZ%(ZL%-1): A%=ZZ%(ZL%): ZL%=ZL%-2
96 RETURN
97
98REM EVAL(A%, E%)) -> R%
99EVAL:
100 ZL%=ZL%+2: ZZ%(ZL%-1)=E%: ZZ%(ZL%)=A%
101 IF ER%=1 THEN GOTO EVAL_RETURN
102
103 REM AZ%=A%: GOSUB PR_STR
104 REM PRINT "EVAL: " + R$ + "(" + STR$(R%) + ")"
105
106 GOSUB LIST_Q
107 IF R% THEN GOTO APPLY_LIST
108 REM ELSE
109 GOSUB EVAL_AST
110 GOTO EVAL_RETURN
111
112 APPLY_LIST:
113 GOSUB EMPTY_Q
114 IF R% THEN R%=A%: GOTO EVAL_RETURN
115
0cb556e0
JM
116 EVAL_INVOKE:
117 GOSUB EVAL_AST
118 IF ER%=1 THEN GOTO EVAL_RETURN
119 F%=R%+1
120 AR%=Z%(R%,1): REM REST
121 R%=F%: GOSUB DEREF
122 F%=R%
123 IF Z%(F%,0)<>12 THEN ER%=1: ER$="apply of non-function": GOTO EVAL_RETURN
124 GOSUB DO_FUNCTION
125 GOTO EVAL_RETURN
b7b1787f
JM
126
127 EVAL_RETURN:
128 E%=ZZ%(ZL%-1): A%=ZZ%(ZL%): ZL%=ZL%-2
129 RETURN
130
131REM DO_FUNCTION(F%, AR%)
132DO_FUNCTION:
133 AZ%=F%: GOSUB PR_STR
134 F$=R$
135 AZ%=AR%: GOSUB PR_STR
136 AR$=R$
137
138 REM Get the function number
139 FF%=Z%(F%,1)
140
141 REM Get argument values
142 R%=AR%+1: GOSUB DEREF
143 AA%=Z%(R%,1)
144 R%=Z%(AR%,1)+1: GOSUB DEREF
145 AB%=Z%(R%,1)
146
147 REM Allocate the return value
148 R%=ZI%
149 ZI%=ZI%+1
150
151 REM Switch on the function number
152 IF FF%=1 THEN DO_ADD
153 IF FF%=2 THEN DO_SUB
154 IF FF%=3 THEN DO_MULT
155 IF FF%=4 THEN DO_DIV
156 ER%=1: ER$="unknown function" + STR$(FF%): RETURN
157
158 DO_ADD:
159 Z%(R%,0)=2
160 Z%(R%,1)=AA%+AB%
161 GOTO DO_FUNCTION_DONE
162 DO_SUB:
163 Z%(R%,0)=2
164 Z%(R%,1)=AA%-AB%
165 GOTO DO_FUNCTION_DONE
166 DO_MULT:
167 Z%(R%,0)=2
168 Z%(R%,1)=AA%*AB%
169 GOTO DO_FUNCTION_DONE
170 DO_DIV:
171 Z%(R%,0)=2
172 Z%(R%,1)=AA%/AB%
173 GOTO DO_FUNCTION_DONE
174
175 DO_FUNCTION_DONE:
176 RETURN
177
178REM PRINT(A%) -> R$
179MAL_PRINT:
180 AZ%=A%: GOSUB PR_STR
181 RETURN
182
183REM REP(A$) -> R$
184REM Assume RE% has repl_env
185REP:
186 GOSUB MAL_READ
187 IF ER% THEN RETURN
188 A%=R%: E%=RE%: GOSUB EVAL
189 IF ER% THEN RETURN
190 A%=R%: GOSUB MAL_PRINT
191 IF ER% THEN RETURN
192 RETURN
193
194REM MAIN program
195MAIN:
196 GOSUB INIT_MEMORY
197
198 REM repl_env
199 GOSUB HASHMAP
200 RE%=R%
201
202 REM + function
203 A%=1: GOSUB NATIVE_FUNCTION
204 HM%=RE%: K$="+": V%=R%: GOSUB ASSOC1_S
205 RE%=R%
206
207 REM - function
208 A%=2: GOSUB NATIVE_FUNCTION
209 HM%=RE%: K$="-": V%=R%: GOSUB ASSOC1_S
210 RE%=R%
211
212 REM * function
213 A%=3: GOSUB NATIVE_FUNCTION
214 HM%=RE%: K$="*": V%=R%: GOSUB ASSOC1_S
215 RE%=R%
216
217 REM / function
218 A%=4: GOSUB NATIVE_FUNCTION
219 HM%=RE%: K$="/": V%=R%: GOSUB ASSOC1_S
220 RE%=R%
221
222 AZ%=RE%: GOSUB PR_STR
223 PRINT "env: " + R$ + "(" + STR$(RE%) + ")"
224
225 MAIN_LOOP:
226 A$="user> "
227 GOSUB READLINE: REM /* call input parser */
228 IF EOF=1 THEN GOTO MAIN_DONE
229 A$=R$: GOSUB REP: REM /* call REP */
230 IF ER% THEN GOTO ERROR
231 PRINT R$
232 GOTO MAIN_LOOP
233
234 ERROR:
235 PRINT "Error: " + ER$
236 ER%=0
237 ER$=""
238 GOTO MAIN_LOOP
239
240 MAIN_DONE:
0cb556e0 241 PRINT "Free: " + STR$(FRE(0))
b7b1787f
JM
242 END
243