5 core MalEnv. constant
repl-env
7 99999999 constant
TCO-eval
12 \
." eval-> " dup pr
-str safe
-type cr
19 \
." Type: " dup mal
-type @ type-name
safe-type cr
22 MalDefault extend mal
-eval
nip ;; drop \
By default, evalutate
to yourself
25 extend eval
-invoke
{ env list
kw -- val }
26 0 kw env list
MalList/start
@ cell
+ @ eval
get
28 \ compute
not-found value
29 list
MalList/count
@ 1 > if
30 env list
MalList/start
@ 2 cells
+ @ TCO-eval
37 \ eval
all but
the first
item of list
38 : eval
-rest
{ env list
-- argv argc
}
39 list
MalList/start
@ cell
+ { expr
-start
}
40 list
MalList/count
@ 1- { argc
}
41 argc cells
allocate throw
{ target
}
43 env expr
-start
i cells
+ @ eval
49 extend eval
-invoke
( env list
this -- list
)
50 MalNativeFn/xt
@ { xt
}
51 eval
-rest
( argv
argc )
52 xt
execute ( return
-val ) ;;
56 extend eval
-invoke
( env list
this -- list
)
57 SpecialOp/xt
@ execute ;;
60 : install
-special
( symbol
xt )
61 SpecialOp. repl-env env
/set
;
64 parse
-allot
-name
MalSymbol.
69 defspecial quote ( env list -- form )
70 nip MalList/start @ cell+ @ ;;
72 defspecial def! { env list -- val }
73 list MalList/start @ cell+ { arg0 }
75 env arg0 cell+ @ eval dup { val } ( key val )
78 defspecial let* { old-env list -- val }
79 old-env MalEnv. { env }
80 list MalList/start @ cell+ dup { arg0 }
82 dup MalList/start @ { bindings-start } ( list )
84 bindings-start i cells + dup @ swap cell+ @ ( sym expr )
88 env arg0 cell+ @ TCO-eval
89 \ TODO: dec refcount of env
92 defspecial do { env list -- val }
93 list MalList/start @ { start }
94 list MalList/count @ dup 1- { last } 1 ?do
103 defspecial if { env list -- val }
104 list MalList/start @ cell+ { arg0 }
105 env arg0 @ eval ( test-val )
113 list MalList/count @ 3 > if
114 env arg0 cell+ cell+ @ TCO-eval
120 env arg0 cell+ @ TCO-eval
123 s" &" MalSymbol. constant &-sym
126 extend eval-invoke { call-env list mal-fn -- list }
127 call-env list eval-rest { argv argc }
129 mal-fn MalUserFn/formal-args @ { f-args-list }
130 mal-fn MalUserFn/env @ MalEnv. { env }
132 f-args-list MalList/start @ { f-args }
133 f-args-list MalList/count @ ?dup 0= if else
134 \ pass empty list for last arg, unless overridden below
135 1- cells f-args + @ MalList new env env/set
141 f-args i 1+ cells + @ ( more-args-symbol )
142 MalList new ( sym more-args )
143 argc i - dup { c } over MalList/count !
144 c cells allocate throw dup { start } over MalList/start !
145 argv i cells + start c cells cmove
153 env mal-fn MalUserFn/body @ TCO-eval ;;
156 defspecial fn* { env list -- val }
157 list MalList/start @ cell+ { arg0 }
159 env over MalUserFn/env !
160 arg0 @ to-list over MalUserFn/formal-args !
161 arg0 cell+ @ over MalUserFn/body ! ;;
164 extend mal-eval { env sym -- val }
168 0 0 s" ' not found" sym pr-str s" '" ...throw-str
174 : eval-ast { env list -- list }
176 list MalList/start @ { expr-start }
177 list MalList/count @ 0 ?do
178 env expr-start i cells + @ eval ,
183 extend mal-eval { env list -- val }
184 list MalList/count @ 0= if
187 env list MalList/start @ @ eval
188 env list rot eval-invoke
193 extend mal-eval ( env vector -- vector )
194 MalVector/list @ eval-ast
195 MalVector new swap over MalVector/list ! ;;
199 extend mal-eval ( env map -- map )
200 MalMap/list @ eval-ast
201 MalMap new swap over MalMap/list ! ;;
204 : rep ( str-addr str-len -- str-addr str-len )
209 create buff 128 allot
210 77777777777 constant stack-leak-detect
212 s\" (def! not (fn* (x) (if x false true)))" rep 2drop
218 buff 128 stdin read-line throw
219 while ( num-bytes-read )
221 buff swap ( str-addr str-len )
223 \
execute ['] nop \ uncomment to see stack traces
226 stack-leak-detect <> if ." --stack leak--" cr endif
228 begin stack-leak-detect = until
230 s" forth-errno" MalKeyword. errno MalInt. MalMap/Empty assoc
233 ." Uncaught exception: "
234 exception-object pr-str safe-type cr