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