Differences From Artifact [0386a7dd31807f87]:
- File
polemy/value.d
- 2010-11-21 15:48:16 - part of checkin [f86026acb8] on branch trunk - macro cache and automemoization reloaded. auto re-run implemented. but automemo and autorerun is currently disabled. we need Table.opCmp... we also need to think more about the memoization (user: kinaba) [annotate]
To Artifact [19366410c0eeb209]:
- File
polemy/value.d
- 2010-11-23 07:42:13 - part of checkin [6ac127ddd0] on branch trunk - new evaluator (user: kinaba) [annotate]
43 43
44 44
45 /// 45 ///
46 abstract class FunValue : Value 46 abstract class FunValue : Value
47 { 47 {
48 const(Parameter[]) params(); 48 const(Parameter[]) params();
49 Table definitionContext(); 49 Table definitionContext();
50 Value invoke(in LexPosition pos, Layer lay, Table ctx); | 50 Value invoke(LexPosition pos, Layer lay, Table ctx);
51 } <
52 <
53 import polemy.eval; // circular... <
54 version = MacroCache; <
55 //version = AutoMemoization; <
56 //version = AutoRerun; <
57 <
58 /// <
59 class UserDefinedFunValue : FunValue <
60 { <
61 FunLiteral ast; <
62 Table defCtx; <
63 <
64 this(FunLiteral ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } <
65 override string toString() const { return sprintf!"(function:%x:%x)"(cas <
66 override bool opEquals(Object rhs_) const /// member-by-member equality <
67 { <
68 if( auto rhs = cast(typeof(this))rhs_ ) <
69 return this.ast==rhs.ast && this.defCtx==rhs.defCtx; <
70 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), <
71 } <
72 override hash_t toHash() const /// member-by-member hash <
73 { <
74 return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx) <
75 } <
76 override int opCmp(Object rhs_) /// member-by-member compare <
77 { <
78 if( auto rhs = cast(typeof(this))rhs_ ) <
79 { <
80 if(auto i = this.ast.opCmp(rhs.ast)) <
81 return i; <
82 return this.defCtx.opCmp(rhs.defCtx); <
83 } <
84 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), <
85 } <
86 <
87 private AST preprocessed_funbody; <
88 private Value[Value[]][Layer] memo; <
89 <
90 override const(Parameter[]) params() { return ast.params; } <
91 override Table definitionContext() { return defCtx; } <
92 override Value invoke(in LexPosition pos, Layer lay, Table ctx) <
93 { <
94 // TODO: only auto raised ones need memo? no? <
95 // how can we integrate re-run ?? <
96 version(AutoMemoization) <
97 { <
98 Value[] memokey; <
99 if( lay != ValueLayer && lay != MacroLayer ) <
100 { <
101 foreach(i,p; ast.params) <
102 memokey ~= ctx.get(p.name, lay); // lay? <
103 if( auto memolay = lay in memo ) <
104 if( auto pv = memokey in *memolay ) <
105 return *pv; <
106 memo[lay][memokey] = lift(ast.pos,new UndValue,l <
107 } <
108 } <
109 <
110 // @macro run!!! <
111 if( lay == MacroLayer ) <
112 return macroEval(ast.funbody, ctx, false); <
113 <
114 version(MacroCache) { <
115 if( preprocessed_funbody is null ) { <
116 // .prototype!, forced macro cannot access param <
117 ctx.kill = true; scope(exit)ctx.kill=false; <
118 preprocessed_funbody = tableToAST(ValueLayer,mac <
119 } <
120 } else { <
121 if( preprocessed_funbody is null ) { <
122 // .prototype!, forced macro cannot access param <
123 ctx.kill = true; scope(exit)ctx.kill=false; <
124 preprocessed_funbody = tableToAST(ValueLayer,mac <
125 } <
126 } <
127 <
128 auto v = eval(preprocessed_funbody, ctx, true, lay); <
129 version(AutoMemoization) <
130 { <
131 if( lay != ValueLayer && lay != MacroLayer ) <
132 { <
133 memo[lay][memokey] = v; <
134 version(AutoReRun) <
135 memo[lay][memokey] = eval(preprocessed_funbody, <
136 } <
137 } <
138 return v; <
139 } <
140 } <
141 <
142 /// <
143 abstract class NativeFunValue : FunValue <
144 { <
145 Parameter[] params_data; <
146 override const(Parameter[]) params() { return params_data; } <
147 override Table definitionContext() { return new Table; } // todo: cache <
148 } <
149 <
150 /// Named Constructor for FunValue <
151 <
152 FunValue native(R,T...)(R delegate (T) dg) <
153 { <
154 return new class NativeFunValue { <
155 this() <
156 { <
157 foreach(i, Ti; T) <
158 params_data ~= new Parameter(text(i), []); <
159 } <
160 override Value invoke(in LexPosition pos, Layer lay, Table ctx) <
161 { <
162 if( lay != ValueLayer ) <
163 throw genex!RuntimeException(pos, "only "~ValueL <
164 T typed_args; <
165 foreach(i, Ti; T) { <
166 typed_args[i] = cast(Ti) ctx.get(text(i), ValueL <
167 if( typed_args[i] is null ) <
168 throw genex!RuntimeException(pos, sprint <
169 } <
170 try { <
171 return dg(typed_args); <
172 } catch( RuntimeException e ) { <
173 throw e.pos is null ? new RuntimeException(pos, <
174 } <
175 } <
176 }; <
177 } 51 }
178 52
179 /// Context (variable environment) 53 /// Context (variable environment)
180 /// Simlar to prototype chain of ECMAScript etc. 54 /// Simlar to prototype chain of ECMAScript etc.
181 /// But extended with the notion of "Layer" 55 /// But extended with the notion of "Layer"
182 56
183 class Table : Value 57 class Table : Value
................................................................................................................................................................................
184 { 58 {
185 enum Kind {PropagateSet, NotPropagateSet}; 59 enum Kind {PropagateSet, NotPropagateSet};
186 bool kill = false; // to refactor 60 bool kill = false; // to refactor
187 61
188 this( Table proto=null, Kind k = Kind.PropagateSet ) 62 this( Table proto=null, Kind k = Kind.PropagateSet )
189 { this.prototype = proto; this.kind = k; } 63 { this.prototype = proto; this.kind = k; }
190 64
191 void set(string i, Layer lay, Value v, in LexPosition pos=null) | 65 void set(string i, Layer lay, Value v, LexPosition pos=null)
192 { 66 {
193 if( setIfExist(i, lay, v) ) 67 if( setIfExist(i, lay, v) )
194 return; 68 return;
195 data[i][lay] = v; 69 data[i][lay] = v;
196 } 70 }
197 71
198 bool has(string i, Layer lay, in LexPosition pos=null) | 72 bool has(string i, Layer lay) const
199 { 73 {
200 if( i in data ) { 74 if( i in data ) {
201 if( lay !in data[i] ) 75 if( lay !in data[i] )
202 return false; 76 return false;
203 if(kill) 77 if(kill)
204 return false; 78 return false;
205 return true; 79 return true;
206 } 80 }
207 if( prototype is null ) 81 if( prototype is null )
208 return false; 82 return false;
209 return prototype.has(i, lay, pos); | 83 return prototype.has(i, lay);
210 } 84 }
211 85
212 Value get(string i, Layer lay, in LexPosition pos=null) | 86 Value get(string i, Layer lay, LexPosition pos=null)
213 { 87 {
214 if( i in data ) { 88 if( i in data ) {
215 // [TODO] consider forwarding to proto also in this case 89 // [TODO] consider forwarding to proto also in this case
216 if( lay !in data[i] ) 90 if( lay !in data[i] )
217 throw genex!RuntimeException(pos, sprintf!"'%s' 91 throw genex!RuntimeException(pos, sprintf!"'%s'
218 if(kill) 92 if(kill)
219 throw genex!RuntimeException(pos, sprintf!"'%s' 93 throw genex!RuntimeException(pos, sprintf!"'%s'
................................................................................................................................................................................
244 string result; 118 string result;
245 bool first = true; 119 bool first = true;
246 foreach(k, l2d; data) 120 foreach(k, l2d; data)
247 foreach(l,d; l2d) 121 foreach(l,d; l2d)
248 { 122 {
249 if(first) first=false; else result~=", "; 123 if(first) first=false; else result~=", ";
250 result ~= k; 124 result ~= k;
> 125 if( l.empty )
> 126 result ~= "(emptylayer)";
> 127 else if( l != ValueLayer )
251 result ~= l; | 128 result ~= l;
252 result ~= ":"; 129 result ~= ":";
253 result ~= text(cast(Value)d); 130 result ~= text(cast(Value)d);
254 } 131 }
255 if( prototype !is null ) 132 if( prototype !is null )
256 { 133 {
257 result ~= " / "; 134 result ~= " / ";
258 result ~= prototype.toStringWithoutParen(); 135 result ~= prototype.toStringWithoutParen();
................................................................................................................................................................................
371 if( nodeType is null ) 248 if( nodeType is null )
372 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST 249 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST
373 auto pos = extractPos(t); 250 auto pos = extractPos(t);
374 switch(nodeType.data) 251 switch(nodeType.data)
375 { 252 {
376 case "int": 253 case "int":
377 if(auto v = t.access!IntValue(theLayer, "data")) 254 if(auto v = t.access!IntValue(theLayer, "data"))
378 return new IntLiteral(pos, v.data); | 255 return new Int(pos, v.data);
379 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 256 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
380 case "str": 257 case "str":
381 if(auto v = t.access!StrValue(theLayer, "data")) 258 if(auto v = t.access!StrValue(theLayer, "data"))
382 return new StrLiteral(pos, v.data); | 259 return new Str(pos, v.data);
383 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 260 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
384 case "var": 261 case "var":
385 if(auto v = t.access!StrValue(theLayer, "name")) 262 if(auto v = t.access!StrValue(theLayer, "name"))
386 return new VarExpression(pos, v.data); | 263 return new Var(pos, v.data);
387 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 264 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
388 case "lay": 265 case "lay":
389 if(auto v = t.access!StrValue(theLayer, "layer")) 266 if(auto v = t.access!StrValue(theLayer, "layer"))
390 if(auto e = t.access!Table(theLayer, "expr")) 267 if(auto e = t.access!Table(theLayer, "expr"))
391 return new LayExpression(pos, v.data, tableToAST | 268 return new Lay(pos, v.data, tableToAST(theLayer,
392 else 269 else
393 throw genex!RuntimeException(cast(LexPosition)nu 270 throw genex!RuntimeException(cast(LexPosition)nu
394 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 271 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
395 case "let": 272 case "let":
396 if(auto n = t.access!StrValue(theLayer, "name")) 273 if(auto n = t.access!StrValue(theLayer, "name"))
397 if(auto e = t.access!Table(theLayer, "init")) 274 if(auto e = t.access!Table(theLayer, "init"))
398 if(auto b = t.access!Table(theLayer, "expr")) 275 if(auto b = t.access!Table(theLayer, "expr"))
................................................................................................................................................................................
399 { 276 {
400 string nn = n.data; 277 string nn = n.data;
401 auto ee = tableToAST(theLayer, e); 278 auto ee = tableToAST(theLayer, e);
402 auto bb = tableToAST(theLayer, b); 279 auto bb = tableToAST(theLayer, b);
403 Layer lay=""; 280 Layer lay="";
404 if(auto l = t.access!StrValue(theLayer, "layer")) 281 if(auto l = t.access!StrValue(theLayer, "layer"))
405 lay = l.data; 282 lay = l.data;
406 return new LetExpression(pos, nn, lay, ee, bb); | 283 return new Let(pos, nn, lay, ee, bb);
407 } 284 }
408 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 285 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
409 case "app": 286 case "app":
410 if(auto f = t.access!Table(theLayer, "fun")) 287 if(auto f = t.access!Table(theLayer, "fun"))
411 if(auto a = t.access!Table(theLayer, "args")) 288 if(auto a = t.access!Table(theLayer, "args"))
412 return new FuncallExpression(pos, tableToAST(theLayer,f) | 289 return new App(pos, tableToAST(theLayer,f), tableToASTLi
413 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 290 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
414 case "fun": 291 case "fun":
415 if(auto p = t.access!Table(theLayer, "params")) 292 if(auto p = t.access!Table(theLayer, "params"))
416 if(auto b = t.access!Table(theLayer, "funbody")) 293 if(auto b = t.access!Table(theLayer, "funbody"))
417 { 294 {
418 Parameter[] ps; 295 Parameter[] ps;
419 foreach(v; tableAsConsList(theLayer, p)) 296 foreach(v; tableAsConsList(theLayer, p))
................................................................................................................................................................................
436 Layer[] emp; 313 Layer[] emp;
437 ps ~= new Parameter(ss.data, emp); 314 ps ~= new Parameter(ss.data, emp);
438 continue; 315 continue;
439 } 316 }
440 throw genex!RuntimeException(cast(LexPosition)nu 317 throw genex!RuntimeException(cast(LexPosition)nu
441 } 318 }
442 auto bb = tableToAST(theLayer, b); 319 auto bb = tableToAST(theLayer, b);
443 return new FunLiteral(pos,ps,bb); | 320 return new Fun(pos,ps,bb);
444 } 321 }
445 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 322 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST
446 default: 323 default:
447 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Inv 324 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Inv
448 } 325 }
449 } 326 }
> 327
> 328 Table makeCons(Value a, Value d)
> 329 {
> 330 Table t = new Table;
> 331 t.set("car", ValueLayer, a);
> 332 t.set("cdr", ValueLayer, d);
> 333 return t;
> 334 }
> 335
> 336 Table fromPos(LexPosition pos)
> 337 {
> 338 Table t = new Table;
> 339 if( pos !is null ) {
> 340 t.set("filename", ValueLayer, new StrValue(pos.filename));
> 341 t.set("lineno", ValueLayer, new IntValue(BigInt(pos.lineno)));
> 342 t.set("column", ValueLayer, new IntValue(BigInt(pos.column)));
> 343 } else {
> 344 t.set("filename", ValueLayer, new StrValue("nullpos"));
> 345 t.set("lineno", ValueLayer, new IntValue(BigInt(0)));
> 346 t.set("column", ValueLayer, new IntValue(BigInt(0)));
> 347 }
> 348 return t;
> 349 }