\section{C-code Representation of Li-code Instructions}
\label{instructions}

When the {\em type} of a source operand, {\tt X}, is known to be
scalar, it is often referred to below as {\tt FAMILY(X)}.\footnote{
Where {\tt FAMILY} is one of {\tt INTEGER}, {\tt BOOLEAN}, {\tt REAL},
{\tt ORDERED{\uline}ENUMERATION}.}
In that case, as indicated in the following definitions, a reference
to it is expanded as either its known constant value or the value of
the corresponding variable (See the definition of {\tt SCALAR} in
Appendix~\ref{representation}).\footnote{
A {\tt SCALAR} or {\tt real} qualifier always has a known constant
value.}

\begin{verbatim}
INTEGER(X) ::= <constant operand value of X> |
               VALCELL(X).integer

BOOLEAN(X) ::= <constant operand value of X> |
               VALCELL(X).boolean

REAL(X) ::= <constant operand value of X> |
            *VALCELL(X).real

ORDERED_ENUMERATION(X) ::= <constant operand value of X> |
                           VALCELL(X).ord_enum



Licode         Arguments              Qualifier


UBIQUITOUS

move           dst src

    DISCARD(dst)
    *DOTS(dst) = *DOTS(src);
    TSDR(src) = & dr_bottom;


copy           dst src

    COPY(dst, src)

discard        dst

    DISCARD(dst)
    TSDR(dst) = & dr_bottom;

equal          dst src1 src2          

    VALCELL(dst).boolean = EQUAL(src1, src2);
    TSDR(dst) = & dr_boolean;

notequal       dst src1 src2          

    VALCELL(dst).boolean = ! EQUAL(src1, src2);
    TSDR(dst) = & dr_boolean;


NOMINAL

unique         dst                    

    ch_returncode = chf_unique(DOTS(dst));
    if (ch_returncode != Normal)
      goto ch_raise_exception;

BOOLEAN

boolean        dst                    boolean

    VALCELL(dst).boolean = BOOLEAN(qualifier);        /* 0 or -1 */
    TSDR(dst) = & dr_boolean;

and            dst src1 src2

    VALCELL(dst).boolean = BOOLEAN(src1) & BOOLEAN(src2);
    TSDR(dst) = & dr_boolean;

or             dst src1 src2          

    VALCELL(dst).boolean = BOOLEAN(src1) | BOOLEAN(src2);
    TSDR(dst) = & dr_boolean;

not            dst src                

    VALCELL(dst).boolean = ! BOOLEAN(src1);
    TSDR(dst) = & dr_boolean;

INTEGER

ilit           dst                    integer            

    VALCELL(dst).integer = INTEGER(qualifier);
    TSDR(dst) = & dr_integer;

iadd           dst src1 src2

    if (not chf_iadd(DOTS(dst), INTEGER(src1), INTEGER(src2)))
      goto ch_depletion;

isubtract      dst src1 src2     

    if (not chf_isubtract(DOTS(dst), INTEGER(src1), INTEGER(src2)))
      goto ch_depletion;

imultiply      dst src1 src2     

    if (not chf_imultiply(DOTS(dst), INTEGER(src1), INTEGER(src2)))
      goto ch_depletion;

idivide        dst src1 src2     

    if (INTEGER(src2) = 0)
      goto ch_dividebyzero;
    VALCELL(dst).integer = INTEGER(src1) / INTEGER(src2)
    TSDR(dst) = & dr_integer;

irem           dst src1 src2     

    if (INTEGER(src2) = 0)
      goto ch_dividebyzero;
    ch_i = INTEGER(src1) % INTEGER(src2);
    if (signbit(ch_i) != signbit(INTEGER(src1)) & ch_i != 0)
      VALCELL(dst).integer = ch_i +
         (signbit(ch_i) != signbit(INTEGER(src2)) ?
           -INTEGER(src2).integer : INTEGER(src2));
    else
      VALCELL(dst).integer = ch_i;
    TSDR(dst) = & dr_integer;

