lojix/wam_prolog/src/main/com/thesett/aima/logic/fol/wam/machine/WAMResolvingJavaMachine.java
protected boolean execute(WAMCallPoint callPoint)
    {
        /*log.fine("protected boolean execute(WAMCallPoint callPoint): called");*/

        boolean failed;

        // Check if the machine is being woken up from being suspended, in which case immediately fail in order to
        // trigger back-tracking to find more solutions.
        if (suspended)
        {
            failed = true;
            suspended = false;
        }
        else
        {
            ip = callPoint.entryPoint;
            uClear();
            failed = false;
        }

        int numOfArgs = 0;

        // Holds the current continuation point.
        cp = codeBuffer.position();

        // Notify any debug monitor that execution is starting.
        if (monitor != null)
        {
            monitor.onExecute(this);
        }

        //while (!failed && (ip < code.length))
        while (true)
        {
            // Attempt to backtrack on failure.
            if (failed)
            {
                failed = backtrack();

                if (failed)
                {
                    break;
                }
            }

            // Grab next instruction and switch on it.
            byte instruction = codeBuffer.get(ip);

            switch (instruction)
            {
            // put_struc Xi, f/n:
            case PUT_STRUC:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": PUT_STRUC " + printSlot(xi, mode) + ", " + fn);*/

                // heap[h] <- STR, h + 1
                data.put(hp, fn);

                // Xi <- heap[h]
                data.put(xi, structureAt(hp));

                // h <- h + 2
                hp += 1;

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            // set_var Xi:
            case SET_VAR:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_VAR " + printSlot(xi, mode));*/

                // heap[h] <- REF, h
                data.put(hp, refTo(hp));

                // Xi <- heap[h]
                data.put(xi, data.get(hp));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 3;

                break;
            }

            // set_val Xi:
            case SET_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_VAL " + printSlot(xi, mode));*/

                // heap[h] <- Xi
                data.put(hp, data.get(xi));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 3;

                break;
            }

            // get_struc Xi,
            case GET_STRUC:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": GET_STRUC " + printSlot(xi, mode) + ", " + fn);*/

                // addr <- deref(Xi);
                int addr = deref(xi);
                byte tag = derefTag;
                int a = derefVal;

                // switch STORE[addr]
                switch (tag)
                {
                // case REF:
                case REF:
                {
                    // heap[h] <- STR, h + 1
                    data.put(hp, structureAt(hp + 1));

                    // heap[h+1] <- f/n
                    data.put(hp + 1, fn);

                    // bind(addr, h)
                    bind(addr, hp);

                    // h <- h + 2
                    hp += 2;

                    // mode <- write
                    writeMode = true;
                    /*trace.fine("-> write mode");*/

                    break;
                }

                // case STR, a:
                case STR:
                {
                    // if heap[a] = f/n
                    if (data.get(a) == fn)
                    {
                        // s <- a + 1
                        sp = a + 1;

                        // mode <- read
                        writeMode = false;
                        /*trace.fine("-> read mode");*/
                    }
                    else
                    {
                        // fail
                        failed = true;
                    }

                    break;
                }

                default:
                {
                    // fail
                    failed = true;
                }
                }

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            // unify_var Xi:
            case UNIFY_VAR:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_VAR " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // Xi <- heap[s]
                    data.put(xi, data.get(sp));
                }
                else
                {
                    // case write:
                    // heap[h] <- REF, h
                    data.put(hp, refTo(hp));

                    // Xi <- heap[h]
                    data.put(xi, data.get(hp));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // unify_val Xi:
            case UNIFY_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_VAL " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // unify (Xi, s)
                    failed = !unify(xi, sp);
                }
                else
                {
                    // case write:
                    // heap[h] <- Xi
                    data.put(hp, data.get(xi));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // put_var Xn, Ai:
            case PUT_VAR:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_VAR " + printSlot(xi, mode) + ", A" + ai);*/

                if (mode == WAMInstruction.REG_ADDR)
                {
                    // heap[h] <- REF, H
                    data.put(hp, refTo(hp));

                    // Xn <- heap[h]
                    data.put(xi, data.get(hp));

                    // Ai <- heap[h]
                    data.put(ai, data.get(hp));
                }
                else
                {
                    // STACK[addr] <- REF, addr
                    data.put(xi, refTo(xi));

                    // Ai <- STACK[addr]
                    data.put(ai, data.get(xi));
                }

                // h <- h + 1
                hp++;

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // put_val Xn, Ai:
            case PUT_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_VAL " + printSlot(xi, mode) + ", A" + ai);*/

                // Ai <- Xn
                data.put(ai, data.get(xi));

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // get var Xn, Ai:
            case GET_VAR:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": GET_VAR " + printSlot(xi, mode) + ", A" + ai);*/

                // Xn <- Ai
                data.put(xi, data.get(ai));

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // get_val Xn, Ai:
            case GET_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": GET_VAL " + printSlot(xi, mode) + ", A" + ai);*/

                // unify (Xn, Ai)
                failed = !unify(xi, ai);

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            case PUT_CONST:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": PUT_CONST " + printSlot(xi, mode) + ", " + fn);*/

                // Xi <- heap[h]
                data.put(xi, constantCell(fn));

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            case GET_CONST:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": GET_CONST " + printSlot(xi, mode) + ", " + fn);*/

                // addr <- deref(Xi)
                int addr = deref(xi);
                int tag = derefTag;
                int val = derefVal;

                failed = !unifyConst(fn, xi);

                // P <- P + instruction_size(P)
                ip += 7;

                break;
            }

            case SET_CONST:
            {
                int fn = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": SET_CONST " + fn);*/

                // heap[h] <- <CON, c>
                data.put(hp, constantCell(fn));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 5;

                break;
            }

            case UNIFY_CONST:
            {
                int fn = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": UNIFY_CONST " + fn);*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // addr <- deref(S)

                    // unifyConst(fn, addr)
                    failed = !unifyConst(fn, sp);
                }
                else
                {
                    // case write:
                    // heap[h] <- <CON, c>
                    data.put(hp, constantCell(fn));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            case PUT_LIST:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": PUT_LIST " + printSlot(xi, mode));*/

                // Xi <- <LIS, H>
                data.put(xi, listCell(hp));

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            case GET_LIST:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": GET_LIST " + printSlot(xi, mode));*/

                int addr = deref(xi);
                int tag = derefTag;
                int val = derefVal;

                // case STORE[addr] of
                switch (tag)
                {
                case REF:
                {
                    // <REF, _> :
                    // HEAP[H] <- <LIS, H+1>
                    data.put(hp, listCell(hp + 1));

                    // bind(addr, H)
                    bind(addr, hp);

                    // H <- H + 1
                    hp += 1;

                    // mode <- write
                    writeMode = true;
                    /*trace.fine("-> write mode");*/

                    break;
                }

                case LIS:
                {
                    // <LIS, a> :
                    // S <- a
                    sp = val;

                    // mode <- read
                    writeMode = false;
                    /*trace.fine("-> read mode");*/

                    break;
                }

                default:
                {
                    // other: fail <- true;
                    failed = true;
                }
                }

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            case SET_VOID:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                /*trace.fine(ip + ": SET_VOID " + n);*/

                // for i <- H to H + n - 1 do
                //  HEAP[i] <- <REF, i>
                for (int addr = hp; addr < (hp + n); addr++)
                {
                    data.put(addr, refTo(addr));
                }

                // H <- H + n
                hp += n;

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            case UNIFY_VOID:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                /*trace.fine(ip + ": UNIFY_VOID " + n);*/

                // case mode of
                if (!writeMode)
                {
                    //  read: S <- S + n
                    sp += n;
                }
                else
                {
                    //  write:
                    //   for i <- H to H + n -1 do
                    //    HEAP[i] <- <REF, i>
                    for (int addr = hp; addr < (hp + n); addr++)
                    {
                        data.put(addr, refTo(addr));
                    }

                    //   H <- H + n
                    hp += n;
                }

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            // put_unsafe_val Yn, Ai:
            case PUT_UNSAFE_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int yi = (int) codeBuffer.get(ip + 2) + (ep + 3);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_UNSAFE_VAL " + printSlot(yi, WAMInstruction.STACK_ADDR) + ", A" + ai);*/

                int addr = deref(yi);

                if (addr < ep)
                {
                    // Ai <- Xn
                    data.put(ai, data.get(addr));
                }
                else
                {
                    data.put(hp, refTo(hp));
                    bind(addr, hp);
                    data.put(ai, data.get(hp));
                    hp++;
                }

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // set_local_val Xi:
            case SET_LOCAL_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_LOCAL_VAL " + printSlot(xi, mode));*/

                int addr = deref(xi);

                if (addr < ep)
                {
                    data.put(hp, data.get(addr));
                }
                else
                {
                    data.put(hp, refTo(hp));
                    bind(addr, hp);
                }

                // h <- h + 1
                hp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // unify_local_val Xi:
            case UNIFY_LOCAL_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_LOCAL_VAL " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // unify (Xi, s)
                    failed = !unify(xi, sp);
                }
                else
                {
                    // case write:
                    int addr = deref(xi);

                    if (addr < ep)
                    {
                        data.put(hp, data.get(addr));
                    }
                    else
                    {
                        data.put(hp, refTo(hp));
                        bind(addr, hp);
                    }

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // call @(p/n), perms:
            case CALL:
            {
                // grab @(p/n), perms
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);
                int numPerms = (int) codeBuffer.get(ip + 6);

                // num_of_args <- n
                numOfArgs = n;

                // Ensure that the predicate to call is known and linked in, otherwise fail.
                if (pn == -1)
                {
                    failed = true;

                    break;
                }

                // STACK[E + 2] <- numPerms
                data.put(ep + 2, numPerms);

                // CP <- P + instruction_size(P)
                cp = ip + 7;

                /*trace.fine(ip + ": CALL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/

                // B0 <- B
                b0 = bp;

                // P <- @(p/n)
                ip = pn;

                break;
            }

            // execute @(p/n):
            case EXECUTE:
            {
                // grab @(p/n)
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);

                // num_of_args <- n
                numOfArgs = n;

                /*trace.fine(ip + ": EXECUTE " + pn + "/" + n + " (cp = " + cp + ")]");*/

                // Ensure that the predicate to call is known and linked in, otherwise fail.
                if (pn == -1)
                {
                    failed = true;

                    break;
                }

                // B0 <- B
                b0 = bp;

                // P <- @(p/n)
                ip = pn;

                break;
            }

            // proceed:
            case PROCEED:
            {
                /*trace.fine(ip + ": PROCEED" + " (cp = " + cp + ")]");*/

                // P <- CP
                ip = cp;

                break;
            }

            // allocate:
            case ALLOCATE:
            {
                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newE] <- E
                data.put(esp, ep);

                // STACK[E + 1] <- CP
                data.put(esp + 1, cp);

                // STACK[E + 2] <- N
                data.put(esp + 2, 0);

                // E <- newE
                // newE <- E + n + 3
                ep = esp;

                /*trace.fine(ip + ": ALLOCATE");*/
                /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            // allocate N:
            case ALLOCATE_N:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newE] <- E
                data.put(esp, ep);

                // STACK[E + 1] <- CP
                data.put(esp + 1, cp);

                // STACK[E + 2] <- N
                data.put(esp + 2, n);

                // E <- newE
                // newE <- E + n + 3
                ep = esp;

                /*trace.fine(ip + ": ALLOCATE_N " + n);*/
                /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            // deallocate:
            case DEALLOCATE:
            {
                int newip = data.get(ep + 1);

                // E <- STACK[E]
                ep = data.get(ep);

                /*trace.fine(ip + ": DEALLOCATE");*/
                /*trace.fine("<- env @ " + ep + " " + traceEnvFrame());*/

                // CP <- STACK[E + 1]
                cp = newip;

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            // try me else L:
            case TRY_ME_ELSE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newB] <- num_of_args
                // n <- STACK[newB]
                int n = numOfArgs;
                data.put(esp, n);

                // for i <- 1 to n do STACK[newB + i] <- Ai
                for (int i = 0; i < n; i++)
                {
                    data.put(esp + i + 1, data.get(i));
                }

                // STACK[newB + n + 1] <- E
                data.put(esp + n + 1, ep);

                // STACK[newB + n + 2] <- CP
                data.put(esp + n + 2, cp);

                // STACK[newB + n + 3] <- B
                data.put(esp + n + 3, bp);

                // STACK[newB + n + 4] <- L
                data.put(esp + n + 4, l);

                // STACK[newB + n + 5] <- TR
                data.put(esp + n + 5, trp);

                // STACK[newB + n + 6] <- H
                data.put(esp + n + 6, hp);

                // STACK[newB + n + 7] <- B0
                data.put(esp + n + 7, b0);

                // B <- new B
                bp = esp;

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": TRY_ME_ELSE");*/
                /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            // retry me else L:
            case RETRY_ME_ELSE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // STACK[B + n + 4] <- L
                data.put(bp + n + 4, l);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": RETRY_ME_ELSE");*/
                /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            // trust me (else fail):
            case TRUST_ME:
            {
                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- STACK[B + n + 6]
                hbp = hp;

                // B <- STACK[B + n + 3]
                bp = data.get(bp + n + 3);

                /*trace.fine(ip + ": TRUST_ME");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            case SWITCH_ON_TERM:
            {
                // grab labels
                int v = codeBuffer.getInt(ip + 1);
                int c = codeBuffer.getInt(ip + 5);
                int l = codeBuffer.getInt(ip + 9);
                int s = codeBuffer.getInt(ip + 13);

                int addr = deref(1);
                int tag = derefTag;

                // case STORE[deref(A1)] of
                switch (tag)
                {
                case REF:

                    // <REF, _> : P <- V
                    ip = v;
                    break;

                case CON:

                    // <CON, _> : P <- C
                    ip = c;
                    break;

                case LIS:

                    // <LIS, _> : P <- L
                    ip = l;
                    break;

                case STR:

                    // <STR, _> : P <- S
                    ip = s;
                    break;
                }

                break;
            }

            case SWITCH_ON_CONST:
            {
                // grab labels
                int t = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.getInt(ip + 5);

                // <tag, val> <- STORE[deref(A1)]
                deref(1);

                int val = derefVal;

                // <found, inst> <- get_hash(val, T, N)
                int inst = getHash(val, t, n);

                // if found
                if (inst > 0)
                {
                    // then P <- inst
                    ip = inst;
                }
                else
                {
                    // else backtrack
                    failed = true;
                }

                break;
            }

            case SWITCH_ON_STRUC:
            {
                // grab labels
                int t = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.getInt(ip + 5);

                // <tag, val> <- STORE[deref(A1)]
                deref(1);

                int val = derefVal;

                // <found, inst> <- get_hash(val, T, N)
                int inst = getHash(val, t, n);

                // if found
                if (inst > 0)
                {
                    // then P <- inst
                    ip = inst;
                }
                else
                {
                    // else backtrack
                    failed = true;
                }

                break;
            }

            case TRY:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newB] <- num_of_args
                // n <- STACK[newB]
                int n = numOfArgs;
                data.put(esp, n);

                // for i <- 1 to n do STACK[newB + i] <- Ai
                for (int i = 0; i < n; i++)
                {
                    data.put(esp + i + 1, data.get(i));
                }

                // STACK[newB + n + 1] <- E
                data.put(esp + n + 1, ep);

                // STACK[newB + n + 2] <- CP
                data.put(esp + n + 2, cp);

                // STACK[newB + n + 3] <- B
                data.put(esp + n + 3, bp);

                // STACK[newB + n + 4] <- L
                data.put(esp + n + 4, ip + 5);

                // STACK[newB + n + 5] <- TR
                data.put(esp + n + 5, trp);

                // STACK[newB + n + 6] <- H
                data.put(esp + n + 6, hp);

                // STACK[newB + n + 7] <- B0
                data.put(esp + n + 7, b0);

                // B <- new B
                bp = esp;

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": TRY");*/
                /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case RETRY:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // STACK[B + n + 4] <- L
                data.put(bp + n + 4, ip + 5);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": RETRY");*/
                /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case TRUST:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- STACK[B + n + 6]
                hbp = hp;

                // B <- STACK[B + n + 3]
                bp = data.get(bp + n + 3);

                /*trace.fine(ip + ": TRUST");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case NECK_CUT:
            {
                if (bp > b0)
                {
                    bp = b0;
                    tidyTrail();
                }

                /*trace.fine(ip + ": NECK_CUT");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                ip += 1;

                break;
            }

            case GET_LEVEL:
            {
                int yn = (int) codeBuffer.get(ip + 1) + (ep + 3);

                data.put(yn, b0);

                /*trace.fine(ip + ": GET_LEVEL " + codeBuffer.get(ip + 1));*/

                ip += 2;

                break;
            }

            case CUT:
            {
                int yn = (int) codeBuffer.get(ip + 1) + (ep + 3);

                int cbp = data.get(yn);

                if (bp > cbp)
                {
                    bp = cbp;
                    tidyTrail();
                }

                /*trace.fine(ip + ": CUT " + codeBuffer.get(ip + 1));*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                ip += 2;

                break;
            }

            case CONTINUE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": CONTINUE " + l);*/

                ip = l;

                break;
            }

            case NO_OP:
            {
                /*trace.fine(ip + ": NO_OP");*/

                ip += 1;

                break;
            }

            // call_internal @(p/n), perms:
            case CALL_INTERNAL:
            {
                // grab @(p/n), perms
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);
                int numPerms = (int) codeBuffer.get(ip + 6);

                // num_of_args <- n
                numOfArgs = n;

                /*trace.fine(ip + ": CALL_INTERNAL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/

                boolean callOk = callInternal(pn, n, numPerms);

                failed = !callOk;

                break;
            }

            // suspend on success:
            case SUSPEND:
            {
                /*trace.fine(ip + ": SUSPEND");*/
                ip += 1;
                suspended = true;

                return true;
            }
            }

            // Notify any debug monitor that the machine has been stepped.
            if (monitor != null)
            {
                monitor.onStep(this);
            }
        }

        return !failed;
    }
