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 46 abstract class FunValue : Value
47 47 {
48 48 const(Parameter[]) params();
49 49 Table definitionContext();
50 - Value invoke(in 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)"(cast(void*)ast, cast(void*)defCtx); }
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), typeid(rhs_)));
71 - }
72 - override hash_t toHash() const /// member-by-member hash
73 - {
74 - return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&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), typeid(rhs_)));
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,lay,ctx);
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 parameters
117 - ctx.kill = true; scope(exit)ctx.kill=false;
118 - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true));
119 - }
120 - } else {
121 - if( preprocessed_funbody is null ) {
122 - // .prototype!, forced macro cannot access parameters
123 - ctx.kill = true; scope(exit)ctx.kill=false;
124 - preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true));
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, ctx, true, lay); // re-Run!!
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 overrie
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 "~ValueLayer~" layer can call native function");
164 - T typed_args;
165 - foreach(i, Ti; T) {
166 - typed_args[i] = cast(Ti) ctx.get(text(i), ValueLayer);
167 - if( typed_args[i] is null )
168 - throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1));
169 - }
170 - try {
171 - return dg(typed_args);
172 - } catch( RuntimeException e ) {
173 - throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e;
174 - }
175 - }
176 - };
50 + Value invoke(LexPosition pos, Layer lay, Table ctx);
177 51 }
178 52
179 53 /// Context (variable environment)
180 54 /// Simlar to prototype chain of ECMAScript etc.
181 55 /// But extended with the notion of "Layer"
182 56
183 57 class Table : Value
................................................................................
184 58 {
185 59 enum Kind {PropagateSet, NotPropagateSet};
186 60 bool kill = false; // to refactor
187 61
188 62 this( Table proto=null, Kind k = Kind.PropagateSet )
189 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 67 if( setIfExist(i, lay, v) )
194 68 return;
195 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 74 if( i in data ) {
201 75 if( lay !in data[i] )
202 76 return false;
203 77 if(kill)
204 78 return false;
205 79 return true;
206 80 }
207 81 if( prototype is null )
208 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 88 if( i in data ) {
215 89 // [TODO] consider forwarding to proto also in this case
216 90 if( lay !in data[i] )
217 91 throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay));
218 92 if(kill)
219 93 throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i));
................................................................................
244 118 string result;
245 119 bool first = true;
246 120 foreach(k, l2d; data)
247 121 foreach(l,d; l2d)
248 122 {
249 123 if(first) first=false; else result~=", ";
250 124 result ~= k;
251 - result ~= l;
125 + if( l.empty )
126 + result ~= "(emptylayer)";
127 + else if( l != ValueLayer )
128 + result ~= l;
252 129 result ~= ":";
253 130 result ~= text(cast(Value)d);
254 131 }
255 132 if( prototype !is null )
256 133 {
257 134 result ~= " / ";
258 135 result ~= prototype.toStringWithoutParen();
................................................................................
371 248 if( nodeType is null )
372 249 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}");
373 250 auto pos = extractPos(t);
374 251 switch(nodeType.data)
375 252 {
376 253 case "int":
377 254 if(auto v = t.access!IntValue(theLayer, "data"))
378 - return new IntLiteral(pos, v.data);
255 + return new Int(pos, v.data);
379 256 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`);
380 257 case "str":
381 258 if(auto v = t.access!StrValue(theLayer, "data"))
382 - return new StrLiteral(pos, v.data);
259 + return new Str(pos, v.data);
383 260 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`);
384 261 case "var":
385 262 if(auto v = t.access!StrValue(theLayer, "name"))
386 - return new VarExpression(pos, v.data);
263 + return new Var(pos, v.data);
387 264 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`);
388 265 case "lay":
389 266 if(auto v = t.access!StrValue(theLayer, "layer"))
390 267 if(auto e = t.access!Table(theLayer, "expr"))
391 - return new LayExpression(pos, v.data, tableToAST(theLayer,e));
268 + return new Lay(pos, v.data, tableToAST(theLayer,e));
392 269 else
393 270 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`);
394 271 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`);
395 272 case "let":
396 273 if(auto n = t.access!StrValue(theLayer, "name"))
397 274 if(auto e = t.access!Table(theLayer, "init"))
398 275 if(auto b = t.access!Table(theLayer, "expr"))
................................................................................
399 276 {
400 277 string nn = n.data;
401 278 auto ee = tableToAST(theLayer, e);
402 279 auto bb = tableToAST(theLayer, b);
403 280 Layer lay="";
404 281 if(auto l = t.access!StrValue(theLayer, "layer"))
405 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 285 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`);
409 286 case "app":
410 287 if(auto f = t.access!Table(theLayer, "fun"))
411 288 if(auto a = t.access!Table(theLayer, "args"))
412 - return new FuncallExpression(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a));
289 + return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a));
413 290 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`);
414 291 case "fun":
415 292 if(auto p = t.access!Table(theLayer, "params"))
416 293 if(auto b = t.access!Table(theLayer, "funbody"))
417 294 {
418 295 Parameter[] ps;
419 296 foreach(v; tableAsConsList(theLayer, p))
................................................................................
436 313 Layer[] emp;
437 314 ps ~= new Parameter(ss.data, emp);
438 315 continue;
439 316 }
440 317 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v));
441 318 }
442 319 auto bb = tableToAST(theLayer, b);
443 - return new FunLiteral(pos,ps,bb);
320 + return new Fun(pos,ps,bb);
444 321 }
445 322 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`);
446 323 default:
447 324 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data));
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 +}