| package jp.ac.kobe_u.cs.prolog.lang; |
| import java.io.Serializable; |
| /** |
| * Trail stack.<br> |
| * The class <code>Trail</code> represents a trail stack.<br> |
| * Entries pushed to this trail stack must implement |
| * the <code>Undoable</code> interface. |
| * @see Undoable |
| * @author Mutsunori Banbara (banbara@kobe-u.ac.jp) |
| * @author Naoyuki Tamura (tamura@kobe-u.ac.jp) |
| * @version 1.0 |
| */ |
| public class Trail implements Serializable { |
| /** Maximum size of enties. Initial size is <code>20000</code>. */ |
| protected int maxContents = 20000; |
| |
| /** An array of <code>Undoable</code> entries. */ |
| protected Undoable[] buffer; |
| |
| /** the top index of this <code>Trail</code>. */ |
| protected int top; |
| |
| /** Holds the Prolog engine that this <code>Trail</code> belongs to. */ |
| protected Prolog engine; |
| |
| /** Constructs a new trail stack. */ |
| public Trail(Prolog _engine) { |
| engine = _engine; |
| buffer = new Undoable[maxContents]; |
| top = -1; |
| } |
| |
| /** Constructs a new trail stack with the given size. */ |
| public Trail(Prolog _engine, int n) { |
| engine = _engine; |
| maxContents = n; |
| buffer = new Undoable[maxContents]; |
| top = -1; |
| } |
| |
| /** Discards all entries. */ |
| public void init() { deleteAll(); } |
| |
| /** Pushs an entry to this <code>Trail</code>. */ |
| public void push(Undoable t) { |
| try { |
| buffer[++top] = t; |
| } catch (ArrayIndexOutOfBoundsException e) { |
| System.out.println("{expanding trail...}"); |
| int len = buffer.length; |
| Undoable[] new_buffer = new Undoable[len+20000]; |
| for(int i=0; i<len; i++){ |
| new_buffer[i] = buffer[i]; |
| } |
| buffer = new_buffer; |
| buffer[top] = t; |
| maxContents = len+20000; |
| } |
| } |
| |
| /** Pops an entry from this <code>Trail</code>. */ |
| public Undoable pop() { |
| Undoable t = buffer[top]; |
| buffer[top--] = null; |
| return t; |
| } |
| |
| /** Discards all entries. */ |
| protected void deleteAll() { |
| while (! empty()) { |
| buffer[top--] = null; |
| } |
| } |
| |
| /** Tests if this stack has no entry. */ |
| public boolean empty() { |
| return top == -1; |
| } |
| |
| /** Returns the value of <code>maxContents</code>. |
| * @see #maxContents |
| */ |
| public int max() { return maxContents; } |
| |
| /** Returns the value of <code>top</code>. |
| * @see #top |
| */ |
| public int top() { return top; } |
| |
| /** Unwinds all entries after the value of <code>i</code>. */ |
| public void unwind(int i) { |
| Undoable t; |
| while (top > i) { |
| t = pop(); |
| t.undo(); |
| } |
| } |
| |
| /** Shows the contents of this <code>Trail</code>. */ |
| public void show() { |
| if (empty()) { |
| System.out.println("{trail stack is empty!}"); |
| return; |
| } |
| for (int i=0; i<=top; i++) { |
| System.out.print("trail[" + i + "]: "); |
| System.out.println(buffer[i]); |
| } |
| } |
| } |
| |