protected boolean execute(WAMCallPoint callPoint)
    {
        /*log.fine("protected boolean execute(WAMCallPoint callPoint): called");*/

        boolean failed;

        // Check if the machine is being woken up from being suspended, in which case immediately fail in order to
        // trigger back-tracking to find more solutions.
        if (suspended)
        {
            failed = true;
            suspended = false;
        }
        else
        {
            ip = callPoint.entryPoint;
            uClear();
            failed = false;
        }

        int numOfArgs = 0;

        // Holds the current continuation point.
        cp = codeBuffer.position();

        // Notify any debug monitor that execution is starting.
        if (monitor != null)
        {
            monitor.onExecute(this);
        }

        //while (!failed && (ip < code.length))
        while (true)
        {
            // Attempt to backtrack on failure.
            if (failed)
            {
                failed = backtrack();

                if (failed)
                {
                    break;
                }
            }

            // Grab next instruction and switch on it.
            byte instruction = codeBuffer.get(ip);

            switch (instruction)
            {
            // put_struc Xi, f/n:
            case PUT_STRUC:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": PUT_STRUC " + printSlot(xi, mode) + ", " + fn);*/

                // heap[h] <- STR, h + 1
                data.put(hp, fn);

                // Xi <- heap[h]
                data.put(xi, structureAt(hp));

                // h <- h + 2
                hp += 1;

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            // set_var Xi:
            case SET_VAR:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_VAR " + printSlot(xi, mode));*/

                // heap[h] <- REF, h
                data.put(hp, refTo(hp));

                // Xi <- heap[h]
                data.put(xi, data.get(hp));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 3;

                break;
            }

            // set_val Xi:
            case SET_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_VAL " + printSlot(xi, mode));*/

                // heap[h] <- Xi
                data.put(hp, data.get(xi));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 3;

                break;
            }

            // get_struc Xi,
            case GET_STRUC:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": GET_STRUC " + printSlot(xi, mode) + ", " + fn);*/

                // addr <- deref(Xi);
                int addr = deref(xi);
                byte tag = derefTag;
                int a = derefVal;

                // switch STORE[addr]
                switch (tag)
                {
                // case REF:
                case REF:
                {
                    // heap[h] <- STR, h + 1
                    data.put(hp, structureAt(hp + 1));

                    // heap[h+1] <- f/n
                    data.put(hp + 1, fn);

                    // bind(addr, h)
                    bind(addr, hp);

                    // h <- h + 2
                    hp += 2;

                    // mode <- write
                    writeMode = true;
                    /*trace.fine("-> write mode");*/

                    break;
                }

                // case STR, a:
                case STR:
                {
                    // if heap[a] = f/n
                    if (data.get(a) == fn)
                    {
                        // s <- a + 1
                        sp = a + 1;

                        // mode <- read
                        writeMode = false;
                        /*trace.fine("-> read mode");*/
                    }
                    else
                    {
                        // fail
                        failed = true;
                    }

                    break;
                }

                default:
                {
                    // fail
                    failed = true;
                }
                }

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            // unify_var Xi:
            case UNIFY_VAR:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_VAR " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // Xi <- heap[s]
                    data.put(xi, data.get(sp));
                }
                else
                {
                    // case write:
                    // heap[h] <- REF, h
                    data.put(hp, refTo(hp));

                    // Xi <- heap[h]
                    data.put(xi, data.get(hp));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // unify_val Xi:
            case UNIFY_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_VAL " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // unify (Xi, s)
                    failed = !unify(xi, sp);
                }
                else
                {
                    // case write:
                    // heap[h] <- Xi
                    data.put(hp, data.get(xi));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // put_var Xn, Ai:
            case PUT_VAR:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_VAR " + printSlot(xi, mode) + ", A" + ai);*/

                if (mode == WAMInstruction.REG_ADDR)
                {
                    // heap[h] <- REF, H
                    data.put(hp, refTo(hp));

                    // Xn <- heap[h]
                    data.put(xi, data.get(hp));

                    // Ai <- heap[h]
                    data.put(ai, data.get(hp));
                }
                else
                {
                    // STACK[addr] <- REF, addr
                    data.put(xi, refTo(xi));

                    // Ai <- STACK[addr]
                    data.put(ai, data.get(xi));
                }

                // h <- h + 1
                hp++;

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // put_val Xn, Ai:
            case PUT_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_VAL " + printSlot(xi, mode) + ", A" + ai);*/

                // Ai <- Xn
                data.put(ai, data.get(xi));

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // get var Xn, Ai:
            case GET_VAR:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": GET_VAR " + printSlot(xi, mode) + ", A" + ai);*/

                // Xn <- Ai
                data.put(xi, data.get(ai));

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // get_val Xn, Ai:
            case GET_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": GET_VAL " + printSlot(xi, mode) + ", A" + ai);*/

                // unify (Xn, Ai)
                failed = !unify(xi, ai);

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            case PUT_CONST:
            {
                // grab addr, f/n
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": PUT_CONST " + printSlot(xi, mode) + ", " + fn);*/

                // Xi <- heap[h]
                data.put(xi, constantCell(fn));

                // P <- instruction_size(P)
                ip += 7;

                break;
            }

            case GET_CONST:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);
                int fn = codeBuffer.getInt(ip + 3);

                /*trace.fine(ip + ": GET_CONST " + printSlot(xi, mode) + ", " + fn);*/

                // addr <- deref(Xi)
                int addr = deref(xi);
                int tag = derefTag;
                int val = derefVal;

                failed = !unifyConst(fn, xi);

                // P <- P + instruction_size(P)
                ip += 7;

                break;
            }

            case SET_CONST:
            {
                int fn = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": SET_CONST " + fn);*/

                // heap[h] <- <CON, c>
                data.put(hp, constantCell(fn));

                // h <- h + 1
                hp++;

                // P <- instruction_size(P)
                ip += 5;

                break;
            }

            case UNIFY_CONST:
            {
                int fn = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": UNIFY_CONST " + fn);*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // addr <- deref(S)

                    // unifyConst(fn, addr)
                    failed = !unifyConst(fn, sp);
                }
                else
                {
                    // case write:
                    // heap[h] <- <CON, c>
                    data.put(hp, constantCell(fn));

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            case PUT_LIST:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": PUT_LIST " + printSlot(xi, mode));*/

                // Xi <- <LIS, H>
                data.put(xi, listCell(hp));

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            case GET_LIST:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": GET_LIST " + printSlot(xi, mode));*/

                int addr = deref(xi);
                int tag = derefTag;
                int val = derefVal;

                // case STORE[addr] of
                switch (tag)
                {
                case REF:
                {
                    // <REF, _> :
                    // HEAP[H] <- <LIS, H+1>
                    data.put(hp, listCell(hp + 1));

                    // bind(addr, H)
                    bind(addr, hp);

                    // H <- H + 1
                    hp += 1;

                    // mode <- write
                    writeMode = true;
                    /*trace.fine("-> write mode");*/

                    break;
                }

                case LIS:
                {
                    // <LIS, a> :
                    // S <- a
                    sp = val;

                    // mode <- read
                    writeMode = false;
                    /*trace.fine("-> read mode");*/

                    break;
                }

                default:
                {
                    // other: fail <- true;
                    failed = true;
                }
                }

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            case SET_VOID:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                /*trace.fine(ip + ": SET_VOID " + n);*/

                // for i <- H to H + n - 1 do
                //  HEAP[i] <- <REF, i>
                for (int addr = hp; addr < (hp + n); addr++)
                {
                    data.put(addr, refTo(addr));
                }

                // H <- H + n
                hp += n;

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            case UNIFY_VOID:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                /*trace.fine(ip + ": UNIFY_VOID " + n);*/

                // case mode of
                if (!writeMode)
                {
                    //  read: S <- S + n
                    sp += n;
                }
                else
                {
                    //  write:
                    //   for i <- H to H + n -1 do
                    //    HEAP[i] <- <REF, i>
                    for (int addr = hp; addr < (hp + n); addr++)
                    {
                        data.put(addr, refTo(addr));
                    }

                    //   H <- H + n
                    hp += n;
                }

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            // put_unsafe_val Yn, Ai:
            case PUT_UNSAFE_VAL:
            {
                // grab addr, Ai
                byte mode = codeBuffer.get(ip + 1);
                int yi = (int) codeBuffer.get(ip + 2) + (ep + 3);
                byte ai = codeBuffer.get(ip + 3);

                /*trace.fine(ip + ": PUT_UNSAFE_VAL " + printSlot(yi, WAMInstruction.STACK_ADDR) + ", A" + ai);*/

                int addr = deref(yi);

                if (addr < ep)
                {
                    // Ai <- Xn
                    data.put(ai, data.get(addr));
                }
                else
                {
                    data.put(hp, refTo(hp));
                    bind(addr, hp);
                    data.put(ai, data.get(hp));
                    hp++;
                }

                // P <- P + instruction_size(P)
                ip += 4;

                break;
            }

            // set_local_val Xi:
            case SET_LOCAL_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": SET_LOCAL_VAL " + printSlot(xi, mode));*/

                int addr = deref(xi);

                if (addr < ep)
                {
                    data.put(hp, data.get(addr));
                }
                else
                {
                    data.put(hp, refTo(hp));
                    bind(addr, hp);
                }

                // h <- h + 1
                hp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // unify_local_val Xi:
            case UNIFY_LOCAL_VAL:
            {
                // grab addr
                byte mode = codeBuffer.get(ip + 1);
                int xi = getRegisterOrStackSlot(mode);

                /*trace.fine(ip + ": UNIFY_LOCAL_VAL " + printSlot(xi, mode));*/

                // switch mode
                if (!writeMode)
                {
                    // case read:
                    // unify (Xi, s)
                    failed = !unify(xi, sp);
                }
                else
                {
                    // case write:
                    int addr = deref(xi);

                    if (addr < ep)
                    {
                        data.put(hp, data.get(addr));
                    }
                    else
                    {
                        data.put(hp, refTo(hp));
                        bind(addr, hp);
                    }

                    // h <- h + 1
                    hp++;
                }

                // s <- s + 1
                sp++;

                // P <- P + instruction_size(P)
                ip += 3;

                break;
            }

            // call @(p/n), perms:
            case CALL:
            {
                // grab @(p/n), perms
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);
                int numPerms = (int) codeBuffer.get(ip + 6);

                // num_of_args <- n
                numOfArgs = n;

                // Ensure that the predicate to call is known and linked in, otherwise fail.
                if (pn == -1)
                {
                    failed = true;

                    break;
                }

                // STACK[E + 2] <- numPerms
                data.put(ep + 2, numPerms);

                // CP <- P + instruction_size(P)
                cp = ip + 7;

                /*trace.fine(ip + ": CALL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/

                // B0 <- B
                b0 = bp;

                // P <- @(p/n)
                ip = pn;

                break;
            }

            // execute @(p/n):
            case EXECUTE:
            {
                // grab @(p/n)
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);

                // num_of_args <- n
                numOfArgs = n;

                /*trace.fine(ip + ": EXECUTE " + pn + "/" + n + " (cp = " + cp + ")]");*/

                // Ensure that the predicate to call is known and linked in, otherwise fail.
                if (pn == -1)
                {
                    failed = true;

                    break;
                }

                // B0 <- B
                b0 = bp;

                // P <- @(p/n)
                ip = pn;

                break;
            }

            // proceed:
            case PROCEED:
            {
                /*trace.fine(ip + ": PROCEED" + " (cp = " + cp + ")]");*/

                // P <- CP
                ip = cp;

                break;
            }

            // allocate:
            case ALLOCATE:
            {
                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newE] <- E
                data.put(esp, ep);

                // STACK[E + 1] <- CP
                data.put(esp + 1, cp);

                // STACK[E + 2] <- N
                data.put(esp + 2, 0);

                // E <- newE
                // newE <- E + n + 3
                ep = esp;

                /*trace.fine(ip + ": ALLOCATE");*/
                /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            // allocate N:
            case ALLOCATE_N:
            {
                // grab N
                int n = (int) codeBuffer.get(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newE] <- E
                data.put(esp, ep);

                // STACK[E + 1] <- CP
                data.put(esp + 1, cp);

                // STACK[E + 2] <- N
                data.put(esp + 2, n);

                // E <- newE
                // newE <- E + n + 3
                ep = esp;

                /*trace.fine(ip + ": ALLOCATE_N " + n);*/
                /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/

                // P <- P + instruction_size(P)
                ip += 2;

                break;
            }

            // deallocate:
            case DEALLOCATE:
            {
                int newip = data.get(ep + 1);

                // E <- STACK[E]
                ep = data.get(ep);

                /*trace.fine(ip + ": DEALLOCATE");*/
                /*trace.fine("<- env @ " + ep + " " + traceEnvFrame());*/

                // CP <- STACK[E + 1]
                cp = newip;

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            // try me else L:
            case TRY_ME_ELSE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newB] <- num_of_args
                // n <- STACK[newB]
                int n = numOfArgs;
                data.put(esp, n);

                // for i <- 1 to n do STACK[newB + i] <- Ai
                for (int i = 0; i < n; i++)
                {
                    data.put(esp + i + 1, data.get(i));
                }

                // STACK[newB + n + 1] <- E
                data.put(esp + n + 1, ep);

                // STACK[newB + n + 2] <- CP
                data.put(esp + n + 2, cp);

                // STACK[newB + n + 3] <- B
                data.put(esp + n + 3, bp);

                // STACK[newB + n + 4] <- L
                data.put(esp + n + 4, l);

                // STACK[newB + n + 5] <- TR
                data.put(esp + n + 5, trp);

                // STACK[newB + n + 6] <- H
                data.put(esp + n + 6, hp);

                // STACK[newB + n + 7] <- B0
                data.put(esp + n + 7, b0);

                // B <- new B
                bp = esp;

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": TRY_ME_ELSE");*/
                /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            // retry me else L:
            case RETRY_ME_ELSE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // STACK[B + n + 4] <- L
                data.put(bp + n + 4, l);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": RETRY_ME_ELSE");*/
                /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 5;

                break;
            }

            // trust me (else fail):
            case TRUST_ME:
            {
                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- STACK[B + n + 6]
                hbp = hp;

                // B <- STACK[B + n + 3]
                bp = data.get(bp + n + 3);

                /*trace.fine(ip + ": TRUST_ME");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- P + instruction_size(P)
                ip += 1;

                break;
            }

            case SWITCH_ON_TERM:
            {
                // grab labels
                int v = codeBuffer.getInt(ip + 1);
                int c = codeBuffer.getInt(ip + 5);
                int l = codeBuffer.getInt(ip + 9);
                int s = codeBuffer.getInt(ip + 13);

                int addr = deref(1);
                int tag = derefTag;

                // case STORE[deref(A1)] of
                switch (tag)
                {
                case REF:

                    // <REF, _> : P <- V
                    ip = v;
                    break;

                case CON:

                    // <CON, _> : P <- C
                    ip = c;
                    break;

                case LIS:

                    // <LIS, _> : P <- L
                    ip = l;
                    break;

                case STR:

                    // <STR, _> : P <- S
                    ip = s;
                    break;
                }

                break;
            }

            case SWITCH_ON_CONST:
            {
                // grab labels
                int t = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.getInt(ip + 5);

                // <tag, val> <- STORE[deref(A1)]
                deref(1);

                int val = derefVal;

                // <found, inst> <- get_hash(val, T, N)
                int inst = getHash(val, t, n);

                // if found
                if (inst > 0)
                {
                    // then P <- inst
                    ip = inst;
                }
                else
                {
                    // else backtrack
                    failed = true;
                }

                break;
            }

            case SWITCH_ON_STRUC:
            {
                // grab labels
                int t = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.getInt(ip + 5);

                // <tag, val> <- STORE[deref(A1)]
                deref(1);

                int val = derefVal;

                // <found, inst> <- get_hash(val, T, N)
                int inst = getHash(val, t, n);

                // if found
                if (inst > 0)
                {
                    // then P <- inst
                    ip = inst;
                }
                else
                {
                    // else backtrack
                    failed = true;
                }

                break;
            }

            case TRY:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // if E > B
                //  then newB <- E + STACK[E + 2] + 3
                // else newB <- B + STACK[B] + 7
                int esp = nextStackFrame();

                // STACK[newB] <- num_of_args
                // n <- STACK[newB]
                int n = numOfArgs;
                data.put(esp, n);

                // for i <- 1 to n do STACK[newB + i] <- Ai
                for (int i = 0; i < n; i++)
                {
                    data.put(esp + i + 1, data.get(i));
                }

                // STACK[newB + n + 1] <- E
                data.put(esp + n + 1, ep);

                // STACK[newB + n + 2] <- CP
                data.put(esp + n + 2, cp);

                // STACK[newB + n + 3] <- B
                data.put(esp + n + 3, bp);

                // STACK[newB + n + 4] <- L
                data.put(esp + n + 4, ip + 5);

                // STACK[newB + n + 5] <- TR
                data.put(esp + n + 5, trp);

                // STACK[newB + n + 6] <- H
                data.put(esp + n + 6, hp);

                // STACK[newB + n + 7] <- B0
                data.put(esp + n + 7, b0);

                // B <- new B
                bp = esp;

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": TRY");*/
                /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case RETRY:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // STACK[B + n + 4] <- L
                data.put(bp + n + 4, ip + 5);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- H
                hbp = hp;

                /*trace.fine(ip + ": RETRY");*/
                /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case TRUST:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                // n <- STACK[B]
                int n = data.get(bp);

                // for i <- 1 to n do Ai <- STACK[B + i]
                for (int i = 0; i < n; i++)
                {
                    data.put(i, data.get(bp + i + 1));
                }

                // E <- STACK[B + n + 1]
                ep = data.get(bp + n + 1);

                // CP <- STACK[B + n + 2]
                cp = data.get(bp + n + 2);

                // unwind_trail(STACK[B + n + 5], TR)
                unwindTrail(data.get(bp + n + 5), trp);

                // TR <- STACK[B + n + 5]
                trp = data.get(bp + n + 5);

                // H <- STACK[B + n + 6]
                hp = data.get(bp + n + 6);

                // HB <- STACK[B + n + 6]
                hbp = hp;

                // B <- STACK[B + n + 3]
                bp = data.get(bp + n + 3);

                /*trace.fine(ip + ": TRUST");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                // P <- L
                ip = l;

                break;
            }

            case NECK_CUT:
            {
                if (bp > b0)
                {
                    bp = b0;
                    tidyTrail();
                }

                /*trace.fine(ip + ": NECK_CUT");*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                ip += 1;

                break;
            }

            case GET_LEVEL:
            {
                int yn = (int) codeBuffer.get(ip + 1) + (ep + 3);

                data.put(yn, b0);

                /*trace.fine(ip + ": GET_LEVEL " + codeBuffer.get(ip + 1));*/

                ip += 2;

                break;
            }

            case CUT:
            {
                int yn = (int) codeBuffer.get(ip + 1) + (ep + 3);

                int cbp = data.get(yn);

                if (bp > cbp)
                {
                    bp = cbp;
                    tidyTrail();
                }

                /*trace.fine(ip + ": CUT " + codeBuffer.get(ip + 1));*/
                /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/

                ip += 2;

                break;
            }

            case CONTINUE:
            {
                // grab L
                int l = codeBuffer.getInt(ip + 1);

                /*trace.fine(ip + ": CONTINUE " + l);*/

                ip = l;

                break;
            }

            case NO_OP:
            {
                /*trace.fine(ip + ": NO_OP");*/

                ip += 1;

                break;
            }

            // call_internal @(p/n), perms:
            case CALL_INTERNAL:
            {
                // grab @(p/n), perms
                int pn = codeBuffer.getInt(ip + 1);
                int n = codeBuffer.get(ip + 5);
                int numPerms = (int) codeBuffer.get(ip + 6);

                // num_of_args <- n
                numOfArgs = n;

                /*trace.fine(ip + ": CALL_INTERNAL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/

                boolean callOk = callInternal(pn, n, numPerms);

                failed = !callOk;

                break;
            }

            // suspend on success:
            case SUSPEND:
            {
                /*trace.fine(ip + ": SUSPEND");*/
                ip += 1;
                suspended = true;

                return true;
            }
            }

            // Notify any debug monitor that the machine has been stepped.
            if (monitor != null)
            {
                monitor.onStep(this);
            }
        }

        return !failed;
    }
