@@ -108,67 +108,66 @@ /// Entry point of this module /// If splitCtx = true, then inner variable declaration do not overwrite ctx. /// lay is the layer ID for evaluation (standard value semantics uses "@v"). - -Value eval(AST _e, Table ctx, bool splitCtx, Layer lay) -{ - if( auto e = cast(StrLiteral)_e ) - { - return new StrValue(e.data); - } - else - if( auto e = cast(IntLiteral)_e ) - { - return new IntValue(e.data); - } - else - if( auto e = cast(VarExpression)_e ) - { - return ctx.get(e.var, lay, e.pos); - } - else - if( auto e = cast(LayeredExpression)_e ) - { - return eval(e.expr, ctx, false, e.lay); - } - else - if( auto e = cast(LetExpression)_e ) - { - // for letrec, we need this, but should avoid overwriting???? - // ctx.set(e.var, "@v", new UndefinedValue, e.pos); - Value v = eval(e.init, ctx, true, lay); - if(splitCtx) - ctx = new Table(ctx, Table.Kind.NotPropagateSet); - ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos); - return eval(e.expr, ctx, false, lay); - } - else - if( auto e = cast(FuncallExpression)_e ) - { - Value _f = eval(e.fun, ctx, true, lay); - if( auto f = cast(FunValue)_f ) { - Value[] args; - foreach(a; e.args) - args ~= eval(a, ctx, true, lay); - return f.call(e.pos, lay, args); - } else +import std.typetuple; +Value eval(AST e, Table ctx, bool splitCtx, Layer lay) +{ + return e.match( + (StrLiteral e) + { + return new StrValue(e.data); + }, + (IntLiteral e) + { + return new IntValue(e.data); + }, + (VarExpression e) + { + return ctx.get(e.var, lay, e.pos); + }, + (LayeredExpression e) + { + return eval(e.expr, ctx, false, e.lay); + }, + (LetExpression e) + { + // for letrec, we need this, but should avoid overwriting???? + // ctx.set(e.var, "@v", new UndefinedValue, e.pos); + Value v = eval(e.init, ctx, true, lay); + if(splitCtx) + ctx = new Table(ctx, Table.Kind.NotPropagateSet); + ctx.set(e.var, (e.layer.length ? e.layer : lay), v, e.pos); + return eval(e.expr, ctx, false, lay); + }, + (FuncallExpression e) + { + Value _f = eval(e.fun, ctx, true, lay); + if( auto f = cast(FunValue)_f ) { + Value[] args; + foreach(a; e.args) + args ~= eval(a, ctx, true, lay); + return f.call(e.pos, lay, args); + } throw genex!RuntimeException(e.pos, "Non-funcion is applied"); - } - else - if( auto e = cast(FunLiteral)_e ) - { - return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){ - if( e.params.length != args.length ) - throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" - (e.params.length, args.length)); - Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); - foreach(i,p; e.params) - ctxNeo.set(p.name, lay, args[i]); - return eval(e.funbody, ctxNeo, true, lay); - }); - } - throw genex!RuntimeException(_e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(_e))); + }, + (FunLiteral e) + { + return new FunValue(delegate Value(immutable LexPosition pos, string lay, Value[] args){ + if( e.params.length != args.length ) + throw genex!RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" + (e.params.length, args.length)); + Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); + foreach(i,p; e.params) + ctxNeo.set(p.name, lay, args[i]); + return eval(e.funbody, ctxNeo, true, lay); + }); + }, + delegate Value (AST e) + { + throw genex!RuntimeException(e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(e))); + } + ); } unittest {