package com.babel17.interpreter.runtime; import com.babel17.interpreter.values.*; import com.babel17.interpreter.program.*; public final class Evaluator { public Evaluator() { } // match accumulates the matched variables in env // in case the match fails, the environment is restored to its original state public MatchResult match(Environment env, Pattern p, Value v) { switch (p.kind()) { case Pattern.KIND_ANY: return MatchResult.success(); case Pattern.KIND_VAR: env.pushValue(v); return MatchResult.success(); case Pattern.KIND_AS: { PatternAs as = (PatternAs) p; MatchResult m = match(env, as.pattern(), v); if (m.status() == MatchResult.STATUS_SUCCESS) env.pushValue(v); return m; } case Pattern.KIND_CONSTR: { PatternConstr pconstr = (PatternConstr) p; v = v.force(); if (v instanceof ExceptionValue) { DynamicException e = ((ExceptionValue) v).toDynamic(); return MatchResult.exception(e); } else if (v instanceof ConstructorValue) { ConstructorValue c = (ConstructorValue) v; if (c.name().equals(pconstr.name())) { return match(env, pconstr.pattern(), c.parameter()); } else return MatchResult.fail(); } else return MatchResult.fail(); } case Pattern.KIND_IF: { PatternIf pif = (PatternIf) p; int oldsize = env.size(); MatchResult m = match(env, pif.pattern(), v); if (m.status() == MatchResult.STATUS_SUCCESS) { Value result = (Value) eval(env, Continuations.defaultContinuation(), pif.condition()).finalResult(); result = result.force(); if (result instanceof BooleanValue) { BooleanValue b = (BooleanValue) result; if (b.value()) return MatchResult.success(); else { env.pop(env.size()-oldsize); return MatchResult.fail(); } } else { env.pop(env.size()-oldsize); return MatchResult.exception(DynamicException.invalidIfTest()); } } else return m; } case Pattern.KIND_VALUE: { PatternValue pval = (PatternValue) p; Value x = pval.value(); try { int compare = x.compareWithOtherValue(this, v); if (compare == 3) return MatchResult.success(); else return MatchResult.fail(); } catch (CompareException e) { return MatchResult.exception(e.exception()); } } case Pattern.KIND_SPLIT: { PatternSplit psplit = (PatternSplit) p; Value vsplit = v.split(this, psplit.message(), psplit.countPatterns()); if (vsplit == null) return MatchResult.fail(); vsplit = vsplit.force(); if (vsplit instanceof ExceptionValue) { ExceptionValue x = (ExceptionValue) vsplit; return MatchResult.exception(x.toDynamic()); } else if (vsplit instanceof SequenceValue) { SequenceValue seq = (SequenceValue) vsplit; int count = seq.size(); if (count != psplit.countPatterns()) return MatchResult.fail(); int oldsize = env.size(); for (int i=0; i<count; i++) { MatchResult m = match(env, psplit.pattern(i), seq.getValueAt(i)); if (m.status() != MatchResult.STATUS_SUCCESS) { env.pop(env.size()-oldsize); return m; } } return MatchResult.success(); } else return MatchResult.exception( DynamicException.invalidSplit(psplit.message())); } case Pattern.KIND_PREDICATE: { PatternPredicate ppred = (PatternPredicate) p; EvalResult r = eval(env, Continuations.defaultContinuation(), ppred.predicate()); Value destructor = ((Value) r.trampoline()).force(); if (destructor instanceof ConstructorValue) { Value destructed = v.deconstruct(this, (ConstructorValue) destructor); if (destructed == null) return MatchResult.fail(); destructed = destructed.force(); if (destructed instanceof ExceptionValue) return MatchResult.exception(((ExceptionValue) destructed).toDynamic()); if (destructed instanceof ConstructorValue) { ConstructorValue cv = (ConstructorValue) destructed; if (cv.isNone()) return MatchResult.fail(); Value param = cv.isSome(); if (param == null) return MatchResult.exception(DynamicException.invalidDeconstruct()); if (ppred.pattern() == null) return MatchResult.success(); return match(env, ppred.pattern(), param); } else return MatchResult.exception(DynamicException.invalidDeconstruct()); } else { Value destructed = (Value) destructor.apply(this, Continuations.defaultContinuation(), v).trampoline(); destructed = destructed.force(); if (destructed instanceof ExceptionValue) return MatchResult.exception(((ExceptionValue) destructed).toDynamic()); if (destructed instanceof ConstructorValue) { ConstructorValue cv = (ConstructorValue) destructed; if (cv.isNone()) return MatchResult.fail(); Value param = cv.isSome(); if (param == null) return MatchResult.exception(DynamicException.invalidDeconstruct()); if (ppred.pattern() == null) return MatchResult.success(); return match(env, ppred.pattern(), param); } else if (destructed instanceof BooleanValue && ppred.pattern() == null) { BooleanValue b = (BooleanValue) destructed; return b.value() ? MatchResult.success() : MatchResult.fail(); } else return MatchResult.exception(DynamicException.invalidDeconstruct()); } } case Pattern.KIND_EXCEPTION: { v = v.force(); if (v instanceof ExceptionValue) { return match(env, ((PatternException)p).pattern(), ((ExceptionValue) v).value()); } else return MatchResult.fail(); } default: throw new RuntimeException("unknown pattern kind: "+p.kind()); } } public EvalResult eval(State state, StateContinuation c, Statement statement) { if (statement == null) return c.apply(state); switch (statement.kind()) { case Program.KIND_YIELD: { Statement next = statement.nextStatement(); StYield y = (StYield) statement; if (next == null) { Continuation jump = c.needsOnlyClosedCollector(); if (jump != null) { Value collector = state.collector(); if (collector instanceof BlockValue && ((BlockValue)collector).empty()) { return eval(state.environment(), jump, y.value()); } } } return eval(state.environment(), new Continuations.Yield(this, c, state, next), y.value()); } case Program.KIND_BEGIN: { StBegin b = (StBegin) statement; int oldsize = state.environment().size(); StateContinuation sc = new Continuations.Begin(this, oldsize, c, statement.nextStatement()); return eval(state, sc, b.nestedStatement()); } case Program.KIND_VAL: { StVal val = (StVal) statement; return eval(state.environment(), new Continuations.Val(this, state, c, val), val.body()); } case Program.KIND_VAL_WITH: { StVal val = (StVal) statement; ExprWith with = (ExprWith) val.body(); return eval(state.environment(), new Continuations.ValWith(this, state, c, val), with.collector()); } case Program.KIND_WHILE: { StWhile w = (StWhile) statement; return eval(state.environment(), new Continuations.While(this, state, c, w), w.condition()); } case Program.KIND_IF: { StIf stif = (StIf) statement; return eval(state.environment(), new Continuations.If(this, state, c, stif), stif.condition()); } case Program.KIND_FOR: { StFor stfor = (StFor) statement; return eval(state.environment(), new Continuations.For(this, state, c, stfor), stfor.collection()); } case Program.KIND_MATCH: { StMatch match = (StMatch) statement; return eval(state.environment(), new Continuations.Match(this, state, c, match), match.value()); } case Program.KIND_LETREC: { StLetRec letrec = (StLetRec) statement; int num = letrec.numDefinitions(); Environment env = state.environment(); for (int i=0; i<num; i++) { Definition d = letrec.definition(i); if (d.takesArg()) env.pushValue(new LambdaFunction(null, d)); else env.pushValue(new LambdaValue(null, d)); } env = env.freeze(); for (int i=0; i<num; i++) ((Lambda)env.getValue(i)).setEnv(env); return eval(state, c, letrec.nextStatement()); } default: throw new RuntimeException("unknown kind of statement: "+statement.kind()); } } public EvalResult eval(final Environment env, final Continuation c, final Expr p) { switch (p.kind()) { case Program.KIND_VAR: { Value v = env.getValue(((ExprVar) p).index()); if (v instanceof LambdaValue) { LambdaValue f = (LambdaValue) v; return c.apply(f.eval(this)); } return c.apply(v); } case Program.KIND_SEND_MESSAGE: { ExprSendMessage expr = (ExprSendMessage) p; return eval(env, new Continuations.SendMessage( expr.message(), c), expr.receiver()); } case Program.KIND_VALUE: return EvalResult.createFinalResult(((ExprValue)p).value()); case Program.KIND_CONSTR: { ExprConstr expr = (ExprConstr) p; return eval(env, new Continuations.Constr(expr.name(), c), expr.param()); } case Program.KIND_APPLY: { ExprApply expr = (ExprApply) p; return eval(env, new Continuations.Apply(this, env, expr.operand(), c), expr.operator()); } case Program.KIND_WITH: { ExprWith with = (ExprWith) p; return eval(env, new Continuations.With(this, env, with.control(), c), with.collector()); } case Program.KIND_LAMBDA: { ExprLambda lambda = (ExprLambda) p; return EvalResult.createFinalResult(new LambdaFunction(env.freeze(), lambda.definition())); } case Program.KIND_OBJECT: { ExprObject obj = (ExprObject) p; Value dummyCollector = new BlockValue(); return eval(new State(env.freeze(), dummyCollector), new Continuations.Obj(obj), obj.body()); } case Program.KIND_COMPARE: { ExprCompare comp = (ExprCompare) p; return eval(env, new Continuations.Compare(this, env, c, comp), comp.expr1()); } default: throw new RuntimeException("unknown kind of expression: "+p.kind()); } } }