        I. INSTRUCTIONS FOR UNIFYING AND CREATING TERMS
        ===============================================


The Get Class of Instructions
=============================

get_variable Xn, Ai

   This instruction is for the first occurrence of a temporary variable
   appearing as a head argument.
   Xi is the data register to be set, and Ai is the data register containing
   (a reference to) a term to which this variable should be bound.
   The effect of this instruction is unchanged from the WAM: the content of
   Ai is copied into Xi.

get_variable Yn, Ai

   This instruction is for the first occurrence of a permanent variable
   appearing as a head argument.
   Yn is the ith argument in the current top environment record which is to
   be set, and Ai is the data register containing (a reference to) a term
   to which this variable should be bound.
   The effect of this instruction is unchanged from the WAM: the content of
   Ai is copied into Yi.

init_variable Xn, Ym

   This instruction is for the first occurrence of a temporary variable
   in clause that is bound already: free variables in an antecedent of
   an implication goal.
   Xn is the data register to be set, and Ym is the mth argument cell in the
   clause environment (referred to by the CE register) holding (a reference
   to) the binding of this variable obtained from previous computation.
   Xn is set to a reference to the dereference result of Ym.

init_variable Yn, Ym

   This instruction is for the first occurrence of a permanent variable
   in clause that is bound already: free variables in an antecedent of
   an implication goal.
   Yn is the nth argument cell of the current top environment record,
   and Ym is the mth argument cell in the clause environment (referred to by
   the CE register) holding (a reference to) the binding of this variable
   obtained from previous computation.
   Yn is set to a reference to the dereference result of Ym.

get_m_constant Ai, c

   This instruction is for a constant without type association appearing as
   a head argument.
   c is a run-time constant symbol table index corresponding to the constant,
   and Ai is a data register holding (a reference to) the term to be unified
   with c.
   Ai is first dereferenced, and head normalized. The next action depends on
   the head normalization result.
   1). free variable:                                                (bind)
       If the universe count of this free variable is smaller than uc, which
       is the universe count of c obtained from the symbol table,
       backtracking is initiated.
       Otherwise, the free variable is updated to a constant cell of form
       (const<c, wo type, uc>). The binding is trailed if necessary.
       The flag BND is set to ON.
   2). constant:                                                     (unify)
       If the symbol table index of this constant is not the same as c,
       backtracking is initiated. Otherwise, computation proceeds to the next
       instruction.
   3). non-constant rigid term or non-variable flexible term (possible under
       abstractions):                                            (delay/fail)
       If the head normal form is a non-constant rigid term and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant and its
       symbol table index is other than c; c) the head is a constant with c
       as its symbol table index, and the number of the abstractions in the
       front is not the same as the number of its arguments.
       If the head normal form is a non-variable flexible term with no
       arguments, ie. (lam(n, fv)), backtracking is initiated.
       Otherwise, a constant cell of form (const<c, wo type, uc>), where uc is
       the universe count of c obtained from the symbol table is pushed onto
       the current top of heap with heap overflow checking.
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.

get_p_constant Ai, c, L

   This instruction is for a constant with type association appearing as
   a head argument.
   c is a run-time constant symbol table index corresponding to the constant,
   and Ai is a data register holding (a reference to) the term to be unified
   with c. L is a label to the instruction following those for writing the
   type environment of the constant.
   Ai is first dereferenced, and head normalized. The next action depends on
   the head normalization result.
   1). free variable:                                                (bind)
       If the universe count of this free variable is smaller than uc, which
       is the universe count of c obtained from the symbol table,
       backtracking is initiated.
       Otherwise, a const cell of form (const<c, w type, uc, H + TCONST_SIZE>)
       is pushed onto the heap, where H is the current value of the top of heap
       register. The free variable is updated to a reference to the newly
       created heap cell. The binding is trailed if necessary.
       Heap overflow is checked against the (TCONST_SIZE + n*ATOMIC_TYPE_SIZE),
       where n is the size of type environment in the run-time symbol table
       entry of index c before the term creation on heap.
       The flag BND is set to ON. Computation proceeds in TYWRITE mode to the
       next instruction.
   2). constant:                                                     (unify)
       If the symbol table index of this constant is not the same as c,
       backtracking is initiated. Otherwise, computation proceeds to the
       instruction at label L.
   3). non-constant rigid term or non-variable flexible term (possible under
       abstractions):                                             (delay/fail)
       If the head normal form is a non-constant rigid term and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant and its
       symbol table index is other than c; c) the head is a constant with c
       as its symbol table index, and the number of the abstractions in the
       front is not the same as the number of its arguments.
       If the head normal form is a non-variable flexible term with no
       arguments, ie. (lam(n, fv)), backtracking is initiated.
       Otherwise, a constant cell of form (const<c, type, uc, H+TCONST_SIZE>),
       where H is the value of the top of heap register, and uc is the universe
       count of c obtained from the symbol table is pushed onto the heap with
       heap overflow checking against the size (TCONST_SIZE+n*ATOMIC_TYPE_SIZE),
       where n is the size of type environment in the run-time symbol table
       entry of index c.
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.
       Computation proceeds in TYWRITE mode to the next instruction.

[ A possible opt is to generate "set_type_" instructions following
  "get_p_const"; then there is no need to set TYWRITE mode.          ]

get_integer Ai, i

   This instruction is for an integer appearing as a head argument.
   i is the value of the integer, and Ai is the data register holding a term
   to be unified with this integer.
   Ai is first dereferenced and head normalized. Note that because of static
   type checking, the result cannot be an abstraction. If the result is a free
   variable, then the variable is updated into an integer cell of form
   (int(i)). The binding is trailed if necessary, and the BND register is set
   to ON. Otherwise, if the result is an integer, backtracking is initiated
   if its value field is different than i. Otherwise, if the result is a
   non-integer rigid term, backtracking is initiated. Otherwise, the result
   is a non-variable flexible term. An integer cell of form (int<i>) is
   pushed onto the heap, with heap overflow checking. A disagreement pair
   whose first component is the complicated term, and the second is the newly
   created heap term is pushed into the PDL stack.

get_float Ai, fl

   This instruction is for a real appearing as a head argument.
   fl is the value of the real, and Ai is the data register holding a term
   to be unified with this real.
   Ai is first dereferenced and head normalized. Note that because of static
   type checking, the result cannot be an abstraction.
   If the result is a free variable, then the variable is updated into a
   float cell of form (float(fl)). The binding is trailed if necessary,
   and the BND register is set to ON. Otherwise, if the result is a float,
   backtracking is initiated if its value field is different than fl.
   Otherwise, if the result is a non-float rigid term, backtracking is
   initiated. Otherwise, the result is a non-variable flexible term. A float
   cell of form (float<fl>) is pushed onto the heap, with heap overflow
   checking. A disagreement pair whose first component is the complicated
   term, and the second is the newly created heap term is pushed into the
   PDL stack.

get_string Ai, s

   This instruction is for a string appearing as a head argument.
   s is the address of the string located in the module space, and Ai is the
   data register holding the term to be unified with the string.
   Ai is first dereferenced and head normalized. Note that because of static
   type checking, the result cannot be an abstraction.
   If the result is a free variable, then the variable is updated into a
   str cell of form (str(s)). The binding is trailed if necessary,
   and the BND register is set to ON. Otherwise, if the result is a string,
   backtracking is initiated if the character list referred by its value field
   is not the same as that referred to by s (in terms of length, and same
   characters pairwise).
   Otherwise, if the result is a non-string rigid term, backtracking is
   initiated. Otherwise, the result is a non-variable flexible term. A string
   cell of form (str<s>) is pushed onto the heap, with heap overflow
   checking. A disagreement pair whose first component is the complicated
   term, and the second is the newly created heap term is pushed into the
   PDL stack.

get_nil Ai

   This instruction is for a nil list appearing as a head argument.
   Ai is the data register holding the term to be unified with the nil list.
   Ai is first dereferenced and head normalized. Note that because of static
   type checking, the result cannot be an abstraction.
   If the result is a free variable, then the variable is updated into a
   cell of form (nil). The binding is trailed if necessary, and the BND register
   is set to ON. If the result is a non-variable flexible term, a cell of
   form (nil) is pushed onto the heap with heap overflow checking. A
   disagreement pair whose first component is the flexible term and the second
   is the newly created heap cell is pushed onto the PDL stack.
   Otherwise, the result is a rigid-term. If it is not a nil, backtracking is
   initiated.

get_m_structure Xi, f, n

   This instruction is the first in compilation of a structure (first-order
   application) in head and not embedded in any higher-order structures, and
   the structure function does not have type association.
   f is a run-time constant symbol table index corresponding to the function
   of the structure, n is the arity (number of arguments) of the structure,
   and Xi is a data register holding (a reference to) a term that to be
   unified with the structure.
   Xi is first dereferenced and then head normalized. The next action
   depends on the head normalization result.
   1). free variable:
       If the universe count of this free variable is smaller than uc, which
       is the universe count of f obtained from the symbol table,
       backtracking is initiated.
       Otherwise, an application object of form (app<func, n, args>) is
       added to the current heap top, where assuming the current value of the
       top of heap register is H, func is (H + APP_SIZE + n * ATOMIC_TERM_SIZE),
       and args is (H + APP_SIZE). The a constant cell of form
       (const<f, wo type, uc>) is created at the heap address func. Then
       the top of heap register is updated to
               (H + APP_SIZE + (n + 1) * ATOMIC_TERM_SIZE).
       Heap overflow is checked against this new heap top before the term
       creations.
       The free variable is updated to a reference to the newly created
       application object. The binding is trailed if necessary.
       The S register is set to the address args; the ADJ register is set
       to the universe count of the free variable; the VAR_BEING_BOUND
       register is set to the new application object; the BND flag is set
       to ON; computation proceeds in WRITE and OCC mode.
   2). constant head application:
       If the symbol table index associating with the constant head of the
       application is not the same as f or its arity is not the same as n,
       backtracking is initiated.
       Otherwise, the S register is set to the beginning of the argument vector
       of the application and computation proceeds in READ mode.
   3). other cases:
       If the term is rigid (possible under abstractions) and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant whose symbol
       table index is different than f; c) the head is a constant indexed by
       f (in which case the number of abstractions m in front of the rigid term
       must be greater than 0), and the number of its argument is not the same
       as (n + m).
       If the term is a non-variable flexible term with no arguments, ie,
       (lam(n, fv)), backtracking is initiated.
       In all other cases, an application object of form (app<func, n, args>) is
       added to the current heap top, where assuming the current value of the
       top of heap register is H, func is (H + APP_SIZE + n * ATOMIC_TERM_SIZE),
       and args is (H + APP_SIZE). The a constant cell of form
       (const<f, wo type, uc>) is created at the heap address func. Then
       the top of heap register is updated to
               (H + APP_SIZE + (n + 1) * ATOMIC_TERM_SIZE).
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.
       The S register is set to the address args, the ADJ register is set to
       the current value of the UC (universe count) register, and computation
       proceeds in WRITE mode and OCC OFF mode.

