36c517dfc4 2010-11-23 kinaba: /** 36c517dfc4 2010-11-23 kinaba: * Authors: k.inaba 36c517dfc4 2010-11-23 kinaba: * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 36c517dfc4 2010-11-23 kinaba: * 36c517dfc4 2010-11-23 kinaba: * Convert values between Polemy and D 36c517dfc4 2010-11-23 kinaba: */ 36c517dfc4 2010-11-23 kinaba: module polemy.valueconv; 36c517dfc4 2010-11-23 kinaba: import polemy._common; 36c517dfc4 2010-11-23 kinaba: import polemy.failure; 36c517dfc4 2010-11-23 kinaba: import polemy.ast; 36c517dfc4 2010-11-23 kinaba: import polemy.layer; 36c517dfc4 2010-11-23 kinaba: import polemy.value; 36c517dfc4 2010-11-23 kinaba: import std.string; 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: LexPosition extractPos( Table t ) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Layer theLayer = ValueLayer; 36c517dfc4 2010-11-23 kinaba: if(auto tt = t.access!Table(theLayer, "pos")) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: auto fn = tt.access!StrValue(theLayer, "filename"); 36c517dfc4 2010-11-23 kinaba: auto ln = tt.access!IntValue(theLayer, "lineno"); 36c517dfc4 2010-11-23 kinaba: auto cl = tt.access!IntValue(theLayer, "column"); 36c517dfc4 2010-11-23 kinaba: if(fn !is null && ln !is null && cl !is null) 36c517dfc4 2010-11-23 kinaba: return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: return null; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: Value[] tableAsConsList( Layer theLayer, Table t ) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Value[] result; 36c517dfc4 2010-11-23 kinaba: while(t) 36c517dfc4 2010-11-23 kinaba: if(auto v = t.access!Value(theLayer, "car")) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: result ~= v; 36c517dfc4 2010-11-23 kinaba: t = t.access!Table(theLayer, "cdr"); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: break; 36c517dfc4 2010-11-23 kinaba: return result; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: AST[] tableToASTList( Layer theLayer, Table t ) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: AST[] result; 36c517dfc4 2010-11-23 kinaba: foreach(v; tableAsConsList(theLayer, t)) 36c517dfc4 2010-11-23 kinaba: if(auto t = cast(Table)v) 36c517dfc4 2010-11-23 kinaba: result ~= tableToAST(theLayer,t); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)"); 36c517dfc4 2010-11-23 kinaba: return result; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: AST tableToAST( Layer theLayer, Value vvvv ) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Table t = cast(Table)vvvv; 36c517dfc4 2010-11-23 kinaba: if( t is null ) 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)"); 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: auto nodeType = t.access!StrValue(theLayer, "is"); 36c517dfc4 2010-11-23 kinaba: if( nodeType is null ) 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); 36c517dfc4 2010-11-23 kinaba: auto pos = extractPos(t); 36c517dfc4 2010-11-23 kinaba: switch(nodeType.data) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: case "int": 36c517dfc4 2010-11-23 kinaba: if(auto v = t.access!IntValue(theLayer, "data")) 36c517dfc4 2010-11-23 kinaba: return new Int(pos, v.data); 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); 36c517dfc4 2010-11-23 kinaba: case "str": 36c517dfc4 2010-11-23 kinaba: if(auto v = t.access!StrValue(theLayer, "data")) 36c517dfc4 2010-11-23 kinaba: return new Str(pos, v.data); 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); 36c517dfc4 2010-11-23 kinaba: case "var": 36c517dfc4 2010-11-23 kinaba: if(auto v = t.access!StrValue(theLayer, "name")) 36c517dfc4 2010-11-23 kinaba: return new Var(pos, v.data); 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 36c517dfc4 2010-11-23 kinaba: case "lay": 36c517dfc4 2010-11-23 kinaba: if(auto v = t.access!StrValue(theLayer, "layer")) 36c517dfc4 2010-11-23 kinaba: if(auto e = t.access!Table(theLayer, "expr")) 36c517dfc4 2010-11-23 kinaba: return new Lay(pos, v.data, tableToAST(theLayer,e)); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 36c517dfc4 2010-11-23 kinaba: case "let": 36c517dfc4 2010-11-23 kinaba: if(auto n = t.access!StrValue(theLayer, "name")) 36c517dfc4 2010-11-23 kinaba: if(auto e = t.access!Table(theLayer, "init")) 36c517dfc4 2010-11-23 kinaba: if(auto b = t.access!Table(theLayer, "expr")) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: string nn = n.data; 36c517dfc4 2010-11-23 kinaba: auto ee = tableToAST(theLayer, e); 36c517dfc4 2010-11-23 kinaba: auto bb = tableToAST(theLayer, b); 36c517dfc4 2010-11-23 kinaba: Layer lay=""; 36c517dfc4 2010-11-23 kinaba: if(auto l = t.access!StrValue(theLayer, "layer")) 36c517dfc4 2010-11-23 kinaba: lay = l.data; 36c517dfc4 2010-11-23 kinaba: return new Let(pos, nn, lay, ee, bb); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 36c517dfc4 2010-11-23 kinaba: case "app": 36c517dfc4 2010-11-23 kinaba: if(auto f = t.access!Table(theLayer, "fun")) 36c517dfc4 2010-11-23 kinaba: if(auto a = t.access!Table(theLayer, "args")) 36c517dfc4 2010-11-23 kinaba: return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 36c517dfc4 2010-11-23 kinaba: case "fun": 36c517dfc4 2010-11-23 kinaba: if(auto p = t.access!Table(theLayer, "params")) 36c517dfc4 2010-11-23 kinaba: if(auto b = t.access!Table(theLayer, "funbody")) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Parameter[] ps; 36c517dfc4 2010-11-23 kinaba: foreach(v; tableAsConsList(theLayer, p)) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: if(auto tt = cast(Table)v) 36c517dfc4 2010-11-23 kinaba: if(auto ss = tt.access!StrValue(theLayer, "name")) 36c517dfc4 2010-11-23 kinaba: if(auto ll = tt.access!Table(theLayer, "layers")) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Layer[] ls; 36c517dfc4 2010-11-23 kinaba: foreach(lll; tableAsConsList(theLayer, ll)) 36c517dfc4 2010-11-23 kinaba: if(auto l = cast(StrValue)lll) 36c517dfc4 2010-11-23 kinaba: ls ~= l.data; 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll)); 36c517dfc4 2010-11-23 kinaba: ps ~= new Parameter(ss.data, ls); 36c517dfc4 2010-11-23 kinaba: continue; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Layer[] emp; 36c517dfc4 2010-11-23 kinaba: ps ~= new Parameter(ss.data, emp); 36c517dfc4 2010-11-23 kinaba: continue; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: auto bb = tableToAST(theLayer, b); 36c517dfc4 2010-11-23 kinaba: return new Fun(pos,ps,bb); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); 36c517dfc4 2010-11-23 kinaba: default: 36c517dfc4 2010-11-23 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: /// Cons of two pairs 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: Table makeCons(Value a, Value d) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Table t = new Table; 36c517dfc4 2010-11-23 kinaba: t.set("car", ValueLayer, a); 36c517dfc4 2010-11-23 kinaba: t.set("cdr", ValueLayer, d); 36c517dfc4 2010-11-23 kinaba: return t; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: /// Experimental!!! Convert D value (except AST) to Polemy Value 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: Value d2polemy(T)(T e) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: return ast2table(e, delegate Value(AST){ assert(false); }); 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: /// Convert AST to Table so that it can be used in Polemy 36c517dfc4 2010-11-23 kinaba: 36c517dfc4 2010-11-23 kinaba: Value ast2table(T)(T e, Value delegate(AST) rec) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: static if(is(T==BigInt) || isIntegral!(T)) 36c517dfc4 2010-11-23 kinaba: return new IntValue(e); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: static if(is(Unqual!(T)==string)) 36c517dfc4 2010-11-23 kinaba: return new StrValue(e); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: static if(is(T S : S[])) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: Table lst = new Table; 36c517dfc4 2010-11-23 kinaba: foreach_reverse(a; e) 36c517dfc4 2010-11-23 kinaba: static if(is(S : AST)) 36c517dfc4 2010-11-23 kinaba: lst = makeCons(rec(a), lst); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: lst = makeCons(ast2table(a,rec), lst); 36c517dfc4 2010-11-23 kinaba: return lst; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: static if(is(T : AST)) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) ); 36c517dfc4 2010-11-23 kinaba: auto t = new Table; 36c517dfc4 2010-11-23 kinaba: t.set("pos", ValueLayer, ast2table(e.pos,rec)); 36c517dfc4 2010-11-23 kinaba: t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower())); 36c517dfc4 2010-11-23 kinaba: foreach(i,m; e.tupleof) 36c517dfc4 2010-11-23 kinaba: static if(is(typeof(m) : AST)) 36c517dfc4 2010-11-23 kinaba: t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 36c517dfc4 2010-11-23 kinaba: return t; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: static if(is(T == class)) 36c517dfc4 2010-11-23 kinaba: { 36c517dfc4 2010-11-23 kinaba: auto t = new Table; 36c517dfc4 2010-11-23 kinaba: foreach(i,m; e.tupleof) 36c517dfc4 2010-11-23 kinaba: static if(is(typeof(m) : AST)) 36c517dfc4 2010-11-23 kinaba: t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 36c517dfc4 2010-11-23 kinaba: return t; 36c517dfc4 2010-11-23 kinaba: } 36c517dfc4 2010-11-23 kinaba: else 36c517dfc4 2010-11-23 kinaba: static assert(false, "unknown type <"~T.stringof~"> during AST encoding"); 36c517dfc4 2010-11-23 kinaba: }