!Graham Toal - latest development version of SKIMPE 23/01/80 18.58
external integer array spec a(1 : 500)

external integer array spec taglink(0 : 255)

external integer array spec tag(1 : 512)

external string (5) array spec display(0 : 15)

external integer spec level, condflag, expropt
!-----------------------------------------------------------------------
external string (7) fn spec s(integer i)
external string (255) fn spec strint(integer n, p)
external string (8) fn spec strhex(integer n)
external routine spec fault(string (63) s)
external string (255) fn spec name(integer ident)
external routine spec dump(string (7) lab, op, reg, addr)
external integer fn spec getwork
external routine spec returnwork(integer work)
external routine spec proc(integer ap)
external routine spec array(integer ap)
external integer fn spec getcoti(integer const)
!-----------------------------------------------------------------------
const integer proceedure = -1, arrayelement = -2, scalar = -3, unary = 11, c
  complex = -2, terminal = 0, true = 1, load = 0, exp = 6, sub = 10, c
  mult = 8, div = 7, shr = 2, shl = 1, cmp = 13
!------------------------------------------------------------------------
external integer fn intstr(string (6) val)
   integer i, total
   total = 0
   for i = 1, 1, length(val) cycle
      total = total * 10 + charno(val, i) - '0'
   repeat
   result = total
end
external routine expr(integer exprp)
   integer fn spec totree(integer exprp)
   routine spec evaluate(integer exprp)
   routine spec opn(integer op, ptr)
   integer array tree(1 : 64)
   integer treep, treenode, treenode1, treenode2, testp, expr1p, expr2p, compp, i, j, l
   const integer array reversecomp(1 : 6) = 1, 2, 5, 6, 3, 4

   treep = 1
   if condflag = 0 then treenode = totree(exprp) else start
      condflag = 0
      testp = exprp
      ! for <test>=<expr><comp><expr>
      expr1p = a(testp + 1)
      compp = a(testp + 2)
      expr2p = a(testp + 3)
      treenode1 = totree(expr1p)
      treenode2 = totree(expr2p)
      tree(treep) = 13
      ! CMP
      if tree(treenode1) = -4 then start
         a(compp) = reversecomp(a(compp))
         tree(treep + 1) = treenode2
         tree(treep + 2) = treenode1
      finish else start
         tree(treep + 1) = treenode1
         tree(treep + 2) = treenode2
      finish
      treenode = treep
   finish
   if expropt = 1 then start
      newline
      if 0 < tree(treenode) <= 10 then l = treenode + 2 else l = treenode + 1
      j = 0
      for i = 1, 1, l cycle
         write(tree(i), 4)
         j = j + 5
         if i = treenode then printstring("*") and j = j + 1
         if tree(i) = -3 then i = i + 1 and printstring("  " . strhex(tree(i))) and j = j + 10
         if j > 70 then newline and j = 0
      repeat
      newlines(2)
   finish
   evaluate(treenode)
   return
   !-----------------------------------------------------------------------
   integer fn totree(integer exprp)
      ! create tree form of expression
      routine spec pseval(integer type, datum)
      integer array os(1 : 4), ps(1 : 5)
      ! operator & pseudo-evaluation stacks
      integer osp, psp, unaryp, operandp, exprrestp, opp, namep, actualp, ident, nametag
      const integer array prec(1 : 12) = 3, 3, 2, 1, 1, 3, 2, 2, 1, 1, 1, 4

      ! <<,>>,&,!!,!,**,/,*,+,-,-(unary),¬
      integer fn constop(integer op, val1)
         switch exec(1:10)
         integer res
         -> exec(op)
exec(1): 
         ! <<
         res = tree(val1 + 1) << tree(val1 + 3)
         -> cont
exec(2): 
         ! >>
         res = tree(val1 + 1) >> tree(val1 + 3)
         -> cont
exec(3): 
         ! &
         res = tree(val1 + 1) & tree(val1 + 3)
         -> cont
exec(4): 
         ! !!
         res = tree(val1 + 1) !! tree(val1 + 3)
         -> cont
exec(5): 
         ! !
         res = tree(val1 + 1) ! tree(val1 + 3)
         -> cont
exec(6): 
         ! **
         res = tree(val1 + 1) ¬¬ tree(val1 + 3)
         -> cont
exec(7): 
         ! /
         if tree(val1 + 3) = 0 then fault("DIVISION BY ZERO") and res = 0 and -> cont
         res = tree(val1 + 1) // tree(val1 + 3)
         -> cont
