{Portable Prolog Unification Module}

{Comment Flags: VAX APM EMAS}

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

%external %INTEGER %spec V,
                         X,
                         TR,
                         GLB0,
                         LCL0,
                         SKEL0,
                         VV1,
                         VV,
                         V1

%external %routine %spec Check V1 (%integer P)

{-G UNIFY-}

{Unifies term TA with global frame GA and local frame V}
{with term TB with global frame GB and local frame X.}
{Result is 1 if unification succeeds and 0 otherwise}

%external %integer %function G Unify (%INTEGER TA,GA,TB,GB)

   %INTEGER ARITY,A,B,PA,PB
   
   {INSERT OFFSET}

   %integer %function Insert Offset (%integer A, Local Frame, Global Frame)
      %if A >= LCL0 %start
         %result = (A - LCL0) + Local Frame
      %else
Print String ("Help Ma Boab in UNIFY") %and New Line %and %stop %if A < GLB0
         %result = (A - GLB0) + Global Frame
      %finish
   %end {Insert Offset}

   {check same functor}
   A = INTEGER (TA)
   %RESULT=0 %IF INTEGER (TB) # A

   ARITY = BYTE INTEGER (A + 4)
      
   {main loop}
   
   %WHILE ARITY > 0 %CYCLE
      TA = TA + 4
      A = INTEGER (TA)

      -> UNFRX %IF A >= GLB0

      TB = TB + 4
      B = INTEGER (TB)

      %IF B < GLB0 %START
         %IF A >= SKEL0 %START
            %RESULT = 0 %IF B < SKEL0 %OR %c
                            GUNIFY (A, GA, B, GB) = 0
            -> LOOP
         %FINISH
         %IF B # A %THEN %c
         %RESULT=0 %c
                 %ELSE ->LOOP
      %FINISH

{*      %IF B>=LCL0 %THEN PB=B&M+X %c
{*                  %ELSE PB=B&M+GB

      PB = Insert Offset (B, X, GB)

      B = INTEGER (PB)
      PB = B %AND B = INTEGER (B) %WHILE B >= GLB0    {Deref}
      %IF B = 0 %START
         %IF A<SKEL0 %start 
            INTEGER(PB)=A
         %ELSE
            Check V1 (8)
            INTEGER(PB)=V1
            INTEGER(V1)=A
            INTEGER(V1+4)=GA
            V1=V1+8
         %FINISH
         ->TR B
      %FINISH

      %IF B >= SKEL0 %START
         %RESULT = 0 %IF A < SKEL0 %OR %c
                         GUNIFY (A, GA, B, INTEGER (PB + 4))=0
         -> LOOP
      %FINISH
      %IF B # A %THEN %c
      %RESULT = 0 %c
               %ELSE ->LOOP
      
   UNFRX:
{*      %IF A>=LCL0 %THEN PA=A&M+V %c
{*                  %ELSE PA=A&M+GA

      PA = Insert Offset (A, V, GA)

      A = INTEGER (PA)
      PA = A %AND A = INTEGER (A) %WHILE A >= GLB0

      TB = TB + 4
      B = INTEGER(TB)
      ->UNFRR %IF B >= GLB0

      %IF B < SKEL0 %START
         INTEGER (PA) = B %AND -> TR A %IF A=0
         %IF A=B %THEN -> LOOP %c
                 %ELSE %RESULT=0
      %FINISH
      %IF A = 0 %START
         INTEGER (PA) = V1
         Check V1 (8)
         INTEGER (V1) = B
         INTEGER (V1 + 4) = GB
         V1 = V1 + 8
         -> TR A
      %FINISH
      %IF A < SKEL0 %OR %c
          GUNIFY (A, INTEGER (PA + 4), B, GB) = 0 %THEN %RESULT = 0 %C
                                         %ELSE ->LOOP
      
   UNFRR:

{*      %IF B>=LCL0 %THEN PB=B&M+X %c
{*                  %ELSE PB=B&M+GB

      PB = Insert Offset (B, X, GB)

      B = INTEGER (PB)

      PB = B %AND B = INTEGER (B) %WHILE B >= GLB0

      ->LOOP %IF PA = PB

      %IF B=0 %START
         %IF A=0 %START
            %IF PA > PB %start
               INTEGER (PA) = PB 
               ->TR A
            %else
               INTEGER (PB)=PA 
               ->TR B
            %finish
         %FINISH
         %IF A >= SKEL0 %THEN INTEGER(PB)=PA %c
                        %ELSE INTEGER(PB)=A
         ->TR B
      %FINISH
      
      %IF A=0 %START
         %IF B >= SKEL0 %THEN INTEGER (PA) = PB %c
                        %ELSE INTEGER (PA) = B
         ->TR A
      %FINISH
      
      %IF A < SKEL0 %START
         %IF A = B %THEN -> LOOP %c
                   %ELSE %RESULT=0
      %FINISH
      %result = 0 %IF B < SKEL0 %OR %c
                      GUNIFY (A, INTEGER(PA + 4), B, INTEGER(PB + 4)) = 0
      -> LOOP
      
   TR A:
      INTEGER (TR) = PA %AND TR = TR + 4 %IF PA < VV1 %OR %c
                                             LCL0 <= PA < VV
      -> LOOP
      
   TR B:
      INTEGER (TR) = PB %AND TR = TR + 4 %IF PB < VV1 %OR %c
                                             LCL0 <= PB < VV
      
   LOOP:
      ARITY = ARITY - 1
   %REPEAT
      
   %RESULT=1
%END

%ENDOFFILE
