DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / forth / step3_env.fs
CommitLineData
69972a83
C
1require reader.fs
2require printer.fs
3require env.fs
4
5: args-as-native { argv argc -- entry*argc... }
6 argc 0 ?do
7 argv i cells + @ as-native
8 loop ;
9
100 MalEnv. constant repl-env
136ce7c9
C
11s" +" MalSymbol. :noname args-as-native + MalInt. ; MalNativeFn. repl-env env/set
12s" -" MalSymbol. :noname args-as-native - MalInt. ; MalNativeFn. repl-env env/set
13s" *" MalSymbol. :noname args-as-native * MalInt. ; MalNativeFn. repl-env env/set
14s" /" MalSymbol. :noname args-as-native / MalInt. ; MalNativeFn. repl-env env/set
69972a83 15
45c1894b
C
16: read read-str ;
17: eval ( env obj ) mal-eval ;
18: print
19 \ ." Type: " dup mal-type @ type-name safe-type cr
20 pr-str ;
69972a83 21
45c1894b 22MalDefault extend mal-eval nip ;; drop \ By default, evalutate to yourself
69972a83
C
23
24MalKeyword
45c1894b
C
25 extend eval-invoke { env list kw -- val }
26 0 kw env list MalList/start @ cell+ @ eval get
e6106d45
C
27 ?dup 0= if
28 \ compute not-found value
29 list MalList/count @ 1 > if
45c1894b 30 env list MalList/start @ 2 cells + @ eval
e6106d45
C
31 else
32 mal-nil
33 endif
34 endif ;;
69972a83
C
35drop
36
45c1894b
C
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 }
42 argc 0 ?do
43 env expr-start i cells + @ eval
44 target i cells + !
69972a83 45 loop
45c1894b
C
46 target argc ;
47
48MalNativeFn
49 extend eval-invoke ( env list this -- list )
50 MalNativeFn/xt @ { xt }
51 eval-rest ( argv argc )
52 xt execute ( return-val ) ;;
69972a83
C
53drop
54
55SpecialOp
45c1894b 56 extend eval-invoke ( env list this -- list )
69972a83
C
57 SpecialOp/xt @ execute ;;
58drop
59
79feb89f
C
60: install-special ( symbol xt )
61 SpecialOp. repl-env env/set ;
69972a83 62
79feb89f
C
63: defspecial
64 parse-allot-name MalSymbol.
65 ['] install-special
66 :noname
67 ;
68
69defspecial quote ( env list -- form )
70 nip MalList/start @ cell+ @ ;;
71
45c1894b 72defspecial def! { env list -- val }
c05d35e8 73 list MalList/start @ cell+ { arg0 }
69972a83 74 arg0 @ ( key )
45c1894b
C
75 env arg0 cell+ @ eval dup { val } ( key val )
76 env env/set val ;;
69972a83 77
45c1894b 78defspecial let* { old-env list -- val }
69972a83 79 old-env MalEnv. { env }
c05d35e8
C
80 list MalList/start @ cell+ dup { arg0 }
81 @ to-list
82 dup MalList/start @ { bindings-start } ( list )
83 MalList/count @ 0 +do
69972a83 84 bindings-start i cells + dup @ swap cell+ @ ( sym expr )
45c1894b 85 env swap eval
69972a83
C
86 env env/set
87 2 +loop
45c1894b 88 env arg0 cell+ @ eval
69972a83 89 \ TODO: dec refcount of env
79feb89f 90 ;;
69972a83
C
91
92MalSymbol
93 extend mal-eval { env sym -- val }
a631063f 94 sym env env/get-addr
69972a83
C
95 dup 0= if
96 drop
9e2a4ab0 97 0 0 s" ' not found" sym pr-str s" '" ...throw-str
a631063f
C
98 else
99 @
69972a83
C
100 endif ;;
101drop
102
45c1894b 103: eval-ast { env list -- list }
69972a83 104 here
c05d35e8
C
105 list MalList/start @ { expr-start }
106 list MalList/count @ 0 ?do
45c1894b 107 env expr-start i cells + @ eval ,
69972a83 108 loop
e6106d45
C
109 here>MalList ;
110
111MalList
112 extend mal-eval { env list -- val }
4e258d3a
DM
113 list MalList/count @ 0= if
114 list
115 else
116 env list MalList/start @ @ eval
117 env list rot eval-invoke
118 endif ;;
69972a83
C
119drop
120
121MalVector
122 extend mal-eval ( env vector -- vector )
45c1894b 123 MalVector/list @ eval-ast
69972a83
C
124 MalVector new swap over MalVector/list ! ;;
125drop
126
127MalMap
128 extend mal-eval ( env map -- map )
45c1894b 129 MalMap/list @ eval-ast
69972a83
C
130 MalMap new swap over MalMap/list ! ;;
131drop
132
45c1894b 133: rep ( str-addr str-len -- str-addr str-len )
69972a83
C
134 read
135 repl-env swap eval
136 print ;
137
138create buff 128 allot
45c1894b 13977777777777 constant stack-leak-detect
69972a83
C
140
141: read-lines
142 begin
143 ." user> "
45c1894b 144 stack-leak-detect
69972a83 145 buff 128 stdin read-line throw
45c1894b 146 while ( num-bytes-read )
9e2a4ab0
JMC
147 dup 0 <> if
148 buff swap ( str-addr str-len )
149 ['] rep
150 \ execute ['] nop \ uncomment to see stack traces
151 catch ?dup 0= if
152 safe-type cr
153 stack-leak-detect <> if ." --stack leak--" cr endif
154 else { errno }
155 begin stack-leak-detect = until
156 errno 1 <> if
157 s" forth-errno" MalKeyword. errno MalInt. MalMap/Empty assoc
158 to exception-object
159 endif
160 ." Uncaught exception: "
161 exception-object pr-str safe-type cr
162 endif
163 endif
69972a83
C
164 repeat ;
165
166read-lines
167cr
168bye