Libraryless. Click here for Pure Java version (22976L/140K).
1 | // This backtracking-enabled stack (BStack) postpones cloning stack |
2 | // frames as long as possible. |
3 | // More specifically, only the current top frame is actually mutable. |
4 | // Some stack frames below (from 0 up to clonePointer) may not be |
5 | // cloned yet, and are cloned (=made mutable) by the pop() function. |
6 | |
7 | // The tests (test_BStack_v3) pass, but they might not test the lazy |
8 | // cloning. So for safety, stick with BStack_v2 until there are more |
9 | // tests for BStack_v3. |
10 | |
11 | // A represents the return type of the backtrackable main computation |
12 | sclass BStack_v3<A> extends VStack is IBStack<A> { |
13 | static int idCounter; |
14 | int stackID = ++idCounter; // for debugging |
15 | |
16 | // elements at this index and below must be cloned before use |
17 | int clonePointer = -1; |
18 | |
19 | // cloned version made at last branch point |
20 | selfType snapshot; |
21 | |
22 | // remaining options at last branch point |
23 | Iterator<IVF1> options; |
24 | |
25 | // steps to undo before switching to the alternative |
26 | L<AutoCloseable> undos; |
27 | |
28 | *() {} |
29 | *(Computable<A> computation) { push(computation); } |
30 | *(Iterable<Computable> l) { pushAll(l); } |
31 | |
32 | selfType cloneStack() { |
33 | new selfType s; |
34 | s.snapshot = snapshot; |
35 | s.options = options; |
36 | s.undos = undos; |
37 | undos = null; |
38 | s.stack = cloneList(stack); |
39 | |
40 | // Directly clone current function, clone older stack entries |
41 | // lazily. |
42 | |
43 | replaceLast(s.stack, shallowClone(last(stack))); |
44 | clonePointer = l(stack)-2; |
45 | ret s; |
46 | } |
47 | |
48 | public void addUndo(AutoCloseable undo) { |
49 | if (undo == null || snapshot == null) ret; |
50 | if (undos == null) undos = new L; |
51 | undos.add(undo); |
52 | } |
53 | |
54 | public <B extends VStack.Computable> void options(B function, IVF1<B>... options) { |
55 | options(function, arrayIterator(options)); |
56 | } |
57 | |
58 | public <B extends VStack.Computable> void options(B function, Iterable<IVF1<B>> options) { |
59 | Iterator<IVF1<B>> iterator = nonNullIterator(iterator(options)); |
60 | |
61 | if (!iterator.hasNext()) |
62 | throw new NoOptionsException; |
63 | |
64 | IVF1<B> firstOption = iterator.next(); |
65 | |
66 | // All options except first are stored as alternatives |
67 | // in cloned stacks. |
68 | |
69 | setOptions(iterator); |
70 | |
71 | // Execute the first option |
72 | firstOption.get(function); |
73 | } |
74 | |
75 | <B> void setOptions(Iterator<IVF1<B>> options) { |
76 | snapshot = cloneStack(); |
77 | this.options = (Iterator) options; |
78 | } |
79 | |
80 | // Try to backtrack one step and return a new stack |
81 | // Returns null if no backtracking possible |
82 | public selfType backtrack() ctex { |
83 | // Apply undos in reverse order |
84 | for (int i = l(undos)-1; i >= 0; i--) |
85 | undos.get(i).close(); |
86 | |
87 | // no more options? done |
88 | if (options == null || !options.hasNext()) null; |
89 | |
90 | // get snapshot and option to execute |
91 | selfType nextStack = snapshot; |
92 | var option = options.next(); |
93 | |
94 | // If there are more options in the list, make another clone |
95 | // of the snapshot |
96 | bool moreOptions = options.hasNext(); |
97 | if (moreOptions) { |
98 | nextStack = new selfType; |
99 | nextStack.stack = shallowCloneElements(snapshot.stack); |
100 | nextStack.snapshot = snapshot; |
101 | nextStack.options = options; |
102 | } |
103 | |
104 | nextStack.push(new ExecuteOption(option)); |
105 | ret nextStack; |
106 | } |
107 | |
108 | public A nextResult() { |
109 | stepAll(this); |
110 | return (A) latestResult; |
111 | } |
112 | |
113 | // calculate next result and print stack at every step |
114 | public A nextResultWithPrintStruct(long maxSteps) { |
115 | stepMaxWithPrintIndentedStruct(this, maxSteps); |
116 | return (A) latestResult; |
117 | } |
118 | |
119 | protected void pop :: after { |
120 | int idx = l(stack)-1; |
121 | |
122 | // Clone the new top stack frame if necessary |
123 | if (idx >= 0 && idx == clonePointer) { |
124 | stack.set(idx, shallowClone(stack.get(idx))); |
125 | --clonePointer; |
126 | } |
127 | } |
128 | |
129 | srecord noeq ExecuteOption(IVF1 option) is VStack.Computable { |
130 | public void step(VStack stack, O subComputationResult) { |
131 | O target = stack.caller(); |
132 | stack.return(); |
133 | option.get(target); |
134 | } |
135 | } |
136 | |
137 | sclass NoOptionsException extends RuntimeException {} |
138 | } |
Began life as a copy of #1035394
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): ekrmjmnbrukm, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1035398 |
Snippet name: | BStack_v3 - a virtual stack with backtracking capability (version 3, copying the stack even more lazily, dev.) |
Eternal ID of this version: | #1035398/11 |
Text MD5: | f95e85c1f74d162b000c79f3ed66309c |
Transpilation MD5: | ce82fffbbbcf338165d8694fca012a5e |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-05-06 23:25:22 |
Source code size: | 4145 bytes / 138 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 131 / 229 |
Version history: | 10 change(s) |
Referenced in: | [show references] |