exec(8): 
         ! *
         res = tree(val1 + 1) * tree(val1 + 3)
         -> cont
exec(9): 
         ! +
         res = tree(val1 + 1) + tree(val1 + 3)
         -> cont
exec(10): 
         ! -
         res = tree(val1 + 1) - tree(val1 + 3)
cont: 
         result = res
      end
      unaryp = a(exprp + 1)
      operandp = a(exprp + 2)
      exprrestp = a(exprp + 3)
      if a(unaryp) <= 2 then os(1) = a(unaryp) + 10 and osp = 1 else osp = 0
      psp = 0
      cycle 
         ! for each operand
         if a(operandp) = 1 then start
            ! <name><actual>
            namep = a(operandp + 1)
            actualp = a(operandp + 2)
            ident = a(namep + 1)
            if taglink(ident) = 0 then start
               !?        fault(name(ident)." NOT DECLARED")
               pseval(-3, -ident)
               ! pseval dummy tag
            finish else start
               nametag = tag(taglink(ident))
               if nametag >> 28 <= 1 then start
                  ! scalar variable
                  if a(actualp) = 1 then start
                     fault("SCALAR " . name(ident) . " HAS PARAMETER")
                     pseval(-3, 0)
                  finish else pseval(-3, nametag)
               finish else start
                  if nametag >> 28 <= 3 then pseval(-2, operandp) else start
                     if nametag >> 24 & 16_F = 0 then start
                        fault("ROUTINE NAME " . name(ident) . " IN EXPRESSION")
                        pseval(-3, 0)
                     finish else pseval(-1, operandp)
                  finish
               finish
            finish
         finish else start
            if a(operandp) = 2 then pseval(-4, a(a(operandp + 1) + 1)) c
            else psp = psp + 1 and ps(psp) = totree(a(operandp + 1))
         finish
         if a(exprrestp) = 2 then exit
         ! no more operands
         opp = a(exprrestp + 1)
         operandp = a(exprrestp + 2)
         exprrestp = a(exprrestp + 3)
         pseval(os(osp), 0) and osp = osp - 1 while osp > 0 and prec(a(opp)) <= prec(os(osp))
         ! unstack while prec(new op)<=
         osp = osp + 1
         ! stack new operator
         os(osp) = a(opp)
      repeat
      pseval(os(osp), 0) and osp = osp - 1 while osp > 0
      ! unstack rest
      result = ps(1)
      !-----------------------------------------------------------------------
      routine pseval(integer type, datum)
         routine spec store(integer t)
         integer nodep, temp
         nodep = treep
         store(type)
         if type > 0 then start
            ! operator
            if type > 10 then start
               store(ps(psp))
            finish else start
               if tree(ps(psp - 1)) = -4 and tree(ps(psp)) = -4 c
                 and ps(psp - 1) = treep - 5 and ps(psp) = treep - 3 start
                  temp = constop(type, treep - 5)
                  if temp >= 0 then start
                     treep = ps(psp - 1) + 2
                     tree(ps(psp - 1) + 1) = temp
                     psp = psp - 1
                     ps(psp) = treep - 2
                     return
                  finish else -> over
               finish else start
over: 
                  store(ps(psp - 1))
                  store(ps(psp))
                  psp = psp - 1
               finish
            finish
         finish else store(datum) and psp = psp + 1
         ps(psp) = nodep
         !-----------------------------------------------------------------------
         routine store(integer t)
            if treep > 64 then fault("EXPRESSION TOO LONG") and stop
            tree(treep) = t
            treep = treep + 1
         end
      end
   end
   !-----------------------------------------------------------------------
   const string (3) array strop(0 : 13) = "LD", "SHL", "SHR", "AND", "EOR", c
     "OR", "EXP", "DIV", "MUL", "ADD", "SUB", "NEG", "COM", "CMP"

   const integer array args(0 : 13) = 1, 0, 0, 1, 1, 1, 0, 0, -1, 1, 1, 1, 1, 1

   const integer array commut(0 : 13) = 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1

   routine doop(integer op, string (10) val)
      string (6) const
      integer value
      switch clever(0:13)
      ! B op VAL
      if args(op) # 1 start
         if val -> ("#") . const then start
            value = intstr(const)
            -> clever(op)
clever(mult): 
            if value = 2 or value = 4 then start
               dump("", "ASL", "B", "") and value = value >> 1 while value # 1
            finish
            return if value = 1
            -> eval