get_p_structure Xi, f, n

   This instruction is the first in compilation of a structure (first-order
   application) in head and not embedded in any higher-order structures, and
   the structure function have type association.
   f is a run-time constant symbol table index corresponding to the function
   of the structure, n is the arity (number of arguments) of the structure,
   and Xi is a data register holding (a reference to) a term that to be
   unified with the structure.

   Xi is first dereferenced and then head normalized. The next action
   depends on the head normalization result.
   1). free variable:
       If the universe count of this free variable is smaller than uc, which
       is the universe count of f obtained from the symbol table,
       backtracking is initiated.
       Otherwise, an application object of form (app<func, n, args>) is
       added to the current heap top, where assuming the current value of the
       top of heap register is H, func is (H + APP_SIZE + n * ATOMIC_TERM_SIZE),
       and args is (H + APP_SIZE). The a constant cell of form
       (const<f, w type, uc, tyaddr>) is created at the heap address func,
       where tyaddr is (H + APP_SIZE + n * ATOMIC_TERM_SIZE + TCONST_SIZE).
       Then the top of heap register is updated to
               (H + APP_SIZE + n * ATOMIC_TERM_SIZE + TCONST_SIZE).
       Heap overflow is checked against this new heap top plus
       (k * ATOMIC_TYPE_SIZE) with k being the type environment size
       associated with f in the run-time constant symbol table, before the term
       creations.
       The free variable is updated to a reference to the newly created
       application object. The binding is trailed if necessary.
       The S register is set to the address args; the ADJ register is set
       to the universe count of the free variable; the VAR_BEING_BOUND
       register is set to the new application object; the BND flag is set
       to ON; computation proceeds in WRITE, TYWRITE and OCC mode.
   2). constant head application:
       If the symbol table index associating with the constant head of the
       application is not the same as f or its arity is not the same as n,
       backtracking is initiated.
       Otherwise, the S register is set to the beginning of the argument vector
       of the application, the TS register is set to the type environment of
       the constant head, and computation proceeds in READ and TYREAD mode.
   3). other cases:
       If the term is rigid (possible under abstractions) and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant whose symbol
       table index is different than f; c) the head is a constant indexed by
       f (in which case the number of abstractions m in front of the rigid term
       must be greater than 0), and the number of its argument is not the same
       as (n + m).
       If the term is a non-variable flexible term with no arguments, ie,
       (lam(n, fv)), backtracking is initiated.
       In all other cases, an application object of form (app<func, n, args>) is
       added to the current heap top, where assuming the current value of the
       top of heap register is H, func is (H + APP_SIZE + n * ATOMIC_TERM_SIZE),
       and args is (H + APP_SIZE). The a constant cell of form
       (const<f, w type, uc, tyaddr>) is created at the heap address func,
       where tyaddr is (H + APP_SIZE + n * ATOMIC_TERM_SIZE + TCONST_SIZE).
       Then the top of heap register is updated to
               (H + APP_SIZE + n * ATOMIC_TERM_SIZE + TCONST_SIZE).
       Heap overflow is checked against this new heap top plus
       (k * ATOMIC_TYPE_SIZE) with k being the type environment size
       associated with f in the run-time constant symbol table, before the term
       creations.
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.
       The S register is set to the address args, the ADJ register is set to
       the current value of the UC (universe count) register, and computation
       proceeds in WRITE and TYWRITE mode and OCC OFF mode.

get_list Xi

   This instruction is the first in compilation of a list cons in head and
   not embedded in any higher-order structures.
   Xi is a data register holding the term that to be unified with the list.
   Xi is first dereferenced and head normalized. Note that because of static
   type checking, the result cannot be an abstraction.
   If the result is a free variable, then the variable is updated to a cell
   of form (cons<H>), where H is the current value of the heap top register
   with heap overflow checked against (H + CONS_ARITY * ATOMIC_TERM_SIZE).
   The binding is trailed if necessary. The S register is updated to H;
   the ADJ register is set to the universe count of the free
   variable; the VAR_BEING_BOUND register is H; the BND flag is set to ON; the
   top of heap register is updated to (H + CONS_ARITY * ATOMIC_TERM_SIZE);
   and computation proceeds in WRITE and OCC mode.
   If the result is list cons, S register is set to the argument vector
   of the cons and computation proceeds in READ mode.
   If the result is a non-variable flexible term, a cell of form
   (cons<H + ATOMIC_TERM_SIZE>) is created onto the current top of heap,
   where H is the current value of the heap top register with heap overflow
   checked against (H + (CONS_ARITY + 1) * ATOMIC_TERM_SIZE). The S register is
   set to H, the ADJ register is set to the current value of the UC
   register (universe count), the top of heap register is set to
   (H + (CONS_ARITY + 1) * ATOMIC_TERM_SIZE). A disagreement pair whose first
   component is the flexible term and the second is the newly created cons
   cell is pushed onto the PDL stack. Computation proceeds in WRITE mode and
   OCC OFF mode.
   In all other cases, backtracking is initiated.


The Put Class of Instructions
=============================

put_variable Xn, Ai

    This instruction is for the first occurrence of a temporary variable
    as 1) a body argument or 2) the head of a higher-order structure.
    Xn and Ai are both data registers to be set.
    A free variable cell of form (fv<uc>) is pushed onto the current top of
    heap with necessary heap overflow check, where uc is the current value
    of the universe count register UC. A reference to this cell is then put
    into Ai and Xn.

put_variable_e Xn, Ai

    Like put_variable Xi except that the universe count recorded in the
    current top environment record is used as the universe count in creating
    the free variable term.

put_variable Yn, Ai

    This instruction is for the first occurrence of a permanent variable
    as 1) a body argument or 2) the head of a higher-order structure.
    (Note in the second situation, this instruction is immediately followed
     by a  globalize to prevent making stack reference inside higher-order
     structures.)
    Yn is the nth environment argument on the current top environment record,
    and Ai is a data register. Both of them are to be set in this instruction.
    A free variable cell of form (fv<uc>) is put into Yn, where uc is the
    value of the UCE field in the current top environment record. A reference
    to this cell is then put into Ai.

put_value Xn, Ai

    This instruction is for the subsequent occurrences of a temporary variable
    as a body argument.
    Xn is a data register holding the binding of this variable generated from
    previous computation, and Ai is a data register to be set.
    The content of Xn is copied into Ai.

put_value Yn, Ai

    This instruction is for the subsequent occurrences of a permanent variable
    as a body argument.
    Yn is the nth env argument on the current top environment record and is
    holding the binding of the variable generated from previous computation.
    Ai is a data register to be set.
    If the dereference of Yn is a heap address or a reference to a variable,
    a reference to the dereference of Yn is set in Ai; otherwise, the content
    of the dereference of Yn is copied into Ai (in which case, this content
    must be a (untyped) constant, a special constant or a cons.)

put_unsafe_value Yn, Ai

    As in WAM, this instruction is for the first occurrence of a permanent
    variable in a goal prior as a body argument to whose invocation it will
    be trimmed and where the variable was not initialized by a get_variable
    or unify_variable instruction.
    Yn is the nth env argument on the current top environment record and is
    holding the (unsafe) binding of the variable generated from previous
    computation, and Ai is a data register to be set.
    Yn is first dereference. If the dereference result is a constant without
    type association, cons, nil, or special constants including int, float and
    string, the content of this cell is copied into Ai. Otherwise, if the cell
    resides in the current environment (in which case it must be a unbound
    variable), the content of this cell is pushed onto the current heap top
    with necessary heap overflow checking. Then this cell (the dereference of
    Yn) and Ai are set to references to the newly created heap cell, and the
    former binding is trailed if necessary. In all other cases, Ai is set to
    a reference to the dereference of Yn.

copy_value Yn, Ai

    This instruction is needed for making sure that the function part of an
    application or the body of a lambda resides in a register, [when the content
    of Yn is known to yield a reference to the heap. -- ** is this true?!]
    It is for a subsequent occurrence of a permanent variable appearing
    as the head of an application or as the body of a lambda, when the
    binding of Yn from pervious computation is known to yield a reference to
    the heap.
    (There is a counterpart to this instruction for the situation when Yn may
     not be a reference to the heap. It is called globalize and appears in the
     set category of instructions.)
    Yn is the nth env argument on the current top environment record, and is
    holding the (a reference to) the app function or lambda body, and Ai is
    the data register to be set.
    Yn is first dereferenced. [If the dereference result is on stack, the
    content of this cell is copied into Ai -- ** needed?]; otherwise, Ai
    is set to a reference to this cell.

put_m_const Ai, c

    This instruction is for a constant without type association as a body
    argument or as a lambda body or as the function of an app embedded in a
    higher-order structure.
    c is the run-time constant symbol table index corresponding to the constant,
    and Ai is the data register to be set.
    Ai is set to (const<c, wo type, uc>), where uc is the universe count
    in the run-time symbol table entry of index c.

