8de5b49cdf 2010-11-09 kinaba: /** b0d8d7875b 2010-11-08 kinaba: * Authors: k.inaba b0d8d7875b 2010-11-08 kinaba: * License: NYSL 0.9982 http://www.kmonos.net/nysl/ b0d8d7875b 2010-11-08 kinaba: * b0d8d7875b 2010-11-08 kinaba: * Runtime data structures for Polemy programming language. b0d8d7875b 2010-11-08 kinaba: */ b0d8d7875b 2010-11-08 kinaba: module polemy.value; b0d8d7875b 2010-11-08 kinaba: import polemy._common; 3464a035ec 2010-11-20 kinaba: import polemy.failure; 3f6f41b558 2010-11-20 kinaba: import polemy.ast; 435fa085ec 2010-11-21 kinaba: import polemy.layer; b0d8d7875b 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: /// Runtime values of Polemy b0d8d7875b 2010-11-08 kinaba: b0d8d7875b 2010-11-08 kinaba: abstract class Value b0d8d7875b 2010-11-08 kinaba: { b0d8d7875b 2010-11-08 kinaba: } b0d8d7875b 2010-11-08 kinaba: 515502e8d1 2010-11-20 kinaba: /// b0d8d7875b 2010-11-08 kinaba: class IntValue : Value b0d8d7875b 2010-11-08 kinaba: { b0d8d7875b 2010-11-08 kinaba: BigInt data; aa770610d3 2010-11-08 kinaba: 7465fcdd7f 2010-11-09 kinaba: mixin SimpleClass; aa770610d3 2010-11-08 kinaba: override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); } b0d8d7875b 2010-11-08 kinaba: } b0d8d7875b 2010-11-08 kinaba: 515502e8d1 2010-11-20 kinaba: /// b0d8d7875b 2010-11-08 kinaba: class StrValue : Value b0d8d7875b 2010-11-08 kinaba: { b0d8d7875b 2010-11-08 kinaba: string data; aa770610d3 2010-11-08 kinaba: 7465fcdd7f 2010-11-09 kinaba: mixin SimpleClass; b0d8d7875b 2010-11-08 kinaba: override string toString() const { return data; } b0d8d7875b 2010-11-08 kinaba: } b0d8d7875b 2010-11-08 kinaba: 515502e8d1 2010-11-20 kinaba: /// 5afe8e3f26 2010-11-13 kinaba: class UndValue : Value 5afe8e3f26 2010-11-13 kinaba: { 5afe8e3f26 2010-11-13 kinaba: mixin SimpleClass; 5afe8e3f26 2010-11-13 kinaba: override string toString() const { return "<undefined>"; } 5afe8e3f26 2010-11-13 kinaba: } 5afe8e3f26 2010-11-13 kinaba: 515502e8d1 2010-11-20 kinaba: a5fe6233c1 2010-11-21 kinaba: /// a5fe6233c1 2010-11-21 kinaba: abstract class FunValue : Value a5fe6233c1 2010-11-21 kinaba: { a5fe6233c1 2010-11-21 kinaba: const(Parameter[]) params(); a5fe6233c1 2010-11-21 kinaba: Table definitionContext(); a5fe6233c1 2010-11-21 kinaba: Value invoke(in LexPosition pos, Layer lay, Table ctx); a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: a5fe6233c1 2010-11-21 kinaba: import polemy.eval; // circular... f86026acb8 2010-11-21 kinaba: version = MacroCache; f86026acb8 2010-11-21 kinaba: //version = AutoMemoization; f86026acb8 2010-11-21 kinaba: //version = AutoRerun; a5fe6233c1 2010-11-21 kinaba: a5fe6233c1 2010-11-21 kinaba: /// a5fe6233c1 2010-11-21 kinaba: class UserDefinedFunValue : FunValue a5fe6233c1 2010-11-21 kinaba: { a5fe6233c1 2010-11-21 kinaba: FunLiteral ast; a5fe6233c1 2010-11-21 kinaba: Table defCtx; f86026acb8 2010-11-21 kinaba: f86026acb8 2010-11-21 kinaba: this(FunLiteral ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } f86026acb8 2010-11-21 kinaba: override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } f86026acb8 2010-11-21 kinaba: override bool opEquals(Object rhs_) const /// member-by-member equality f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) f86026acb8 2010-11-21 kinaba: return this.ast==rhs.ast && this.defCtx==rhs.defCtx; f86026acb8 2010-11-21 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: override hash_t toHash() const /// member-by-member hash f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&this.defCtx); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: override int opCmp(Object rhs_) /// member-by-member compare f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: if( auto rhs = cast(typeof(this))rhs_ ) f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: if(auto i = this.ast.opCmp(rhs.ast)) f86026acb8 2010-11-21 kinaba: return i; f86026acb8 2010-11-21 kinaba: return this.defCtx.opCmp(rhs.defCtx); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: f86026acb8 2010-11-21 kinaba: private AST preprocessed_funbody; f86026acb8 2010-11-21 kinaba: private Value[Value[]][Layer] memo; f86026acb8 2010-11-21 kinaba: a5fe6233c1 2010-11-21 kinaba: override const(Parameter[]) params() { return ast.params; } a5fe6233c1 2010-11-21 kinaba: override Table definitionContext() { return defCtx; } a5fe6233c1 2010-11-21 kinaba: override Value invoke(in LexPosition pos, Layer lay, Table ctx) a5fe6233c1 2010-11-21 kinaba: { a5fe6233c1 2010-11-21 kinaba: // TODO: only auto raised ones need memo? no? f86026acb8 2010-11-21 kinaba: // how can we integrate re-run ?? f86026acb8 2010-11-21 kinaba: version(AutoMemoization) a5fe6233c1 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: Value[] memokey; f86026acb8 2010-11-21 kinaba: if( lay != ValueLayer && lay != MacroLayer ) f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: foreach(i,p; ast.params) f86026acb8 2010-11-21 kinaba: memokey ~= ctx.get(p.name, lay); // lay? f86026acb8 2010-11-21 kinaba: if( auto memolay = lay in memo ) f86026acb8 2010-11-21 kinaba: if( auto pv = memokey in *memolay ) f86026acb8 2010-11-21 kinaba: return *pv; f86026acb8 2010-11-21 kinaba: memo[lay][memokey] = lift(ast.pos,new UndValue,lay,ctx); f86026acb8 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: a5fe6233c1 2010-11-21 kinaba: // @macro run!!! 435fa085ec 2010-11-21 kinaba: if( lay == MacroLayer ) a5fe6233c1 2010-11-21 kinaba: return macroEval(ast.funbody, ctx, false); f86026acb8 2010-11-21 kinaba: f86026acb8 2010-11-21 kinaba: version(MacroCache) { f86026acb8 2010-11-21 kinaba: if( preprocessed_funbody is null ) { f86026acb8 2010-11-21 kinaba: // .prototype!, forced macro cannot access parameters f86026acb8 2010-11-21 kinaba: ctx.kill = true; scope(exit)ctx.kill=false; f86026acb8 2010-11-21 kinaba: preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: } else { f86026acb8 2010-11-21 kinaba: if( preprocessed_funbody is null ) { f86026acb8 2010-11-21 kinaba: // .prototype!, forced macro cannot access parameters f86026acb8 2010-11-21 kinaba: ctx.kill = true; scope(exit)ctx.kill=false; f86026acb8 2010-11-21 kinaba: preprocessed_funbody = tableToAST(ValueLayer,macroEval(ast.funbody, ctx, true)); f86026acb8 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: f86026acb8 2010-11-21 kinaba: auto v = eval(preprocessed_funbody, ctx, true, lay); f86026acb8 2010-11-21 kinaba: version(AutoMemoization) f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: if( lay != ValueLayer && lay != MacroLayer ) f86026acb8 2010-11-21 kinaba: { f86026acb8 2010-11-21 kinaba: memo[lay][memokey] = v; f86026acb8 2010-11-21 kinaba: version(AutoReRun) f86026acb8 2010-11-21 kinaba: memo[lay][memokey] = eval(preprocessed_funbody, ctx, true, lay); // re-Run!! f86026acb8 2010-11-21 kinaba: } f86026acb8 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: return v; a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: a5fe6233c1 2010-11-21 kinaba: /// a5fe6233c1 2010-11-21 kinaba: abstract class NativeFunValue : FunValue 515502e8d1 2010-11-20 kinaba: { a5fe6233c1 2010-11-21 kinaba: Parameter[] params_data; a5fe6233c1 2010-11-21 kinaba: override const(Parameter[]) params() { return params_data; } a5fe6233c1 2010-11-21 kinaba: override Table definitionContext() { return new Table; } // todo: cache overrie 515502e8d1 2010-11-20 kinaba: } 515502e8d1 2010-11-20 kinaba: 515502e8d1 2010-11-20 kinaba: /// Named Constructor for FunValue 515502e8d1 2010-11-20 kinaba: 515502e8d1 2010-11-20 kinaba: FunValue native(R,T...)(R delegate (T) dg) 515502e8d1 2010-11-20 kinaba: { a5fe6233c1 2010-11-21 kinaba: return new class NativeFunValue { a5fe6233c1 2010-11-21 kinaba: this() a5fe6233c1 2010-11-21 kinaba: { a5fe6233c1 2010-11-21 kinaba: foreach(i, Ti; T) a5fe6233c1 2010-11-21 kinaba: params_data ~= new Parameter(text(i), []); a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: override Value invoke(in LexPosition pos, Layer lay, Table ctx) 515502e8d1 2010-11-20 kinaba: { 435fa085ec 2010-11-21 kinaba: if( lay != ValueLayer ) 435fa085ec 2010-11-21 kinaba: throw genex!RuntimeException(pos, "only "~ValueLayer~" layer can call native function"); a5fe6233c1 2010-11-21 kinaba: T typed_args; a5fe6233c1 2010-11-21 kinaba: foreach(i, Ti; T) { 435fa085ec 2010-11-21 kinaba: typed_args[i] = cast(Ti) ctx.get(text(i), ValueLayer); a5fe6233c1 2010-11-21 kinaba: if( typed_args[i] is null ) a5fe6233c1 2010-11-21 kinaba: throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1)); a5fe6233c1 2010-11-21 kinaba: } a5fe6233c1 2010-11-21 kinaba: try { a5fe6233c1 2010-11-21 kinaba: return dg(typed_args); a5fe6233c1 2010-11-21 kinaba: } catch( RuntimeException e ) { a5fe6233c1 2010-11-21 kinaba: throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e; a5fe6233c1 2010-11-21 kinaba: } 515502e8d1 2010-11-20 kinaba: } a5fe6233c1 2010-11-21 kinaba: }; 515502e8d1 2010-11-20 kinaba: } aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: /// Context (variable environment) aa770610d3 2010-11-08 kinaba: /// Simlar to prototype chain of ECMAScript etc. aa770610d3 2010-11-08 kinaba: /// But extended with the notion of "Layer" aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: class Table : Value b0d8d7875b 2010-11-08 kinaba: { aa770610d3 2010-11-08 kinaba: enum Kind {PropagateSet, NotPropagateSet}; a5fe6233c1 2010-11-21 kinaba: bool kill = false; // to refactor aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: this( Table proto=null, Kind k = Kind.PropagateSet ) aa770610d3 2010-11-08 kinaba: { this.prototype = proto; this.kind = k; } aa770610d3 2010-11-08 kinaba: 8de5b49cdf 2010-11-09 kinaba: void set(string i, Layer lay, Value v, in LexPosition pos=null) 8de5b49cdf 2010-11-09 kinaba: { 8de5b49cdf 2010-11-09 kinaba: if( setIfExist(i, lay, v) ) 8de5b49cdf 2010-11-09 kinaba: return; 8de5b49cdf 2010-11-09 kinaba: data[i][lay] = v; 8de5b49cdf 2010-11-09 kinaba: } 8de5b49cdf 2010-11-09 kinaba: 515502e8d1 2010-11-20 kinaba: bool has(string i, Layer lay, in LexPosition pos=null) 515502e8d1 2010-11-20 kinaba: { 515502e8d1 2010-11-20 kinaba: if( i in data ) { 515502e8d1 2010-11-20 kinaba: if( lay !in data[i] ) 515502e8d1 2010-11-20 kinaba: return false; a5fe6233c1 2010-11-21 kinaba: if(kill) a5fe6233c1 2010-11-21 kinaba: return false; 515502e8d1 2010-11-20 kinaba: return true; 515502e8d1 2010-11-20 kinaba: } 515502e8d1 2010-11-20 kinaba: if( prototype is null ) 515502e8d1 2010-11-20 kinaba: return false; 515502e8d1 2010-11-20 kinaba: return prototype.has(i, lay, pos); 515502e8d1 2010-11-20 kinaba: } 515502e8d1 2010-11-20 kinaba: 8de5b49cdf 2010-11-09 kinaba: Value get(string i, Layer lay, in LexPosition pos=null) aa770610d3 2010-11-08 kinaba: { 5afe8e3f26 2010-11-13 kinaba: if( i in data ) { 515502e8d1 2010-11-20 kinaba: // [TODO] consider forwarding to proto also in this case 5afe8e3f26 2010-11-13 kinaba: if( lay !in data[i] ) f86026acb8 2010-11-21 kinaba: throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay)); a5fe6233c1 2010-11-21 kinaba: if(kill) f86026acb8 2010-11-21 kinaba: throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i)); aa770610d3 2010-11-08 kinaba: return data[i][lay]; 5afe8e3f26 2010-11-13 kinaba: } aa770610d3 2010-11-08 kinaba: if( prototype is null ) f86026acb8 2010-11-21 kinaba: throw new RuntimeException(pos, sprintf!"'%s' not found"(i)); 5afe8e3f26 2010-11-13 kinaba: return prototype.get(i, lay, pos); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: 3f6f41b558 2010-11-20 kinaba: T access(T,S...)( Layer lay, string path, S rest ) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: static if( rest.length == 0 ) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: if( this.has(path, lay) ) 3f6f41b558 2010-11-20 kinaba: return cast(T) this.get(path, lay); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: else 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: if(auto next = this.access!Table(lay,path)) 3f6f41b558 2010-11-20 kinaba: return next.access!T(lay,rest); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: return null; 8e3db9ef20 2010-11-20 kinaba: } 8e3db9ef20 2010-11-20 kinaba: 8e3db9ef20 2010-11-20 kinaba: string toStringWithoutParen() const 8e3db9ef20 2010-11-20 kinaba: { 8e3db9ef20 2010-11-20 kinaba: string result; 8e3db9ef20 2010-11-20 kinaba: bool first = true; 8e3db9ef20 2010-11-20 kinaba: foreach(k, l2d; data) 8e3db9ef20 2010-11-20 kinaba: foreach(l,d; l2d) 8e3db9ef20 2010-11-20 kinaba: { 8e3db9ef20 2010-11-20 kinaba: if(first) first=false; else result~=", "; 8e3db9ef20 2010-11-20 kinaba: result ~= k; 8e3db9ef20 2010-11-20 kinaba: result ~= l; 8e3db9ef20 2010-11-20 kinaba: result ~= ":"; 8e3db9ef20 2010-11-20 kinaba: result ~= text(cast(Value)d); 8e3db9ef20 2010-11-20 kinaba: } 8e3db9ef20 2010-11-20 kinaba: if( prototype !is null ) 8e3db9ef20 2010-11-20 kinaba: { 8e3db9ef20 2010-11-20 kinaba: result ~= " / "; 8e3db9ef20 2010-11-20 kinaba: result ~= prototype.toStringWithoutParen(); 8e3db9ef20 2010-11-20 kinaba: } 8e3db9ef20 2010-11-20 kinaba: return result; 8e3db9ef20 2010-11-20 kinaba: } 8e3db9ef20 2010-11-20 kinaba: 8e3db9ef20 2010-11-20 kinaba: string toString() const 8e3db9ef20 2010-11-20 kinaba: { 8e3db9ef20 2010-11-20 kinaba: return "{" ~ toStringWithoutParen() ~ "}"; aa770610d3 2010-11-08 kinaba: } aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: private: aa770610d3 2010-11-08 kinaba: Table prototype; aa770610d3 2010-11-08 kinaba: Kind kind; aa770610d3 2010-11-08 kinaba: Value[Layer][string] data; aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: bool setIfExist(string i, Layer lay, Value v) aa770610d3 2010-11-08 kinaba: { aa770610d3 2010-11-08 kinaba: if( i in data ) aa770610d3 2010-11-08 kinaba: { aa770610d3 2010-11-08 kinaba: data[i][lay] = v; aa770610d3 2010-11-08 kinaba: return true; aa770610d3 2010-11-08 kinaba: } aa770610d3 2010-11-08 kinaba: if( kind==Kind.PropagateSet && prototype !is null ) aa770610d3 2010-11-08 kinaba: return prototype.setIfExist(i, lay, v); aa770610d3 2010-11-08 kinaba: return false; aa770610d3 2010-11-08 kinaba: } b0d8d7875b 2010-11-08 kinaba: } aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: unittest b0d8d7875b 2010-11-08 kinaba: { aa770610d3 2010-11-08 kinaba: Table c0 = new Table; aa770610d3 2010-11-08 kinaba: Table c01 = new Table(c0, Table.Kind.NotPropagateSet); aa770610d3 2010-11-08 kinaba: Table c012 = new Table(c01, Table.Kind.PropagateSet); aa770610d3 2010-11-08 kinaba: Table c013 = new Table(c01, Table.Kind.PropagateSet); aa770610d3 2010-11-08 kinaba: 435fa085ec 2010-11-21 kinaba: assert_nothrow( c012.set("x", ValueLayer, new IntValue(BigInt(12))) ); 435fa085ec 2010-11-21 kinaba: assert_throw!RuntimeException( c013.get("x", ValueLayer) ); 435fa085ec 2010-11-21 kinaba: assert_nothrow( c013.set("x", ValueLayer, new IntValue(BigInt(13))) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c013.get("x", ValueLayer), new IntValue(BigInt(13)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c012.get("x", ValueLayer), new IntValue(BigInt(12)) ); 435fa085ec 2010-11-21 kinaba: assert_throw!RuntimeException( c01.get("x", ValueLayer) ); 435fa085ec 2010-11-21 kinaba: 435fa085ec 2010-11-21 kinaba: assert_nothrow( c01.set("y", ValueLayer, new IntValue(BigInt(1))) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(1)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(1)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(1)) ); aa770610d3 2010-11-08 kinaba: 435fa085ec 2010-11-21 kinaba: assert_nothrow( c0.set("z", ValueLayer, new IntValue(BigInt(0))) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(0)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); aa770610d3 2010-11-08 kinaba: 435fa085ec 2010-11-21 kinaba: assert_nothrow( c012.set("y", ValueLayer, new IntValue(BigInt(444))) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(444)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(444)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(444)) ); aa770610d3 2010-11-08 kinaba: 435fa085ec 2010-11-21 kinaba: assert_nothrow( c012.set("z", ValueLayer, new IntValue(BigInt(555))) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 435fa085ec 2010-11-21 kinaba: assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); aa770610d3 2010-11-08 kinaba: aa770610d3 2010-11-08 kinaba: // [TODO] define the semantics and test @layers 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: 3f6f41b558 2010-11-20 kinaba: immutable(LexPosition) extractPos( Table t ) 3f6f41b558 2010-11-20 kinaba: { 435fa085ec 2010-11-21 kinaba: Layer theLayer = ValueLayer; 3f6f41b558 2010-11-20 kinaba: if(auto tt = t.access!Table(theLayer, "pos")) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: auto fn = tt.access!StrValue(theLayer, "filename"); 3f6f41b558 2010-11-20 kinaba: auto ln = tt.access!IntValue(theLayer, "lineno"); 3f6f41b558 2010-11-20 kinaba: auto cl = tt.access!IntValue(theLayer, "column"); 3f6f41b558 2010-11-20 kinaba: if(fn !is null && ln !is null && cl !is null) 3f6f41b558 2010-11-20 kinaba: return new immutable(LexPosition)(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: return null; 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: 3f6f41b558 2010-11-20 kinaba: Value[] tableAsConsList( Layer theLayer, Table t ) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: Value[] result; 3f6f41b558 2010-11-20 kinaba: while(t) 3f6f41b558 2010-11-20 kinaba: if(auto v = t.access!Value(theLayer, "car")) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: result ~= v; 3f6f41b558 2010-11-20 kinaba: t = t.access!Table(theLayer, "cdr"); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: else 3f6f41b558 2010-11-20 kinaba: break; 3f6f41b558 2010-11-20 kinaba: return result; 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: 3f6f41b558 2010-11-20 kinaba: AST[] tableToASTList( Layer theLayer, Table t ) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: AST[] result; 3f6f41b558 2010-11-20 kinaba: foreach(v; tableAsConsList(theLayer, t)) 3f6f41b558 2010-11-20 kinaba: if(auto t = cast(Table)v) 3f6f41b558 2010-11-20 kinaba: result ~= tableToAST(theLayer,t); 3f6f41b558 2010-11-20 kinaba: else 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)"); 3f6f41b558 2010-11-20 kinaba: return result; 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: 8e3db9ef20 2010-11-20 kinaba: AST tableToAST( Layer theLayer, Value vvvv ) 3f6f41b558 2010-11-20 kinaba: { 8e3db9ef20 2010-11-20 kinaba: Table t = cast(Table)vvvv; 8e3db9ef20 2010-11-20 kinaba: if( t is null ) 8e3db9ef20 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)"); 8e3db9ef20 2010-11-20 kinaba: 3f6f41b558 2010-11-20 kinaba: auto nodeType = t.access!StrValue(theLayer, "is"); 3f6f41b558 2010-11-20 kinaba: if( nodeType is null ) 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); 3f6f41b558 2010-11-20 kinaba: auto pos = extractPos(t); 3f6f41b558 2010-11-20 kinaba: switch(nodeType.data) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: case "int": 3f6f41b558 2010-11-20 kinaba: if(auto v = t.access!IntValue(theLayer, "data")) 3f6f41b558 2010-11-20 kinaba: return new IntLiteral(pos, v.data); 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); 3f6f41b558 2010-11-20 kinaba: case "str": 3f6f41b558 2010-11-20 kinaba: if(auto v = t.access!StrValue(theLayer, "data")) 3f6f41b558 2010-11-20 kinaba: return new StrLiteral(pos, v.data); 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); 3f6f41b558 2010-11-20 kinaba: case "var": 3f6f41b558 2010-11-20 kinaba: if(auto v = t.access!StrValue(theLayer, "name")) 3f6f41b558 2010-11-20 kinaba: return new VarExpression(pos, v.data); 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 3f6f41b558 2010-11-20 kinaba: case "lay": 3f6f41b558 2010-11-20 kinaba: if(auto v = t.access!StrValue(theLayer, "layer")) 3f6f41b558 2010-11-20 kinaba: if(auto e = t.access!Table(theLayer, "expr")) 3995a5eb6a 2010-11-21 kinaba: return new LayExpression(pos, v.data, tableToAST(theLayer,e)); 3f6f41b558 2010-11-20 kinaba: else 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 3f6f41b558 2010-11-20 kinaba: case "let": 3f6f41b558 2010-11-20 kinaba: if(auto n = t.access!StrValue(theLayer, "name")) 3f6f41b558 2010-11-20 kinaba: if(auto e = t.access!Table(theLayer, "init")) 3f6f41b558 2010-11-20 kinaba: if(auto b = t.access!Table(theLayer, "expr")) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: string nn = n.data; 3f6f41b558 2010-11-20 kinaba: auto ee = tableToAST(theLayer, e); 3f6f41b558 2010-11-20 kinaba: auto bb = tableToAST(theLayer, b); 3f6f41b558 2010-11-20 kinaba: Layer lay=""; 3f6f41b558 2010-11-20 kinaba: if(auto l = t.access!StrValue(theLayer, "layer")) 3f6f41b558 2010-11-20 kinaba: lay = l.data; 3f6f41b558 2010-11-20 kinaba: return new LetExpression(pos, nn, lay, ee, bb); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 3f6f41b558 2010-11-20 kinaba: case "app": 3f6f41b558 2010-11-20 kinaba: if(auto f = t.access!Table(theLayer, "fun")) 3995a5eb6a 2010-11-21 kinaba: if(auto a = t.access!Table(theLayer, "args")) 3f6f41b558 2010-11-20 kinaba: return new FuncallExpression(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 3995a5eb6a 2010-11-21 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 3f6f41b558 2010-11-20 kinaba: case "fun": 3995a5eb6a 2010-11-21 kinaba: if(auto p = t.access!Table(theLayer, "params")) 3995a5eb6a 2010-11-21 kinaba: if(auto b = t.access!Table(theLayer, "funbody")) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: Parameter[] ps; 3f6f41b558 2010-11-20 kinaba: foreach(v; tableAsConsList(theLayer, p)) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: if(auto tt = cast(Table)v) 3f6f41b558 2010-11-20 kinaba: if(auto ss = tt.access!StrValue(theLayer, "name")) 3995a5eb6a 2010-11-21 kinaba: if(auto ll = tt.access!Table(theLayer, "layers")) 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: Layer[] ls; 3f6f41b558 2010-11-20 kinaba: foreach(lll; tableAsConsList(theLayer, ll)) 3f6f41b558 2010-11-20 kinaba: if(auto l = cast(StrValue)lll) 3f6f41b558 2010-11-20 kinaba: ls ~= l.data; 3f6f41b558 2010-11-20 kinaba: else 8e3db9ef20 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll)); 3f6f41b558 2010-11-20 kinaba: ps ~= new Parameter(ss.data, ls); 3f6f41b558 2010-11-20 kinaba: continue; 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: else 3f6f41b558 2010-11-20 kinaba: { 3f6f41b558 2010-11-20 kinaba: Layer[] emp; 3f6f41b558 2010-11-20 kinaba: ps ~= new Parameter(ss.data, emp); 8e3db9ef20 2010-11-20 kinaba: continue; 3f6f41b558 2010-11-20 kinaba: } 8e3db9ef20 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: auto bb = tableToAST(theLayer, b); 3f6f41b558 2010-11-20 kinaba: return new FunLiteral(pos,ps,bb); 3f6f41b558 2010-11-20 kinaba: } 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); 3f6f41b558 2010-11-20 kinaba: default: 3f6f41b558 2010-11-20 kinaba: throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); 3f6f41b558 2010-11-20 kinaba: } b0d8d7875b 2010-11-08 kinaba: }