Differences From Artifact [a7c677ad83621b47]:
- File
polemy/eval.d
- 2010-11-23 13:55:15 - part of checkin [2134cd44cc] on branch trunk - further clean-up for polemy2d (user: kinaba) [annotate]
To Artifact [cd1c3d2598ac30ce]:
- File
polemy/eval.d
- 2010-11-23 18:28:47 - part of checkin [ba11f1d551] on branch trunk - fixed the macro scoping rules concerning non-macro let (user: kinaba) [annotate]
20 public: 20 public:
21 /// Initialize evaluator with empty context 21 /// Initialize evaluator with empty context
22 this() { theContext = new Table; } 22 this() { theContext = new Table; }
23 23
24 /// Evaluate the AST 24 /// Evaluate the AST
25 Value evalAST(AST e) 25 Value evalAST(AST e)
26 { 26 {
27 return eval(e, ValueLayer, theContext, OverwriteCtx); | 27 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx)[0];
28 } 28 }
29 29
30 /// Evaluate the string 30 /// Evaluate the string
31 Value evalString(S,T...)(S str, T fn_ln_cn) 31 Value evalString(S,T...)(S str, T fn_ln_cn)
32 { 32 {
33 return evalAST(parseString(str,fn_ln_cn)); 33 return evalAST(parseString(str,fn_ln_cn));
34 } 34 }
................................................................................................................................................................................
45 return theContext; 45 return theContext;
46 } 46 }
47 47
48 private: 48 private:
49 Table theContext; 49 Table theContext;
50 50
51 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 51 enum : bool { CascadeCtx=false, OverwriteCtx=true };
> 52
52 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 53 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
53 { 54 {
54 // dynamic-overload-resolution-pattern: modify here 55 // dynamic-overload-resolution-pattern: modify here
55 enum funName = "eval"; 56 enum funName = "eval";
56 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 57 alias TypeTuple!(e,lay,ctx,overwriteCtx) params;
57 58
58 // dynamic-overload-resolution-pattern: dispatch 59 // dynamic-overload-resolution-pattern: dispatch
................................................................................................................................................................................
65 66
66 // dynamic-overload-resolution-pattern: default behavior 67 // dynamic-overload-resolution-pattern: default behavior
67 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 68 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not
68 } 69 }
69 70
70 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 71 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
71 { 72 {
72 if( isMacroishLayer(lay) ) | 73 if( isASTLayer(lay) )
73 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 74 return ast2table(e, (AST e){return eval(e,lay,ctx);});
74 if( lay==ValueLayer ) 75 if( lay==ValueLayer )
75 return new StrValue(e.data); 76 return new StrValue(e.data);
76 return lift(new StrValue(e.data), lay, ctx, e.pos); 77 return lift(new StrValue(e.data), lay, ctx, e.pos);
77 } 78 }
78 79
79 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 80 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
80 { 81 {
81 if( isMacroishLayer(lay) ) | 82 if( isASTLayer(lay) )
82 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 83 return ast2table(e, (AST e){return eval(e,lay,ctx);});
83 if( lay==ValueLayer ) 84 if( lay==ValueLayer )
84 return new IntValue(e.data); 85 return new IntValue(e.data);
85 return lift(new IntValue(e.data), lay, ctx, e.pos); 86 return lift(new IntValue(e.data), lay, ctx, e.pos);
86 } 87 }
87 88
88 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 89 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
89 { 90 {
90 if( isMacroishLayer(lay) ) | 91 if( isASTLayer(lay) )
91 if( ctx.has(e.name,MacroLayer) ) | 92 if( isMacroLayer(lay) && ctx.has(e.name,MacroLayer) )
92 return ctx.get(e.name, MacroLayer, e.pos); 93 return ctx.get(e.name, MacroLayer, e.pos);
93 else 94 else
94 return ast2table(e, (AST e){return eval(e,lay,ct 95 return ast2table(e, (AST e){return eval(e,lay,ct
95 if( lay==ValueLayer || ctx.has(e.name, lay) ) 96 if( lay==ValueLayer || ctx.has(e.name, lay) )
96 return ctx.get(e.name, lay, e.pos); 97 return ctx.get(e.name, lay, e.pos);
97 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 98 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos)
98 } 99 }
99 100
100 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
101 { 102 {
102 Value f = eval( e.fun, lay, ctx ); 103 Value f = eval( e.fun, lay, ctx );
103 if( isMacroishLayer(lay) ) | 104 if( isASTLayer(lay) ) {
104 if( auto ff = cast(FunValue)f ) | 105 auto ff = cast(FunValue)f;
> 106 if( ff !is null && isMacroLayer(lay) )
105 return invokeFunction(ff, e.args, MacroLayer, ct | 107 return invokeFunction(ff, e.args, lay, ctx, e.po
106 else 108 else
107 return ast2table(e, (AST e){return eval(e,lay,ct 109 return ast2table(e, (AST e){return eval(e,lay,ct
> 110 }
108 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi 111 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi
109 } 112 }
110 113
111 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 114 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
112 { 115 {
113 if( isMacroishLayer(lay) ) | 116 if( isASTLayer(lay) )
> 117 {
> 118 // need this for correct scoping (outer scope macro vari
> 119 Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet
> 120 foreach(p; e.params)
> 121 newCtx.set(p.name, ValueLayer, new UndefinedValu
114 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 122 return ast2table(e, (AST e){return eval(e,lay,newCtx);})
> 123 }
115 else 124 else
116 return createNewFunction(e, ctx); 125 return createNewFunction(e, ctx);
117 } 126 }
118 127
119 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 128 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
120 { 129 {
121 if( isNoLayerChangeLayer(lay) ) 130 if( isNoLayerChangeLayer(lay) )
................................................................................................................................................................................
122 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 131 return ast2table(e, (AST e){return eval(e,lay,ctx);});
123 else 132 else
124 return eval(e.expr, e.layer, ctx); 133 return eval(e.expr, e.layer, ctx);
125 } 134 }
126 135
127 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 136 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx )
128 { 137 {
129 // todo @macro let | 138 Table newCtx = overwriteCtx ? ctx : new Table(ctx, Table.Kind.No
130 if( isMacroishLayer(lay) ) | 139 if( isASTLayer(lay) )
131 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 140 return ast2table(e, (AST ee){
> 141 if(ee is e.expr) // need this for correct scopin
> 142 newCtx.set(e.name, ValueLayer, new Undef
> 143 return eval(ee,lay,newCtx);
> 144 });
132 else 145 else
133 { 146 {
> 147 Value ri = eval(e.init, lay, newCtx);
> 148 newCtx.set(e.name, e.layer.empty ? lay : e.layer, ri);
> 149 return eval(e.expr, lay, newCtx, OverwriteCtx);
> 150 }
> 151 }
> 152
> 153 private:
> 154 // little little bit incremental macro defining version.
> 155 // enables @macro foo(x)=... in ... foo ..., only at the top level of th
> 156 // interpreter and functions. better than nothing :P
> 157 Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overw
> 158 {
> 159 assert( !isASTLayer(lay) );
> 160
> 161 AST decodeAST(Value v, LexPosition pos)
> 162 {
> 163 // [TODO] more informative error message
> 164 return polemy2d!(AST)(v, pos);
> 165 }
> 166
> 167 if(auto e = cast(Let)e_)
> 168 {
> 169 AST ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e
> 170 Value vi = eval(ai, lay, ctx);
> 171
134 if( !overwriteCtx ) 172 if( !overwriteCtx )
135 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 173 ctx = new Table(ctx, Table.Kind.NotPropagateSet)
136 Value ri = eval(e.init, lay, ctx); <
137 string theLayer = e.layer.empty ? lay : e.layer; // neut | 174 string theLayer = e.layer.empty ? lay : e.layer;
138 ctx.set(e.name, theLayer, ri); | 175 ctx.set(e.name, theLayer, vi);
> 176
139 return eval(e.expr, lay, ctx, OverwriteCtx); | 177 auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx
> 178 AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]);
> 179 return tuple(ave[0], a);
> 180 }
> 181 else
> 182 {
> 183 AST a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos
> 184 Value v = eval(a, lay, ctx);
> 185 return tuple(v, a);
140 } 186 }
141 } 187 }
142 188
143 private: 189 private:
144 string getNameIfPossible(AST e) 190 string getNameIfPossible(AST e)
145 { 191 {
146 if(auto v = cast(Var)e) 192 if(auto v = cast(Var)e)
................................................................................................................................................................................
151 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 197 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi
152 { 198 {
153 if(auto f = cast(FunValue)_f) 199 if(auto f = cast(FunValue)_f)
154 { 200 {
155 Table newCtx = new Table(f.definitionContext(), Table.Ki 201 Table newCtx = new Table(f.definitionContext(), Table.Ki
156 foreach(i,p; f.params()) 202 foreach(i,p; f.params())
157 if( p.layers.empty ) 203 if( p.layers.empty )
158 newCtx.set(p.name, (lay==RawMacroLayer ? | 204 newCtx.set(p.name, isMacroLayer(lay)?Mac
159 else 205 else
160 foreach(argLay; p.layers) 206 foreach(argLay; p.layers)
161 newCtx.set(p.name, argLay, eval( 207 newCtx.set(p.name, argLay, eval(
162 scope _ = new PushCallStack(pos, callstackmsg); 208 scope _ = new PushCallStack(pos, callstackmsg);
163 return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, n | 209 return f.invoke(isMacroLayer(lay)?MacroLayer:lay, newCtx
164 } 210 }
165 throw genex!RuntimeException(pos, text("tried to call non-functi 211 throw genex!RuntimeException(pos, text("tried to call non-functi
166 } 212 }
167 213
168 Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 214 Value lift(Value v, Layer lay, Table ctx, LexPosition pos)
169 { 215 {
170 assert( !isMacroishLayer(lay), "lift to the @macro layer should | 216 assert( !isASTLayer(lay), "lift to the @macro layer should never
171 217
172 // functions are automatically lifterd 218 // functions are automatically lifterd
173 if( cast(FunValue) v ) 219 if( cast(FunValue) v )
174 return v; 220 return v;
175 221
176 if( !ctx.has(lay, SystemLayer) ) 222 if( !ctx.has(lay, SystemLayer) )
177 throw genex!RuntimeException(pos, "lift function for "~l 223 throw genex!RuntimeException(pos, "lift function for "~l
................................................................................................................................................................................
229 return this.defCtx.opCmp(rhs.defCtx); 275 return this.defCtx.opCmp(rhs.defCtx);
230 } 276 }
231 assert(false, sprintf!"Cannot compare %s with %s 277 assert(false, sprintf!"Cannot compare %s with %s
232 } 278 }
233 279
234 override Value invoke(Layer lay, Table ctx, LexPosition 280 override Value invoke(Layer lay, Table ctx, LexPosition
235 { 281 {
236 if( lay == MacroLayer ) | 282 if( isASTLayer(lay) )
237 return eval(ast.funbody, lay, ctx); 283 return eval(ast.funbody, lay, ctx);
238 try { <
239 if( afterMacroAST is null ) | 284 if( afterMacroAST is null )
> 285 {
240 afterMacroAST = polemy2d!(AST)(e | 286 auto va = macroAndEval(e.funbody, lay, c
241 return eval(afterMacroAST, lay, ctx); | 287 afterMacroAST = va[1];
242 } catch( RuntimeException e ) { | 288 return va[0];
243 throw e.pos is null ? new RuntimeExcepti <
244 } 289 }
> 290 else
> 291 return eval(afterMacroAST, lay, ctx);
245 } 292 }
246 293
247 AST afterMacroAST; 294 AST afterMacroAST;
248 } 295 }
249 return new UserDefinedFunValue(e,ctx); 296 return new UserDefinedFunValue(e,ctx);
250 } 297 }
251 298
................................................................................................................................................................................
310 } 357 }
311 unittest 358 unittest
312 { 359 {
313 auto e = new Evaluator; 360 auto e = new Evaluator;
314 enrollRuntimeLibrary(e); 361 enrollRuntimeLibrary(e);
315 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 362 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) );
316 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 363 assert_eq( r, new IntValue(BigInt(21+21*21)) );
317 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+2 | 364 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) )
318 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 365 assert_nothrow( e.globalContext.get("x",ValueLayer) );
319 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 366 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) );
320 } 367 }
321 unittest 368 unittest
322 { 369 {
323 auto e = new Evaluator; 370 auto e = new Evaluator;
324 enrollRuntimeLibrary(e); 371 enrollRuntimeLibrary(e);
325 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(Big | 372 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(1)
326 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I | 373 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I
327 } 374 }
328 375
329 unittest 376 unittest
330 { 377 {
331 auto e = new Evaluator; 378 auto e = new Evaluator;
332 enrollRuntimeLibrary(e); 379 enrollRuntimeLibrary(e);
333 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1) 380 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1)