imod           dst src1 src2     

    if (INTEGER(src2) = 0)
      goto ch_dividebyzero;
    ch_i = INTEGER(src1) % INTEGER(src2);
    if (signbit(ch_i) != signbit(INTEGER(src1)) & ch_i != 0)
      VALCELL(dst).integer = ch_i + INTEGER(src2));
    else
      VALCELL(dst).integer = ch_i;

igt            dst src1 src2     

    VALCELL(dst).boolean = (INTEGER(src1) > INTEGER(src2));
    TSDR(dst) = & dr_boolean;

ilt            dst src1 src2     

    VALCELL(dst).boolean = (INTEGER(src1) < INTEGER(src2));
    TSDR(dst) = & dr_boolean;

ige            dst src1 src2     

    VALCELL(dst).boolean = (INTEGER(src1) >= INTEGER(src2));
    TSDR(dst) = & dr_boolean;

ile            dst src1 src2     

    VALCELL(dst).boolean = (INTEGER(src1) <= INTEGER(src2));
    TSDR(dst) = & dr_boolean;

inegate        dst src

    VALCELL(dst).integer = - INTEGER(src);
    TSDR(dst) = & dr_integer;

icvt_enum      dst src                integer            

    if (INTEGER(src) < 0 !! INTEGER(src) >= INTEGER(qualifier))
      goto ch_range_error;
    VALCELL(dst).ord_enum = INTEGER(src);
    TSDR(dst) = & dr_ordenumeration;

icvt_real      dst src                

    if ((ch_real = new(dfd_real)) == nil)
      goto ch_depletion;
    VALCELL(dst).real = ch_real;
    *ch_real = INTEGER(src));
    TSDR(dst) = & dr_real;

REAL

rlit           dst                    real               

    if ((ch_real = new(dfd_real)) == nil)
      goto ch_depletion;
    VALCELL(dst).real = ch_real;
    *ch_real = REAL(qualifier);
    TSDR(dst) = & dr_real;

radd           dst src1 src2     

    if (not chf_radd(DOTS(dst), REAL(src1), REAL(src2)))
      goto ch_depletion;

rsubtract      dst src1 src2     

    if (not chf_rsubtract(DOTS(dst), REAL(src1), REAL(src2)))
      goto ch_depletion;

rmultiply      dst src1 src2     

    if (not chf_rmultiply(DOTS(dst), REAL(src1), REAL(src2)))
      goto ch_depletion;

rdivide        dst src1 src2     

    if (REAL(src2) = 0)
      goto ch_dividebyzero;
    if (not chf_rdivide(DOTS(dst), REAL(src1), REAL(src2)))
      goto ch_depletion;

rgt            dst src1 src2     

    VALCELL(dst).boolean = (REAL(src1) > REAL(src2));
    TSDR(dst) = & dr_boolean;

rlt            dst src1 src2     

    VALCELL(dst).boolean = (REAL(src1) < REAL(src2));
    TSDR(dst) = & dr_boolean;

rge            dst src1 src2     

    VALCELL(dst).boolean = (REAL(src1) >= REAL(src2));
    TSDR(dst) = & dr_boolean;

rle            dst src1 src2     

    VALCELL(dst).boolean = (REAL(src1) <= REAL(src2));
    TSDR(dst) = & dr_boolean;

rnegate        dst src


    if ((ch_real = new(dfd_real)) == nil)
      goto ch_depletion;
    VALCELL(dst).real = ch_real;
    *ch_real = - REAL(src);
    TSDR(dst) = & dr_real;

rcvt_int       dst src                

    if (REAL(src) <= REALINTLB !! REAL(src) >= REALINTUB)
      goto ch_range_error;
    VALCELL(dst).integer = REAL(src);
    TSDR(dst) = & dr_integer;

rcvt_enum      dst src                integer            

    if (REAL(src) < 0 || REAL(src) >= INTEGER(qualifier))
      goto ch_range_error;
    VALCELL(dst).enumeration = REAL(src);
    TSDR(dst) = & dr_ordenumeration;

