// A represents the return type of the backtrackable main computation sclass BStack_v2b extends VStack is IBStack { static int idCounter; int stackID = ++idCounter; // for debugging // Last backtracking point where we will go next when backtracking // this stack. Branch branch; sclass Branch { // stack that the branch starts with BStack_v2b stack; // remaining options to execute on top of stack Iterator options; // what to undo before branching L undos; void addUndo(AutoCloseable undo) { if (undos == null) undos = new L; undos.add(undo); } } *() {} *(Computable computation) { push(computation); } *(Iterable l) { pushAll(l); } sclass NoOptionsException extends RuntimeException {} BStack_v2b newBranch() { new BStack_v2b b; b.branchsnapshot = snapshot; s.options = options; s.undos = undos; undos = null; s.stack = shallowCloneElements(stack); ret s; } public void addUndo(AutoCloseable undo) { if (undo == null || branch == null) ret; branch.addUndo(undo); } public void options(B function, IVF1... options) { options(function, arrayIterator(options)); } public void options(B function, Iterable> options) { Iterator> iterator = nonNullIterator(iterator(options)); if (!iterator.hasNext()) throw new NoOptionsException; IVF1 firstOption = iterator.next(); // All options except first are stored as alternatives // in cloned stacks. setOptions(iterator); // Execute the first option firstOption.get(function); } srecord noeq ExecuteOption(IVF1 option) is VStack.Computable { public void step(VStack stack, O subComputationResult) { O target = stack.caller(); stack.return(); option.get(target); } } void setOptions(Iterator> options) { branch = new Branch; snapshot = cloneStack(); this.options = (Iterator) options; } // Try to backtrack one step and return a new stack // Returns null if no backtracking possible public BStack_v2b backtrack() ctex { if (branch == null) null; ret branch.backtrack(); // Apply undos in reverse order for (int i = l(undos)-1; i >= 0; i--) undos.get(i).close(); // no more options? done if (options == null || !options.hasNext()) null; // get snapshot and option to execute BStack_v2b nextStack = snapshot; var option = options.next(); // If there are more options in the list, make another clone // of the snapshot bool moreOptions = options.hasNext(); if (moreOptions) { nextStack = new BStack_v2; nextStack.stack = shallowCloneElements(snapshot.stack); nextStack.snapshot = snapshot; nextStack.options = options; } nextStack.push(new ExecuteOption(option)); ret nextStack; } public A nextResult() { stepAll(this); return (A) latestResult; } // calculate next result and print stack at every step public A nextResultWithPrintStruct(long maxSteps) { stepMaxWithPrintIndentedStruct(this, maxSteps); return (A) latestResult; } }