clever(div): 
            if value = 2 or value = 4 then start
               dump("", "ASR", "B", "") and value = value >> 1 while value # 1
            finish
            return if value = 1
            -> eval
clever(exp): 
            if value = 2 then start
               dump("", "TFR", "", "B,A")
               dump("", "MUL", "", "")
               return
            finish else -> eval
clever(shl): 
            if 1 <= value <= 2 then start
               dump("", "LSL", "B", "") and value = value - 1 until value = 0
            finish
            return unless 3 <= value <= 7
            -> eval
clever(shr): 
            if 1 <= value <= 2 then start
               dump("", "LSR", "B", "") and value = value - 1 until value = 0
            finish
            return unless 3 <= value <= 7
            -> eval
            clever(*):

eval: 
         finish
         dump("", "LD", "A", val)
         if args(op) < 0 start
            dump("", "MUL", "", "")
         finish else start
            dump("", "LBSR", "", strop(op))
         finish
      finish else start
         dump("", strop(op), "B", val)
      finish
   end
   routine opn(integer op, nodep)
      integer type, basep, varp, disp
      string (4) base
      type = tree(nodep)
      if type > scalar then fault("*BUG")
      varp = tree(nodep + 1)
      if varp < 0 then start
         doop(op, name(-varp))
      finish else start
         if type = scalar start
            basep = varp >> 16 & 16_F
            base = display(basep)
            base = ",Y" if basep = level
            base = ",X" if basep = 1
            disp = varp & 16_FFFF
            if varp >> 28 = 1 start
               if basep = level # 1 start
                  doop(op, "[" . "-" . s(disp) . base . "]")
               finish else if basep # level # 1 start
                  dump("", "PSH", "U", "A,B")
                  dump("", "LD", "D", base)
                  dump("", "ADD", "D", "#" . s(disp))
                  dump("", "ST", "D", "0,X")
                  dump("", "PUL", "U", "A,B")
                  doop(op, "[0,X]")
               finish
               return
            finish
            if basep = level or basep = 1 start
               doop(op, "-" . s(disp) . base)
            finish else start
               dump("", "PSH", "U", "A,B")
               dump("", "LD", "D", base)
               dump("", "ADD", "D", "#" . s(disp))
               dump("", "ST", "D", "0,X")
               dump("", "PUL", "U", "A,B")
               doop(op, "[0,X]")
            finish
         finish else start
            doop(op, "#" . s(varp))
         finish
      finish
   end
   routine regop(integer op, string (7) r1, r2)
      ! R1 op R2
      if args(op) # 1 start
         if args(op) < 0 start
            dump("", "MUL", "", "")
         finish else start
            dump("", "LBSR", "", strop(op))
         finish
      finish else start
         dump("", strop(op), r1, r2)
      finish
   end
   routine loadb(integer nodep)
      integer type, datum
      type = tree(nodep)
      datum = tree(nodep + 1)
      if type = proceedure start
         proc(datum)
         return
      finish
      if type = arrayelement start
         array(datum)
         dump("", "LD", "B", "[0,X]")
         return
      finish
      opn(load, nodep)
   end
   routine evaluate(integer nodep)
      integer op, opd1p, opd2p
      if tree(nodep) <= terminal start
         loadb(nodep)
         return
      finish
      op = tree(nodep)
      opd1p = tree(nodep + 1)
      if cmp > op >= unary start
         !
         ! TEST FOR CONST NODE HERE
         !
         evaluate(opd1p)
         dump("", strop(op), "B", "")
         return
      finish
      opd2p = tree(nodep + 2)
      !
      ! TEST FOR BOTH NODES CONST HERE
      !
      if tree(opd1p) >= complex start
         if tree(opd2p) >= complex start
            evaluate(opd2p)
            dump("", "PSH", "U", "B")
            evaluate(opd1p)
            doop(op, ",U+")
         finish else start
            evaluate(opd1p)
            opn(op, opd2p)
         finish
      finish else start
         if tree(opd2p) >= complex start
            evaluate(opd2p)
            if commut(op) = true start
               opn(op, opd1p)
               return
            finish
            if args(op) <= 0 start
               dump("", "TFR", "", "B,A")
               opn(load, opd1p)
               regop(op, "B", "A")
            finish else start
               dump("", "PSH", "U", "B")
               opn(load, opd1p)
               doop(op, ",U+")
            finish
         finish else start
            opn(load, opd1p)
            opn(op, opd2p)
         finish
      finish
   end
end
end of file