ENUMERATION

enum_lit       dst                    integer            

    VALCELL(dst).enumeration = INTEGER(qualifier);
    TSDR(dst) = & dr_enumeration;


ORDERED ENUMERATION

ordenum_lit    dst                    integer            

    VALCELL(dst).ord_enum = INTEGER(qualifier);
    TSDR(dst) = & dr_ordenumeration;

oegt           dst src1 src2  

    VALCELL(dst).boolean = (ORDERED_ENUMERATION(src1) >
                            ORDERED_ENUMERATION(src2));
    TSDR(dst) = & dr_boolean;

   
oelt           dst src1 src2     

    VALCELL(dst).boolean = (ORDERED_ENUMERATION(src1) <
                            ORDERED_ENUMERATION(src2));
    TSDR(dst) = & dr_boolean;

oege           dst src1 src2     
 
    VALCELL(dst).boolean = (ORDERED_ENUMERATION(src1) >=
                            ORDERED_ENUMERATION(src2));
    TSDR(dst) = & dr_boolean;

oele           dst src1 src2     

    VALCELL(dst).boolean = (ORDERED_ENUMERATION(src1) <=
                            ORDERED_ENUMERATION(src2));
    TSDR(dst) = & dr_boolean;

oecvt_int      dst src                

    VALCELL(dst).integer = ORDERED_ENUMERATION(src);
    TSDR(dst) = & dr_integer;

oecvt_real     dst src                

    if ((ch_real = new(dfd_real)) == nil)
      goto ch_depletion;
    VALCELL(dst).real = ch_real;
    *ch_real = ORDERED_ENUMERATION(src);
    TSDR(dst) = & dr_real;

oeinitloop     dst                                                      **
oeloop         dst                    integer_pair                      **


RECORD

new_record     dst                    integer                           **


VARIANT

unite          dst src                integer                           **
dissolve       dst src                                                  **
reveal         dst                    integer        

    if (INTEGER(qualifier) != VALCELL(dst).variant->info.variant_case)
      goto ch_case_error;

hide           dst       

/* no-op */
             
case           dst src                

    VALCELL(dst).enumeration = VALCELL(src).variant->info.variant_case;
    TSDR(dst) = & dr_enumeration;

TABLE

size           dst src                

    VALCELL(dst).integer = VALCELL(src).table->size;
    TSDR(dst) = & dr_integer;


new_table      dst                    table_initializer                 **
insert         dst src                                                  **
merge          dst src                                                  **
initget        dst table              integer_pair                      **
endget         dst table                                                **
get_or_err     dst table                                                **
get_or_goto    dst table              label                             **
remove         dst src table                                            **
privatize      dst

    if (VALCELL(dst).table->refcount != 1) {
      ch_returncode = doCopyOnWrite(DOTS(dst));
      if (ch_returncode != Normal) goto ch_raise_exception;
    }

ORDERED TABLE

insert_at      dst src pos                                              **
merge_at       dst src pos                                              **
concat         dst src1 src2                                            **
position       dst src                                                  **
scan_position  dst src table                                            **
remove_at      dst src pos                                              **
lookup_at      dst src pos                                              **
lookup_at_or_goto dst src pos         label                             **

KEYED OR INDEXED TABLE

find           dst table src1 src2 ...  integer                         **
find_or_goto   dst table src1 src2 ...  integer_pair                    **
fremove        dst src table          integer                           **

INDEXED TABLE

initidxfind    dst table src1 src2 ...  integer                         **
idxfind_or_err dst table                                                **
idxfind_or_goto dst table             integer                           **
endidxfind     dst table                                                **

CHARACTER STRING TABLE

chs_lit        dst                    string

  if ( !chs_lit(& DOTS(dst), STRING(qualifier)) )
     goto raise_depletion;


POLYMORPHS

