package com.babel17.interpreter.runtime; import com.babel17.interpreter.values.*; import com.babel17.interpreter.program.*; import java.util.*; public final class Continuations { public static Continuation defaultContinuation() { return new Default(); } private final static class Default implements Continuation { public EvalResult apply(Value v) { return EvalResult.createFinalResult(v); } } public final static class SendMessage implements Continuation { public SendMessage(String message, Continuation c) { this.message = message; this.c = c; } public EvalResult apply(Value v) { return c.apply(v.sendMessage(message)); } private final String message; private final Continuation c; } public final static class Constr implements Continuation { public Constr(String name, Continuation c) { this.name = name; this.c = c; } public EvalResult apply(Value v) { if (v instanceof DynamicException) { return c.apply(v); } else { return c.apply(new ConstructorValue(name, v)); } } private final String name; private final Continuation c; } public final static class Apply implements Continuation { public Apply(Evaluator e, Environment env, Expr operand, Continuation c) { this.e = e; this.operand = operand; this.c = c; this.env = env; this.f = null; } public EvalResult apply(Value v) { if (f != null) return f.apply(e, c, v); if (v instanceof ExceptionValue) return c.apply(((ExceptionValue) v).toDynamic()); f = v; return e.eval(env, this, operand); } private final Evaluator e; private final Environment env; private final Continuation c; private final Expr operand; private Value f; } public static abstract class NeedsOnlyClosedCollector implements StateContinuation { public abstract Continuation needsOnlyClosedCollector(); public NeedsOnlyClosedCollector(Evaluator e) { this.evaluator = e; } public EvalResult apply(State state) { return needsOnlyClosedCollector().apply( state.collector().sendMessage(Value.COLLECTOR_CLOSE)); } protected Evaluator evaluator; } public final static class Begin implements StateContinuation { private final int oldsize; private final StateContinuation c; private final Statement next; private final Evaluator e; public Begin(Evaluator e, int oldsize, StateContinuation c, Statement next) { this.oldsize = oldsize; this.c = c; this.next = next; this.e = e; } public EvalResult apply(State state) { Environment env = state.environment(); env.pop(env.size() - oldsize); return e.eval(state, c, next); } public Continuation needsOnlyClosedCollector() { return null; } } public final static class Yield implements Continuation { private StateContinuation c; private State s; private Statement next; private Evaluator e; public Yield(Evaluator e, StateContinuation c, State s, Statement next) { this.e = e; this.c = c; this.s = s; this.next = next; } public EvalResult apply(Value v) { if (v instanceof DynamicException) { return c.apply(new State(s.environment(), v)); } Expr f = new ExprValue(s.collector().sendMessage(Value.COLLECTOR_ADD)); Expr x = new ExprValue(v); return e.eval(s.environment(), new Yield1(e, c, s.environment(), next), new ExprApply(f, x)); } } public final static class Yield1 implements Continuation { private Evaluator e; private Statement next; private StateContinuation c; private Environment env; public Yield1(Evaluator e, StateContinuation c, Environment env, Statement next) { this.e = e; this.c = c; this.env = env; this.next = next; } public EvalResult apply(Value collector) { if (collector instanceof ExceptionValue) { ExceptionValue p = (ExceptionValue) collector; return EvalResult.createFinalResult(new State(env, p.toDynamic())); } return e.eval(new State(env, collector), c, next); } } public final static class Val implements Continuation { public Val(Evaluator e, State state, StateContinuation c, StVal stval) { this.e = e; this.state = state; this.c = c; this.stval = stval; } public EvalResult apply(Value v) { Environment env = state.environment(); int oldsize = env.size(); MatchResult m = e.match(state.environment(), stval.pattern(), v); switch (m.status()) { case MatchResult.STATUS_EXCEPTION: env.pop(env.size() - oldsize); return c.apply(new State(env, m.exceptionDuringMatch())); case MatchResult.STATUS_FAIL: env.pop(env.size() - oldsize); return c.apply(new State(env, DynamicException.noMatch())); } if (stval.assign()) { int count = stval.countAssignments(); for (int i = 0; i < count; i++) { env.updateValue(oldsize - i, env.getValue(stval.assignment(i))); } env.pop(env.size() - oldsize); } return e.eval(state, c, stval.nextStatement()); } private Evaluator e; private State state; private StateContinuation c; private StVal stval; } public final static class With extends NeedsOnlyClosedCollector implements Continuation { private Environment env; private ControlStatement cs; private Continuation c; public With(Evaluator e, Environment env, ControlStatement cs, Continuation c) { super(e); this.env = env; this.cs = cs; this.c = c; } public EvalResult apply(Value collector) { if (collector instanceof DynamicException) { return c.apply(collector); } State state = new State(env.freeze(), collector); return evaluator.eval(state, this, cs); } public Continuation needsOnlyClosedCollector() { return c; } } public final static class ValWith implements Continuation, StateContinuation { public ValWith(Evaluator e, State state, StateContinuation c, StVal stval) { this.e = e; this.state = state; this.c = c; this.stval = stval; } public Continuation needsOnlyClosedCollector() { return null; } public EvalResult apply(Value collector) { oldsize = state.environment().size(); return e.eval(new State(state.environment(), collector), this, ((ExprWith) stval.body()).control()); } public EvalResult apply(State afterwith) { Value v = afterwith.collector().sendMessage(Value.COLLECTOR_CLOSE); Environment env = afterwith.environment(); env.pop(env.size() - oldsize); oldsize = env.size(); MatchResult m = e.match(env, stval.pattern(), v); switch (m.status()) { case MatchResult.STATUS_EXCEPTION: env.pop(env.size() - oldsize); return c.apply(new State(env, m.exceptionDuringMatch())); case MatchResult.STATUS_FAIL: env.pop(env.size() - oldsize); return c.apply(new State(env, DynamicException.noMatch())); } if (stval.assign()) { int count = stval.countAssignments(); for (int i = 0; i < count; i++) { env.updateValue(oldsize - i, env.getValue(stval.assignment(i))); } env.pop(env.size() - oldsize); } return e.eval(state, c, stval.nextStatement()); } private Evaluator e; private State state; private int oldsize; private StateContinuation c; private StVal stval; } public final static class While implements Continuation, StateContinuation { private Evaluator e; private State state; private StWhile w; private StateContinuation c; private int oldsize; public While(Evaluator e, State state, StateContinuation c, StWhile w) { this.e = e; this.state = state; this.c = c; this.w = w; } public EvalResult apply(Value test) { test = test.force(); if (test instanceof DynamicException) { return c.apply(new State(state.environment(), test)); } else if (!(test instanceof BooleanValue)) { return c.apply(new State(state.environment(), DynamicException.invalidWhileTest())); } BooleanValue b = (BooleanValue) test; if (b.value()) { oldsize = state.environment().size(); return e.eval(state, this, w.body()); } else { return e.eval(state, c, w.nextStatement()); } } public EvalResult apply(State after) { Environment env = after.environment(); env.pop(env.size() - oldsize); if (after.collector() instanceof DynamicException) { return c.apply(after); } state = after; return e.eval(state.environment(), this, w.condition()); } public Continuation needsOnlyClosedCollector() { return null; } } public final static class If implements Continuation, StateContinuation { private Evaluator e; private State state; private StIf stif; private StateContinuation c; private int oldsize; public If(Evaluator e, State state, StateContinuation c, StIf stif) { this.e = e; this.state = state; this.c = c; this.stif = stif; } public EvalResult apply(Value test) { test = test.force(); if (test instanceof DynamicException) { return c.apply(new State(state.environment(), test)); } else if (!(test instanceof BooleanValue)) { return c.apply(new State(state.environment(), DynamicException.invalidIfTest())); } BooleanValue b = (BooleanValue) test; if (stif.nextStatement() == null && c.needsOnlyClosedCollector() != null) { if (b.value()) { return e.eval(state, c, stif.true_branch()); } else { return e.eval(state, c, stif.false_branch()); } } oldsize = state.environment().size(); if (b.value()) { return e.eval(state, this, stif.true_branch()); } else { return e.eval(state, this, stif.false_branch()); } } public EvalResult apply(State state) { Environment env = state.environment(); env.pop(env.size() - oldsize); if (state.collector() instanceof DynamicException) { return c.apply(state); } else { return e.eval(state, c, stif.nextStatement()); } } public Continuation needsOnlyClosedCollector() { return null; } } public final static class For implements Continuation, StateContinuation { private Evaluator e; private State state; private StFor stfor; private StateContinuation c; public For(Evaluator e, State state, StateContinuation c, StFor stfor) { this.e = e; this.state = state; this.c = c; this.stfor = stfor; } public EvalResult apply(Value collection) { loop: do { collection = collection.sendMessage(Value.ITERATE).force(); SequenceValue seq; if (collection instanceof ExceptionValue) { return c.apply(new State(state.environment(), ((ExceptionValue) collection).toDynamic())); } else if (collection instanceof SequenceValue) { seq = (SequenceValue) collection; } else { return c.apply(new State(state.environment(), DynamicException.invalidIterate())); } if (seq.isEmpty()) { return e.eval(state, c, stfor.nextStatement()); } else if (seq.size() == 2) { Value elem = seq.getValueAt(0); collection = seq.getValueAt(1); Environment env = state.environment(); int oldsize = env.size(); MatchResult m = e.match(env, stfor.pattern(), elem); switch (m.status()) { case MatchResult.STATUS_EXCEPTION: env.pop(env.size() - oldsize); return c.apply(new State(env, m.exceptionDuringMatch())); case MatchResult.STATUS_FAIL: env.pop(env.size() - oldsize); continue loop; } EvalResult result = e.eval(state , this, stfor.body()); state = (State) result.trampoline(); env.pop(env.size()-oldsize); continue loop; } else { return c.apply(new State(state.environment(), DynamicException.invalidIterate())); } } while (true); } public EvalResult apply(State after) { return EvalResult.createFinalResult(after); } public Continuation needsOnlyClosedCollector() { return null; } } public final static class Match implements Continuation, StateContinuation { private Evaluator e; private State state; private StMatch match; private StateContinuation c; private int oldsize; public Match(Evaluator e, State state, StateContinuation c, StMatch match) { this.e = e; this.state = state; this.c = c; this.match = match; } public EvalResult apply(Value value) { value = value.force(); int numCases = match.numCases(); Environment env = state.environment(); oldsize = env.size(); loop: for (int i=0; i<numCases; i++) { CaseStatement cs = match.getCase(i); MatchResult m = e.match(env, cs.pattern(), value); switch (m.status()) { case MatchResult.STATUS_EXCEPTION: env.pop(env.size()-oldsize); return c.apply(new State(env, m.exceptionDuringMatch())); case MatchResult.STATUS_FAIL: env.pop(env.size()-oldsize); continue loop; } if (match.nextStatement() == null && c.needsOnlyClosedCollector() != null) return e.eval(state, c, cs.body()); else return e.eval(state, this, cs.body()); } return e.eval(state, c, match.nextStatement()); } public EvalResult apply(State state) { Environment env = state.environment(); env.pop(env.size()-oldsize); return e.eval(state, c, match.nextStatement()); } public Continuation needsOnlyClosedCollector() { return null; } } public final static class Obj implements StateContinuation { private ExprObject expr; public Obj(ExprObject expr) { this.expr = expr; } public EvalResult apply(State state) { if (state.collector() instanceof DynamicException) return EvalResult.createFinalResult(state.collector()); ObjectValue obj = new ObjectValue(); int count = expr.countMessages(); Environment env = state.environment(); for (int i=0; i<count; i++) { ExprObject.MessageIndex mi = expr.messageIndex(i); obj.put(mi.message(), env.getValue(mi.index())); } obj.seal(); return EvalResult.createFinalResult(obj); } public Continuation needsOnlyClosedCollector() { return null; } } public final static class Compare implements Continuation { private ExprCompare compare; private Evaluator e; private Environment env; private Continuation c; private Value v1; public Compare(Evaluator e, Environment env, Continuation c, ExprCompare compare) { this.e = e; this.env = env; this.c = c; this.compare = compare; v1 = null; } public EvalResult apply(Value v) { if (v1 != null) { try { boolean b = compare.result() == v1.compareWithOtherValue(e, v); return c.apply(BooleanValue.create(b)); } catch (CompareException x) { return EvalResult.createFinalResult(x.exception()); } } else { v1 = v; return e.eval(env, this, compare.expr2()); } } } }