sclass VStack implements Steppable { new L stack; O latestResult; // was last instruction a return? // can be used by computations to switch without a label transient bool justReturned; transient O subComputationResult; // the null sentinel replaces a null function result // when stored in latestResult sclass NullSentinel {} static new NullSentinel nullSentinel; *() {} *(Computable computation) { push(computation); } *(Iterable l) { pushAll(l); } // A is what the function returns interface Computable { public void step(VStack stack, O subComputationResult); } private O deSentinel(O o) { ret o instanceof NullSentinel ? null : o; } private O sentinel(O o) { ret o == null ? nullSentinel : o; } // called by computations or users to start a subroutine void push aka call(Computable computation) { stack.add(computation); } // perform a computation step. returns false iff done public bool step() { if (empty(stack)) false; justReturned = latestResult != null; subComputationResult = deSentinel(latestResult); latestResult = null; last(stack).step(this, subComputationResult); subComputationResult = null; true; } // called from a computation to return a value void _return(O value default null) { latestResult = sentinel(value); removeLast(stack); } // called from a computation to tail-call another routine void tailCall aka replace(Computable computation) { removeLast(stack); stack.add(computation); } // all-in-one evaluation function - call on an empty stack A compute(Computable computation) { if (computation == null) null; push(computation); stepAll(this); ret (A) latestResult; } // return result of just completed computation O result aka subResult() { ret deSentinel(latestResult); } bool hasSubResult() { ret justReturned; } void pushAll(Iterable l) { fOr (Computable c : l) push(c); } }