DISABLE FDs (REMOVE ME).
[jackhill/mal.git] / chuck / step4_if_fn_do.ck
CommitLineData
2e3d457e 1// @import readline.ck
674e1c56
VS
2// @import types/boxed/*.ck
3// @import types/MalObject.ck
98c1ecf2
VS
4// @import types/mal/MalAtom.ck
5// @import types/mal/MalError.ck
6// @import types/mal/MalNil.ck
7// @import types/mal/MalFalse.ck
8// @import types/mal/MalTrue.ck
9// @import types/mal/MalInt.ck
10// @import types/mal/MalString.ck
11// @import types/mal/MalSymbol.ck
12// @import types/mal/MalKeyword.ck
13// @import types/mal/MalList.ck
14// @import types/mal/MalVector.ck
15// @import types/mal/MalHashMap.ck
674e1c56
VS
16// @import util/*.ck
17// @import reader.ck
18// @import printer.ck
aa0ac94f 19// @import env.ck
7cabea4f 20// @import func.ck
674e1c56
VS
21// @import types/MalSubr.ck
22// @import types/subr/*.ck
674e1c56 23// @import core.ck
674e1c56
VS
24
25fun MalObject READ(string input)
26{
27 return Reader.read_str(input);
28}
29
30fun MalObject EVAL(MalObject m, Env env)
31{
32 if( m.type == "list" )
33 {
34 if( (m$MalList).value().size() == 0 )
35 {
36 return m;
37 }
38
39 (m$MalList).value() @=> MalObject ast[];
40
41 if( ast[0].type == "symbol" )
42 {
43 (ast[0]$MalSymbol).value() => string a0;
44
45 if( a0 == "def!" )
46 {
47 (ast[1]$MalSymbol).value() => string a1;
48
49 EVAL(ast[2], env) @=> MalObject value;
50 if( value.type == "error" )
51 {
52 return value;
53 }
54
55 env.set(a1, value);
56 return value;
57 }
58 else if( a0 == "let*" )
59 {
60 Env.create(env) @=> Env let_env;
61 Util.sequenceToMalObjectArray(ast[1]) @=> MalObject bindings[];
62
63 for( 0 => int i; i < bindings.size(); 2 +=> i)
64 {
65 (bindings[i]$MalSymbol).value() => string symbol;
66 EVAL(bindings[i+1], let_env) @=> MalObject value;
67
68 if( value.type == "error" )
69 {
70 return value;
71 }
72
73 let_env.set(symbol, value);
74 }
75
76 return EVAL(ast[2], let_env);
77 }
78 else if( a0 == "do" )
79 {
80 MalObject.slice(ast, 1) @=> MalObject forms[];
81 eval_ast(MalList.create(forms), env) @=> MalObject value;
82
83 if( value.type == "error" )
84 {
85 return value;
86 }
87
88 (value$MalList).value() @=> MalObject values[];
89
90 return values[values.size()-1];
91 }
92 else if( a0 == "if" )
93 {
94 EVAL(ast[1], env) @=> MalObject condition;
95
96 if( condition.type == "error" )
97 {
98 return condition;
99 }
100
101 if( !(condition.type == "nil") && !(condition.type == "false") )
102 {
103 return EVAL(ast[2], env);
104 }
105 else
106 {
107 if( ast.size() < 4 )
108 {
f823ec25 109 return Constants.NIL;
674e1c56
VS
110 }
111 else
112 {
113 return EVAL(ast[3], env);
114 }
115 }
116 }
117 else if( a0 == "fn*" )
118 {
119 (ast[1]$MalList).value() @=> MalObject arg_values[];
120 string args[arg_values.size()];
121
122 for( 0 => int i; i < arg_values.size(); i++ )
123 {
124 (arg_values[i]$MalSymbol).value() => args[i];
125 }
126
127 ast[2] @=> MalObject _ast;
128
129 return Func.create(env, args, _ast);
130 }
131 }
132
133 eval_ast(m, env) @=> MalObject result;
134 if( result.type == "error" )
135 {
136 return result;
137 }
138
139 (result$MalList).value() @=> MalObject values[];
140 values[0].type => string type;
141 MalObject.slice(values, 1) @=> MalObject args[];
142
143 if( type == "subr" )
144 {
145 values[0]$MalSubr @=> MalSubr subr;
146 return subr.call(args);
147 }
148 else // type == "func"
149 {
150 values[0]$Func @=> Func func;
151 Env.create(func.env, func.args, args) @=> Env eval_env;
152 return EVAL(func.ast, eval_env);
153 }
154 }
155 else
156 {
157 eval_ast(m, env) @=> MalObject result;
158 return result;
159 }
160}
161
162fun MalObject eval_ast(MalObject m, Env env)
163{
164 m.type => string type;
165
166 if( type == "symbol" )
167 {
168 (m$MalSymbol).value() => string symbol;
169 return env.get(symbol);
170 }
171 else if( type == "list" || type == "vector" || type == "hashmap" )
172 {
173 (m$MalList).value() @=> MalObject values[];
174 MalObject results[values.size()];
175
176 if( type != "hashmap" )
177 {
178 for( 0 => int i; i < values.size(); i++ )
179 {
180 EVAL(values[i], env) @=> MalObject result;
181
182 if( result.type == "error" )
183 {
184 return result;
185 }
186
187 result @=> results[i];
188 }
189 }
190 else
191 {
192 for( 0 => int i; i < values.size(); i++ )
193 {
194 if( i % 2 == 0 )
195 {
196 values[i] @=> results[i];
197 }
198 else
199 {
200 EVAL(values[i], env) @=> results[i];
201 }
202 }
203 }
204
205 if( type == "list" )
206 {
207 return MalList.create(results);
208 }
209 else if( type == "vector" )
210 {
211 return MalVector.create(results);
212 }
213 else if( type == "hashmap" )
214 {
215 return MalHashMap.create(results);
216 }
217 }
218 else
219 {
220 return m;
221 }
222}
223
224fun string PRINT(MalObject m)
225{
226 return Printer.pr_str(m, true);
227}
228
229Env.create(null) @=> Env repl_env;
230for( 0 => int i; i < Core.names.size(); i++ )
231{
232 Core.names[i] => string name;
233 repl_env.set(name, Core.ns[name]);
234}
235
98c1ecf2
VS
236fun string errorMessage(MalObject m)
237{
238 (m$MalError).value() @=> MalObject value;
dd7a4f55 239 return "exception: " + Printer.pr_str(value, true);
98c1ecf2
VS
240}
241
674e1c56
VS
242fun string rep(string input)
243{
244 READ(input) @=> MalObject m;
245
246 if( m.type == "error" )
247 {
98c1ecf2 248 return errorMessage(m);
674e1c56
VS
249 }
250
251 EVAL(m, repl_env) @=> MalObject result;
252 if( result.type == "error" )
253 {
98c1ecf2 254 return errorMessage(result);
674e1c56
VS
255 }
256
257 return PRINT(result);
258}
259
260rep("(def! not (fn* (a) (if a false true)))");
261
262fun void main()
263{
2e3d457e 264 int done;
674e1c56 265
2e3d457e 266 while( !done )
674e1c56 267 {
2e3d457e 268 Readline.readline("user> ") => string input;
674e1c56 269
2e3d457e 270 if( input != null )
674e1c56 271 {
2e3d457e
VS
272 rep(input) => string output;
273
274 if( output == "empty input" )
275 {
276 // proceed immediately with prompt
277 }
278 else
279 {
280 Util.println(output);
281 }
674e1c56
VS
282 }
283 else
284 {
2e3d457e 285 true => done;
674e1c56
VS
286 }
287 }
288}
289
290main();