put_p_const Ai, c

    This instruction is for a constant with type association as a body
    argument or as a lambda body or as the function of an app embedded in
    a higher-order structure.
    c is the run-time constant symbol table index corresponding to the
    constant, and Ai is the data register to be set.
    The cell (const<c, w type, uc, H + TCONST_SIZE>) is pushed onto the
    heap, where uc is the universe count in the run-time symbol table entry
    of index c, and H is the current value of the top of heap register.
    Ai is set to a reference of the newly created heap cell.
    Heap overflow is checked against the (TCONST_SIZE + n*ATOMIC_TYPE_SIZE),
    where n is the size of type environment in the run-time symbol table
    entry of index c before the term creation on heap.

put_nil Ai

    This instruction is for an empty list as a body argument or as a lambda
    body.
    Ai is the data register to be set.
    Ai is set to (nil).

put_integer Ai, i

    This instruction is for an integer as a body argument or as a lambda body.
    Ai is the data register to be set, and i is the integer value.
    Ai is set to (int<i>).

put_float Ai, fl

    This instruction is for a real as a body argument or as a lambda body.
    Ai is the data register to be set, and fl is the float value.
    Ai is set to (float<fl>).

put_string Ai, s

    This instruction is for a string as a body argument or as a lambda body.
    Ai is the data register to be set, and s is the address into the
    module string space where the string is stored.
    Ai is set to (str<s>).

put_index Ai,i

    This instruction is for a bound variable as a lambda body or the function
    of an app embedded inside a higher-order structure.
    Ai is the data register to be set, and i is the de bruijn index.
    A cell of form (bv<i>) is pushed onto the top of heap, with heap overflow
    checking. Ai is set to a reference to this cell.

put_app Ai, Xj, n

    This instruction is for applications appearing in body, or embedded in
    higher-order structure in clause head.
    Xj is the data register containing (a reference to) the function of this
    application, n is the application arity, and Ai is the data register to
    be set.
    The content of Xj is first checked. It is pushed onto the top of heap when
    not being a reference, and Xj is set to a reference to the new heap cell.
    Heap overflow is checked. Then a application cell of form
    (app<n, func, (H+APP_SIZE)>) is created onto the top of heap, where func
    is the addr component of the reference cell currently in Xj. Ai is set to
    a reference to the application cell, and the S register is set to refer to
    (H+APP_SIZE); finally, the top of heap register is moved to
    (H+APP_SIZE + n * ATOMIC_TERM_SIZE). Heap overflow is checked against
    (APP_SIZE + n * ATOMIC_TERM_SIZE) before the heap term creation.

put_list Ai

    This instruction is for list cons appearing in body, embedded in
    higher-order structures in clause head.
    Ai is the data register to be set.
    Ai is set to the form of (cons<H>). Heap overflow is checked against
    (CONS_ARITY * ATOMIC_TERM_SIZE). The S register is set to H (referring
    to the current top of heap).

put_lambda Ai, Xj, n

    This instruction is for the appearance of a lambda structure in the clause.
    Ai is the data register to be set. Xj is the data register holding
    (a reference to) the body of the abstraction, and n is the number of
    lambda appearing in this abstraction term.
    The content of Xj is first checked. It is pushed onto the top of heap when
    not being a reference, and Xj is set to a reference to the new heap cell.
    Heap overflow is checked. The an abstraction cell of form (abs<n, addr>)
    is pushed onto the current top of heap, where addr is the addr component
    of the reference cell currently in Xj. Heap overflow is checked against
    LAM_SIZE before the creation of the abstraction term.


The Unify Class of Instructions
===============================

unify_variable Xi

   This instruction is for the first occurrence of a temporary variable in a
   clause head that is within a structure but not embedded in a higher-order
   structure.
   Xi is the data register to be set to a reference to the free variable.
   Write mode:
   The cell referred to by S is updated to (fv<uc>), where uc is the current
   value of the ADJ register. Xi is set to (ref<S>) and then S is moved to
   the next atomic term in the argument vector.
   Read mode:
   If the cell referred to by S is a free variable cell, Xi is set to a
   reference to this cell. Otherwise, the content of the cell is copied into
   Xi. Si is incremented to the next atomic term in the argument vector.

unify_variable Yn

   This instruction is the same as the previous one except that Yn denotes
   the nth argument cell in the current top environment record.


unify_value Xi

   This instruction is for the subsequent occurrences of a temporary variable
   in a clause head that is within a structure but not embedded in a
   higher-order structure and that is bound to some global (heap)
   value (ie. initialized by unify_variable or put_variable instruction,
   or has been explicitly globalized already.).
   Xi is a data register holding (a reference to) the term that the variable
   is bound to.
   Write mode:
   The action depends on whether the OCC mode is ON or OFF. If it is OFF,
   the content in Xi is copied into the cell referred to by S, and S is
   incremented to the next atomic cell in the argument vector. If OCC mode
   is ON, a procedure is invoked to check if VAR_BEING_BOUND or a constant
   a variable with universe count greater than that in ADJ occurs in the
   term referred to by Xi. If VAR_BEING_BOUND or a constant with universe
   count larger than ADJ occurs along rigid paths, backtracking is
   initiated; Otherwise, a substitution of suitable form for the variable
   denoted by the S register together with ADJ is returned. Note if
   there are variables with universe counts larger than ADJ occurring in
   places other than rigid paths, a variable of universe count being the
   value of ADJ is pushed onto the heap with necessary heap overflow checking,
   a disagreement pair with the first term being the new free variable,
   and the second being the complicated term is added to the live list, and
   the new free variable is returned as the substitution. Upon the
   successful return of this procedure, a copy of or a reference to the
   returned substitution is set in the atomic cell referred to by S, with
   necessary globalization to avoid making a register or stack reference.
   Then S is incremented to the next atomic cell in the argument vector.
   Read mode:
   An interpretive pattern unification procedure is invoked on the pair of
   terms referred to by Xi and S. Binding could be resulted during the
   course of this unification process and in that case the BND register is
   set to ON in place; exception could be raised upon un-unifiability, and
   triggers backtracking. Care has been taken to globalize the
   substitution for a variable when binding occurs so that the variable
   won't become a reference to a register or stack address.
   Upon successful return of the interpretive unification procedure, the
   S register is incremented to the next atomic term cell in the argument
   vector.


unify_value Yn

   This instruction is for the subsequent occurrences of a permanent variable
   in a clause head that is within a structure but not embedded in a
   higher-order structure and that is bound to some global (heap)
   value (ie. initialized by unify_variable instruction, or has been
   explicitly globalized already.).
   Yn is the nth argument cell in the current top environment holding (a
   reference to) the term that the variable is bound to.
   The actions are the same as the previous one except that in
   WRITE mode if OCC mode is OFF, a checking on whether the dereference of
   Yn is a stack address is made; [if it is the case, the content of it is
   copied to the location referred to by the S register; -- ** needed?]
   otherwise, a reference is placed and S is incremented to the next
   argument cell.

unify_local_value Xi

   This instruction is for the subsequent occurrences of a temporary variable
   in a clause head that is within a structure but not embedded in a
   higher-order structure and that is not necessary bound to a global (heap)
   value (ie, initialized by a get_variable instruction.).
   Xi is a data register holding (a reference to) the term that the variable
   is bound to.
   The action of this instruction is similar to unify_value Xn, except if
   Xi dereference to a stack address in WRITE mode with OCC mode OFF.
   In this case, the dereference result is copied to the atomic cell referred
   to by S, and S is incremented to the next argument cell. The dereference
   result of Xi is trailed and updated to a reference to the newly created
   heap cell when necessary, if it is a free variable. Xi is updated to a
   reference to the newly created heap cell too. Otherwise, the dereference
   of Xi refers to a heap address, and Xi and the atomic cell referred to by S
   are updated to a reference to this dereference result.

unify_local_value Yn

   This instruction is the same as unify_local_value Xi except that Yn is
   the nth argument cell on the current top environment record.

unify_m_constant c

   This instruction results from the compilation of a constant without
   type association appearing as an argument of a structure that is not
   embedded in any higher-order structures in clause head.
   c is a run-time constant symbol table index corresponding to the constant.
   Write mode:
   If OCC mode is ON, a checking on whether ADJ is less than uc which is the
   universe count associated with c in the run-time constant symbol table is
   made. If it is the case, backtrack is initiated. Otherwise or when OCC mode
   is OFF, the atomic cell referred to by S is set to a constant cell of form
   (const <c, wo type, uc>), and S is moved to the next argument cell.
   Read mode:
   The term referred to by S is first dereferenced, and head normalized. The
   next action depends on the head normalization result.
   1). free variable:                                                (bind)
       If the universe count of this free variable is smaller than uc, which
       is the universe count of c obtained from the symbol table,
       backtracking is initiated.
       Otherwise, the free variable is updated to a constant cell of form
       (const<c, wo type, uc>). The binding is trailed if necessary.
       The flag BND is set to ON.
   2). constant:                                                     (unify)
       If the symbol table index of this constant is not the same as c,
       backtracking is initiated. Otherwise, computation proceeds to the next
       instruction.
   3). non-constant rigid term or non-variable flexible term (possible under
       abstractions):                                            (delay/fail)
       If the head normal form is a non-constant rigid term and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant and its
       symbol table index is other than c; c) the head is a constant with c
       as its symbol table index, and the number of the abstractions in the
       front is not the same as the number of its arguments.
       If the head normal form is a non-variable flexible term with no
       arguments, ie. (lam(n, fv)), backtracking is initiated.
       Otherwise, a constant cell of form (const<c, wo type, uc>), where uc is
       the universe count of c obtained from the symbol table is pushed onto
       the current top of heap with heap overflow checking.
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.
   Finally, the S register is incremented to the next argument cell.

