File Annotation
Not logged in
8de5b49cdf 2010-11-09        kinaba: /**
4198578702 2010-11-07        kinaba:  * Authors: k.inaba
4198578702 2010-11-07        kinaba:  * License: NYSL 0.9982 http://www.kmonos.net/nysl/
4198578702 2010-11-07        kinaba:  *
4198578702 2010-11-07        kinaba:  * Evaluator for Polemy programming language.
423f308350 2010-11-07        kinaba:  */
4198578702 2010-11-07        kinaba: module polemy.eval;
4198578702 2010-11-07        kinaba: import polemy._common;
3464a035ec 2010-11-20        kinaba: import polemy.failure;
423f308350 2010-11-07        kinaba: import polemy.ast;
3f5dc76a75 2010-11-07        kinaba: import polemy.parse;
b0d8d7875b 2010-11-08        kinaba: import polemy.value;
435fa085ec 2010-11-21        kinaba: import polemy.layer;
36c517dfc4 2010-11-23        kinaba: import polemy.value;
36c517dfc4 2010-11-23        kinaba: import polemy.valueconv;
552d43f567 2010-11-26        kinaba: import std.signals;
a5fe6233c1 2010-11-21        kinaba: 
b97bd4f713 2010-11-23        kinaba: /// Objects for maitaining global environment and evaluation of expression on it
6ac127ddd0 2010-11-23        kinaba: class Evaluator
423f308350 2010-11-07        kinaba: {
6ac127ddd0 2010-11-23        kinaba: public:
b97bd4f713 2010-11-23        kinaba: 	/// Evaluate the AST
6ac127ddd0 2010-11-23        kinaba: 	Value evalAST(AST e)
203e4cb208 2010-11-27        kinaba: 		{ return getLayerEval(ValueLayer).macroAndEval(e, theContext, LayerEval.OverwriteCtx); }
6ac127ddd0 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 	/// Evaluate the string
6ac127ddd0 2010-11-23        kinaba: 	Value evalString(S,T...)(S str, T fn_ln_cn)
203e4cb208 2010-11-27        kinaba: 		{ return evalAST(parseString(str,fn_ln_cn)); }
6ac127ddd0 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 	/// Evaluate the file
6ac127ddd0 2010-11-23        kinaba: 	Value evalFile(S,T...)(S filename, T ln_cn)
203e4cb208 2010-11-27        kinaba: 		{ return evalAST(parseFile(filename,ln_cn)); }
6ac127ddd0 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 	/// Get the global context
6ac127ddd0 2010-11-23        kinaba: 	Table globalContext()
203e4cb208 2010-11-27        kinaba: 		{ return theContext; }
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 	/// Initialize evaluator with empty context
203e4cb208 2010-11-27        kinaba: 	this()
6ac127ddd0 2010-11-23        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		theContext = new Table;
203e4cb208 2010-11-27        kinaba: 		theLayers[ValueLayer]    = new ValueLayerEval;
203e4cb208 2010-11-27        kinaba: 		theLayers[MacroLayer]    = new MacroLayerEval;
203e4cb208 2010-11-27        kinaba: 		theLayers[RawMacroLayer] = new RawMacroLayerEval;
6ac127ddd0 2010-11-23        kinaba: 	}
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: private:
203e4cb208 2010-11-27        kinaba: 	Table            theContext;
203e4cb208 2010-11-27        kinaba: 	LayerEval[Layer] theLayers;
b97bd4f713 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: 	/// Get the layer evaluator from layer ID
203e4cb208 2010-11-27        kinaba: 	LayerEval getLayerEval(Layer lay)
6ac127ddd0 2010-11-23        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		if(auto p = lay in theLayers)
203e4cb208 2010-11-27        kinaba: 			return *p;
203e4cb208 2010-11-27        kinaba: 		return theLayers[lay] = new UserDefinedLayerEval(lay);
6ac127ddd0 2010-11-23        kinaba: 	}
6ac127ddd0 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: 	/// Interface of layers
6760e0dd02 2010-11-26        kinaba: 	abstract class LayerEval
a5fe6233c1 2010-11-21        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		enum : bool { CascadeCtx=false, OverwriteCtx=true };
203e4cb208 2010-11-27        kinaba: 
6760e0dd02 2010-11-26        kinaba: 		/// Concrete layers should implement these
203e4cb208 2010-11-27        kinaba: 		protected Layer layerID();
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Die e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Str e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Int e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Var e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Lay e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Let e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( App e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 		protected Value eval_( Fun e, Table ctx, bool ctxMod );///
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 		/// Should override this also, if the layer may return null for optimization
203e4cb208 2010-11-27        kinaba: 		Value evalToNonNull( AST e, Table ctx, bool ctxMod = CascadeCtx )
203e4cb208 2010-11-27        kinaba: 			{ return eval(e,ctx,ctxMod); }
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 		/// Do macro expansion first, and then eval. Should override this also if it is NOT macro layer.
203e4cb208 2010-11-27        kinaba: 		Value macroAndEval( AST e, Table ctx, bool ctxMod = CascadeCtx )
203e4cb208 2010-11-27        kinaba: 			{ return evalToNonNull(e,ctx,ctxMod); }
6760e0dd02 2010-11-26        kinaba: 
6760e0dd02 2010-11-26        kinaba: 		/// dynamic-overload-resolution
203e4cb208 2010-11-27        kinaba: 		Value eval( AST e, Table ctx, bool ctxMod = CascadeCtx )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			enum funName = "eval_";                 // modify here for customization
203e4cb208 2010-11-27        kinaba: 			alias TypeTuple!(e,ctx,ctxMod) params;  // modify here for customization
6760e0dd02 2010-11-26        kinaba: 
6760e0dd02 2010-11-26        kinaba: 			alias typeof(__traits(getOverloads, this, funName)) ovTypes;
6760e0dd02 2010-11-26        kinaba: 			alias staticMap!(firstParam, ovTypes)              fstTypes;
6760e0dd02 2010-11-26        kinaba: 			alias DerivedToFront!(fstTypes)             fstTypes_sorted;
6760e0dd02 2010-11-26        kinaba: 			foreach(i, T; fstTypes_sorted)
6760e0dd02 2010-11-26        kinaba: 				static if( is(T == typeof(params[0])) ) {} else if( auto _x = cast(T)params[0] )
6760e0dd02 2010-11-26        kinaba: 					return __traits(getOverloads, this, funName)[i](_x, params[1..$]);
6760e0dd02 2010-11-26        kinaba: 
6760e0dd02 2010-11-26        kinaba: 			// modify here to customize the default behavior
6760e0dd02 2010-11-26        kinaba: 			assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not defined"));
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 		/// Function calling convention.
203e4cb208 2010-11-27        kinaba: 		/// Run all arugment AST in the appropriate layer and invoke the function.
203e4cb208 2010-11-27        kinaba: 		Value invokeFunction(Value f_, AST[] args, Table ctx, LexPosition pos, string callstackmsg)
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			FunValue f = cast(FunValue)f_;
203e4cb208 2010-11-27        kinaba: 			if( f is null )
203e4cb208 2010-11-27        kinaba: 				throw genex!RuntimeException(pos, text("tried to call non-function: ",f));
203e4cb208 2010-11-27        kinaba: 			if( f.params().length != args.length )
203e4cb208 2010-11-27        kinaba: 				throw genex!RuntimeException(pos,
203e4cb208 2010-11-27        kinaba: 					sprintf!("%d arguments required but %d passed")(f.params().length, args.length));
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 			Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
203e4cb208 2010-11-27        kinaba: 			foreach(i,p; f.params())
203e4cb208 2010-11-27        kinaba: 				if( p.layers.empty )
203e4cb208 2010-11-27        kinaba: 					newCtx.set(p.name, layerID(), this.evalToNonNull(args[i], ctx));
203e4cb208 2010-11-27        kinaba: 				else
203e4cb208 2010-11-27        kinaba: 					foreach(argLay; p.layers)
203e4cb208 2010-11-27        kinaba: 					{
203e4cb208 2010-11-27        kinaba: 						Layer ll = argLay;
203e4cb208 2010-11-27        kinaba: 						if( isMacroLayer(argLay) && typeid(this)!=typeid(MacroLayerEval) )
203e4cb208 2010-11-27        kinaba: 							ll = RawMacroLayer; // explicit @macro invokes (rawmacro)
203e4cb208 2010-11-27        kinaba: 						newCtx.set(p.name, argLay, getLayerEval(ll).evalToNonNull(args[i], ctx));
6760e0dd02 2010-11-26        kinaba: 					}
203e4cb208 2010-11-27        kinaba: 			scope _ = new PushCallStack(pos, callstackmsg);
203e4cb208 2010-11-27        kinaba: 			return f.invoke(layerID(), newCtx, pos);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 		/// Lift the value v to the current layer
6760e0dd02 2010-11-26        kinaba: 		Value lift(Value v, Table ctx, LexPosition pos)
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			// functions are automatically lifted by itself
6760e0dd02 2010-11-26        kinaba: 			if( cast(FunValue) v )
6760e0dd02 2010-11-26        kinaba: 				return v;
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 			Layer lay = layerID();
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 			// load the lift function
6760e0dd02 2010-11-26        kinaba: 			if( !ctx.has(lay, LiftLayer) )
6760e0dd02 2010-11-26        kinaba: 				throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" );
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 			Value    f_ = ctx.get(lay, LiftLayer, pos);
203e4cb208 2010-11-27        kinaba: 			FunValue f  = cast(FunValue) f_;
203e4cb208 2010-11-27        kinaba: 			if( f is null )
203e4cb208 2010-11-27        kinaba: 				throw genex!RuntimeException(pos,
203e4cb208 2010-11-27        kinaba: 					text("non-function ", f_, " is registered as the lift function for ", lay));
203e4cb208 2010-11-27        kinaba: 			if( f.params().length != 1 || f.params()[0].layers.length>=1 )
203e4cb208 2010-11-27        kinaba: 				throw genex!RuntimeException(pos,
203e4cb208 2010-11-27        kinaba: 					text("lift function must take exactly 1 neutral parameter:",lay));
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 			// invokeFunction
203e4cb208 2010-11-27        kinaba: 			Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet);
203e4cb208 2010-11-27        kinaba: 			newCtx.set(f.params()[0].name, ValueLayer, v);
203e4cb208 2010-11-27        kinaba: 			scope _ = new PushCallStack(pos, "lift to "~lay);
203e4cb208 2010-11-27        kinaba: 			return f.invoke(ValueLayer, newCtx, pos);
6760e0dd02 2010-11-26        kinaba: 		}
2134cd44cc 2010-11-23        kinaba: 	}
2134cd44cc 2010-11-23        kinaba: 
6760e0dd02 2010-11-26        kinaba: 	/// Evaluator for standard @value semantics
6760e0dd02 2010-11-26        kinaba: 	class ValueLayerEval : LayerEval
2134cd44cc 2010-11-23        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		override Layer layerID()
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return ValueLayer;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Die e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			throw genex!RuntimeException(e.pos, "undefined case");
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Str e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return new StrValue(e.data);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Int e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return new IntValue(e.data);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Var e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return ctx.get(e.name, layerID(), e.pos);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Lay e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return getLayerEval(e.layer).evalToNonNull(e.expr, ctx);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Let e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			if( !ctxMod )
203e4cb208 2010-11-27        kinaba: 				ctx = new Table(ctx, Table.Kind.NotPropagateSet);
a795c97dc3 2010-11-27        kinaba: 			Value ri = this.eval(e.vdef, ctx);
203e4cb208 2010-11-27        kinaba: 			ctx.set(e.name, e.layer.empty ? layerID(): e.layer, ri);
203e4cb208 2010-11-27        kinaba: 			return this.eval(e.expr, ctx, OverwriteCtx);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( App e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			Value f = this.eval( e.fun, ctx, CascadeCtx );
6760e0dd02 2010-11-26        kinaba: 			return this.invokeFunction(f, e.args, ctx, e.pos, getNameIfPossible(e.fun));
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Fun e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
ba11f1d551 2010-11-23        kinaba: 			return createNewFunction(e, ctx);
6760e0dd02 2010-11-26        kinaba: 		}
203e4cb208 2010-11-27        kinaba: 		override Value macroAndEval( AST e, Table ctx, bool ctxMod )
203e4cb208 2010-11-27        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			// incremental execution of let-expressions
203e4cb208 2010-11-27        kinaba: 			if(auto le = cast(Let)e)
203e4cb208 2010-11-27        kinaba: 			{
a795c97dc3 2010-11-27        kinaba: 				AST ai = runMacro(le.vdef, ctx);
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 				if( !ctxMod )
203e4cb208 2010-11-27        kinaba: 					ctx = new Table(ctx, Table.Kind.NotPropagateSet);
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 				Value vi = this.eval(ai, ctx);
203e4cb208 2010-11-27        kinaba: 				ctx.set(le.name, le.layer.empty ? layerID() : le.layer, vi);
203e4cb208 2010-11-27        kinaba: 				return this.macroAndEval(le.expr, ctx, OverwriteCtx);
203e4cb208 2010-11-27        kinaba: 			}
203e4cb208 2010-11-27        kinaba: 			else
203e4cb208 2010-11-27        kinaba: 				return this.eval(runMacro(e,ctx,ctxMod), ctx, ctxMod);
203e4cb208 2010-11-27        kinaba: 		}
ba11f1d551 2010-11-23        kinaba: 	}
ba11f1d551 2010-11-23        kinaba: 
6760e0dd02 2010-11-26        kinaba: 	/// Evaluator for user-defined layer
6760e0dd02 2010-11-26        kinaba: 	class UserDefinedLayerEval : ValueLayerEval
ba11f1d551 2010-11-23        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		Layer theID;
6760e0dd02 2010-11-26        kinaba: 		mixin SimpleConstructor;
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 		override Layer layerID()
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return theID;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Die e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return new BottomValue;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Str e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Int e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return this.lift(super.eval_(e,ctx,ctxMod), ctx, e.pos);
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Var e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			if( ctx.has(e.name, layerID()) )
203e4cb208 2010-11-27        kinaba: 				return ctx.get(e.name, layerID());
a795c97dc3 2010-11-27        kinaba: 			Value v;
a795c97dc3 2010-11-27        kinaba: 			try { v = ctx.get(e.name, ValueLayer, e.pos); }
a795c97dc3 2010-11-27        kinaba: 			catch ( RuntimeException ) {
a795c97dc3 2010-11-27        kinaba: 				throw genex!RuntimeException(e.pos, e.name~" not found in layer "~layerID()~" nor "~ValueLayer);
a795c97dc3 2010-11-27        kinaba: 			}
a795c97dc3 2010-11-27        kinaba: 			return this.lift(v, ctx, e.pos);
ba11f1d551 2010-11-23        kinaba: 		}
ba11f1d551 2010-11-23        kinaba: 	}
ba11f1d551 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: 	// Macro layer. For optimization, if AST didn't change it returns null
6760e0dd02 2010-11-26        kinaba: 	class MacroLayerEval : LayerEval
ba11f1d551 2010-11-23        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		override Layer layerID()
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return MacroLayer;
203e4cb208 2010-11-27        kinaba: 		}
203e4cb208 2010-11-27        kinaba: 		override Value evalToNonNull( AST e, Table ctx, bool ctxMod = CascadeCtx )
203e4cb208 2010-11-27        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			Value v = this.eval(e, ctx, ctxMod);
203e4cb208 2010-11-27        kinaba: 			return v is null ? ast2table(e) : v;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Die e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return null;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Str e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return null;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Int e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
6760e0dd02 2010-11-26        kinaba: 			return null;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Var e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			if( ctx.has(e.name, layerID()) )
203e4cb208 2010-11-27        kinaba: 				return ctx.get(e.name, layerID(), e.pos);
203e4cb208 2010-11-27        kinaba: 			return null;
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Lay e, Table ctx, bool ctxMod )
ba11f1d551 2010-11-23        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			return getLayerEval(e.layer).eval(e.expr,ctx);
ba11f1d551 2010-11-23        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Let e, Table ctx, bool ctxMod )
ba11f1d551 2010-11-23        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			if( !ctxMod )
203e4cb208 2010-11-27        kinaba: 				ctx = new Table(ctx, Table.Kind.NotPropagateSet);
203e4cb208 2010-11-27        kinaba: 
a795c97dc3 2010-11-27        kinaba: 			Value ai = this.eval(e.vdef, ctx);
203e4cb208 2010-11-27        kinaba: 			ctx.set(e.name, NoopLayer, null);
203e4cb208 2010-11-27        kinaba: 			Value ae = this.eval(e.expr, ctx, OverwriteCtx);
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: 			if( ai is null && ae is null ) return null;
a795c97dc3 2010-11-27        kinaba: 			if( ai is null ) ai = ast2table(e.vdef);
6760e0dd02 2010-11-26        kinaba: 			if( ae is null ) ae = ast2table(e.expr);
203e4cb208 2010-11-27        kinaba: 
6760e0dd02 2010-11-26        kinaba: 			return ast2table(e, delegate Value (AST _){
a795c97dc3 2010-11-27        kinaba: 				if(_ is e.vdef) { return ai; }
6760e0dd02 2010-11-26        kinaba: 				if(_ is e.expr) { return ae; }
6760e0dd02 2010-11-26        kinaba: 				assert(false);
6760e0dd02 2010-11-26        kinaba: 			});
552d43f567 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( App e, Table ctx, bool ctxMod )
552d43f567 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			Value f = this.eval( e.fun, ctx );
6760e0dd02 2010-11-26        kinaba: 			if(auto ff = cast(FunValue)f)
6760e0dd02 2010-11-26        kinaba: 				return this.invokeFunction(ff, e.args, ctx, e.pos, getNameIfPossible(e.fun));
203e4cb208 2010-11-27        kinaba: 			else
203e4cb208 2010-11-27        kinaba: 			{
6760e0dd02 2010-11-26        kinaba: 				bool allNull = (f is null);
6760e0dd02 2010-11-26        kinaba: 				Value[] vas;
203e4cb208 2010-11-27        kinaba: 				foreach(a; e.args)
203e4cb208 2010-11-27        kinaba: 				{
6760e0dd02 2010-11-26        kinaba: 					Value va = this.eval(a, ctx, CascadeCtx);
6760e0dd02 2010-11-26        kinaba: 					if(va !is null) allNull = false;
6760e0dd02 2010-11-26        kinaba: 					vas ~= va;
6760e0dd02 2010-11-26        kinaba: 				}
6760e0dd02 2010-11-26        kinaba: 				if( allNull )
6760e0dd02 2010-11-26        kinaba: 					return null;
6760e0dd02 2010-11-26        kinaba: 				return ast2table(e, delegate Value (AST _){
6760e0dd02 2010-11-26        kinaba: 					if(_ is e.fun) return (f is null ? ast2table(e.fun) : f);
6760e0dd02 2010-11-26        kinaba: 					foreach(i,a; e.args) if(_ is a) return (vas[i] is null ? ast2table(a) : vas[i]);
6760e0dd02 2010-11-26        kinaba: 					assert(false);
6760e0dd02 2010-11-26        kinaba: 				});
552d43f567 2010-11-26        kinaba: 			}
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Fun e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			ctx = new Table(ctx, Table.Kind.NotPropagateSet);
6760e0dd02 2010-11-26        kinaba: 			foreach(p; e.params)
203e4cb208 2010-11-27        kinaba: 				ctx.set(p.name, NoopLayer, null);
203e4cb208 2010-11-27        kinaba: 			Value af = this.eval(e.funbody, ctx);
6760e0dd02 2010-11-26        kinaba: 			if( af is null )
6760e0dd02 2010-11-26        kinaba: 				return null;
6760e0dd02 2010-11-26        kinaba: 			return ast2table(e, (AST _){if(_ is e.funbody)return af; assert(false);});
6760e0dd02 2010-11-26        kinaba: 		}
6760e0dd02 2010-11-26        kinaba: 	}
6760e0dd02 2010-11-26        kinaba: 
203e4cb208 2010-11-27        kinaba: 	/// (rawmacro) layer. almost same as @macro, but the Layer expression becomes AST, too.
6760e0dd02 2010-11-26        kinaba: 	class RawMacroLayerEval : MacroLayerEval
6760e0dd02 2010-11-26        kinaba: 	{
6760e0dd02 2010-11-26        kinaba: 		override Value eval_( Lay e, Table ctx, bool ctxMod )
6760e0dd02 2010-11-26        kinaba: 		{
203e4cb208 2010-11-27        kinaba: 			Value ae = this.eval(e.expr, ctx);
6760e0dd02 2010-11-26        kinaba: 			return ae is null ? null
6760e0dd02 2010-11-26        kinaba: 			       : ast2table(e, delegate Value (AST _){if(_ is e.expr)return ae; assert(false);});
6ac127ddd0 2010-11-23        kinaba: 		}
ba11f1d551 2010-11-23        kinaba: 	}
ba11f1d551 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: private: // short utils
6760e0dd02 2010-11-26        kinaba: 
ba11f1d551 2010-11-23        kinaba: 	string getNameIfPossible(AST e)
ba11f1d551 2010-11-23        kinaba: 	{
ba11f1d551 2010-11-23        kinaba: 		if(auto v = cast(Var)e)
ba11f1d551 2010-11-23        kinaba: 			return v.name;
ba11f1d551 2010-11-23        kinaba: 		return "";
ba11f1d551 2010-11-23        kinaba: 	}
ba11f1d551 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: 	AST runMacro(AST e, Table ctx, bool ctxMod=LayerEval.CascadeCtx)
203e4cb208 2010-11-27        kinaba: 	{
203e4cb208 2010-11-27        kinaba: 		Value v = getLayerEval(RawMacroLayer).eval(e, ctx, ctxMod);
203e4cb208 2010-11-27        kinaba: 		return (v is null ? e : polemy2d!(AST)(v, e.pos));
203e4cb208 2010-11-27        kinaba: 	}
203e4cb208 2010-11-27        kinaba: 
203e4cb208 2010-11-27        kinaba: private:
6ac127ddd0 2010-11-23        kinaba: 	Value createNewFunction(Fun e, Table ctx)
6ac127ddd0 2010-11-23        kinaba: 	{
6ac127ddd0 2010-11-23        kinaba: 		class UserDefinedFunValue : FunValue
3f6f41b558 2010-11-20        kinaba: 		{
20be503cae 2010-11-24        kinaba: 			Fun   ast;
20be503cae 2010-11-24        kinaba: 			Table defCtx;
6ac127ddd0 2010-11-23        kinaba: 			override const(Parameter[]) params() { return ast.params; }
20be503cae 2010-11-24        kinaba: 			override Table definitionContext()   { return defCtx; }
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: 			this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; }
153a14cec0 2010-11-24        kinaba: 			override string toString() const
153a14cec0 2010-11-24        kinaba: 				{ return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); }
20be503cae 2010-11-24        kinaba: 			override int opCmp(Object rhs) {
20be503cae 2010-11-24        kinaba: 				if(auto r = cast(UserDefinedFunValue)rhs) {
b993a8ad16 2010-11-24        kinaba: 					if(auto c = typeid(void*).compare(cast(void*)ast, cast(void*)r.ast))
b993a8ad16 2010-11-24        kinaba: 						return c;
b993a8ad16 2010-11-24        kinaba: 					if(auto c = typeid(void*).compare(cast(void*)defCtx, cast(void*)r.defCtx))
b993a8ad16 2010-11-24        kinaba: 						return c;
b993a8ad16 2010-11-24        kinaba: 					return 0;// [TODO] avoid using pointer value...
20be503cae 2010-11-24        kinaba: 				}
153a14cec0 2010-11-24        kinaba: 				if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r));
20be503cae 2010-11-24        kinaba: 				throw genex!RuntimeException("comparison with value and something other");
20be503cae 2010-11-24        kinaba: 			}
b993a8ad16 2010-11-24        kinaba: 			override hash_t toHash() {
b993a8ad16 2010-11-24        kinaba: 				return (cast(hash_t)cast(void*)ast) + (cast(hash_t)cast(void*)defCtx);
b993a8ad16 2010-11-24        kinaba: 			}
20be503cae 2010-11-24        kinaba: 
552d43f567 2010-11-26        kinaba: 			AST[void*] mandeCache;
b993a8ad16 2010-11-24        kinaba: 			static class MemokeyType
b993a8ad16 2010-11-24        kinaba: 			{
203e4cb208 2010-11-27        kinaba: 				void* a; Layer b; Table c;
203e4cb208 2010-11-27        kinaba: 				mixin SimpleClass;
b993a8ad16 2010-11-24        kinaba: 			}
b993a8ad16 2010-11-24        kinaba: 			static Tuple!(Value,int)[MemokeyType] memo;
b993a8ad16 2010-11-24        kinaba: 
b97bd4f713 2010-11-23        kinaba: 			override Value invoke(Layer lay, Table ctx, LexPosition pos)
3f6f41b558 2010-11-20        kinaba: 			{
203e4cb208 2010-11-27        kinaba: 				auto evlay = getLayerEval(lay);
203e4cb208 2010-11-27        kinaba: 				auto nonMemoizedRun = (){ return evlay.macroAndEval(ast.funbody, ctx); };
b993a8ad16 2010-11-24        kinaba: 
b993a8ad16 2010-11-24        kinaba: 				if( !isUserDefinedLayer(lay) )
b993a8ad16 2010-11-24        kinaba: 					return nonMemoizedRun();
b993a8ad16 2010-11-24        kinaba: 
203e4cb208 2010-11-27        kinaba: 				// automatic memoized co-recursive execution
203e4cb208 2010-11-27        kinaba: 				MemokeyType memokey = new MemokeyType(cast(void*)ast, lay, ctx);
b993a8ad16 2010-11-24        kinaba: 				if(auto p = memokey in memo)
ba11f1d551 2010-11-23        kinaba: 				{
b993a8ad16 2010-11-24        kinaba: 					(*p)[1] ++;
b993a8ad16 2010-11-24        kinaba: 					return (*p)[0];
b993a8ad16 2010-11-24        kinaba: 				}
950fc6d3d4 2010-11-27        kinaba: 				else {
950fc6d3d4 2010-11-27        kinaba: 					Value v;
950fc6d3d4 2010-11-27        kinaba: 					try { v = evlay.lift(new BottomValue, ctx, pos); } catch { v = new BottomValue; }
950fc6d3d4 2010-11-27        kinaba: 					memo[memokey] = tuple(v, 0);
950fc6d3d4 2010-11-27        kinaba: 				}
b993a8ad16 2010-11-24        kinaba: 
b993a8ad16 2010-11-24        kinaba: 				Value r = nonMemoizedRun();
b993a8ad16 2010-11-24        kinaba: 
b993a8ad16 2010-11-24        kinaba: 				int touched = memo[memokey][1];
b993a8ad16 2010-11-24        kinaba: 				memo[memokey] = tuple(r, 12345678);
b993a8ad16 2010-11-24        kinaba: 				return r;
3f6f41b558 2010-11-20        kinaba: 			}
6ac127ddd0 2010-11-23        kinaba: 		}
6ac127ddd0 2010-11-23        kinaba: 		return new UserDefinedFunValue(e,ctx);
6ac127ddd0 2010-11-23        kinaba: 	}
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: public:
b97bd4f713 2010-11-23        kinaba: 	/// Add primitive function to the global context
b97bd4f713 2010-11-23        kinaba: 	void addPrimitive(R,T...)(string name, Layer defLay, R delegate (T) dg)
6ac127ddd0 2010-11-23        kinaba: 	{
6ac127ddd0 2010-11-23        kinaba: 		class NativeFunValue : FunValue
1c01f44f52 2010-11-13        kinaba: 		{
6ac127ddd0 2010-11-23        kinaba: 			override const(Parameter[]) params() { return params_data; }
b97bd4f713 2010-11-23        kinaba: 			override Table definitionContext()   { return theContext; }
b97bd4f713 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 			override string toString() { return sprintf!"(native:%x)"(dg.funcptr); }
b97bd4f713 2010-11-23        kinaba: 			override int opCmp(Object rhs) {
b97bd4f713 2010-11-23        kinaba: 				if(auto r = cast(NativeFunValue)rhs) return typeid(typeof(dg)).compare(&dg,&r.dg);
b97bd4f713 2010-11-23        kinaba: 				if(auto r = cast(Value)rhs)          return typeid(this).opCmp(typeid(r));
153a14cec0 2010-11-24        kinaba: 				throw genex!RuntimeException("comparison with value and something other");
b97bd4f713 2010-11-23        kinaba: 			}
b993a8ad16 2010-11-24        kinaba: 			override hash_t toHash() const {
b993a8ad16 2010-11-24        kinaba: 				return typeid(dg).getHash(&dg);
b993a8ad16 2010-11-24        kinaba: 			}
b97bd4f713 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 			R delegate(T) dg;
b97bd4f713 2010-11-23        kinaba: 			Parameter[] params_data;
b97bd4f713 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 			this(R delegate(T) dg)
b97bd4f713 2010-11-23        kinaba: 			{
b97bd4f713 2010-11-23        kinaba: 				this.dg = dg;
6ac127ddd0 2010-11-23        kinaba: 				foreach(i, Ti; T)
6ac127ddd0 2010-11-23        kinaba: 					params_data ~= new Parameter(text(i), []);
6ac127ddd0 2010-11-23        kinaba: 			}
b97bd4f713 2010-11-23        kinaba: 
b97bd4f713 2010-11-23        kinaba: 			override Value invoke(Layer lay, Table ctx, LexPosition pos)
6ac127ddd0 2010-11-23        kinaba: 			{
b97bd4f713 2010-11-23        kinaba: 				if( lay != defLay )
153a14cec0 2010-11-24        kinaba: 					throw genex!RuntimeException(pos,
153a14cec0 2010-11-24        kinaba: 						text("only ", defLay, " layer can call native function: ", name));
6ac127ddd0 2010-11-23        kinaba: 				T typed_args;
6ac127ddd0 2010-11-23        kinaba: 				foreach(i, Ti; T) {
005474ba5b 2010-11-27        kinaba: 					Value vi = ctx.get(text(i), ValueLayer, pos);
005474ba5b 2010-11-27        kinaba: 					typed_args[i] = cast(Ti) vi;
6ac127ddd0 2010-11-23        kinaba: 					if( typed_args[i] is null )
153a14cec0 2010-11-24        kinaba: 						throw genex!RuntimeException(pos,
005474ba5b 2010-11-27        kinaba: 							sprintf!"type mismatch on the argument %d of native function %s. %s required but %s passed."(i+1,name,typeid(Ti),vi));
6ac127ddd0 2010-11-23        kinaba: 				}
6ac127ddd0 2010-11-23        kinaba: 				try {
6ac127ddd0 2010-11-23        kinaba: 					return dg(typed_args);
6ac127ddd0 2010-11-23        kinaba: 				} catch( RuntimeException e ) {
6ac127ddd0 2010-11-23        kinaba: 					throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e;
6ac127ddd0 2010-11-23        kinaba: 				}
6ac127ddd0 2010-11-23        kinaba: 			}
1c01f44f52 2010-11-13        kinaba: 		}
b97bd4f713 2010-11-23        kinaba: 		theContext.set(name, defLay, new NativeFunValue(dg));
6ac127ddd0 2010-11-23        kinaba: 	}
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: 
203e4cb208 2010-11-27        kinaba: version(unittest)
203e4cb208 2010-11-27        kinaba: 	import polemy.runtime;
005474ba5b 2010-11-27        kinaba: 
005474ba5b 2010-11-27        kinaba: unittest
005474ba5b 2010-11-27        kinaba: {
005474ba5b 2010-11-27        kinaba: 	auto e = new Evaluator;
005474ba5b 2010-11-27        kinaba: 	enrollRuntimeLibrary(e);
005474ba5b 2010-11-27        kinaba: 	assert_eq( e.evalString(`
005474ba5b 2010-11-27        kinaba: @@foo(x){x*2};
005474ba5b 2010-11-27        kinaba: @foo "+" (x,y){x};
005474ba5b 2010-11-27        kinaba: @foo(3+4)
005474ba5b 2010-11-27        kinaba: `), new IntValue(6) );
005474ba5b 2010-11-27        kinaba: }
203e4cb208 2010-11-27        kinaba: 
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) );
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( r, new IntValue(BigInt(21+21*21)) );
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21)) );
6ac127ddd0 2010-11-23        kinaba: 	assert_nothrow( e.globalContext.get("x",ValueLayer) );
6ac127ddd0 2010-11-23        kinaba: 	assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) );
6ac127ddd0 2010-11-23        kinaba: }
203e4cb208 2010-11-27        kinaba: 
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) );
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( r, new IntValue(BigInt(21+21*21)) );
ba11f1d551 2010-11-23        kinaba: 	assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) );
6ac127ddd0 2010-11-23        kinaba: 	assert_nothrow( e.globalContext.get("x",ValueLayer) );
6ac127ddd0 2010-11-23        kinaba: 	assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) );
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
ba11f1d551 2010-11-23        kinaba: 	assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(1) );
ba11f1d551 2010-11-23        kinaba: 	assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new IntValue(2) );
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1)) );
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.evalString(`@a x=1; @b x=2; @b(x)`), new IntValue(BigInt(2)) );
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.evalString(`let x=1; let _ = (@a x=2;2); x`), new IntValue(BigInt(1)) );
6ac127ddd0 2010-11-23        kinaba: 	e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	assert_throw!Throwable( e.evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) );
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.evalString(`
6ac127ddd0 2010-11-23        kinaba: 		@@s(x){x};
6ac127ddd0 2010-11-23        kinaba: 		@s "+" = fun(x, y) {@value(
6ac127ddd0 2010-11-23        kinaba: 			@s(x) - @s(y)
6ac127ddd0 2010-11-23        kinaba: 		)};
6ac127ddd0 2010-11-23        kinaba: 		@s(1 + 2)
6ac127ddd0 2010-11-23        kinaba: 	`), new IntValue(BigInt(-1)) );
6ac127ddd0 2010-11-23        kinaba: }
6ac127ddd0 2010-11-23        kinaba: 
6ac127ddd0 2010-11-23        kinaba: unittest
6ac127ddd0 2010-11-23        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	assert_eq( e.evalString(`
6ac127ddd0 2010-11-23        kinaba: @@3(x){x};
6ac127ddd0 2010-11-23        kinaba: def incr(x) { x+1 };
3ae09b8cbf 2010-11-24        kinaba: @ 3 incr(x) {@value( if @ 3(x)+1< 3 then @3(x)+1 else 0 )};
6ac127ddd0 2010-11-23        kinaba: def fb(n @value @3) { @3(n) };
6ac127ddd0 2010-11-23        kinaba: fb(incr(incr(incr(0))))
6ac127ddd0 2010-11-23        kinaba: 	`), new IntValue(BigInt(0)) );
0f02103885 2010-11-09        kinaba: }
0f02103885 2010-11-09        kinaba: 
0f02103885 2010-11-09        kinaba: unittest
0f02103885 2010-11-09        kinaba: {
6ac127ddd0 2010-11-23        kinaba: 	auto e = new Evaluator;
6ac127ddd0 2010-11-23        kinaba: 	enrollRuntimeLibrary(e);
6ac127ddd0 2010-11-23        kinaba: 	assert_nothrow( e.evalString(`
6ac127ddd0 2010-11-23        kinaba: @macro twice(x) { x; x };
6ac127ddd0 2010-11-23        kinaba: def main() { twice(1) };
6ac127ddd0 2010-11-23        kinaba: main()
6ac127ddd0 2010-11-23        kinaba: 	`) );
0f02103885 2010-11-09        kinaba: }
0f02103885 2010-11-09        kinaba: unittest
0f02103885 2010-11-09        kinaba: {
f9c31f3cd8 2010-11-24        kinaba: 	auto e = new Evaluator;
f9c31f3cd8 2010-11-24        kinaba: 	enrollRuntimeLibrary(e);
f7e9e77316 2010-11-26        kinaba: 	assert_throw!RuntimeException( e.evalString(`case 1`) );
f9c31f3cd8 2010-11-24        kinaba: 	assert_nothrow( e.evalString(`case 1 when 1: 2`) );
f8684f4d69 2010-11-26        kinaba: 
f8684f4d69 2010-11-26        kinaba: 	// this is a shorthand for
f8684f4d69 2010-11-26        kinaba: 	//   @macro x = fun(){} in @macro(x)
f8684f4d69 2010-11-26        kinaba: 	// so it is ok to fail, but it is really incovenient on REPL
f8684f4d69 2010-11-26        kinaba: 	assert_nothrow( e.evalString(`@macro x=fun(){}`) );
f7e9e77316 2010-11-26        kinaba: }
f7e9e77316 2010-11-26        kinaba: 
f7e9e77316 2010-11-26        kinaba: unittest
f7e9e77316 2010-11-26        kinaba: {
f7e9e77316 2010-11-26        kinaba: 	auto e = new Evaluator;
f7e9e77316 2010-11-26        kinaba: 	enrollRuntimeLibrary(e);
f7e9e77316 2010-11-26        kinaba: 	assert_throw!RuntimeException( e.evalString(`...`) );
203e4cb208 2010-11-27        kinaba: 	assert_eq( e.evalString(`@@foo(x){x}; @foo(...)`), new BottomValue );
423f308350 2010-11-07        kinaba: }