File Annotation
Not logged in
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: }