{Portable Prolog Integer Expression Munger}

{-INTV-}

{                                                Lawrence}
{                                                Updated: 22 January 82}
{                                                Richard}
{                                                Again:   February 84}

{Comment Flags: VAX EMAS APM I77}
{All systems need I77 but EMAS}

{This recursive function traverses the term producing an integer value.}
{  T is the term (derefed and unwrapped),}
{  G is the associated global frame (if T is a Skel)}

!VAX! %include "Prolog_Interpreter:GDec.Inc"
!EMAS!%include "ECSC56.GDec#Inc"
{APM} %include "IPlog:GDec.Inc"

%external %INTEGER %spec HEAPUSED,SKEL0,GLB0,ATOMNIL,LISTFUNC
%EXTERNALINTEGERFNSPEC VVALUE(%INTEGER V,%INTEGERNAME F)
%EXTERNALINTEGERFNSPEC ARGV(%INTEGER A,F,%INTEGERNAME AF)
%EXTERNALROUTINE %SPEC SIGNAL PROLOG EVENT(%INTEGER N)

%external %integer %function Int Val(%integer P)

   
   %INTEGER F
   
   {-INTV-}
   
   %INTEGER %function INTV(%INTEGER T, G)
      %INTEGER B, F, N, I1, I2
      %SWITCH S (1:12)
   
      {UndefCell}
      -> ILG OP %IF T >= GLB0 %AND %c
                    INTEGER (T) = 0

      {Integer (or Reference)}
      %IF T <0  %START
         ->ILG OP %IF T&INT0 # INT0               {throw out Reference}
         T = T&(\INT0) %IF T&SIGN=0;            {extract integer}
         %RESULT=T
      %FINISH

      {Atom or Skel}
      {grab expression info field}
      B = BYTE INTEGER (INTEGER (T) + FLGS OF FE)&15
      ->ILGOP %IF B=0

      {Atom}
      %IF T<SKEL0 %START
         ->ILGOP %IF B>=3
         %RESULT = HEAPUSED %IF B = 2
!EMAS!   %RESULT = INT PT (CPU TIME*1000.0)
{I77}    %result = CPU Time
      %FINISH

      {Skel   (first check for [_])}
      %IF INTEGER(T)=LISTFUNC %START
         ->ILGOP %UNLESS ARGV(T+8,G,F)=ATOMNIL
         %RESULT=INTV(ARGV(T+4,G,F),F)
      %FINISH

      {Skel   (general case)}
      ->ILGOP %IF B>12
      N=BYTEINTEGER(INTEGER(T)+4)      {grab arity}
      %WHILE N>0 %CYCLE
         I1=I2
         T=T+4
         N=N-1
         I2=INTV(ARGV(T,G,F),F)
      %REPEAT
      ->S(B)
   
   ILGOP: 
      SIGNAL PROLOG EVENT(4)     {error in arithmetic expression}

   S(1): %RESULT=I2
   S(2): %RESULT=-I2
   S(3): %RESULT=I1+I2
   S(4): %RESULT=I1-I2
   S(5): %RESULT=I1*I2
   S(6): %RESULT=I1//I2
   S(7): %RESULT=I1-(I1//I2)*I2
   S(8): %RESULT=I1&I2
   S(9): %RESULT=I1!I2
   S(10): %RESULT=\I2
   S(11): %RESULT=I1<<I2
   S(12): %RESULT=I1>>I2
   %END {Int V}
   
   {-MAIN CODE OF INT VAL-}
   
   %RESULT = INTV(VVALUE(P,F),F)
   
%END {Int Val}
   
%ENDOFFILE