unify_p_constant c, L

   This instruction results from the compilation of a constant with
   type association appearing as an argument of a structure that is not
   embedded in any higher-order structures in clause head.
   c is a run-time constant symbol table index corresponding to the constant,
   and L is a label to the instruction following those for writing the
   type environment of the constant.
   Write mode:
   If OCC mode is ON, a checking on whether ADJ is less than uc which is the
   universe count associated with c in the run-time constant symbol table is
   made. If it is the case, backtrack is initiated. Otherwise or when OCC mode
   is OFF, a constant cell of form (const<c, w type, uc, (H + TCONST_SIZE)>)
   is created on the top of heap, where H is the current value of the top of
   heap register.  Heap overflow is checked against
        (H + TCONST_SIZE + n * ATOMIC_TYPE_SIZE),
   where n is the size of type environment in the run-time symbol table
   entry of index c before the term creation on heap.
   Then the atomic cell referred to by S is set to a reference to the newly
   created heap cell, S is incremented to the next argument cell and H is
   incremented to (H + TCONST_SIZE). Computation proceeds in TYWRITE mode
   to the next instruction.
   Read mode:
   The term referred to by S is first dereferenced, and head normalized. The
   next action depends on the head normalization result.
   1). free variable:                                                (bind)
       If the universe count of this free variable is smaller than uc, which
       is the universe count of c obtained from the symbol table,
       backtracking is initiated.
       Otherwise, a const cell of form (const<c, w type, uc, H + TCONST_SIZE>)
       is pushed onto the heap, where H is the current value of the top of heap
       register. The free variable is updated to a reference to the newly
       created heap cell. The binding is trailed if necessary.
       Heap overflow is checked against the (TCONST_SIZE + n*ATOMIC_TYPE_SIZE),
       where n is the size of type environment in the run-time symbol table
       entry of index c before the term creation on heap.
       The flag BND is set to ON. Computation proceeds in TYWRITE mode to the
       next instruction.
   2). constant:                                                     (unify)
       If the symbol table index of this constant is not the same as c,
       backtracking is initiated. Otherwise, computation proceeds to the
       instruction at label L.
   3). non-constant rigid term or non-variable flexible term (possible under
       abstractions):                                             (delay/fail)
       If the head normal form is a non-constant rigid term and one of the
       following conditions is met, backtracking is initiated.
       a) the head is not a constant; b) the head is a constant and its
       symbol table index is other than c; c) the head is a constant with c
       as its symbol table index, and the number of the abstractions in the
       front is not the same as the number of its arguments.
       If the head normal form is a non-variable flexible term with no
       arguments, ie. (lam(n, fv)), backtracking is initiated.
       Otherwise, a constant cell of form (const<c, type, uc, H+TCONST_SIZE>),
       where H is the value of the top of heap register, and uc is the universe
       count of c obtained from the symbol table is pushed onto the heap with
       heap overflow checking against the size (TCONST_SIZE+n*ATOMIC_TYPE_SIZE),
       where n is the size of type environment in the run-time symbol table
       entry of index c.
       A disagreement pair whose first component is the complicated term, and
       the second is the newly created heap term is pushed into the PDL stack.
       Computation proceeds in TYWRITE mode to the next instruction.
   Finally, the S register is incremented to the next argument cell.

[ A possible opt is to generate "set_type_" instructions following
  "unify_p_const"; then there is no need to set TYWRITE mode.          ]

unify_nil

   This instruction is for a nil list as an argument of a structure that is
   not embedded in any higher-order structures in a clause head.
   Write mode:
   The cell of form (nil) is set in the location referred to by S, and S
   is incremented to the next argument cell.
   Read mode:
   The term referred to by S is first dereferenced and head normalized.
   Note that because of static type checking, the result cannot be an
   abstraction.
   If the result is a free variable, then the variable is updated into a
   cell of form (nil). The binding is trailed if necessary, and the BND register
   is set to ON. If the result is a non-variable flexible term, a cell of
   form (nil) is pushed onto the heap with heap overflow checking. A
   disagreement pair whose first component is the flexible term and the second
   is the newly created heap cell is pushed onto the PDL stack.
   Otherwise, the result is a rigid-term. If it is not a nil, backtracking is
   initiated.
   Finally, S is incremented to the next argument cell.

unify_integer i

   This instruction is for an integer as an argument of a structure that is
   not embedded in any higher-order structures in a clause head.
   i is the value of this integer
   Write mode:
   The cell of form (int<i>) is set in the location referred to by S, and S
   is incremented to the next argument cell.
   Read mode:
   The term referred to by S is first dereferenced and head normalized.
   Note that because of static type checking, the result cannot be an
   abstraction.
   If the result is a free variable, then the variable is updated into an
   integer cell of form (int(i)). The binding is trailed if necessary, and
   the BND register is set to ON. Otherwise, if the result is an integer,
   backtracking is initiated if its value field is different than i. Otherwise,
   if the result is a non-integer rigid term, backtracking is initiated.
   Otherwise, the result is a non-variable flexible term. An integer cell of
   form (int<i>) is  pushed onto the heap, with heap overflow checking.
   A disagreement pair whose first component is the complicated term, and
   the second is the newly created heap term is pushed into the PDL stack.
   Finally, S is incremented to the next argument cell.

unify_float fl

   This instruction is for a float as an argument of a structure that is
   not embedded in any higher-order structures in a clause head.
   fl is the value of this real number.
   Write mode:
   The cell of form (float<fl>) is set in the location referred to by S, and S
   is incremented to the next argument cell.
   Read mode:
   The term referred to by S is first dereferenced and head normalized.
   Note that because of static type checking, the result cannot be an
   abstraction.
   If the result is a free variable, then the variable is updated into a
   float cell of form (float(fl)). The binding is trailed if necessary, and
   the BND register is set to ON. Otherwise, if the result is an integer,
   backtracking is initiated if its value field is different than fl.
   Otherwise,  if the result is a non-float rigid term, backtracking is
   initiated.  Otherwise, the result is a non-variable flexible term. A float
   cell of form (float<fl>) is  pushed onto the heap, with heap overflow
   checking.  A disagreement pair whose first component is the complicated
   term, and the second is the newly created heap term is pushed into the
   PDL stack.
   Finally, S is incremented to the next argument cell.


unify_string s

   This instruction is for a string as an argument of a structure that is
   not embedded in any higher-order structures in a clause head.
   s is the address of the string located in the module space.
   Write mode:
   The cell of form (str<s>) is set in the location referred to by S, and S
   is incremented to the next argument cell.
   Read mode:
   The term referred to by S is first dereferenced and head normalized.
   Note that because of static type checking, the result cannot be an
   abstraction.
   If the result is a free variable, then the variable is updated into a
   string cell of form (str(s)). The binding is trailed if necessary, and
   the BND register is set to ON. Otherwise, if the result is a string,
   backtracking is initiated if the character list referred by its value field
   is not the same as that referred to by s (in terms of length, and same
   characters pairwise).
   Otherwise, if the result is a non-string rigid term, backtracking is
   initiated. Otherwise, the result is a non-variable flexible term. A string
   cell of form (str<s>) is  pushed onto the heap, with heap overflow checking.
   A disagreement pair whose first component is the complicated term, and
   the second is the newly created heap term is pushed into the PDL stack.
   Finally, S is incremented to the next argument cell.

unify_void n

   This instruction is for n anonymous variables (or variables with only
   one appearance in the clause) as contiguous arguments of a structure
   in clause head and not embedded in any higher-order structures.
   Write mode:
   Cells of form (fv<uc>) is put into n arguments starting from that referred
   to by the register S, where uc is the content of the universe count
   register, and S is incremented to the (n+1) argument position.
   Read mode:
   S is moved to the (n+1) argument position.


The Set Class of Instructions
=============================

set_variable Xi

    This instruction is for the first occurrence of a temporary variable
    appears 1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause.
    Xi is the data register to be set.
    Xi is made a reference to the location referred to by the S register.
    A cell of form (fv<uc>) is pushed into the location referred to by S,
    where uc is the current content of the UC register.

set_variable_e Xi

    Like set_variable Xi except that the universe count recorded in the
    current top environment record is used as the universe count in creating
    the free variable term.

set_variable Yi

    This instruction is for the first occurrence of a permanent variable
    appears 1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause.
    Yi is the ith argument of the current top environment record.
    Yi is made a reference to the location referred to by the S register.
    A cell of form (fv<uc>) is pushed into the location referred to by S,
    where uc is the universe count recorded in the current top environment
    record.

set_value Xi

    This instruction is for the subsequent occurrence of a temporary variable
    appears 1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause, and Xi is known to yield a reference
    to the heap (ie, initialized by set_variable, put_variable or already
    explicitly globalized.).
    Xi is the data register holding the (reference to) binding of the variable
    obtained from previous computation.
    The content of Xi is copied into the location referred to by the S register,
    and S is incremented to the next argument cell.

set_value Yi

    This instruction is for the subsequent occurrence of a permanent variable
    appears 1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause, when Yi is known to yield a reference
    to the heap (ie, initialized by set_variable or already explicitly
    globalized.).
    Yi is the ith argument of the current top environment record holding
    the (reference to) binding of the variable obtained from previous
    computation.
    Yi is first dereferenced. [If the dereference result is a stack address, the
    the content of it is copied onto the location referred to by the S
    register, and S is incremented to the next argument cell -- ** needed? ]
    Otherwise, a reference to the dereference of Yi is pushed into the location
    referred to by the S register.

globalize Yj, Xi

    This instruction is used in place of 1) set_value Yj when it is not known
    whether Yj yields a reference to the heap (ie. was initialized by a
    get_variable Yj or put_variable Yj instruction.); 2) making sure that
    the body of a lambda or the function of an application resides in a
    register as the counter part of copy_value Yj, Xi when Yj could yield
    a reference to the stack.
    Yj is the ith argument of the current top environment record holding
    the (reference to) binding of the variable obtained from previous
    computation. Xi is a data register to be set to hold the "heap copy"
    of the binding of the variable.
    Yj is first dereferenced. If the dereference result if a stack address,
    copy it onto the current heap top with heap overflow check and increment
    the top of heap register by ATOMIC_TERM_SIZE. The dereference result (on
    the stack) is trailed and updated to a reference to the newly created
    heap cell when necessary if it is a free variable. A reference to the
    newly created heap cell is set into Xi. Otherwise, the dereference of Yj
    refers to a heap address, and a reference to it is set to Xi.

    Note that the WAM instruction set_unsafe_value Yj is replaced to
    globalize Yj, Xi followed by set_value Xi.

