Differences From Artifact [27ad20bc14df9938]:
- File
polemy/eval.d
- 2010-11-21 08:18:05 - part of checkin [a5fe6233c1] on branch trunk - layered parameters implemented (user: kinaba) [annotate]
To Artifact [0e6e0e9d77fcbedc]:
- File
polemy/eval.d
- 2010-11-21 09:53:17 - part of checkin [435fa085ec] on branch trunk - refactored predefined layer names, and filled readme.txt. (user: kinaba) [annotate]
6 */ 6 */
7 module polemy.eval; 7 module polemy.eval;
8 import polemy._common; 8 import polemy._common;
9 import polemy.failure; 9 import polemy.failure;
10 import polemy.ast; 10 import polemy.ast;
11 import polemy.parse; 11 import polemy.parse;
12 import polemy.value; 12 import polemy.value;
> 13 import polemy.layer;
13 import std.typecons; 14 import std.typecons;
14 import std.stdio; 15 import std.stdio;
15 16
16 /// 17 ///
17 Table createGlobalContext() 18 Table createGlobalContext()
18 { 19 {
19 auto ctx = new Table; 20 auto ctx = new Table;
20 ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 21 ctx.set("+", ValueLayer, native( (IntValue lhs, IntValue rhs){return new
21 ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 22 ctx.set("-", ValueLayer, native( (IntValue lhs, IntValue rhs){return new
22 ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 23 ctx.set("*", ValueLayer, native( (IntValue lhs, IntValue rhs){return new
23 ctx.set("/", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 24 ctx.set("/", ValueLayer, native( (IntValue lhs, IntValue rhs){return new
24 ctx.set("%", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa | 25 ctx.set("%", ValueLayer, native( (IntValue lhs, IntValue rhs){return new
25 ctx.set("||", "@v", native( (IntValue lhs, IntValue rhs){return new IntV | 26 ctx.set("||", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne
26 ctx.set("&&", "@v", native( (IntValue lhs, IntValue rhs){return new IntV | 27 ctx.set("&&", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne
27 ctx.set("<", "@v", native( (Value lhs, Value rhs){return new IntValue(Bi | 28 ctx.set("<", ValueLayer, native( (Value lhs, Value rhs){return new IntVa
28 ctx.set(">", "@v", native( (Value lhs, Value rhs){return new IntValue(Bi | 29 ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntVa
29 ctx.set("<=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 30 ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntV
30 ctx.set(">=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 31 ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntV
31 ctx.set("==", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 32 ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntV
32 ctx.set("!=", "@v", native( (Value lhs, Value rhs){return new IntValue(B | 33 ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntV
33 ctx.set("print", "@v", native( (Value a){ | 34 ctx.set("print", ValueLayer, native( (Value a){
34 writeln(a); 35 writeln(a);
35 return new IntValue(BigInt(178)); 36 return new IntValue(BigInt(178));
36 })); 37 }));
37 ctx.set("if", "@v", native( (IntValue x, FunValue ft, FunValue fe){ | 38 ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe)
38 auto toRun = (x.data==0 ? fe : ft); 39 auto toRun = (x.data==0 ? fe : ft);
39 return toRun.invoke(null, "@v", toRun.definitionContext()); | 40 return toRun.invoke(null, ValueLayer, toRun.definitionContext())
40 // return toRun.invoke(pos, lay, toRun.definitionContext()); 41 // return toRun.invoke(pos, lay, toRun.definitionContext());
41 })); 42 }));
42 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cas | 43 ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigI
43 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cas | 44 ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigI
44 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cas | 45 ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigI
45 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigI | 46 ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValu
46 ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(c | 47 ctx.set("_istable", ValueLayer, native( (Value v){return new IntValue(Bi
47 ctx.set(".", "@v", native( (Table t, StrValue s){ | 48 ctx.set(".", ValueLayer, native( (Table t, StrValue s){
48 return (t.has(s.data, "@v") ? t.get(s.data, "@v") : new UndValue | 49 return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) :
> 50 }) );
> 51 ctx.set(".?", ValueLayer, native( (Table t, StrValue s){
> 52 return new IntValue(BigInt(t.has(s.data, ValueLayer) ? 1 : 0));
49 }) ); 53 }) );
50 ctx.set(".?", "@v", native( (Table t, StrValue s){ <
51 return new IntValue(BigInt(t.has(s.data, "@v") ? 1 : 0)); <
52 }) ); <
53 ctx.set(".=", "@v", native( (Table t, StrValue s, Value v){ | 54 ctx.set(".=", ValueLayer, native( (Table t, StrValue s, Value v){
54 auto t2 = new Table(t, Table.Kind.NotPropagateSet); 55 auto t2 = new Table(t, Table.Kind.NotPropagateSet);
55 t2.set(s.data, "@v", v); | 56 t2.set(s.data, ValueLayer, v);
56 return t2; 57 return t2;
57 }) ); 58 }) );
58 ctx.set("{}", "@v", native( (){ | 59 ctx.set("{}", ValueLayer, native( (){
59 return new Table; 60 return new Table;
60 }) ); 61 }) );
61 return ctx; 62 return ctx;
62 } 63 }
63 64
64 /// Entry point of this module 65 /// Entry point of this module
65 66
................................................................................................................................................................................
76 } 77 }
77 78
78 /// Entry point of this module 79 /// Entry point of this module
79 80
80 Tuple!(Value,"val",Table,"ctx") eval(AST e) 81 Tuple!(Value,"val",Table,"ctx") eval(AST e)
81 { 82 {
82 Table ctx = createGlobalContext(); 83 Table ctx = createGlobalContext();
83 return typeof(return)(eval(e, ctx, false, "@v"), ctx); | 84 return typeof(return)(eval(e, ctx, false, ValueLayer), ctx);
84 } 85 }
85 86
86 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, 87 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx,
87 { 88 {
88 if(auto f = cast(FunValue)_f) 89 if(auto f = cast(FunValue)_f)
89 { 90 {
90 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 91 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa
91 foreach(i,p; f.params()) 92 foreach(i,p; f.params())
92 if( p.layers.empty ) 93 if( p.layers.empty )
93 if(lay=="@macro") | 94 if(lay==MacroLayer)
94 ctx.set(p.name, lay, macroEval(args[i], 95 ctx.set(p.name, lay, macroEval(args[i],
95 else 96 else
96 ctx.set(p.name, lay, eval(args[i], calle 97 ctx.set(p.name, lay, eval(args[i], calle
97 else 98 else
98 foreach(argLay; p.layers) 99 foreach(argLay; p.layers)
99 if(argLay=="@macro") | 100 if(argLay==MacroLayer)
100 ctx.set(p.name, argLay, macroEva 101 ctx.set(p.name, argLay, macroEva
101 else 102 else
102 ctx.set(p.name, argLay, eval(arg 103 ctx.set(p.name, argLay, eval(arg
103 return f.invoke(pos, lay, ctx); 104 return f.invoke(pos, lay, ctx);
104 } 105 }
105 throw genex!RuntimeException(pos, "tried to call non-function"); 106 throw genex!RuntimeException(pos, "tried to call non-function");
106 } 107 }
107 108
108 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) 109 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx)
109 { 110 {
110 // similar to invoke Function, but with only one argument bound to @v | 111 // similar to invoke Function, but with only one argument bound to Value
111 Value _f = callerCtx.get(lay, "(system)", pos); | 112 Value _f = callerCtx.get(lay, SystemLayer, pos);
112 if(auto f = cast(FunValue)_f) 113 if(auto f = cast(FunValue)_f)
113 { 114 {
114 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa 115 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa
115 auto ps = f.params(); 116 auto ps = f.params();
116 if( ps.length != 1 ) 117 if( ps.length != 1 )
117 throw genex!RuntimeException(pos, "lift function must ta | 118 throw genex!RuntimeException(pos, "lift function must ta
118 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la | 119 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la
119 { 120 {
120 ctx.set(ps[0].name, "@v", v); | 121 ctx.set(ps[0].name, ValueLayer, v);
121 return f.invoke(pos, "@v", ctx); | 122 return f.invoke(pos, ValueLayer, ctx);
122 } 123 }
123 else 124 else
124 throw genex!RuntimeException(pos, "lift function must ta | 125 throw genex!RuntimeException(pos, "lift function must ta
125 } 126 }
126 throw genex!RuntimeException(pos, "tried to call non-function"); 127 throw genex!RuntimeException(pos, "tried to call non-function");
127 } 128 }
128 129
129 /// Entry point of this module 130 /// Entry point of this module
130 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. 131 /// If splitCtx = true, then inner variable declaration do not overwrite ctx.
131 /// lay is the layer ID for evaluation (standard value semantics uses "@v"). | 132 /// lay is the layer ID for evaluation (standard value semantics uses ValueLayer
132 133
133 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) 134 Value eval(AST e, Table ctx, bool splitCtx, Layer lay)
134 { 135 {
135 return e.match( 136 return e.match(
136 (StrLiteral e) 137 (StrLiteral e)
137 { 138 {
138 Value v = new StrValue(e.data); 139 Value v = new StrValue(e.data);
139 if( lay == "@v" ) | 140 if( lay == ValueLayer )
140 return v; 141 return v;
141 else 142 else
142 return lift(e.pos,v,lay,ctx); 143 return lift(e.pos,v,lay,ctx);
143 }, 144 },
144 (IntLiteral e) 145 (IntLiteral e)
145 { 146 {
146 Value v = new IntValue(e.data); 147 Value v = new IntValue(e.data);
147 if( lay == "@v" ) | 148 if( lay == ValueLayer )
148 return v; 149 return v;
149 else // rise 150 else // rise
150 return lift(e.pos,v,lay,ctx); 151 return lift(e.pos,v,lay,ctx);
151 }, 152 },
152 (VarExpression e) 153 (VarExpression e)
153 { 154 {
154 if( lay == "@v" ) | 155 if( lay == ValueLayer )
155 return ctx.get(e.var, lay, e.pos); 156 return ctx.get(e.var, lay, e.pos);
156 try { 157 try {
157 return ctx.get(e.var, lay, e.pos); 158 return ctx.get(e.var, lay, e.pos);
158 } catch( Throwable ) { // [TODO] more precise... 159 } catch( Throwable ) { // [TODO] more precise...
159 return lift(e.pos, ctx.get(e.var, "@v", e.pos), | 160 return lift(e.pos, ctx.get(e.var, ValueLayer, e.
160 } 161 }
161 }, 162 },
162 (LayeredExpression e) 163 (LayeredExpression e)
163 { 164 {
164 if( e.lay == "@macro" ) | 165 if( e.lay == MacroLayer )
165 return macroEval(e.expr, ctx, false); 166 return macroEval(e.expr, ctx, false);
166 else 167 else
167 return eval(e.expr, ctx, true, e.lay); 168 return eval(e.expr, ctx, true, e.lay);
168 }, 169 },
169 (LetExpression e) 170 (LetExpression e)
170 { 171 {
171 // for letrec, we need this, but should avoid overwritin 172 // for letrec, we need this, but should avoid overwritin
172 // ctx.set(e.var, "@v", new UndefinedValue, e.pos); | 173 // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos)
173 if(splitCtx) 174 if(splitCtx)
174 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 175 ctx = new Table(ctx, Table.Kind.NotPropagateSet)
175 Value v = eval(e.init, ctx, true, lay); 176 Value v = eval(e.init, ctx, true, lay);
176 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.po 177 ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.po
177 return eval(e.expr, ctx, false, lay); 178 return eval(e.expr, ctx, false, lay);
178 }, 179 },
179 (FuncallExpression e) 180 (FuncallExpression e)
................................................................................................................................................................................
195 } 196 }
196 ); 197 );
197 } 198 }
198 199
199 // [TODO] Optimization 200 // [TODO] Optimization
200 Value macroEval(AST e, Table ctx, bool AlwaysMacro) 201 Value macroEval(AST e, Table ctx, bool AlwaysMacro)
201 { 202 {
202 Layer theLayer = "@v"; | 203 Layer theLayer = ValueLayer;
203 204
204 Table pos = new Table; 205 Table pos = new Table;
205 pos.set("filename", theLayer, new StrValue(e.pos.filename)); 206 pos.set("filename", theLayer, new StrValue(e.pos.filename));
206 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno))); 207 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno)));
207 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column))); 208 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column)));
208 return e.match( 209 return e.match(
209 (StrLiteral e) 210 (StrLiteral e)
................................................................................................................................................................................
221 t.set("is", theLayer, new StrValue("int")); 222 t.set("is", theLayer, new StrValue("int"));
222 t.set("data", theLayer, new IntValue(e.data)); 223 t.set("data", theLayer, new IntValue(e.data));
223 return t; 224 return t;
224 }, 225 },
225 (VarExpression e) 226 (VarExpression e)
226 { 227 {
227 try { 228 try {
228 return ctx.get(e.var, "@macro", e.pos); | 229 return ctx.get(e.var, MacroLayer, e.pos);
229 } catch( Throwable ) {// [TODO] more precies... 230 } catch( Throwable ) {// [TODO] more precies...
230 Table t = new Table; 231 Table t = new Table;
231 t.set("pos", theLayer, pos); 232 t.set("pos", theLayer, pos);
232 t.set("is", theLayer, new StrValue("var")); 233 t.set("is", theLayer, new StrValue("var"));
233 t.set("name", theLayer, new StrValue(e.var)); 234 t.set("name", theLayer, new StrValue(e.var));
234 return cast(Value)t; 235 return cast(Value)t;
235 } 236 }
................................................................................................................................................................................
243 t.set("is", theLayer, new StrValue("lay")); 244 t.set("is", theLayer, new StrValue("lay"));
244 t.set("layer", theLayer, new StrValue(e.lay)); 245 t.set("layer", theLayer, new StrValue(e.lay));
245 t.set("expr", theLayer, macroEval(e.expr,ctx,Alw 246 t.set("expr", theLayer, macroEval(e.expr,ctx,Alw
246 return cast(Value)t; 247 return cast(Value)t;
247 } 248 }
248 else 249 else
249 { 250 {
250 if( e.lay == "@macro" ) | 251 if( e.lay == MacroLayer )
251 return macroEval(e.expr, ctx, false); 252 return macroEval(e.expr, ctx, false);
252 else 253 else
253 return eval(e.expr, ctx, true, e.lay); 254 return eval(e.expr, ctx, true, e.lay);
254 } 255 }
255 }, 256 },
256 (LetExpression e) 257 (LetExpression e)
257 { 258 {
................................................................................................................................................................................
264 return t; 265 return t;
265 }, 266 },
266 (FuncallExpression e) 267 (FuncallExpression e)
267 { 268 {
268 Value _f = macroEval(e.fun,ctx,AlwaysMacro); 269 Value _f = macroEval(e.fun,ctx,AlwaysMacro);
269 270
270 if( auto f = cast(FunValue)_f ) 271 if( auto f = cast(FunValue)_f )
271 return invokeFunction(e.pos, f, e.args, ctx, "@m | 272 return invokeFunction(e.pos, f, e.args, ctx, Mac
272 273
273 Table t = new Table; 274 Table t = new Table;
274 t.set("pos", theLayer, pos); 275 t.set("pos", theLayer, pos);
275 t.set("is", theLayer, new StrValue("app")); 276 t.set("is", theLayer, new StrValue("app"));
276 t.set("fun", theLayer, _f); 277 t.set("fun", theLayer, _f);
277 Table args = new Table; 278 Table args = new Table;
278 foreach_reverse(a; e.args) { 279 foreach_reverse(a; e.args) {
................................................................................................................................................................................
317 ); 318 );
318 } 319 }
319 320
320 unittest 321 unittest
321 { 322 {
322 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); 323 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) );
323 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 324 assert_eq( r.val, new IntValue(BigInt(21+21*21)) );
324 assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21)) ); | 325 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21)) );
325 assert_nothrow( r.ctx.get("x","@v") ); | 326 assert_nothrow( r.ctx.get("x",ValueLayer) );
326 assert_throw!RuntimeException( r.ctx.get("y","@v") ); | 327 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) );
327 } 328 }
328 unittest 329 unittest
329 { 330 {
330 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); 331 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) );
331 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 332 assert_eq( r.val, new IntValue(BigInt(21+21*21)) );
332 assert_eq( r.ctx.get("x","@v"), new IntValue(BigInt(21+21*21)) ); | 333 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) );
333 assert_nothrow( r.ctx.get("x","@v") ); | 334 assert_nothrow( r.ctx.get("x",ValueLayer) );
334 assert_throw!RuntimeException( r.ctx.get("y","@v") ); | 335 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) );
335 } 336 }
336 unittest 337 unittest
337 { 338 {
338 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B 339 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B
339 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new 340 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new
340 } 341 }
341 unittest 342 unittest
................................................................................................................................................................................
364 fib(5);`).val, new IntValue(BigInt(8))); 365 fib(5);`).val, new IntValue(BigInt(8)));
365 } 366 }
366 367
367 unittest 368 unittest
368 { 369 {
369 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1 370 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1
370 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In 371 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In
371 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};1+2`) | 372 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};1
372 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@v(@s(x)-@s(y))};@s(1+ | 373 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};@
373 } 374 }
374 375
375 unittest 376 unittest
376 { 377 {
377 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 378 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi
378 // there was a bug that declaration in the first line of function defini 379 // there was a bug that declaration in the first line of function defini
379 // cannot be recursive 380 // cannot be recursive
380 assert_nothrow( evalString(`def foo() { 381 assert_nothrow( evalString(`def foo() {
381 def bar(y) { if(y<1) {0} else {bar(0)} }; 382 def bar(y) { if(y<1) {0} else {bar(0)} };
382 bar(1) 383 bar(1)
383 }; foo()`) ); 384 }; foo()`) );
384 } 385 }
385 <