Merge pull request #380 from bjh21/bjh21-bbc-basic
[jackhill/mal.git] / chuck / step3_env.ck
CommitLineData
2e3d457e 1// @import readline.ck
0c8b871a
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
0c8b871a
VS
16// @import util/*.ck
17// @import reader.ck
18// @import printer.ck
aa0ac94f 19// @import env.ck
7cabea4f 20// @import func.ck
f823ec25
VS
21// @import types/MalSubr.ck
22// @import types/subr/*.ck
0c8b871a
VS
23
24fun MalObject READ(string input)
25{
26 return Reader.read_str(input);
27}
28
29fun MalObject EVAL(MalObject m, Env env)
30{
31 if( m.type == "list" )
32 {
33 if( (m$MalList).value().size() == 0 )
34 {
35 return m;
36 }
37
38 (m$MalList).value() @=> MalObject ast[];
39 (ast[0]$MalSymbol).value() => string a0;
40
41 if( a0 == "def!" )
42 {
43 (ast[1]$MalSymbol).value() => string a1;
44
45 EVAL(ast[2], env) @=> MalObject value;
46 if( value.type == "error" )
47 {
48 return value;
49 }
50
51 env.set(a1, value);
52 return value;
53 }
54 else if( a0 == "let*" )
55 {
56 Env.create(env) @=> Env let_env;
57 Util.sequenceToMalObjectArray(ast[1]) @=> MalObject bindings[];
58
59 for( 0 => int i; i < bindings.size(); 2 +=> i)
60 {
61 (bindings[i]$MalSymbol).value() => string symbol;
62 EVAL(bindings[i+1], let_env) @=> MalObject value;
63
64 if( value.type == "error" )
65 {
66 return value;
67 }
68
69 let_env.set(symbol, value);
70 }
71
72 return EVAL(ast[2], let_env);
73 }
74
75 eval_ast(m, env) @=> MalObject result;
76 if( result.type == "error" )
77 {
78 return result;
79 }
80
81 (result$MalList).value() @=> MalObject values[];
82 values[0]$MalSubr @=> MalSubr subr;
83 MalObject.slice(values, 1) @=> MalObject args[];
84
85 return subr.call(args);
86 }
87 else
88 {
89 eval_ast(m, env) @=> MalObject result;
90 return result;
91 }
92}
93
94fun MalObject eval_ast(MalObject m, Env env)
95{
96 m.type => string type;
97
98 if( type == "symbol" )
99 {
100 (m$MalSymbol).value() => string symbol;
101 return env.get(symbol);
102 }
103 else if( type == "list" || type == "vector" || type == "hashmap" )
104 {
105 (m$MalList).value() @=> MalObject values[];
106 MalObject results[values.size()];
107
108 if( type != "hashmap" )
109 {
110 for( 0 => int i; i < values.size(); i++ )
111 {
112 EVAL(values[i], env) @=> MalObject result;
113
114 if( result.type == "error" )
115 {
116 return result;
117 }
118
119 result @=> results[i];
120 }
121 }
122 else
123 {
124 for( 0 => int i; i < values.size(); i++ )
125 {
126 if( i % 2 == 0 )
127 {
128 values[i] @=> results[i];
129 }
130 else
131 {
132 EVAL(values[i], env) @=> results[i];
133 }
134 }
135 }
136
137 if( type == "list" )
138 {
139 return MalList.create(results);
140 }
141 else if( type == "vector" )
142 {
143 return MalVector.create(results);
144 }
145 else if( type == "hashmap" )
146 {
147 return MalHashMap.create(results);
148 }
149 }
150 else
151 {
152 return m;
153 }
154}
155
156fun string PRINT(MalObject m)
157{
158 return Printer.pr_str(m, true);
159}
160
161Env.create(null) @=> Env repl_env;
162repl_env.set("+", new MalAdd);
163repl_env.set("-", new MalSub);
164repl_env.set("*", new MalMul);
165repl_env.set("/", new MalDiv);
166
98c1ecf2
VS
167fun string errorMessage(MalObject m)
168{
169 (m$MalError).value() @=> MalObject value;
dd7a4f55 170 return "exception: " + Printer.pr_str(value, true);
98c1ecf2
VS
171}
172
0c8b871a
VS
173fun string rep(string input)
174{
175 READ(input) @=> MalObject m;
176
177 if( m.type == "error" )
178 {
98c1ecf2 179 return errorMessage(m);
0c8b871a
VS
180 }
181
182 EVAL(m, repl_env) @=> MalObject result;
183 if( result.type == "error" )
184 {
98c1ecf2 185 return errorMessage(result);
0c8b871a
VS
186 }
187
188 return PRINT(result);
189}
190
191fun void main()
192{
2e3d457e 193 int done;
0c8b871a 194
2e3d457e 195 while( !done )
0c8b871a 196 {
2e3d457e 197 Readline.readline("user> ") => string input;
0c8b871a 198
2e3d457e 199 if( input != null )
0c8b871a 200 {
2e3d457e
VS
201 rep(input) => string output;
202
203 if( output == "empty input" )
204 {
205 // proceed immediately with prompt
206 }
207 else
208 {
209 Util.println(output);
210 }
0c8b871a
VS
211 }
212 else
213 {
2e3d457e 214 true => done;
0c8b871a
VS
215 }
216 }
217}
218
219main();