globalize Xi

    This instruction is used for globalizing a temporary variable that could
    dereference to something on the stack. Specifically, it is used in
    place of 1) set_value Xi when Xi was not initialized by a put_variable Xi
    or set_variable Xi instruction; 2) making sure the the body of a lambda or
    the head of an application resides in a register when Xi may yield a
    reference to the stack.
    Xi is the data register holding the binding of the variable obtained from
    previous computation.
    Xi is first dereferenced. If the result is not a heap address, copy it
    onto the current top of heap with heap overflow check and increment the
    heap top register. The dereference result of Xi is trailed and updated to
    a reference to the newly created heap cell when necessary, if it is a free
    variable (which must locate on the stack then). Xi is updated to a reference
    to the newly created heap cell too. Otherwise, the dereference of Xi
    refers to a heap address, and Xi is updated to a reference to this
    dereference result.

set_m_constant c

    This instruction is for a constant without type association appearing
    1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause.
    c is an index to the run-time constant symbol table corresponding to
    the constant.
    A cell of form (const<c, wo type, uc>) is pushed to the location referred
    to by the S register, where uc is the universe count stored in the
    run-time constant symbol table entry indexed by c.

set_p_constant c

    This instruction is for a constant with type association appearing
    1) as an argument of a first-order structure (application)
    in clause body, or 2) as an argument of an application embedded within
    a higher-order structure in clause.
    A cell of form (const<c, w type, uc, H + TCONST_SIZE>) is pushed onto the
    heap, where uc is the universe count in the run-time symbol table entry
    of index c, and H is the current value of the top of heap register.
    A reference to the newly created heap cell is pushed to the location
    referred to by the S register.
    Heap overflow is checked against the (TCONST_SIZE + n*ATOMIC_TYPE_SIZE),
    where n is the size of type environment in the run-time symbol table
    entry of index c before the term creation on heap.

set_nil

    This instruction is for an empty list appearing 1) as an argument of a
    first-order structure (cons or application) in clause body, or 2) as an
    argument of an application embedded within a higher-order structure
    in clause.
    A cell of form (nil) is put to the location referred to by the S
    register, and the S register is incremented to the next argument position.

set_integer i

    This instruction is for an integer appearing 1) as an argument of a
    first-order structure (cons or application) in clause body, or 2) as an
    argument of an application embedded within a higher-order structure
    in clause.
    i is the integer value.
    A cell of form (int<i>) is put to the location referred to by the S
    register, and the S register is incremented to the next argument position.

set_float fl

    This instruction is for a float appearing 1) as an argument of a
    first-order structure (cons or application) in clause body, or 2) as an
    argument of an application embedded within a higher-order structure
    in clause.
    fl is the real value.
    A cell of form (float<fl>) is put to the location referred to by the S
    register, and the S register is incremented to the next argument position.

set_string s

    This instruction is for an integer appearing 1) as an argument of a
    first-order structure (cons or application) in clause body, or 2) as an
    argument of an application embedded within a higher-order structure
    in clause.
    s is the address of the string in the string area of the module space.
    A cell of form (str<s>) is put to the location referred to by the S
    register, and the S register is incremented to the next argument position.

set_index i

    This instruction is for a lambda bound variable appearing as an argument
    of an application embedded within a higher-order structure in clause.
    i is the de Bruijn index.
    A cell of form (bv<i>) is put to the location referred to by the S
    register, and the S register is incremented to the next argument position.

set_void n

    This instruction is for n anonymous variables (or variables with only
    one appearance in the clause) as contiguous application arguments
    in clause body or embedded in higher-order structures in clause.
    Cells of form (fv<uc>) is put into n arguments starting from that referred
    to by the register S, where uc is the content of the universe count
    register, and S is incremented to the (n+1) argument position.


-- deref Xi
-- set_lambda n, Xi


       II. INSTRUCTIONS FOR UNIFYING AND CREATING TYPES
       ================================================

A. General Comments
===================

The representation of types is the same as that of first-order terms in the
WAM. Function types are represented in the curried form and the arrow type
constructor gets special treatment similar to that for list cons in the WAM.

B. The Get Class of Instructions
================================

get_type_variable Xn, Ai

   This instruction is for the first occurrence of a temporary variable as
   a type argument of the predicate name in clause head.
   Xn is the data register to be set, and Ai is the data register holding
   (a reference to) the type to be unified with this type variable.
   The content of register Ai is copied into Xn.

get_type_variable Yn, Ai

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

init_type_variable Xn, Ym

   This instruction is for the first occurrence of a temporary type variable
   in clause that is bound already: free type variables in an antecedent of
   an implication goal.
   Xn is the data register to be set, and Ym is the mth argument cell in the
   clause environment (referred to by the CE register) holding (a reference
   to) the binding of this type variable obtained from previous computation.
   Xn is set to a reference to the dereference result of Ym.

init_type_variable Yn, Ym

   This instruction is the same as the previous one except that Yn denotes
   the nth argument cell of the current top environment record for a
   permanent variable.

get_type_value Xn, Ai

   This instruction is for the subsequent occurrence of a temporary variable
   as a type argument of the predicate name in clause head.
   Xn is the data register with (a reference to) the type bound to the variable,
   and Ai is the data register holding (a reference to) the type to be unified
   with.
   The pair of terms are pushed onto the PDL stack, and an interpretive type
   unification (with occ) is invoked to solve the pair. Exception may be
   raised in case of un-unifiability.

get_type_value Yn, Ai

   This instruction is the same as the previous one except that Yn denotes
   the nth argument cell of the current top environment record for a
   permanent variable.

get_type_constant Xi, k

   This instruction is for a sort as a type argument of a predicate name in
   clause head.
   k is a run-time kind symbol table index corresponding to the sort, and
   Xi is a data register holding (a reference to) the type to be unified with
   the sort.
   Xi is dereferenced. If the dereference result is a reference (indicating
   a free type variable), the variable is updated to a type sort cell of
   form (sort<k>).  The binding is trailed if necessary.
   Otherwise, if the dereference result is a sort and has
   kind symbol table index field the same as k, computation proceeds to the
   next instruction. In all other cases, backtracking is initiated.

get_type_structure Xi, f

   This instruction is for a type structure appearing in the head of a clause.
   f is a run-time kind table index corresponding to the structure functor,
   and Xi is the data register holding (a reference to) the type to be unified
   with the structure.
   Xi is first dereferenced. If the dereference result is a reference
   (indicating a free variable), a type functor cell of form (func<f, n>) is
   pushed onto the current top of heap with heap overflow checking against
   (n + 1) * ATOMIC_TYPE_SIZE, where n is the arity of the type constructor
   associated with f in the run-time kind symbol table. Then the free variable
   is updated to a type structure object of form (str<addr>), where addr is
   the address of the newly created heap cell. The binding is trailed if
   necessary. The TY_VAR_BEING_BOUND register is set to the newly created
   heap cell and computation proceeds in TYWRITE mode.
   Otherwise, if the dereference result is a type structure with the run-time
   symbol table index of its functor being k, the TS register is set to the
   beginning of the argument vector of the structure, and computation proceeds
   in TYREAD mode.
   In all other cases, backtracking is initiated.

get_type_arrow Xi

   This instruction is for a function type appearing in the head of a clause.
   Xi is the data register holding (a reference to) the type to be unified with
   the function type.
   Xi is first dereferenced. If the dereference result is a reference
   (indicating a free variable), it is updated to a arrow cell of form
   (arrow<H>), where H is the current value of the top of heap register.
   The binding is trailed if necessary. Heap overflow is checked against
   (TY_ARROW_ARITY * ATOMIC_TYPE_SIZE). The TY_VAR_BEING_BOUND register is set
   to H and computation proceeds in TYWRITE mode.
   Otherwise, if the dereference result of Xi is an arrow object of form
   (arrow<addr>), then the TS register is set to addr, and computation proceeds
   in TYREAD mode.
   In all other cases, backtracking is initiated.


C. The Put Class of Instructions
================================

put_type_variable Xn, Ai

    This instruction is for the first occurrence of a temporary type variable
    as a type argument of a predicate name in goals.
    Xn and Ai are both data registers to be set.
    A self-referenced type cell is pushed onto the current heap top with
    heap overflow checking against an atomic type size, and copied to the
    registers Xn and Ai.

put_type_variable Yn, Ai

    This instruction is for the first occurrence of a permanent type variable
    as a type argument of a predicate name in goals.
    Yn is the nth argument cell on the current top environment record, and
    Ai is a data registers. Both of them are to be set.
    A self-referenced type cell is placed in Yn, and it is copied to the
    register Ai.

put_type_value Xn, Ai

    This instruction is for the subsequent occurrences of a temporary type
    variable as a type argument of a predicate name in goals.
    Xn is the data register holding the binding of this variable obtained from
    previous computation, and Ai is the data register to be set.
    The dereference result of Xn is copied over to the register Ai.

put_type_value Yn, Ai

    This instruction is for the subsequent occurrences of a permanent type
    variable as a type argument of a predicate name in goals when it is known
    that the value of Yn is on heap or on env record other than the top-most
    one (thus is protected) (ie. Yn is not initialized by a put_type_variable
    instruction.).
    Yn is the nth argument cell on the current top environment record holding
    the binding of this variable obtained from previous computation, and Ai is
    the data register to be set.
    The dereference result of Yn is copied over to the register Ai.

put_type_unsafe_value Yn, Ai

    This instruction is for the subsequent occurrences of a permanent type
    variable as a type argument of a predicate name in goals when the value of
    Yn may be a reference to a location in the current top environment record
    and may be lost in trimming. (ie. Yn is initialized by a put_type_variable
    instruction.).
    Yn is the nth argument cell on the current top environment record holding
    the binding of this variable obtained from previous computation, and Ai is
    the data register to be set.
    Yn is first dereferenced. If the dereference result is still a reference
    and is on the current top environment record, a self-reference type cell
    is pushed onto the current top of heap with heap overflow checking over
    the atomic type size. The register Ai and the free type variable are set to
    a reference to the newly created heap cell, and the binding is trailed if
    necessary. Otherwise, the dereference result of Yn is simply copied over
    to the register Ai.

