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 env list
eval-rest
( argv
argc )
52 extend invoke ( argv
argc this -- val )
53 MalNativeFn/xt
@ execute
;;
57 extend eval-invoke ( env list
this -- list
)
58 SpecialOp/xt
@ execute
;;
61 : install
-special
( symbol
xt )
62 SpecialOp. repl-env env
/set
;
65 parse
-allot
-name
MalSymbol.
70 : is-pair? ( obj -- bool )
73 defspecial quote ( env list -- form )
74 nip MalList/start @ cell+ @ ;;
76 s" concat" MalSymbol. constant concat-sym
77 s" cons" MalSymbol. constant cons-sym
80 : quasiquote0 { ast -- form }
82 here quote-sym , ast , here>MalList
84 ast to-list MalList/start @ { ast-start }
85 ast-start @ { ast[0] }
86 ast[0] unquote-sym m= if
90 ast[0] to-list MalList/start @ { ast[0]-start }
91 ast[0]-start @ splice-unquote-sym m= if
94 ast[0]-start cell+ @ ,
95 ast to-list MalList/rest quasiquote ,
104 ast to-list MalList/rest quasiquote ,
109 ' quasiquote0
is quasiquote
111 defspecial
quasiquote ( env list
)
112 MalList/start
@ cell+ @ ( ast
)
113 quasiquote TCO-eval ;;
115 defspecial
def! { env list
-- val }
116 list
MalList/start
@ cell+ { arg0
}
118 env arg0
cell+ @ eval dup { val } ( key
val )
121 defspecial
let* { old
-env list
-- val }
122 old
-env
MalEnv. { env
}
123 list
MalList/start
@ cell+ dup { arg0
}
125 dup MalList/start
@ { bindings
-start
} ( list
)
126 MalList/count
@ 0 +do
127 bindings
-start
i cells
+ dup @ swap
cell+ @ ( sym expr
)
131 env arg0
cell+ @ TCO-eval
132 \
TODO: dec refcount
of env
135 defspecial
do { env list
-- val }
136 list
MalList/start
@ { start
}
137 list
MalList/count
@ dup 1- { last
} 1 ?do
138 env start
i cells
+ @
146 defspecial
if { env list
-- val }
147 list
MalList/start
@ cell+ { arg0
}
148 env arg0
@ eval ( test
-val )
156 list
MalList/count
@ 3 > if
157 env arg0
cell+ cell+ @ TCO-eval
163 env arg0
cell+ @ TCO-eval
166 s
" &" MalSymbol. constant
&-sym
168 : new-user
-fn
-env
{ argv
argc mal
-fn
-- env
}
169 mal
-fn
MalUserFn/formal
-args
@ { f
-args
-list
}
170 mal
-fn
MalUserFn/env
@ MalEnv. { env
}
172 f
-args
-list
MalList/start
@ { f
-args
}
173 f
-args
-list
MalList/count
@ ?dup 0= if else
174 \ pass
empty list
for last
arg, unless
overridden below
175 1- cells
f-args
+ @ MalList new env env
/set
182 c cells
allocate throw
{ start
}
183 argv
i cells
+ start
c cells
cmove
184 f-args
i 1+ cells
+ @ ( more
-args
-symbol
)
185 start
c MalList. env env
/set
194 extend eval-invoke { call
-env list
mal-fn
-- list
}
195 call
-env list
eval-rest
198 extend invoke ( argv
argc mal-fn
)
199 dup { mal-fn
} new-user
-fn
-env
{ env
}
200 env
mal-fn
MalUserFn/body
@ TCO-eval ;;
203 defspecial
fn* { env list
-- val }
204 list
MalList/start
@ cell+ { arg0
}
206 env over
MalUserFn/env
!
207 arg0
@ to-list
over MalUserFn/formal
-args
!
208 arg0
cell+ @ over MalUserFn/body
! ;;
211 extend mal-eval { env sym
-- val }
215 ." Symbol '" sym pr
-str
safe-type ." ' not found." cr
222 : eval-ast
{ env list
-- list
}
224 list
MalList/start
@ { expr
-start
}
225 list
MalList/count
@ 0 ?do
226 env expr
-start
i cells
+ @ eval ,
231 extend mal-eval { env list
-- val }
232 env list
MalList/start
@ @ eval
233 env list
rot eval-invoke ;;
237 extend mal-eval ( env vector
-- vector
)
238 MalVector/list
@ eval-ast
239 MalVector new swap
over MalVector/list
! ;;
243 extend mal-eval ( env map
-- map
)
244 MalMap/list
@ eval-ast
245 MalMap new swap
over MalMap/list
! ;;
248 defcore
eval ( argv
argc )
249 drop @ repl-env swap
eval ;;
251 : rep
( str
-addr str
-len
-- str
-addr str
-len
)
256 : mk
-args
-list
( -- )
259 next
-arg 2dup 0 0 d
<> while
264 create
buff 128 allot
265 77777777777 constant
stack-leak
-detect
269 defcore
swap! { argv
argc -- val }
270 \ argv
is (atom
fn args
...)
273 argc 1- { call
-argc }
274 call
-argc cells
allocate throw
{ call
-argv
}
275 atom
Atom/val call-argv
1 cells
cmove
276 argv
cell+ cell+ call-argv
cell+ call-argc 1- cells
cmove
277 call-argv
call-argc fn invoke
278 dup TCO-eval = if drop eval endif { new-val }
279 new-val atom Atom/val !
282 s
\" (def! load
-file
(fn* (f) (eval (read
-string (str
\"(do \" (slurp
f) \")\")))))" rep 2drop
288 buff 128 stdin read-line throw
289 while ( num-bytes-read )
290 buff swap ( str-addr str-len )
293 catch ?dup 0= if safe-type else ." Caught error " . endif
295 stack-leak-detect <> if ." --stack leak
--" cr endif
299 mk-args-list { args-list }
300 args-list MalList/count @ 0= if
301 s" *ARGV*" MalSymbol. MalList/Empty repl-env env/set
304 args-list MalList/start @ @ { filename }
305 s" *ARGV*" MalSymbol. args-list MalList/rest repl-env env/set
308 here s" load
-file
" MalSymbol. , filename , here>MalList