%begin; ! 82S101 FPLA Simulator (Fast version)

%externalintegerfnspec switches
%externalroutinespec display(%integer a)

%predicate attention
%integer z
  *16_e1fb; *16_4000; *0
  z=integer(0); %falseif z=0
  %stopif switches=16_76
  %true
%end

%integerarray amask1,amask0(0:47),omask(0:23)
%integer inv

%routine moan(%integer offender,%string(63)would have liked)
  selectoutput(0)
  printstring("Encountered '"); printsymbol(offender)
  printstring("' when expecting "); printstring(would have liked)
  newline; %stop
%end

%routine read matrices
%integerarray and(0:15,0:47),or(0:47,0:7),invert(0:7)
%integer i,j,k,sym
%integername w
  selectinput(1)
  invert(i)=0 %for i=0,1,7; inv=0
  %cycle
    readsymbol(k); %signal 9 %if k='*'
    moan(k,"& or ! or O or *") %unless k='&' %or k='!' %or k&95='O'
    readsymbol(sym); moan(sym,"NL") %unless sym=nl
    %for i=0,1,47 %cycle
      %for j=0,1,15 %cycle
        %exitif j=8 %and k#'&'
        readsymbol(sym)
        %if sym='0' %start
          sym=2
        %finishelseif sym='1' %start
          sym=1
        %finishelseif sym='?' %start
          sym=0
        %finishelseif sym&95='X' %start
          sym=3
        %finishelse moan(sym,"0 or 1 or ? or X")
        %if k='&' %start
          and(j,i)=sym
        %finishelseif k='!' %start
          or(i,j)=sym&1
        %else
          invert(j)=1 %and inv=inv!!(1<<j) %if sym=2
        %finish
      %repeat
      readsymbol(sym); moan(sym,"NL") %unless sym=nl
      %exitif k&95='O'
    %repeat
    %if k='&' %start
      %for i=0,1,47 %cycle
        amask1(i)=0; amask0(i)=0
        %for j=0,1,15 %cycle
          k=and(j,i)
          amask1(i)=amask1(i)+1<<j %if k&1#0
          amask0(i)=amask0(i)+1<<j %if k&2#0
        %repeat
      %repeat
    %elseif k='!' %start
      omask(i)=0 %for i=0,1,23
      %for i=0,1,47 %cycle
        %for j=0,1,7 %cycle
          w==omask(j+j+j+i>>4)
          w=w!!1<<(i&15) %if or(i,j)#0
        %repeat
      %repeat
    %finish
  %repeat
%end

%routine simulate
%integer input,output,i,j,k

  %integerfn function(%integer input)
  %integerarray term(0:2)
  %integername w
  %integer i,j,o
    term(i)=0 %for i=0,1,2
    %for i=0,1,47 %cycle
      %if input&amask0(i) ! (\input)&amask1(i) # 0 %start
        w==term(i>>4); w=w!!1<<(i&15)
      %finish
    %repeat
    o=0
    %for i=0,1,7 %cycle
      j=i*3
      %if omask(j)  &term(0)#0 %c
      %or omask(j+1)&term(1)#0 %c
      %or omask(j+2)&term(2)#0 %then o=o!!1<<i
    %repeat
    %result=o!!inv
  %end

  display(-1); display(-1); input=switches
  %while input=switches %cycle; %repeat

  %cycle
    input=switches; display(input); display(-1)
    output=function(input); display(-1); display(output)
    %if attention %start
      newline; printstring("Inputs: ")
      printsymbol(input>>i&1+'0') %for i=15,-1,0
      newline; printstring("Outputs: ")
      printsymbol(output>>i&1+'0') %for i=7,-1,0
      newline
    %finish
  %repeat
%end

%onevent 9 %start
  simulate
%finish

read matrices

%endofprogram