put_type_const Ai, k

    This instruction is for a sort as a type argument of a predicate name in
    goals.
    Ai is the data register to be set, and k is the run-time kind table index
    corresponding to the sort.
    Ai is set to a sort cell of form (sort<k>).

put_type_structure Ai, f

    This instruction is for a type structure appearing in body, or as the type
    association of a constant that is embedded in a higher-order structure in
    clause head either as a type argument of the predicate name or in the
    type environment of a constant not embedded in higher-order structures.
    Ai is the data register to be set, and f is the run-time kind table index
    corresponding to the structure functor.
    A type functor cell of form (func<f, n>) is pushed onto the current top
    of heap with heap overflow checking against (n + 1) * ATOMIC_TYPE_SIZE,
    where n is the arity of the type constructor associated with f in the
    run-time kind symbol table. Ai is set to a type structure object of form
    (str<addr>), where addr is the address of the newly created heap cell.

put_type_arrow Ai

    This instruction is for a type arrow appearing in body, or as the type
    association of a constant that is embedded in a higher-order structure in
    clause head either as a type argument of the predicate name or in the type
    environment of a constant not embedded in higher-order structures.
    Ai is the data register to be set.
    Heap overflow is checked against TY_ARROW_ARITY * ATOMIC_TYPE_SIZE. Then
    a type arrow object of form (arrow<H>) is set to Ai, where H is the value
    of the current heap top.

D. The Unify Class of Instructions
==================================

unify_type_variable Xi

    This instruction is for the first occurrence of a temporary variable
    as an argument of a type structure that appears in the clause head
    either as a type argument of the predicate name or in the type environment
    of a constant not embedded in higher-order structures.
    Xi is the data register to be set.
    TYWRITE mode:
    A self-referenced type cell is pushed to the heap, and its content is
    copied into Xi.
    TYREAD mode:
    The type cell referred to by the TS register is copied to the register
    Xi, and TS is incremented to the next type argument cell.

unify_type_variable Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

unify_type_value Xi

    This instruction is for the subsequent occurrences of a temporary variable
    as an argument of a type structure that appears in the clause head
    either as a type argument of the predicate name or in the type environment
    of a constant not embedded in higher-order structures.
    Xi is the data register holding (a reference to) the type to be unified
    with.
    TYWRITE mode:
    The dereference of Xi is pushed onto the PDL stack. An interpretive
    procedure is invoked to occurs-check against TY_VAR_BEING_BOUND.
    If the procedure returns successfully, the dereference result of Xi is
    pushed onto the heap.
    TYREAD mode:
    The dereference of Xi and the term referred to by the TS register are
    pushed onto the PDL stack. An interpretive types unification procedure
    is invoked to unify this pair. The TS register is incremented to the
    next type argument cell.

unify_type_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

unify_envty_value Xi

    This instruction is for the subsequent occurrences of a temporary variable
    as a type environment of a constant not embedded in higher-order
    structures.
    Xi is the data register holding (a reference to) the type to be unified
    with.
    TYWRITE mode:
    The dereference result of Xi is pushed onto the heap. (Note since the type
    variable is not embedded in a type structure, occurs-check against
    TY_VAR_BEING_BOUND is not performed.)
    TYREAD mode:
    The dereference of Xi and the term referred to by the TS register are
    pushed onto the PDL stack. An interpretive types unification procedure
    is invoked to unify this pair. The TS register is incremented to the
    next type argument cell.

    [For example, let c be
     a constant of declared type (A -> B) and p be a predicate name of
     declared type C -> o. For a clause head of form (p (c X)) should be
     type annotated as: (p [B] (c [A, B] X)), where the second occurrence
     of B should be treated by a unify_envty_value instruction.
    ]

unify_envty_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

unify_type_local_value Xi

    This instruction is used in places of unify_type_value Xi when Xi may
    refer to a stack address (ie, initialized by a get_type_variable
    instruction.).
    Xi is the data register holding (a reference to) the type to be unified
    with.
    TYWRITE mode:
    Xi is dereferenced. If it is still a reference (indicating a free type
    variable), and resides on stack, a self-referenced type cell is pushed
    on the heap. The newly created cell is copied to the free type variable
    and the register Xi. The binding is trailed if necessary. Otherwise,
    if the dereference result is a reference but on heap, the content of
    the cell is pushed onto the heap.
    In all other cases, the dereference of Xi is pushed onto the PDL stack.
    An interpretive procedure is invoked to occurs-check against
    TY_VAR_BEING_BOUND.
    If the procedure returns successfully, the dereference result of Xi is
    pushed onto the heap.
    TYREAD mode:
    The dereference of Xi and the term referred to by the TS register are
    pushed onto the PDL stack. An interpretive types unification procedure
    is invoked to unify this pair. The TS register is incremented to the
    next type argument cell.

unify_type_local_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

unify_envty_local_value Xi

    This instruction is used in places of unify_envty_value Xi when Xi may
    refer to a stack address (ie, initialized by a get_type_variable
    instruction.).
    Xi is the data register holding (a reference to) the type to be unified
    with.
    TYWRITE mode:
    Xi is dereferenced. If it is still a reference (indicating a free type
    variable), and resides on stack, a self-referenced type cell is pushed
    on the heap. The newly created cell is copied to the free type variable
    and the register Xi. The binding is trailed if necessary. In all other
    cases, the dereference result is pushed onto the heap.
    TYREAD mode:
    The dereference of Xi and the term referred to by the TS register are
    pushed onto the PDL stack. An interpretive types unification procedure
    is invoked to unify this pair. The TS register is incremented to the
    next type argument cell.

unify_envty_local_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

unify_type_constant k

    This instruction is for a sort appearing in the type environment of a
    constant not embedded in higher-order structures, or as an argument of a
    type structure that appears in the clause head either as a type argument
    of the predicate name or in the type environment of a constant not embedded
    in higher-order structures.
    k is the run-time kind symbol table index corresponding to this type
    constant.
    TYWRITE mode:
    A type sort cell of form (sort<k>) is pushed onto the heap.
    TYREAD mode:
    The term referred to by the TS register is dereferenced. If the dereference
    result is a reference (indicating a free type variable), the variable is
    updated to a type sort cell of form (sort<k>). The binding is trailed if
    necessary. The TS register is incremented to the next argument cell.
    Otherwise, if the dereference result is a sort and has kind symbol table
    index field the same as k, the TS register is incremented to the next
    argument cell and computation proceeds to the next instruction.
    In all other cases, backtracking is initiated.


E. The Set Class of Instructions
================================

set_type_variable Xi

    This instruction is for the first occurrence of a temporary variable
    as an argument of a type structure that appears in the clause body or
    inside the type association of a constant term embedded in higher-order
    structures in the clause head.
    Xi is the data register to be set.
    A self-referenced type cell is pushed onto the current top of heap and
    copied into Xi.

set_type_variable Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

set_type_value Xi

    This instruction is for the subsequent occurrences of a temporary variable
    as an argument of a type structure that appears in the clause body or
    inside the type association of a constant term embedded in higher-order
    structures in the clause head, when it is known that Xi will yield a
    heap address (ie, initialized by set_type_variable, put_type_variable or
    already been explicitly globalized.)
    Xi is the data register holding (a reference to) the type to which
    the variable is bound obtained from the previous computation.
    Xi is dereferenced. The dereference result is pushed onto the heap.

set_type_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

set_type_local_value Xi

    This instruction is for the subsequent occurrences of a temporary variable
    as an argument of a type structure that appears in the clause body or
    inside the type association of a constant term embedded in higher-order
    structures in the clause head, when it is not known that Xi will yield a
    heap address (ie, not initialized by set_type_variable, put_type_variable
    nor already been explicitly globalized.)
    Xi is dereferenced. If the dereference result is a reference to the stack
    (indicating a free type variable on stack), then a self-referenced type
    cell is pushed onto heap, and its value is copied over to the stack
    free type variable. The binding is trailed if necessary. Otherwise, the
    dereference result of Xi is pushed onto the heap.

set_type_local_value Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

set_type_constant k

    This instruction is for a type sort appearing as an argument of a type
    structure that appears in the clause body or inside the type association
    of a constant term embedded in higher-order structures in the clause head.
    k is the run-time kind symbol table index corresponding to this type
    constant.
    A type sort cell of form (sort<k>) is pushed onto the heap.


            III. HIGHER-ORDER INSTRUCTIONS
            ==============================

pattern_unify Xn, Ai

    This instruction is for invoking an interpretive unification procedure
    over a pair of terms.
    Xn and Ai are data registers holding (references to) the pair of terms
    to be unified.
    Care is taken to avoid make references to stack or register addresses
    when perform variable binding in this process. If non-Llambda pairs
    are encountered in this process, they are delayed onto the the live list,
    which is to be examined by the finish_unify instruction.

pattern_unify Yn, Ai

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.

finish_unify

    This instruction is used at the end of the compilation of a clause head,
    when disagreement pairs may be delayed either on the PDL stack or on the
    live list.
    An interpretive unification procedure is first invoked on the PDL stack
    to finish the unification problems left over there. Then the procedure
    is invoked repeatedly over the live list to solve the (possible) LLambda
    problems until the live list becomes empty or no more LLambda problems
    remains on it (Eager estimation on this is performed by the usage of the
    BND flag.).

    Note: "proceed_finish_unify" in the current Teyjus is replaced by
          "finish_unify" followed by a "proceed". "execute_finish_unify"
          and "call_finish_unify" are removed. (The branch point records are
          removed from the new virtual machine.)

head_normalize Xi

    Head normalize the term in or referred to by the data register Xi.
    The head normalization procedure performed destructive changes, and so
    upon its termination, the head normal form is still referred to by the
    register Xi.

head_normalize Yn

    This instruction is the same as the previous one except that Yn denotes
    the nth argument cell of the current top environment record for a
    permanent variable.


               IV. LOGICAL INSTRUCTIONS
               ========================

A. General Comments
===================

(1) The following instructions are for compiling the effects of
    quantifiers and implications in goals.

B. The Instruction Collection
=============================

incr_universe

    This instruction is for entering a universal goal in clause body.
    The UC register is incremented by 1 after checking for universe counter
    overflow error.

decr_universe

    This instruction is for leaving a universal goal in clause body.
    The UC register is decremented by 1.