wrap           dst src                polymorph_info                    **
unwrap         dst src                polymorph_info                    **
inspect_poly   dst src                polymorph_info                    **
endinspect_poly dst                                                     **
type_of        dst src                                                  *
typestate_of   dst src                                                  *

PORTS

new_inport     dst

    if ((ch_inport = make_inport()) == nil)
      goto ch_depletion;
    fin_DATAREP(VALCELL(dst), F_DISCARD, sched);
    VALCELL(dst).inport = ch_inport;
    TSDR(dst) = & dr_inport;

connect        dst src     

    if (VALCELL(src).inport->refcount == MAXCOUNTER)
      goto ch_depletion;
    fin_DATAREP(VALCELL(dst), F_DISCARD, sched);
    VALCELL(src).inport->refcount++;
    VALCELL(dst).outport = VALCELL(src).inport;
    TSDR(dst) = & dr_outport;
             
send           dst src                                                  **
receive        dst src                                                  **
empty          dst src                 

    VALCELL(dst).boolean = (VALCELL(src).inport->info.inport.queue == nil);
    TSDR(dst) = & dr_boolean;

call           dst src1 src2 ...      typename                          **
return         dst

    if ((ch_caller = do_return(VALCELL(dst))) {
      if (not ch_caller->interpreter)
        ch_caller->ip++;
      sched->wakeup_proc(sched, ch_caller);
    }
    else
      rem_return(VALCELL(dst));
    TSDR(dst) = & dr_bottom;

return_exception dst                  user_exception

    if (ch_caller = do_return(VALCELL(dst)) {
      raise_user((dfd_integer) INTEGER(qualifier), ch_caller);
      sched->wakeup_proc(sched, ch_caller);
    }
    else
      rem_return_exception(DOTS(dst));
    TSDR(dst) = & dr_bottom;

PROCESSES

create         dst src                typename                          **
procedure      dst src                typename                          **
endprocess                                                              **

PROGRAMS

new_program    dst                    

    if ((ch_program = (pd_program *) new_record(PROGRAM_SIZE)) == nil)
      goto ch_depletion;
    ch_program->info.program_refcount = 1;
    fin_DATAREP(DOTS(dst), F_DISCARD, sched);
    VALCELL(dst).program = ch_program;
    TSDR(dst) = & dr_program;

link           dst                    integer                           **
currentprogram dst

    ch_program = sched->ready->prog;
    if (ch_program->info.program_refcount == MAXCOUNTER)
      goto ch_depletion;
    ch_program->info.program_refcount++;
    fin_DATAREP(VALCELL(dst), F_DISCARD, sched);
    VALCELL(dst).program = ch_program;
    TSDR(dst) = & dr_program;

prog_lit       dst                    program                           **
checkdefinitions dst                                                    *
typename       dst                    typename                          **
attributename  dst                    attributename                     **


CONSTRAINTS

assert         dst1 dst ...           constraint                        *
drop           dst1 dst2 ...          constraint                        *


CONTROL CONSTRUCTS

block                                 handler_list                      **
endblock                                                                **
exit                                  exitid                            **
select         e1 g1 e2 g2 ...        label_list                        **
jumpselect     index                  label_list                        **
branch                                label

    current->ip = INTEGER(label);
    return;

branch_false   dst                    label              

    if (! VALCELL(dst).boolean) {
      current->ip = INTEGER(label);
      return;
    }

branch_true    dst                    label              

    if (VALCELL(dst).boolean) {
      current->ip = INTEGER(label);
      return;
    }

raise                                 builtin_exception

    ch_returncode = INTEGER(qualifier);
    goto ch_raise_exception;

NONCONTROL CONSTRUCTS

noop               

/* no-op */

DEBUGGING

print          dst                    

    re_print(stderr, 0, DOTS(dst);
    fflush(stderr);

write          dst src                                                  **
read           dst src                                                  **


NEW

trace                                 integer                           **


* Unimplemented instructions.
** Representation omitted - see hermes/chcode/chdescriptors .
\end{verbatim}
