function interact(var processes :Value):boolean;

   function findIP(var IP :Value):boolean;        {IP - Input Process}
      function traverseIP(subIP :Value):boolean;
         function findOP(var OP :Value):boolean;  {OP - Output Process}
            function traverseOP(subOP :Value):boolean;

               function complementary:boolean;
                  var chan :integer; val :Value;
               begin {?can IP and OP interact?}
                     complementary := false {unless ...};
                     chan   := subIP^.chnl^.n;
                     if chan = subOP^.chnl^.n then {exchange msg}
                     begin complementary:=true;
                           if chan=2{input} then
                               {val:= ...} error('not impl  ')
                           else val:=defer(subOP^.msg,subOP^.pr);
                           {trace} if chan=1 then
                           {trace}    begin writeln; write(' output ') end
                           {trace} else write(' ch',chan:1, ' ');
                           {trace} ShowValue(val);
                           OP:=eval(subOP^.cont,subOP^.pr);
                           IP:=eval(subIP^.cont,
                                    bind(subIP^.msg^.id,val,subIP^.pr))
               end   end{complementary};

            begin {find an output process}
                  case subOP^.tag of
                  inprocessval:     traverseOP:=false;
                  outprocessval:    traverseOP:={?}complementary;
                  choiceprocessval: if traverseOP(subOP^.p1) then
                                       traverseOP:=true
                                    else traverseOP:=traverseOP(subOP^.p2);
                  stopprocessval:   traverseOP:=false; {can't interact!}
                  paraprocessval:   error('|| under |')
            end   end{traverseOP};

         begin if OP^.tag=paraprocessval then  {p1||p2}
                    if findOP(OP^.p1) then findOP:=true
                    else findOP:=findOP(OP^.p2)
               else findOP:=traverseOP(OP) {p1|p2, a->p, stop}
         end{findOP};

      begin {find an input process}
            case subIP^.tag of
            inprocessval:     traverseIP:=findOP(processes);
            outprocessval:    traverseIP:=false;
            choiceprocessval: if traverseIP(subIP^.p1) then traverseIP:=true
                              else traverseIP:=traverseIP(subIP^.p2);
            stopprocessval:   traverseIP:=false; {can't interact!}
            paraprocessval:   error('|| under |')
      end   end{traverseIP};

   begin if IP^.tag=paraprocessval then   {p1||p2}
              if findIP(IP^.p1) then findIP:=true
              else findIP:=findIP(IP^.p2)
         else findIP:=traverseIP(IP)  {p1|p2, a->p, stop}
   end{findIP};

begin interact := findIP(processes)
end {interact};

{\fB Find two Processes that can Interact:  (ch?x->...)||(ch!e->...) \fP}
{ Do not remove: This program is released under Gnu `copyleft' General }
{ Public Licence (GPL)    -- L.Allison, CSSE, Monash Uni., .au, 7/2004 }