set_univ_tag Yn, c

    This instruction compiles a universal quantifier over a variable in clause
    body.
    Yn is the nth argument cell in the current top environment record to be
    set to a hidden constant for this universal variable, and c is a run-time
    symbol table index corresponding to the hidden constant.
    A cell of form (const<c, wo type, uc>) is set in the nth argument cell of
    the current top environment record, where uc is the value of the UC
    register.

    Note: a) Since hidden constant never has type association in our new
             computation scheme, the "set_univ_tag_p" instruction from the
             existing Teyjus virtual machine is removed.
          b) In the situation of compiling top-level queries, c may be a dummy
             run-time constant symbol table index (possibly a negative number)
             which does not have a physical entry in the table.

tag_exists Yn

   This instruction compiles an existential quantifier over a variable in clause
   body when the variable is permanent.
   Yn is the nth argument cell in the current top environment record to be set
   to this variable.
   A free variable cell of form (fv<uc>) is set in the nth argument cell of
   the current top environment record, where uc is the value of the UC
   register.

tag_exists Xi

   This instruction compiles an existential quantifier over a variable in clause
   body when the variable is temporary (ie, this variable occurs only in the
   last goal that is not the consequent of an implication.).
   Xi is the data register to be set.
   A free variable cell of form (fv<uc>) is pushed onto the current top of heap
   after heap overflow check,  where uc is the value of the UC register.
   A reference cell to this newly created heap cell is set into the register
   Xi.

tag_variable Yn

   This instruction is used for associating a tag with a variable whose first
   occurrence (including explicit quantifiers) is in the antecedent of an
   implication goal; this initialization is done just prior to invoking the
   implication goal.
   Yn is the nth argument cell in the current top environment record to be set
   to this variable.
   A free variable cell of form (fv<uc>) is set in the nth argument cell of
   the current top environment record, where uc is the value of the UCE field
   of the current top environment record.

push_impl_point n, t

   This instruction is needed for creating an implication point record
   for an implication that appears in a goal.
   n is the number of arguments of the current top environment record, and
   t is a module space address of the implication table, the structure of
   which is described in the sibling file dataarea.txt.
   The instruction first uses n and the registers TOS and E to determine
   where the new implication record should be located depending on whether
   an environment record or a choice point/imp record is on the top of the
   stack. Stack overflow is checked against the allocation of the new
   implication record.
   Then a new implication record (whose structure is described in the sibling
   file dataarea.txt) is created: the current value in the E register, the current
   value in the I register, the size of the predicate search table, the
   starting address of the predicate search table, and the find code function
   pointer (the latter three are obtained from the implication table at t)
   are stored in the relevant field of the implication record, and the
   record is tagged as an implication record; the next clause table of
   this record is filled in for each predicate constant in the link table
   of the implication table at address t, by using the current program context
   indicated by the I register. Then the I register is updated to the newly
   created implication record, and the TOS register is updated to the new
   stack top.

pop_impl_point

   This instruction is used upon leaving an implication goal. It complements
   the push_impl_point instruction.
   The I register is set to the value stored in "previous I" field (PIP) of the
   current implication point, and the TOS register is set to the top choice/
   imp record after "popping" the this one.

add_imports n, m, label

   This instruction is the first in a sequence of instructions that are
   used for realizing the addition of code in imported modules.
   n is the index to the back chained vector in the imp record referred to by
   the CI register; m is the number of arguments of current top environment
   record, and label is a code address.
   The nth  backchained field of form <counter, most recent choice point>
   in the import point record pointed to by the CI register is examined.
   If the most recent choice point in this backchained field refers to an
   address lower than the current value of the B register, this backchained
   field is trailed. Then the backchained field is updated to
   <counter + 1, bc>, where bc is the value of the B register.
   Now if the previous counter is larger than 0, computation proceeds to
   the instruction at address label; otherwise, the TOS register is set to
   the current top of the stack determined by the current value of TOS,
   the register E and the argument m, and computation proceeds to the next
   instruction which must be a (sequence of) "push_import".

remove_imports n, label

   This instruction manipulates the backchained cell in the course of
   ``removing'' code added due to an import.
   n is the index to the back chained vector in the imp record referred to
   by the CI register; label is a code address.
   The nth backchained field of form <counter, most recent choice point> in
   the import point record pointed to by the CI register is examined.
   If the most recent choice point in this backchained field referrs to an
   address lower than the current value of the B register, this backchained
   field is trailed. Then the backchained field is updated to
   <counter - 1, bc>, where bc is the value of the B register.
   Now if the previous counter is larger than 1, computation proceeds to
   the instruction at address label; otherwise, computation proceeds to the
   next instruction which must be a "pop_imports".

push_import t

   This instruction is needed for creating an import point record when a
   clause from a module with imports is used.
   t is a module space address of the import table, the structure of
   which is described in the sibling file dataarea.txt.
   The instruction first uses the register TOS (which is set to the current
   top of heap in the previous add_imports or push_import instruction),
   the size of the link table (lts) and the number of the code segments (ncseg)
   (obtained from the import table at address t) to allocate a new import
   record with stack overflow checking.
   Then a new import record (whose structure is described in the sibling
   file dataarea.txt) is created: the current value in the I register,
   the size of the predicate search table, the starting address of the predicate
   search table, the find code function pointer and the number of predicates
   in the imported module (the latter four are obtained from the import
   table at t) are stored in the relevant field of the implication record.
   The backchained vector of size ncseg is initiated as <0, b> pairs where
   b the value of the current B register; the next clause table of
   this record is filled in for each predicate constant in the link table
   of the implication table at address t, by using the current program context
   indicated by the I register; then if the number of local constants in the
   module is not 0, the UC register is incremented by 1 with overflow checking,
   and the uc fields of the local constants in the run-time constant symbol
   table are set to the value of UC (the number and the indexes of these local
   constants are provided in the import table at t), and the imp record is
   tagged as an import one with local constants. Otherwise, the imp record
   is tagged as an import one without local constants.
   Finally, the I register is set to point to the newly created imp record,
   and the TOS register is set to the new top of stack.

pop_imports n

   This instruction removes n import point records essentially by
   deleting n items from the chain of import point records pointed to by the
   I register. Notice that in the process the UC register must is decreased by
   one for each import record along this chain that is tagged as one with local
   constants.
   Finally, the TOS register is set to the top choice/imp record after the
   sequence of popping.



                V. CONTROL INSTRUCTIONS
                =======================

allocate n

   This instruction is used to allocate a new environment on the stack,
   needed for a clause that has more than one goal in its body.
   The argument n is the number of argument cells in the environment record,
   needed in this instruction for stack overflow detection.
   First, the current stack top is determined by using the TOS and E registers.
   In the situation that the current top env record resides in a higher address
   than the current top choice/imp record, the number of living arguments
   in that top-level env record is determined by the argument of the "call"
   instructions immediately previous to the instruction pointed by the CP
   register. Stack overflow is checked against the size of the new environment
   record with n argument cells. Then the fix part of the new env record is
   pushed onto the top of stack, with the current values of the E, CP, UC
   and CI registers being stored in relevant fields. (The structure of an
   environment record is described in the sibling file dataarea.txt).
   Then the E register is set to the newly created env record.

deallocate

   Remove the current top environment record from the stack.
   This is achieved simply by setting the E and CP registers to the values of
   the continuation environment and continuation (code) point that is stored
   in the environment record currently referred to by E.

call n, label

   This instruction invokes a goal in the clause body after all the
   argument registers are set.
   The argument n is the number of permanent variables to be retained in the
   continuation environment; label is the address to the code area where the
   definition of the callee resides.
   The CP register is set to the address of instruction following this one.
   The register P is set to label, CE is set E and B0 is set to B.
   The argument n is accessed as an offset by subsequent allocate, try_me_else,
   try or try_else instructions to decide stack top.

call_name n, predname

   This instruction is like call, except that the address for the code to
   be called has to be determined dynamically using a name, given as a
   symbol table index.
   The argument n is the number of permanent variables to be retained in the
   continuation environment; predname is an index to the run-time constant
   symbol table corresponding to the name of predicate to be invoked.
   A procedure is invoked for finding the code for predname in the program
   context defined by the I register. If such code is found, its address and
   the address of the impl/import record in which that code is found are
   returned by this procedure. The register P is set to the returned code
   address, and the register CI is set to the returned impl/import point
   address. If it is an impl point, then the register CE is set to the
   corresponding closure environment ("CE" field in that impl point).
   The CP register is set to the instruction following this one and the B0
   register is set to B.
   Otherwise, backtracking is initiated.

execute label

   This instruction is for calling the last goal in the body of a clause.
   The argument label is the address to the code area where the definition of
   the callee resides.
   The register P is set to label, and B0 is set to B.

execute_name predname

   This instruction is like execute, except that the address for the code to
   be called has to be determined dynamically using a name, given as a
   symbol table index.
   The argument predname is an index to the run-time constant symbol table
   corresponding to the name of prediacte to be invoked.
   A procedure is invoked for finding the code for predname in the program
   context defined by the I register.
   If such code is found, its address and the address of the impl/import record
   in which that code is found are returned by this procedure. The register P
   is set to the returned code address, and the register CI is set to the
   returned impl/import point address. If it is an impl point, then the
   register CE is set to the  corresponding closure environment ("CE" field
   in that impl point). The B0 register is set to B.
   Otherwise, backtracking is initiated.

proceed

   This instruction is used at the end of a unit clause.
   If there is no environment record left on the stack implying that no more
   instructions need to be executed), then the simulator exit to the upper
   level control successfully. Otherwise, the P register is set to the value
   stored in CP, the CI register is set to the value stored in the (CIE)
   filed of the environment pointed to by E. If this is an impl point,
   CE is set to the corresponding closure environment ("CE" field in that
   impl point).


               VI. CHOICE INSTRUCTIONS
               =======================