protected boolean execute ( WAMCallPoint callPoint ) { /*log.fine("protected boolean execute(WAMCallPoint callPoint): called");*/ boolean failed ; // Check if the machine is being woken up from being suspended, in which case immediately fail in order to // trigger back-tracking to find more solutions. if ( suspended ) { failed = true ; suspended = false ; } else { ip = callPoint . entryPoint ; uClear ( ) ; failed = false ; } int numOfArgs = 0 ; // Holds the current continuation point. cp = codeBuffer . position ( ) ; // Notify any debug monitor that execution is starting. if ( monitor != null ) { monitor . onExecute ( this ) ; } //while (!failed && (ip < code.length)) while ( true ) { // Attempt to backtrack on failure. if ( failed ) { failed = backtrack ( ) ; if ( failed ) { break ; } } // Grab next instruction and switch on it. byte instruction = codeBuffer . get ( ip ) ; switch ( instruction ) { // put_struc Xi, f/n: case PUT_STRUC : { // grab addr, f/n byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; int fn = codeBuffer . getInt ( ip + 3 ) ; /*trace.fine(ip + ": PUT_STRUC " + printSlot(xi, mode) + ", " + fn);*/ // heap[h] <- STR, h + 1 data . put ( hp , fn ) ; // Xi <- heap[h] data . put ( xi , structureAt ( hp ) ) ; // h <- h + 2 hp += 1 ; // P <- instruction_size(P) ip += 7 ; break ; } // set_var Xi: case SET_VAR : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": SET_VAR " + printSlot(xi, mode));*/ // heap[h] <- REF, h data . put ( hp , refTo ( hp ) ) ; // Xi <- heap[h] data . put ( xi , data . get ( hp ) ) ; // h <- h + 1 hp ++ ; // P <- instruction_size(P) ip += 3 ; break ; } // set_val Xi: case SET_VAL : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": SET_VAL " + printSlot(xi, mode));*/ // heap[h] <- Xi data . put ( hp , data . get ( xi ) ) ; // h <- h + 1 hp ++ ; // P <- instruction_size(P) ip += 3 ; break ; } // get_struc Xi, case GET_STRUC : { // grab addr, f/n byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; int fn = codeBuffer . getInt ( ip + 3 ) ; /*trace.fine(ip + ": GET_STRUC " + printSlot(xi, mode) + ", " + fn);*/ // addr <- deref(Xi); int addr = deref ( xi ) ; byte tag = derefTag ; int a = derefVal ; // switch STORE[addr] switch ( tag ) { // case REF: case REF : { // heap[h] <- STR, h + 1 data . put ( hp , structureAt ( hp + 1 ) ) ; // heap[h+1] <- f/n data . put ( hp + 1 , fn ) ; // bind(addr, h) bind ( addr , hp ) ; // h <- h + 2 hp += 2 ; // mode <- write writeMode = true ; /*trace.fine("-> write mode");*/ break ; } // case STR, a: case STR : { // if heap[a] = f/n if ( data . get ( a ) == fn ) { // s <- a + 1 sp = a + 1 ; // mode <- read writeMode = false ; /*trace.fine("-> read mode");*/ } else { // fail failed = true ; } break ; } default : { // fail failed = true ; } } // P <- instruction_size(P) ip += 7 ; break ; } // unify_var Xi: case UNIFY_VAR : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": UNIFY_VAR " + printSlot(xi, mode));*/ // switch mode if ( ! writeMode ) { // case read: // Xi <- heap[s] data . put ( xi , data . get ( sp ) ) ; } else { // case write: // heap[h] <- REF, h data . put ( hp , refTo ( hp ) ) ; // Xi <- heap[h] data . put ( xi , data . get ( hp ) ) ; // h <- h + 1 hp ++ ; } // s <- s + 1 sp ++ ; // P <- P + instruction_size(P) ip += 3 ; break ; } // unify_val Xi: case UNIFY_VAL : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": UNIFY_VAL " + printSlot(xi, mode));*/ // switch mode if ( ! writeMode ) { // case read: // unify (Xi, s) failed = ! unify ( xi , sp ) ; } else { // case write: // heap[h] <- Xi data . put ( hp , data . get ( xi ) ) ; // h <- h + 1 hp ++ ; } // s <- s + 1 sp ++ ; // P <- P + instruction_size(P) ip += 3 ; break ; } // put_var Xn, Ai: case PUT_VAR : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; byte ai = codeBuffer . get ( ip + 3 ) ; /*trace.fine(ip + ": PUT_VAR " + printSlot(xi, mode) + ", A" + ai);*/ if ( mode == WAMInstruction . REG_ADDR ) { // heap[h] <- REF, H data . put ( hp , refTo ( hp ) ) ; // Xn <- heap[h] data . put ( xi , data . get ( hp ) ) ; // Ai <- heap[h] data . put ( ai , data . get ( hp ) ) ; } else { // STACK[addr] <- REF, addr data . put ( xi , refTo ( xi ) ) ; // Ai <- STACK[addr] data . put ( ai , data . get ( xi ) ) ; } // h <- h + 1 hp ++ ; // P <- P + instruction_size(P) ip += 4 ; break ; } // put_val Xn, Ai: case PUT_VAL : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; byte ai = codeBuffer . get ( ip + 3 ) ; /*trace.fine(ip + ": PUT_VAL " + printSlot(xi, mode) + ", A" + ai);*/ // Ai <- Xn data . put ( ai , data . get ( xi ) ) ; // P <- P + instruction_size(P) ip += 4 ; break ; } // get var Xn, Ai: case GET_VAR : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; byte ai = codeBuffer . get ( ip + 3 ) ; /*trace.fine(ip + ": GET_VAR " + printSlot(xi, mode) + ", A" + ai);*/ // Xn <- Ai data . put ( xi , data . get ( ai ) ) ; // P <- P + instruction_size(P) ip += 4 ; break ; } // get_val Xn, Ai: case GET_VAL : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; byte ai = codeBuffer . get ( ip + 3 ) ; /*trace.fine(ip + ": GET_VAL " + printSlot(xi, mode) + ", A" + ai);*/ // unify (Xn, Ai) failed = ! unify ( xi , ai ) ; // P <- P + instruction_size(P) ip += 4 ; break ; } case PUT_CONST : { // grab addr, f/n byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; int fn = codeBuffer . getInt ( ip + 3 ) ; /*trace.fine(ip + ": PUT_CONST " + printSlot(xi, mode) + ", " + fn);*/ // Xi <- heap[h] data . put ( xi , constantCell ( fn ) ) ; // P <- instruction_size(P) ip += 7 ; break ; } case GET_CONST : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; int fn = codeBuffer . getInt ( ip + 3 ) ; /*trace.fine(ip + ": GET_CONST " + printSlot(xi, mode) + ", " + fn);*/ // addr <- deref(Xi) int addr = deref ( xi ) ; int tag = derefTag ; int val = derefVal ; failed = ! unifyConst ( fn , xi ) ; // P <- P + instruction_size(P) ip += 7 ; break ; } case SET_CONST : { int fn = codeBuffer . getInt ( ip + 1 ) ; /*trace.fine(ip + ": SET_CONST " + fn);*/ // heap[h] <- <CON, c> data . put ( hp , constantCell ( fn ) ) ; // h <- h + 1 hp ++ ; // P <- instruction_size(P) ip += 5 ; break ; } case UNIFY_CONST : { int fn = codeBuffer . getInt ( ip + 1 ) ; /*trace.fine(ip + ": UNIFY_CONST " + fn);*/ // switch mode if ( ! writeMode ) { // case read: // addr <- deref(S) // unifyConst(fn, addr) failed = ! unifyConst ( fn , sp ) ; } else { // case write: // heap[h] <- <CON, c> data . put ( hp , constantCell ( fn ) ) ; // h <- h + 1 hp ++ ; } // s <- s + 1 sp ++ ; // P <- P + instruction_size(P) ip += 5 ; break ; } case PUT_LIST : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": PUT_LIST " + printSlot(xi, mode));*/ // Xi <- <LIS, H> data . put ( xi , listCell ( hp ) ) ; // P <- P + instruction_size(P) ip += 3 ; break ; } case GET_LIST : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": GET_LIST " + printSlot(xi, mode));*/ int addr = deref ( xi ) ; int tag = derefTag ; int val = derefVal ; // case STORE[addr] of switch ( tag ) { case REF : { // <REF, _> : // HEAP[H] <- <LIS, H+1> data . put ( hp , listCell ( hp + 1 ) ) ; // bind(addr, H) bind ( addr , hp ) ; // H <- H + 1 hp += 1 ; // mode <- write writeMode = true ; /*trace.fine("-> write mode");*/ break ; } case LIS : { // <LIS, a> : // S <- a sp = val ; // mode <- read writeMode = false ; /*trace.fine("-> read mode");*/ break ; } default : { // other: fail <- true; failed = true ; } } // P <- P + instruction_size(P) ip += 3 ; break ; } case SET_VOID : { // grab N int n = ( int ) codeBuffer . get ( ip + 1 ) ; /*trace.fine(ip + ": SET_VOID " + n);*/ // for i <- H to H + n - 1 do //  HEAP[i] <- <REF, i> for ( int addr = hp ; addr < ( hp + n ) ; addr ++ ) { data . put ( addr , refTo ( addr ) ) ; } // H <- H + n hp += n ; // P <- P + instruction_size(P) ip += 2 ; break ; } case UNIFY_VOID : { // grab N int n = ( int ) codeBuffer . get ( ip + 1 ) ; /*trace.fine(ip + ": UNIFY_VOID " + n);*/ // case mode of if ( ! writeMode ) { //  read: S <- S + n sp += n ; } else { //  write: //   for i <- H to H + n -1 do //    HEAP[i] <- <REF, i> for ( int addr = hp ; addr < ( hp + n ) ; addr ++ ) { data . put ( addr , refTo ( addr ) ) ; } //   H <- H + n hp += n ; } // P <- P + instruction_size(P) ip += 2 ; break ; } // put_unsafe_val Yn, Ai: case PUT_UNSAFE_VAL : { // grab addr, Ai byte mode = codeBuffer . get ( ip + 1 ) ; int yi = ( int ) codeBuffer . get ( ip + 2 ) + ( ep + 3 ) ; byte ai = codeBuffer . get ( ip + 3 ) ; /*trace.fine(ip + ": PUT_UNSAFE_VAL " + printSlot(yi, WAMInstruction.STACK_ADDR) + ", A" + ai);*/ int addr = deref ( yi ) ; if ( addr < ep ) { // Ai <- Xn data . put ( ai , data . get ( addr ) ) ; } else { data . put ( hp , refTo ( hp ) ) ; bind ( addr , hp ) ; data . put ( ai , data . get ( hp ) ) ; hp ++ ; } // P <- P + instruction_size(P) ip += 4 ; break ; } // set_local_val Xi: case SET_LOCAL_VAL : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": SET_LOCAL_VAL " + printSlot(xi, mode));*/ int addr = deref ( xi ) ; if ( addr < ep ) { data . put ( hp , data . get ( addr ) ) ; } else { data . put ( hp , refTo ( hp ) ) ; bind ( addr , hp ) ; } // h <- h + 1 hp ++ ; // P <- P + instruction_size(P) ip += 3 ; break ; } // unify_local_val Xi: case UNIFY_LOCAL_VAL : { // grab addr byte mode = codeBuffer . get ( ip + 1 ) ; int xi = getRegisterOrStackSlot ( mode ) ; /*trace.fine(ip + ": UNIFY_LOCAL_VAL " + printSlot(xi, mode));*/ // switch mode if ( ! writeMode ) { // case read: // unify (Xi, s) failed = ! unify ( xi , sp ) ; } else { // case write: int addr = deref ( xi ) ; if ( addr < ep ) { data . put ( hp , data . get ( addr ) ) ; } else { data . put ( hp , refTo ( hp ) ) ; bind ( addr , hp ) ; } // h <- h + 1 hp ++ ; } // s <- s + 1 sp ++ ; // P <- P + instruction_size(P) ip += 3 ; break ; } // call @(p/n), perms: case CALL : { // grab @(p/n), perms int pn = codeBuffer . getInt ( ip + 1 ) ; int n = codeBuffer . get ( ip + 5 ) ; int numPerms = ( int ) codeBuffer . get ( ip + 6 ) ; // num_of_args <- n numOfArgs = n ; // Ensure that the predicate to call is known and linked in, otherwise fail. if ( pn == - 1 ) { failed = true ; break ; } // STACK[E + 2] <- numPerms data . put ( ep + 2 , numPerms ) ; // CP <- P + instruction_size(P) cp = ip + 7 ; /*trace.fine(ip + ": CALL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/ // B0 <- B b0 = bp ; // P <- @(p/n) ip = pn ; break ; } // execute @(p/n): case EXECUTE : { // grab @(p/n) int pn = codeBuffer . getInt ( ip + 1 ) ; int n = codeBuffer . get ( ip + 5 ) ; // num_of_args <- n numOfArgs = n ; /*trace.fine(ip + ": EXECUTE " + pn + "/" + n + " (cp = " + cp + ")]");*/ // Ensure that the predicate to call is known and linked in, otherwise fail. if ( pn == - 1 ) { failed = true ; break ; } // B0 <- B b0 = bp ; // P <- @(p/n) ip = pn ; break ; } // proceed: case PROCEED : { /*trace.fine(ip + ": PROCEED" + " (cp = " + cp + ")]");*/ // P <- CP ip = cp ; break ; } // allocate: case ALLOCATE : { // if E > B //  then newB <- E + STACK[E + 2] + 3 // else newB <- B + STACK[B] + 7 int esp = nextStackFrame ( ) ; // STACK[newE] <- E data . put ( esp , ep ) ; // STACK[E + 1] <- CP data . put ( esp + 1 , cp ) ; // STACK[E + 2] <- N data . put ( esp + 2 , 0 ) ; // E <- newE // newE <- E + n + 3 ep = esp ; /*trace.fine(ip + ": ALLOCATE");*/ /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/ // P <- P + instruction_size(P) ip += 1 ; break ; } // allocate N: case ALLOCATE_N : { // grab N int n = ( int ) codeBuffer . get ( ip + 1 ) ; // if E > B //  then newB <- E + STACK[E + 2] + 3 // else newB <- B + STACK[B] + 7 int esp = nextStackFrame ( ) ; // STACK[newE] <- E data . put ( esp , ep ) ; // STACK[E + 1] <- CP data . put ( esp + 1 , cp ) ; // STACK[E + 2] <- N data . put ( esp + 2 , n ) ; // E <- newE // newE <- E + n + 3 ep = esp ; /*trace.fine(ip + ": ALLOCATE_N " + n);*/ /*trace.fine("-> env @ " + ep + " " + traceEnvFrame());*/ // P <- P + instruction_size(P) ip += 2 ; break ; } // deallocate: case DEALLOCATE : { int newip = data . get ( ep + 1 ) ; // E <- STACK[E] ep = data . get ( ep ) ; /*trace.fine(ip + ": DEALLOCATE");*/ /*trace.fine("<- env @ " + ep + " " + traceEnvFrame());*/ // CP <- STACK[E + 1] cp = newip ; // P <- P + instruction_size(P) ip += 1 ; break ; } // try me else L: case TRY_ME_ELSE : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; // if E > B //  then newB <- E + STACK[E + 2] + 3 // else newB <- B + STACK[B] + 7 int esp = nextStackFrame ( ) ; // STACK[newB] <- num_of_args // n <- STACK[newB] int n = numOfArgs ; data . put ( esp , n ) ; // for i <- 1 to n do STACK[newB + i] <- Ai for ( int i = 0 ; i < n ; i ++ ) { data . put ( esp + i + 1 , data . get ( i ) ) ; } // STACK[newB + n + 1] <- E data . put ( esp + n + 1 , ep ) ; // STACK[newB + n + 2] <- CP data . put ( esp + n + 2 , cp ) ; // STACK[newB + n + 3] <- B data . put ( esp + n + 3 , bp ) ; // STACK[newB + n + 4] <- L data . put ( esp + n + 4 , l ) ; // STACK[newB + n + 5] <- TR data . put ( esp + n + 5 , trp ) ; // STACK[newB + n + 6] <- H data . put ( esp + n + 6 , hp ) ; // STACK[newB + n + 7] <- B0 data . put ( esp + n + 7 , b0 ) ; // B <- new B bp = esp ; // HB <- H hbp = hp ; /*trace.fine(ip + ": TRY_ME_ELSE");*/ /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/ // P <- P + instruction_size(P) ip += 5 ; break ; } // retry me else L: case RETRY_ME_ELSE : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; // n <- STACK[B] int n = data . get ( bp ) ; // for i <- 1 to n do Ai <- STACK[B + i] for ( int i = 0 ; i < n ; i ++ ) { data . put ( i , data . get ( bp + i + 1 ) ) ; } // E <- STACK[B + n + 1] ep = data . get ( bp + n + 1 ) ; // CP <- STACK[B + n + 2] cp = data . get ( bp + n + 2 ) ; // STACK[B + n + 4] <- L data . put ( bp + n + 4 , l ) ; // unwind_trail(STACK[B + n + 5], TR) unwindTrail ( data . get ( bp + n + 5 ) , trp ) ; // TR <- STACK[B + n + 5] trp = data . get ( bp + n + 5 ) ; // H <- STACK[B + n + 6] hp = data . get ( bp + n + 6 ) ; // HB <- H hbp = hp ; /*trace.fine(ip + ": RETRY_ME_ELSE");*/ /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/ // P <- P + instruction_size(P) ip += 5 ; break ; } // trust me (else fail): case TRUST_ME : { // n <- STACK[B] int n = data . get ( bp ) ; // for i <- 1 to n do Ai <- STACK[B + i] for ( int i = 0 ; i < n ; i ++ ) { data . put ( i , data . get ( bp + i + 1 ) ) ; } // E <- STACK[B + n + 1] ep = data . get ( bp + n + 1 ) ; // CP <- STACK[B + n + 2] cp = data . get ( bp + n + 2 ) ; // unwind_trail(STACK[B + n + 5], TR) unwindTrail ( data . get ( bp + n + 5 ) , trp ) ; // TR <- STACK[B + n + 5] trp = data . get ( bp + n + 5 ) ; // H <- STACK[B + n + 6] hp = data . get ( bp + n + 6 ) ; // HB <- STACK[B + n + 6] hbp = hp ; // B <- STACK[B + n + 3] bp = data . get ( bp + n + 3 ) ; /*trace.fine(ip + ": TRUST_ME");*/ /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/ // P <- P + instruction_size(P) ip += 1 ; break ; } case SWITCH_ON_TERM : { // grab labels int v = codeBuffer . getInt ( ip + 1 ) ; int c = codeBuffer . getInt ( ip + 5 ) ; int l = codeBuffer . getInt ( ip + 9 ) ; int s = codeBuffer . getInt ( ip + 13 ) ; int addr = deref ( 1 ) ; int tag = derefTag ; // case STORE[deref(A1)] of switch ( tag ) { case REF : // <REF, _> : P <- V ip = v ; break ; case CON : // <CON, _> : P <- C ip = c ; break ; case LIS : // <LIS, _> : P <- L ip = l ; break ; case STR : // <STR, _> : P <- S ip = s ; break ; } break ; } case SWITCH_ON_CONST : { // grab labels int t = codeBuffer . getInt ( ip + 1 ) ; int n = codeBuffer . getInt ( ip + 5 ) ; // <tag, val> <- STORE[deref(A1)] deref ( 1 ) ; int val = derefVal ; // <found, inst> <- get_hash(val, T, N) int inst = getHash ( val , t , n ) ; // if found if ( inst > 0 ) { // then P <- inst ip = inst ; } else { // else backtrack failed = true ; } break ; } case SWITCH_ON_STRUC : { // grab labels int t = codeBuffer . getInt ( ip + 1 ) ; int n = codeBuffer . getInt ( ip + 5 ) ; // <tag, val> <- STORE[deref(A1)] deref ( 1 ) ; int val = derefVal ; // <found, inst> <- get_hash(val, T, N) int inst = getHash ( val , t , n ) ; // if found if ( inst > 0 ) { // then P <- inst ip = inst ; } else { // else backtrack failed = true ; } break ; } case TRY : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; // if E > B //  then newB <- E + STACK[E + 2] + 3 // else newB <- B + STACK[B] + 7 int esp = nextStackFrame ( ) ; // STACK[newB] <- num_of_args // n <- STACK[newB] int n = numOfArgs ; data . put ( esp , n ) ; // for i <- 1 to n do STACK[newB + i] <- Ai for ( int i = 0 ; i < n ; i ++ ) { data . put ( esp + i + 1 , data . get ( i ) ) ; } // STACK[newB + n + 1] <- E data . put ( esp + n + 1 , ep ) ; // STACK[newB + n + 2] <- CP data . put ( esp + n + 2 , cp ) ; // STACK[newB + n + 3] <- B data . put ( esp + n + 3 , bp ) ; // STACK[newB + n + 4] <- L data . put ( esp + n + 4 , ip + 5 ) ; // STACK[newB + n + 5] <- TR data . put ( esp + n + 5 , trp ) ; // STACK[newB + n + 6] <- H data . put ( esp + n + 6 , hp ) ; // STACK[newB + n + 7] <- B0 data . put ( esp + n + 7 , b0 ) ; // B <- new B bp = esp ; // HB <- H hbp = hp ; /*trace.fine(ip + ": TRY");*/ /*trace.fine("-> chp @ " + bp + " " + traceChoiceFrame());*/ // P <- L ip = l ; break ; } case RETRY : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; // n <- STACK[B] int n = data . get ( bp ) ; // for i <- 1 to n do Ai <- STACK[B + i] for ( int i = 0 ; i < n ; i ++ ) { data . put ( i , data . get ( bp + i + 1 ) ) ; } // E <- STACK[B + n + 1] ep = data . get ( bp + n + 1 ) ; // CP <- STACK[B + n + 2] cp = data . get ( bp + n + 2 ) ; // STACK[B + n + 4] <- L data . put ( bp + n + 4 , ip + 5 ) ; // unwind_trail(STACK[B + n + 5], TR) unwindTrail ( data . get ( bp + n + 5 ) , trp ) ; // TR <- STACK[B + n + 5] trp = data . get ( bp + n + 5 ) ; // H <- STACK[B + n + 6] hp = data . get ( bp + n + 6 ) ; // HB <- H hbp = hp ; /*trace.fine(ip + ": RETRY");*/ /*trace.fine("-- chp @ " + bp + " " + traceChoiceFrame());*/ // P <- L ip = l ; break ; } case TRUST : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; // n <- STACK[B] int n = data . get ( bp ) ; // for i <- 1 to n do Ai <- STACK[B + i] for ( int i = 0 ; i < n ; i ++ ) { data . put ( i , data . get ( bp + i + 1 ) ) ; } // E <- STACK[B + n + 1] ep = data . get ( bp + n + 1 ) ; // CP <- STACK[B + n + 2] cp = data . get ( bp + n + 2 ) ; // unwind_trail(STACK[B + n + 5], TR) unwindTrail ( data . get ( bp + n + 5 ) , trp ) ; // TR <- STACK[B + n + 5] trp = data . get ( bp + n + 5 ) ; // H <- STACK[B + n + 6] hp = data . get ( bp + n + 6 ) ; // HB <- STACK[B + n + 6] hbp = hp ; // B <- STACK[B + n + 3] bp = data . get ( bp + n + 3 ) ; /*trace.fine(ip + ": TRUST");*/ /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/ // P <- L ip = l ; break ; } case NECK_CUT : { if ( bp > b0 ) { bp = b0 ; tidyTrail ( ) ; } /*trace.fine(ip + ": NECK_CUT");*/ /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/ ip += 1 ; break ; } case GET_LEVEL : { int yn = ( int ) codeBuffer . get ( ip + 1 ) + ( ep + 3 ) ; data . put ( yn , b0 ) ; /*trace.fine(ip + ": GET_LEVEL " + codeBuffer.get(ip + 1));*/ ip += 2 ; break ; } case CUT : { int yn = ( int ) codeBuffer . get ( ip + 1 ) + ( ep + 3 ) ; int cbp = data . get ( yn ) ; if ( bp > cbp ) { bp = cbp ; tidyTrail ( ) ; } /*trace.fine(ip + ": CUT " + codeBuffer.get(ip + 1));*/ /*trace.fine("<- chp @ " + bp + " " + traceChoiceFrame());*/ ip += 2 ; break ; } case CONTINUE : { // grab L int l = codeBuffer . getInt ( ip + 1 ) ; /*trace.fine(ip + ": CONTINUE " + l);*/ ip = l ; break ; } case NO_OP : { /*trace.fine(ip + ": NO_OP");*/ ip += 1 ; break ; } // call_internal @(p/n), perms: case CALL_INTERNAL : { // grab @(p/n), perms int pn = codeBuffer . getInt ( ip + 1 ) ; int n = codeBuffer . get ( ip + 5 ) ; int numPerms = ( int ) codeBuffer . get ( ip + 6 ) ; // num_of_args <- n numOfArgs = n ; /*trace.fine(ip + ": CALL_INTERNAL " + pn + "/" + n + ", " + numPerms + " (cp = " + cp + ")]");*/ boolean callOk = callInternal ( pn , n , numPerms ) ; failed = ! callOk ; break ; } // suspend on success: case SUSPEND : { /*trace.fine(ip + ": SUSPEND");*/ ip += 1 ; suspended = true ; return true ; } } // Notify any debug monitor that the machine has been stepped. if ( monitor != null ) { monitor . onStep ( this ) ; } } return ! failed ; }
{@inheritDoc}
{