1 // @import types/boxed/*.ck
2 // @import types/MalObject.ck
3 // @import types/mal/*.ck
8 // @import types/MalSubr.ck
9 // @import types/subr/*.ck
13 fun MalObject READ(string input)
15 return Reader.read_str(input);
18 fun MalObject EVAL(MalObject m, Env env)
22 if( m.type != "list" )
24 return eval_ast(m, env);
27 if( (m$MalList).value().size() == 0 )
32 (m$MalList).value() @=> MalObject ast[];
34 if( ast[0].type == "symbol" )
36 (ast[0]$MalSymbol).value() => string a0;
40 (ast[1]$MalSymbol).value() => string a1;
42 EVAL(ast[2], env) @=> MalObject value;
43 if( value.type == "error" )
51 else if( a0 == "let*" )
53 Env.create(env) @=> Env let_env;
54 Util.sequenceToMalObjectArray(ast[1]) @=> MalObject bindings[];
56 for( 0 => int i; i < bindings.size(); 2 +=> i)
58 (bindings[i]$MalSymbol).value() => string symbol;
59 EVAL(bindings[i+1], let_env) @=> MalObject value;
61 if( value.type == "error" )
66 let_env.set(symbol, value);
75 MalObject.slice(ast, 1, ast.size()) @=> MalObject forms[];
76 eval_ast(MalList.create(forms), env) @=> MalObject value;
78 if( value.type == "error" )
83 // HACK: this assumes do gets at least one argument...
84 ast[ast.size()-1] @=> m;
89 EVAL(ast[1], env) @=> MalObject condition;
91 if( condition.type == "error" )
96 if( !(condition.type == "nil") && !(condition.type == "false") )
105 return Constants.NIL;
114 else if( a0 == "fn*" )
116 (ast[1]$MalList).value() @=> MalObject arg_values[];
117 string args[arg_values.size()];
119 for( 0 => int i; i < arg_values.size(); i++ )
121 (arg_values[i]$MalSymbol).value() => args[i];
124 ast[2] @=> MalObject _ast;
126 return Func.create(env, args, _ast);
130 eval_ast(m, env) @=> MalObject result;
131 if( result.type == "error" )
136 (result$MalList).value() @=> MalObject values[];
137 values[0].type => string type;
138 MalObject.slice(values, 1) @=> MalObject args[];
142 values[0]$MalSubr @=> MalSubr subr;
143 return subr.call(args);
145 else // type == "func"
147 values[0]$Func @=> Func func;
148 Env.create(func.env, func.args, args) @=> Env eval_env;
156 fun MalObject eval_ast(MalObject m, Env env)
158 m.type => string type;
160 if( type == "symbol" )
162 (m$MalSymbol).value() => string symbol;
163 return env.get(symbol);
165 else if( type == "list" || type == "vector" || type == "hashmap" )
167 (m$MalList).value() @=> MalObject values[];
168 MalObject results[values.size()];
170 if( type != "hashmap" )
172 for( 0 => int i; i < values.size(); i++ )
174 EVAL(values[i], env) @=> MalObject result;
176 if( result.type == "error" )
181 result @=> results[i];
186 for( 0 => int i; i < values.size(); i++ )
190 values[i] @=> results[i];
194 EVAL(values[i], env) @=> results[i];
201 return MalList.create(results);
203 else if( type == "vector" )
205 return MalVector.create(results);
207 else if( type == "hashmap" )
209 return MalHashMap.create(results);
218 fun string PRINT(MalObject m)
220 return Printer.pr_str(m, true);
223 Env.create(null) @=> Env repl_env;
224 for( 0 => int i; i < Core.names.size(); i++ )
226 Core.names[i] => string name;
227 repl_env.set(name, Core.ns[name]);
230 fun string rep(string input)
232 READ(input) @=> MalObject m;
234 if( m.type == "error" )
236 return Status.toMessage(m$MalError);
239 EVAL(m, repl_env) @=> MalObject result;
240 if( result.type == "error" )
242 return Status.toMessage(result$MalError);
245 return PRINT(result);
248 rep("(def! not (fn* (a) (if a false true)))");
257 stdin.prompt("user>") => now;
258 stdin.getLine() => input;
259 rep(input) => string output;
261 if( output == "empty input" )
263 // proceed immediately with prompt
267 Util.println(output);