try_me_else n, label

   This instruction precedes the code for the first clause defining a
   predicate defined by more than one clause and is responsible for
   setting up a choice point record (the structure of which is described
   in the sibling file dataarea.txt.)
   The argument n is the number of arguments to be stored in the choice point,
   and label is address to the code area where an alternative definition
   of the predicate resides.
   First, the current stack top is determined by using the TOS and E registers.
   In the situation that the current top env record resides in a higher address
   than the current top choice/imp record, the number of living arguments
   in that top-level env record is determined by the argument of the "call"
   instructions immediately previous to the instruction pointed by the CP
   register. Stack overflow is checked against the size of the choice point
   with n argument cells. Then the value of data registers A1 ... An is
   copied into the argument cells of the choice point, and the values of
   the registers UC, E, CP, I, CI, LL, B, B0, H, TR and label are stored into
   relevant fields of the new choice point. The register B is updated to refer
   to the newly created choice point, the value of the H register (top of heap)
   is copied into HB, and the register TOS is set to the current top of stack.

retry_me_else n, label

   This instruction precedes the code for an intermediate clause in the
   definition of a predicate or the last clause for a predicate whose
   definition in this ``module'' might be an extension of another
   definition.
   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point, and label is address to the
   code area where the next alternative definition of the predicate resides.
   First, the values stored in the current top choice point for data registers
   A1 to An are backed up to those registers. Then the values in the
   UC, E, LL, CP, I, B0, H and CI fields of the choice point is set into
   the corresponding registers. (We assume that the procedure that initiates
   backtracking would have unwound the trail and set the TR register already.)
   The HB register is set to contain the value of the H register (after the
   recovery). If the imp record referred to by the CI register (after the
   recovery) is an implication record, the CE register is set to the
   corresponding closure environment ("CE" field in that impl point). Finally,
   the NCL (next clause) field of the choice point is updated to label.

trust_me n

   This instruction precedes the code for the last clause for a predicate
   whose definition (in this ``module'') cannot be an extension of
   another definition.
   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point.
   First, the values stored in the current top choice point for data registers
   A1 to An are backed up to those registers. Then the values in the
   UC, E, LL, CP, I, B0, H and CI fields of the choice point is set into
   the corresponding registers. (We assume that the procedure that initiates
   backtracking would have unwound the trail and set the TR register already.)
   If the imp record referred to by the CI register (after the
   recovery) is an implication record, the CE register is set to the
   corresponding closure environment ("CE" field in that impl point).
   Then the B register is set to the value in the B field of the this choice
   point. After that, the HB register is set to the value stored in the H field
   of the choice point currently referred to by B.
   Finally, the TOS register is set to the top imp/choice point on the
   stack after "poping" this one.

try n, label

   This instruction precedes the code for the first clause defining a
   predicate defined by more than one clause and is responsible for
   setting up a choice point record.
   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point, and label is the address
   to the code area to which computation should proceed.
   First, the current stack top is determined by using the TOS and E registers.
   In the situation that the current top env record resides in a higher address
   than the current top choice/imp record, the number of living arguments
   in that top-level env record is determined by the argument of the "call"
   instructions immediately previous to the instruction pointed by the CP
   register. Stack overflow is checked against the size of the choice point
   with n argument cells. Then the value of data registers A1 ... An is
   copied into the argument cells of the choice point, and the values of
   the registers UC, E, CP, I, CI, LL, B, B0, H, TR and the address of the
   instruction next to this one are stored into relevant fields of the new
   choice point. The register B is updated to refer to the newly created choice
   point, the value of the H register (top of heap) is copied into HB, and the
   register TOS is set to the current top of stack. Then computation proceeds
   to the instruction at the address label.

retry n, label

   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point, and label is address to the
   code area where the next alternative definition of the predicate resides,
   and label is the address to the code area to which computation should
   proceed.
   First, the values stored in the current top choice point for data registers
   A1 to An are backed up to those registers. Then the values in the
   UC, E, LL, CP, I, B0, H and CI fields of the choice point is set into
   the corresponding registers. (We assume that the procedure that initiates
   backtracking would have unwound the trail and set the TR register already.)
   The HB register is set to contain the value of the H register (after the
   recovery). If the imp record referred to by the CI register (after the
   recovery) is an implication record, the CE register is set to the
   corresponding closure environment ("CE" field in that impl point). Finally,
   the NCL (next clause) field of the choice point is updated to the
   instruction next to this one, and computation proceeds to the instruction
   at the address label.

trust n, label

   This instruction precedes the code for the last clause for a predicate
   whose definition (in this ``module'') cannot be an extension of
   another definition.
   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point, and label is the address
   to the code area to which computation should proceed.
   First, the values stored in the current top choice point for data registers
   A1 to An are backed up to those registers. Then the values in the
   UC, E, LL, CP, I, B0, H and CI fields of the choice point is set into
   the corresponding registers. (We assume that the procedure that initiates
   backtracking would have unwound the trail and set the TR register already.)
   If the imp record referred to by the CI register (after the
   recovery) is an implication record, the CE register is set to the
   corresponding closure environment ("CE" field in that impl point).
   Then the B register is set to the value in the B field of the this choice
   point. After that, the HB register is set to the value stored in the H field
   of the choice point currently referred to by B.
   Finally, the TOS register is set to the top imp/choice point on the
   stack after "poping" this one, and computation proceeds to the instruction
   at address label.

trust_ext n, m

   This instruction is the last in the code for a predicate whose
   definition could be an extension of an existing definition.
   The argument n is the number of data registers (A1 ... An) needs to be
   restored from the current top choice point, and m is the index to the
   the next clause table referred to by the continuate program context field
   in the current choice point for an alternative definition of the predicate
   added dynamically.
   If the mth field of the next clause table referred to by the continuate
   program context field in the current choice point is a fail instruction,
   the B register is backed up from the current choice point, and the TOS
   register is set to the top imp/choice point on the stack after "poping"
   this one. The P register is set to refer to the fall instruction and then
   backtracking is initiated.
   Otherwise, the values stored in the current top choice point for data
   registers A1 to An are backed up to those registers. Then the values in the
   UC, E, LL, CP, I, B0 and H fields of the choice point are set into
   the corresponding registers. (We assume that the procedure that initiates
   backtracking would have unwound the trail and set the TR register already.)
   The P register is set to the next clause found from the next clause table,
   and the CI register is set to the associated program context. If it is an
   implication record the CE register is set to the corresponding closure
   environment ("CE" field in that impl point).
   Then the B register is set to the value in the B field of the this choice
   point. After that, the HB register is set to the value stored in the H field
   of the choice point currently referred to by B.
   Finally, the TOS register is set to the top imp/choice point on the
   stack after "poping" this one.

try_else n, label1, label2

   This instruction is the same as try_me_else except that computation proceeds
   to the instruction at address label2.

retry_else n, label1, label2

   Same as retry except that computation proceeds to the instruction at address
   label2.

branch label

   This instruction is for the compilation of disjunctive goals. Computation
   proceeds to the instruction at the address label.



              VII. INDEXING INSTRUCTIONS
              ==========================

switch_on_term V,C,L,BV

   Jump to the instruction labelled, respectively V, C, L, or BV,
   depending on whether the (normalized, dereferenced) value of
   argument register A1 is a flexible term, a rigid term with a constant
   (integer, float, string, nil, stream) as head, a non-empty list (list cons)
   or a rigid term with a bound variable as its head.


switch_on_constant n,tab_addr

   This instruction is encountered when the dereferenced value of the
   register A1 is known to be a rigid term with a constant as its head.
   In this case, a hash table of size n with starting location tab_addr is
   looked up for a match. If one is found, a branch is executed to the
   instruction address associated with it. If no match is found,
   backtracking is initiated.


switch_on_bvar n,tab_addr

   The dereferenced value of register A1 is known to be a rigid term with
   a bound variable as its head. Let the difference between the binder
   length and the bound variable index of the term be m (decided in the
   previous switch_on_term instruction). tab_addr is the address
   of a table of size m pairing natural numbers with code locations. If a
   match is found in tab_addr to m, this yields the address of the next
   instruction.  Otherwise backtracking is initiated. (The argument n is
   the max number that m could take. It is used to compare with m, and
   if m is larger, then backtracking can be decided immediately without a
   searching through the branch table.)


switch_on_reg i,L1,L2

   Look up the ith next clause entry in the implication/import point
   record pointed to by CI. If this happens to be the address of the
   failing procedure, branch to L2. Otherwise branch to L1.


              VIII. CUT INSTRUCTIONS
              ======================

   neck_cut

   Discard the choice points up to the one pointed to by the B0 register
   by setting the B register to this value and resetting the HB register
   to H field of the choice/branch point record now pointed to by the B
   register. The trail can now be shrunk to reflect the fact that
   bindings between the new HB and top of the heap need not be undone on
   backtracking and similarly between the new B and the top of stack.
   Execution continues with the next instruction.


   get_level Yn

   Set Yn to the current value of the B0 register. Continue execution
   with the next instruction.


   put_level Yn

   Set the B0 register to the value in environment variable Yn. Continue
   execution with the next instruction. (This instruction is a hack for
   realizing the right pruning action in interpreted goals with cut.)


   cut Yn

   Discard all the choice points created after that pointed to by Yn by a
   process similar to that carried out with neck_cut, except using Yn
   instead if B0. Continue execution with the next instruction.


            IX. MISCELLANEOUS INSTRUCTIONS
            ==============================

   ***CHANGE
   call_builtin n, i

   Invoke the ith builtin instruction in the dispatch table.
   The compiler will ensure that argument registers are set up the way needed
   prior to this instruction.
   n in this instruction is the number of permanent variables to be retained
   in the continuation environment. This is accessed as an offset by the
   instructions allocate, and try_me_else.

   ***CHANGE
   builtin n, i

   [Set CI to the CIE field of the current environment, if it exist.
    If CI refers to a implication record, set CE to the clause environment field
    stored in the impl record referred to by CI.
    Invoke the ith builtin instruction in the dispatch table.
    n in this instruction is the number of permanent variables to be retained
    in the continuation environment. This is accessed as an offset by the
    instructions allocate, and try_me_else.
   ]


   stop

   Exit the simulator, returning to the top level.


   halt

   Terminate the lambdaProlog session.


   fail

   Go to last backtrack (choice) point.
