Differences From Artifact [b6c76b48bfdecce6]:
- File
polemy/value.d
- 2010-11-23 09:36:27 - part of checkin [b97bd4f713] on branch trunk - automatic AST to table encoder (user: kinaba) [annotate]
To Artifact [6d85ee04f34c61b7]:
- File
polemy/value.d
- 2010-11-23 10:09:03 - part of checkin [36c517dfc4] on branch trunk - refactored d-value and polemy-value conversion (user: kinaba) [annotate]
5 5 * Runtime data structures for Polemy programming language.
6 6 */
7 7 module polemy.value;
8 8 import polemy._common;
9 9 import polemy.failure;
10 10 import polemy.ast;
11 11 import polemy.layer;
12 -import std.string;
13 12
14 13 /// Runtime values of Polemy
15 14
16 15 abstract class Value
17 16 {
18 17 override bool opEquals(Object rhs) { return 0==opCmp(rhs); }
19 18 }
20 19
21 20 ///
22 21 class IntValue : Value
23 22 {
24 23 BigInt data;
25 24
25 + this(bool n) { this.data = n?1:0; }
26 26 this(int n) { this.data = n; }
27 27 this(long n) { this.data = n; }
28 28 this(BigInt n) { this.data = n; }
29 29 this(string n) { this.data = BigInt(n); }
30 30 override string toString() const { return toDecimalString(cast(BigInt)data); }
31 31 override int opCmp(Object rhs) {
32 32 if(auto r = cast(IntValue)rhs) return data.opCmp(r.data);
................................................................................
216 216 assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) );
217 217 assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) );
218 218 assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) );
219 219 assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) );
220 220
221 221 // [TODO] define the semantics and test @layers
222 222 }
223 -
224 -immutable(LexPosition) extractPos( Table t )
225 -{
226 - Layer theLayer = ValueLayer;
227 - if(auto tt = t.access!Table(theLayer, "pos"))
228 - {
229 - auto fn = tt.access!StrValue(theLayer, "filename");
230 - auto ln = tt.access!IntValue(theLayer, "lineno");
231 - auto cl = tt.access!IntValue(theLayer, "column");
232 - if(fn !is null && ln !is null && cl !is null)
233 - return new immutable(LexPosition)(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt);
234 - }
235 - return null;
236 -}
237 -
238 -Value[] tableAsConsList( Layer theLayer, Table t )
239 -{
240 - Value[] result;
241 - while(t)
242 - if(auto v = t.access!Value(theLayer, "car"))
243 - {
244 - result ~= v;
245 - t = t.access!Table(theLayer, "cdr");
246 - }
247 - else
248 - break;
249 - return result;
250 -}
251 -
252 -AST[] tableToASTList( Layer theLayer, Table t )
253 -{
254 - AST[] result;
255 - foreach(v; tableAsConsList(theLayer, t))
256 - if(auto t = cast(Table)v)
257 - result ~= tableToAST(theLayer,t);
258 - else
259 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)");
260 - return result;
261 -}
262 -
263 -AST tableToAST( Layer theLayer, Value vvvv )
264 -{
265 - Table t = cast(Table)vvvv;
266 - if( t is null )
267 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)");
268 -
269 - auto nodeType = t.access!StrValue(theLayer, "is");
270 - if( nodeType is null )
271 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}");
272 - auto pos = extractPos(t);
273 - switch(nodeType.data)
274 - {
275 - case "int":
276 - if(auto v = t.access!IntValue(theLayer, "data"))
277 - return new Int(pos, v.data);
278 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`);
279 - case "str":
280 - if(auto v = t.access!StrValue(theLayer, "data"))
281 - return new Str(pos, v.data);
282 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`);
283 - case "var":
284 - if(auto v = t.access!StrValue(theLayer, "name"))
285 - return new Var(pos, v.data);
286 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`);
287 - case "lay":
288 - if(auto v = t.access!StrValue(theLayer, "layer"))
289 - if(auto e = t.access!Table(theLayer, "expr"))
290 - return new Lay(pos, v.data, tableToAST(theLayer,e));
291 - else
292 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`);
293 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`);
294 - case "let":
295 - if(auto n = t.access!StrValue(theLayer, "name"))
296 - if(auto e = t.access!Table(theLayer, "init"))
297 - if(auto b = t.access!Table(theLayer, "expr"))
298 - {
299 - string nn = n.data;
300 - auto ee = tableToAST(theLayer, e);
301 - auto bb = tableToAST(theLayer, b);
302 - Layer lay="";
303 - if(auto l = t.access!StrValue(theLayer, "layer"))
304 - lay = l.data;
305 - return new Let(pos, nn, lay, ee, bb);
306 - }
307 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`);
308 - case "app":
309 - if(auto f = t.access!Table(theLayer, "fun"))
310 - if(auto a = t.access!Table(theLayer, "args"))
311 - return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a));
312 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`);
313 - case "fun":
314 - if(auto p = t.access!Table(theLayer, "params"))
315 - if(auto b = t.access!Table(theLayer, "funbody"))
316 - {
317 - Parameter[] ps;
318 - foreach(v; tableAsConsList(theLayer, p))
319 - {
320 - if(auto tt = cast(Table)v)
321 - if(auto ss = tt.access!StrValue(theLayer, "name"))
322 - if(auto ll = tt.access!Table(theLayer, "layers"))
323 - {
324 - Layer[] ls;
325 - foreach(lll; tableAsConsList(theLayer, ll))
326 - if(auto l = cast(StrValue)lll)
327 - ls ~= l.data;
328 - else
329 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll));
330 - ps ~= new Parameter(ss.data, ls);
331 - continue;
332 - }
333 - else
334 - {
335 - Layer[] emp;
336 - ps ~= new Parameter(ss.data, emp);
337 - continue;
338 - }
339 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v));
340 - }
341 - auto bb = tableToAST(theLayer, b);
342 - return new Fun(pos,ps,bb);
343 - }
344 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`);
345 - default:
346 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data));
347 - }
348 -}
349 -
350 -Table makeCons(Value a, Value d)
351 -{
352 - Table t = new Table;
353 - t.set("car", ValueLayer, a);
354 - t.set("cdr", ValueLayer, d);
355 - return t;
356 -}
357 -
358 -Table fromPos(LexPosition pos)
359 -{
360 - Table t = new Table;
361 - if( pos !is null ) {
362 - t.set("filename", ValueLayer, new StrValue(pos.filename));
363 - t.set("lineno", ValueLayer, new IntValue(pos.lineno));
364 - t.set("column", ValueLayer, new IntValue(pos.column));
365 - } else {
366 - t.set("filename", ValueLayer, new StrValue("nullpos"));
367 - t.set("lineno", ValueLayer, new IntValue(0));
368 - t.set("column", ValueLayer, new IntValue(0));
369 - }
370 - return t;
371 -}
372 -
373 -/// Convert AST to Table so that it can be used in Polemy
374 -/// TODO: generalize to DValue2PolemyValue
375 -
376 -Value ast2table(T)(T e, Value delegate(AST) rec)
377 -{
378 - assert( typeid(e) == typeid(T) );
379 -
380 - static if(is(T==BigInt) || is(T==long) || is(T==int))
381 - return new IntValue(e);
382 - else
383 - static if(is(T==string))
384 - return new StrValue(e);
385 - else
386 - static if(is(T S : S[]))
387 - {
388 - Table lst = new Table;
389 - foreach_reverse(a; e)
390 - static if(is(S : AST))
391 - lst = makeCons(rec(a), lst);
392 - else
393 - lst = makeCons(ast2table(a,rec), lst);
394 - return lst;
395 - }
396 - else
397 - static if(is(T : AST))
398 - {
399 - auto t = new Table;
400 - t.set("pos", ValueLayer, fromPos(e.pos));
401 - t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower()));
402 - foreach(i,m; e.tupleof)
403 - static if(is(typeof(m) : AST))
404 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
405 - else
406 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
407 - return t;
408 - }
409 - else
410 - static if(is(T == class))
411 - {
412 - auto t = new Table;
413 - foreach(i,m; e.tupleof)
414 - static if(is(typeof(m) : AST))
415 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
416 - else
417 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
418 - return t;
419 - }
420 - else
421 - static assert(false, "unknown type <"~T.stringof~"> during AST encoding");
422 -}