
/*
  function expandfmac(int f) as string
  ====================================
  if (tranpass=1)or(compact<>0)
    exit function
  endif
  int a=1, c=0
  string w1,w2
  w2=mrcso(f,1)
  do 'expand macro recursively
    a=instr(a,w2,"%")
    if a=0
      exit do
    endif
    a++
    w1=tword(w2,a)
    c=lookupm(w1)
    if c
      w2=left(w2,swd-2)+mrcso(c,1)+mid(w2,a)
    else
      ert=1003 : ers="unidentified macro in deff: %" + w1
      exit do
    endif
  loop
  return w2+cr
  end function
*/


  'CONVERT NUMERIC ACCUM TO STRING ACCUM
  '
  function numtostr(int typx,typa) as string
  '=========================================
  int c
  string wt
  if typa<0x80 'CONVERT NUM ACCUM TO STRING APPEND
    if jn
      c=43
    else
      c=1
    endif
    wt=cvtai(typa,0xc1) 'VAL TO STRING THEN APPEND
    if (c=43)or(isstr(typx)=0)or(parx>0)
      wt+=logas() 'LOG TEMP STRING FOR DELETION
    endif
    wt+=operi(c,0xc1,qeax)
  endif
  return wt
  end function
  '
  '
  '
  '
  '  #################
  ' #### EXPRESSIONS ##
  ' ##################
  ' ###
  ' ###
  ' ###          ###   ###
  ' ###            #   #
  ' ###########     # #    ####   ###
  ' ############     #     #   # #  
  ' ###########     # #    ####  #
  ' ###            #   #   #     #
  ' ###          ###   ### #     #
  ' ###
  ' ###
  ' ##################
  ' ###################
  '  #################
  '
  '
  '
  function express(string*s, int *i,*typx) as string
  ==================================================
  '
  int    a,b,c,d,e,f,m,r,n,v,irx,typa,typc,typi,typu,opo,cp,tp,clbr,cbj,qp,pid,ctop
  int    nsl,ofpu,noto,noth,savh,fxsq,ocp,omp,ojn,uex,usx,ixnd,ixnt,pargl
  int    xmode,xoffs,opcn,lazn,tya1,arcc,wmp,wvarf
  string w1,w2,w3,w4,w5,w6,wr,wrp,wt,wp,laz,lazt
  string ixns,wpfxa,wpfxi,wra,wri,wbx,memba,xcalc,wta
  string opsh,cpsh,wacc,waccp,hlex

  static int    po[8]
  static double dw=0x7fffffff
  '
  jmp fwd begin

  subroutine chareval
  ===================
  b=i
  c=i
  d=ascn
  if d=lbr
    c=i+1 : nextinstruct(s,c)
  endif
  'number literals sequence
  if isn(ascn)
    i=c
    w1="" 'byte accumulator
    c=0 'byte length counter
    do
      wordval(s,i,i)
      c+=m
      if m=1
        w2=hexb(dv)
      else
        w2=hexw(dv)
      endif
      w1+=w2
      select ascn
      case 44
        i++ : nextinstruct(s,i)
        continue do
      case 41
        if m
          i++ : skiplspace(s,i)
        endif
      case 48 to 57
        continue do
      case 0 to 47
        goto revertchr
      end select
      'literals termination
      w1+=hexw(0) 'terminating nulls
      wpfx+=stodat(w1,c) : wr=cpua
      typ=0xc0+m : typa=typ
      m=1
      exit subroutine 'goto cvtop
    loop
  endif
  revertchr:
  i=b : ascn=d : m=0 : ret 'goto procedcall
  end subroutine


  subroutine operationsh
  ======================
  '
  'wr could be [...] or rax
  a=0
  m=typ
  int opk=0
  if op<2
    opsh="move"
  endif
  if findop(typ,opsh,w2)
    if op<2
      if findop(typ,"save",w3)
        savh=1
        opk=1
      else
        wacc=owa
      endif
    else
      opk=1
    endif
    if opk
      if savh
        hlex+=w2+"("+owa+")"+cr
      else
        newcleanvar(w5,null,m)
        hlex+=w2+"("+w5+cm+wacc+cm+owa+")"+cr
        wacc=w5
      endif
      rps=1
      skiplspace(s,i)
    endif
    typ=m
    typa=m
    typc=m
    uex or=4096
    a=1
  else
    ert=433 : ers="requires operator: "+opsh
  endif
  end subroutine
  

  subroutine unaryh
  =================
  m=typc
  if findop(m,w1,w2)
    w4=owa
    newcleanvar(owa,wr,m) 'new owa and wr
    hiex+=w2+"("+owa+cm+w4+")"+cr
    w1=""
    rps=1
  endif
  typ=typc
  typa=typc
  end subroutine


  ======
  begin:
  ======

  accg=""
  tya1=typx
  wvarf=varf
  varf=0
  '
  if nst=0
    '
    if typx>=typh
      if cpa>2
        opsh=identops(op)
        wacc=osg
      endif
    endif
    if op=-1
      w2=mid(s,i,1)
      i++
    elseif typx
      'expandexpr(s,i,typx) 'EXPAND IIF EXPRESIONS: AA=(A>B ? C : D )
      'if rps=2
      '  if typx>=typh
      '    ilc=1 : owa=gword(s,i) : goto exitexpr
      '  endif
      'endif
    endif
    '
    w1=w2+precedence(s,i,0)
    inserts(s,w1,i)
    skiplspace(s,i)
    '
    if divi
      if typx<typh
        fpum=1 'prefer floating point when expression contains "/"
      endif
    endif
  endif
  '
  cp=0 : nsl=nst : ascw=0 : e=1 : bvg=0 : nstu.c=0
  '
  skiplspace(s,i)
  '
  'IF (A==B) ++C;
  '
  if cnd
    if nst=0
      if (ascn=lbr)and(sr2=59)
        clbr=1 'C STYLE CONDITIONAL (CONF: #SEMICOLON SEPARATOR)
      endif
    endif
  endif
  '
  if fpum>0
    typc=0x68 ' FPU PREFERRED
  elseif fpum<0
    typc=cpuw ' CPU PREFERRED
  elseif typx
    typc=typx
  endif
  '
  '
  'EMPTY EXPRESSION TERMINATED BY COMMA OR RIGHT BRACKET , ) ]
  '
  'if (ascn=44)or(ascn=rbr)or(ascn=93)
  select ascn
  case 44,41,93
    typc=cpuw : wr="0" : op=1 : wt+=operi(op,typc,wr)
    goto endexpr
  end select
  '
  '
  '=======
   oploop:
  '=======
  '
  select typc
  case 0xe0 to 0xff
    typc-=32 'set as BSTR BY VALUE
  end select
  '
  select op
  case -1
    typc=typx : op=0 : irx=1
    goto nestpush 'ARRAY INDEX EVALUATION
  case -2
    typc=typx : goto nextops  'OPERATOR OR TERMINATOR EXPECTED
  case 47 '/
    if typc<0x40
      wt+=cvtai(typc,0x68) : typc=0x68
    endif
  end select
  '
  if typc>=0x40
    if typc<0x80
      if (op>2)or(noto=1) 'BITWISE OPS ON FLOAT EXPRESSIONS
        a=op
        if noto
          a=11
        endif
        select a
        case 42,43,45,47,92 '* + - / \
          '
        case 11,33,34,35,74,75,76,77 'NOT AND OR XOR SHL SHR ROL ROR
          if fpum>0
            fpum=0
          endif
          if typc>=0x40
            wt+=cvtai(typc,cpuw)
            typc=cpuw
          endif
        end select
      endif
    endif
  endif
  '
  wrp=wr
  wr=pword(s,i)
  ' 
  dct++ 'each oploop
  if dct>1000
    ert=102 'macro recursion suspected
    goto exitexpr
  endif
  '
  if lenw=0
    ers="unexpected end of prog" : ert=9
    goto exitexpr
  endif
  a=0
  select mc
  case -3,-8,-15
    if ascn=lbr '(
      if wr="int"
        inserts(s,"round ",i)
        goto oploop
      endif
    endif
    a=1
  end select
  '
  'TYPG=
  'if typ and 2
  '  if isstr(typ)
  '    typu=2
  '  endif  
  'endif
  '
  if ascw=0x63 'c
    if wr="convert"
      wr=pword(s,i)
      a=1
    endif
  endif
  if a 'cvx
    a=identype(wr)
    if a
      rps=4
      wr=NewTmpVar(wr)
      hlex+=wr+"="+captsx(s,i)+cr
      inserts(s,wr,i)
      wr=pword(s,i)
      typk=typ
      if op<=1
       typc=typ
      endif
    endif
  endif
  '
  if nfnd
    ert=255
    ers="Not found"
  endif
  '
  if ert
    goto endexpr
  endif
  '
  if cpoint
    if typ>=typh
      typ=cpuw
    endif
  endif
  '
  'CAPTURE FOR ARRAY TERMS
  '
  if irx=1
    a=0
    if varf>=8
      a=1
    elseif mc>=0
      a=1
    endif
    if (a<>0)and(op<2)and(ctop=0)
      typi=typ
      if varf>=8
        typi=4
      endif
      wpfxi=wpfx : wri=wr
    endif
  endif
  '
  typa=typ
  '
  if varf>=8
    goto phproc
  endif
  '
  'HIGHER TYPES
  if typc>=typh
    'UNARY
    if ascw=0x6e 'n
      if wr="not"
        noth=1
        goto oploop
      endif
    endif
  endif
  '
  'HIGHER TYPES
  if typ>=typh
    '
    'PASSING POINTER IN PARAMS
    if (isxn()<>0)and(op<2)and(cp=0)
      if findop(typ,"move",w2)=0
        typc=typ
        accg=owa
        wt+=wpfx+"lea "+qeax+cm+wr+cr 'RETURN WITH ADDRESS
        goto endexpr
      endif
    endif
    if cnd
      if op<2
        typc=typ
      endif
    endif
  endif
  '
  '
  '
  'HIGHER ACCUM
  if (typc>=typh)and(typi=0)
    '
    'NESTED EXPRESSION
    if ascw=lbr
      a=i
      opo=op
      op=0
      nst++
      w4=captsx(s,i)
      i=a
      w1=express(s,i,typx) 'RECURSE
      i++
      skiplspace(s,i)
      nst--
      op=opo
      'accum operand wg
      'if ascn=rbr
      '  i++
      'endif
      typa=typg
      owa=accg
      wr=wg
    endif
    '
    'TYPE CONVERSION REQUIRED
    if typa<>typc
      w1="conv" : gosub unaryh
    endif
    if noth
      w1="not" : gosub unaryh
      noth=0
    endif
    if wordahead(s,i)="_neg"
      i=nwd : skiplspace(s,i)
      w1="neg" : gosub unaryh
    endif
  endif
  '
  if typ>=typh
    '
    'PRIMITIVE ACCUM
    if (typx>0)and(typx<typh)
      ert=437 : ers="primitive requires conversion"
    endif
    '
    'HIGHER OPERATION
    gosub operationsh
    if ert
      jmp fwd exitexpr
    endif
    skiplspace(s,i)
    goto nextops
  endif
  '
  '
  phproc:
  =======
  '
  '
  select ascw
  case 0x63 'c'
    if wr="call"
      nobr=1
      c=typk
      do
        if wr="call"
          wr=pword(s,i)
        else
          exit do
        endif
      loop
      typk=c
      nobr=0
      varf=8
      goto procedcall
    elseif wr="chr"
      m=1 : gosub chareval
      if m
        goto cvtop
      endif
      goto procedcall
    endif
  case 0x77 'w'
    if wr="wchr"
      m=2 : gosub chareval
      if m
        goto cvtop
      endif
      goto procedcall
    endif
  case 0x6e 'n'
    if wr="null"
      bvg=1 'always accept as param
      wr="0"
      typc=typx
      if cnd=0
        wt+=operi(1,cpuw,"0")
        goto endexpr
      endif
    elseif wr="not"
      noto=1-noto : goto oploop 'continue do
    endif
  case 95 '_'
    if wr="_neg"
      w1=""
      wt+=operi(7,typc,w1)
'      op=7
      goto nextops
    endif
  case 43 to 45
    '
    'CHECK PRE INCREMENT / DECREMENT ++ --
    '
    if (ascw=43)or(ascw=45)
      if ascw=asc(s,swd+1)
        if ascw=43
          a=12
        else
          a=13
        endif
        i++ : wr=pword(s,i) '++A --A
        if cnsterr()
          return 0
        endif
        if cpoint
          if typ>=typh
            typ=cpuw
          endif
        endif
        epfx+=wpfx+operi(a,typ,wr)
        if ert
          goto exitexpr
        endif
        inserts(s,owa+" ",i)
        goto oploop
      endif
      '
      if (ascw=45)and(mc<>-31)
        op=1
        if ascn=lbr
          a=i : capture(s,m,i,0)
          w1=mid(s,a,i-a)
          inserts(s,w1+" _neg ",i)
          goto oploop
        else
          wr=pword(s,i)
          if ascn=lbr
            a=i : capture(s,m,i,0)
            w1=mid(s,a,i-a)
            inserts(s,w1+" _neg ",i)
          else  
            inserts(s,"_neg ",i)
          endif
        endif
      endif
    endif
  case 42 to 255
    '
  case 40
    goto nestpush
  case 41 ')'
    goto nestpop
  case 37
    goto oploop 'IGNORE % IN EXPRESSION
  end select 'ascw
  '
  '
  ' (A>B) SIMPLE STRING COMPARATORS OPTIM
  '======================================
  '
  if (ascn=rbr)and(cp<>0)and(op<2)
    if (isstr(typ)<>0)and(isstr(tp)<>0)
      wt+=makestrptrfun(wr)
      goto oploop
    endif
  endif
  '
  '
  select mc
  '
  case 0
    'variables
  case -5 to -4
    goto procedcall
  case -10
    goto cvtop 'regs
  case -15 'PRIMITIVE TYPE
    'EXPLICITLY CHANGE ACCUM TYPE 'a=double b + 7
    if typx=0
      if op<2
        typ=identype(wr) : typx=typ : typc=typ 'force expression type
      endif
    endif
    goto oploop
  case -16
    goto procedcall
  case -17
    if typc<0xa0
      goto floatmacros
    endif
  case -30
    goto cvtop 'LABELS
  case -31
    '
    'LITERAL NUMBERS
    '
    '
    'TYPE CONVERSIONS
    '
    if typc=0
      typc=typ 'SET ACCUM TYPE (INT)
    elseif isfpu(typc)
      typ=typc 'TREAT AS FLOAT
    elseif typc<0x40
      if typ=0x68
        if op>1
          wt+=cvtai(typc,0x68) 'UPGRADE ACCUM
        endif
        typc=0x68
      else
        typ=typc 'MATCH INTEGER ACCUM TYPE
      endif
    endif
    '
    typa=typ
  case -32  'STRING LITERAL
    goto cvtop
  end select 'mc
  '
  '
  if mp+parx=0
    if isa(ascw)
      if ow=wr
        ers="Unidentified operand" : ert=100 : goto endexpr
      endif
    endif
  endif
  '
  'CONVERT STRING ACCUM TO NUMERIC ACCUM
  '=====================================
  '
  'STRING ACCUMULATOR BUT FLOAT MACRO OR NUMERIC OPERAND
  '
  if isstr(typc)
    typa=typ
    if funi
      lcls=1
    endif
    if (mc=-17) 'FLOAT MACRO
      typc=0x68
      fpum=1
      op=1
      uex or=1024 'SIGNAL TO USE FULL EXPRESSION
    elseif (typa>0)and(typa<0x80) 'NUMBER
      op=1
      typc=typa
      if typc<0x40
        if lent<cpuw
          typc=4 'INT ACCUM
        endif
      else
        fpum=1
        typc=0x68 'FLOAT ACCUM
      endif
      uex or=1024 'SIGNAL TO USE FULL EXPRESSION
    endif
  endif
  '
  '
  '===========================
  procedcall: 'PROCEDURE CALLS
  '===========================
  'procs
  if typ=0
    'ADOPT ASSIGNMENT TYPE
    if (nst<1)and(typx<>0)
      typ=typx
    else
      typ=cpuw
    endif
  endif
  '
  typa=typ
  '
  n=0
  '
  '
  if varf>7
    '
    'PRELIM CHECKS
    '-------------
    '
      
    '
    'PARAMS WILL BE RESOLVED RECURSIVELY (procedures calls express)
    '
    '
    ojn=jn
    w1=""
    w2=""
    w3=ow
    nst++
    opo=op
    ofpu=fpum : fpum=0
    c=typk 'cast-type if any
    jn=0
    b=bvg
    typ=cpuw
    '
    wp=procedures(s,i,wr)
    if ert
      goto exitexpr
    endif
    '
    skiplspace(s,i)
    fpum=ofpu
    op=opo
    jn=ojn
    bvg=b
    nst--
    if fpum>0
      if (op<2)and(typx=0)and(typ<0x40)and(isxn()<>0)
        fpum=0 : typc=cpuw
      endif
    endif
    if indt
      if (nisxn<>0)or(op>1)
        typc=cpuw
        goto doneprocs 'TREAT POINTER AS VALUE
      else
        typc=typ 'TREAT AS SPECIFIC TYPE
        wt=wp
        uex or=1024
        goto endexpr
      endif
    endif
    if typ=0
      typc=cpuw
      goto doneprocs 'NOTIONAL RETURN TYPE
    endif
    '
    if (typc>=typh)and(typ>=typh)and(indt=0)
      '
      hiex+=storecode(wp) 'preprocess the procedure
      rps=16
      wr=wg
      '
      'TYPE CONVERSION REQUIRED
      if typ<>typc
        w1="conv" : gosub unaryh
      endif
      if noth
        w1="not" : gosub unaryh
        noth=0
      endif
      if wordahead(s,i)="_neg"
        i=nwd : skiplspace(s,i)
        w1="neg" : gosub unaryh
      endif
      if op<2
        if isxn
          if findop(typ,"move",w2)=0
            typa=typ
            typc=typ
            uex or=1024 or 4096 'SIGNAL TO USE FULL HIGHER EXPRESSION
            jmp fwd endexpr
          endif
        endif
      endif
      gosub operationsh
      if ert
        jmp fwd exitexpr
      endif
      goto nextops
    endif
    '
    'TRANSFER FLOAT FROM SIMD TO FPU
    '
    'FPU TYPE 0x40 IS EXCLUDED
    'APPLIES ONLY TO MS64 CALLING CONVENTION
    '
    if (cpuw=8)and(cco=2)
      if (typ>0x60)and(typ<=0x68)
        wp+=simdtofpu(typ)
      endif
    endif
    '
    if typ=0x40
      typ=0x6a 'TREAT FPU TYPE AS EXTENDED PRECISION
    elseif (typ>0x40)and(typ<0x60)
      w2+=fpuquad
    endif
    '
    if c
      typ=c 'USE CAST FOR THE RETURN TYPE
    endif
    '
    typa=typ
    '
    '==============
    'STRING OPERAND
    '==============
    '
    'CONVERT NUMERIC ACCUM TO STRING
    '===============================
    '
    if isstr(typ)
      if (typc>0)and(typc<0x80)
        if op>1
          '
          'NUMBER ACCUM FOLLOWED BY RETURNED STRING
          '
          if jn
            a=43
          else
            a=1
          endif
          w1=cvtai(typc,0xc1)+logas()+operi(a,0xc1,cpua) 'STRING ACCUM
        endif
        typc=0xc1 'NOW STRING ACCUMULATOR
      endif
    endif
    '
    if isdstr(typ)
      '
      '
      'BSTRING LOADING / CONCATENATION
      '===============================
      '
      a=typ and 15
      b=typx and 15
      c=isxn()
      d=0
      typ=upgradelen(0xc1,a)
      typa=typ
      if op=0
        op=1
      endif
      '
      '
      'CHECK FOR DIRECT STRING ASSIGNMENT
      '
      if (c<>0)and(jn=0)and(op<2)
        '
        tya1=typx
        if (isdstr(tya1)<>0)and(a=b)
          '
          d=1 'ASSIGN TO VARIABLE
          '
        elseif (typx=0)and(parx>0)
          '
          d=1
          w2=logas() 'TO FUNCTION PARAM (ALSO LOG FOR DELETION)
          '
        endif
        '
      endif
      '
      if d=0 'USE CONCATENATOR
        if typ<>0xb1 'exclude midstr
          w2=logas()+operi(op,typ,qeax) 'LOG FOR DELETION AND USE CONCATENATE
        endif
      endif
      '
      typc=typa
      '
      'if (op<2)and(cnd<>0)
      '  usx=typ
      'endif
      if op<2
        usx=typ
      endif
      goto doneprocs
      '
    elseif iszstra(typ) 'ZSTRING (assume is PTR)
      '
      w2=operi(op,typ,cpua)
      '
      if typc<typa
        typc=typa 'itr wide string check
      endif
      '
      'if (op<2)and(cnd<>0)
      '  usx=typ
      'endif
      if op<2
        usx=typ
      endif
      goto doneprocs
      '
    endif
    '
    if op<2
      if typc=0
        typc=typa 'NO CONVERSION REQUIRED
        if typc<&h40
          wp+=cvtai(typa,cpuw)
          typc=cpuw : typa=cpuw
        endif
      endif
    endif
    '
    if noto
      w5=""
      wp+=operi(11,typ,w5)
      noto=0 'NOT
    endif
    '
    '
    'OTHER PRIMITIVES
    '================
    '
    if typc<typh
      '
      a=typa
      '
      '
      '
      if (isstr(typc)<>0)and(a>0)and(a<0xa0)
        '
        'STRING ACCUM BUT NUMERIC RETURNED FROM PROC
        '===========================================
        '
        'SUPPORT NUMERIC EXPRESSION
        typc=typa
        op=1
        goto doneprocs
        '
      else 'NON STRING
        '
        if typc>typa
          w2=cvtai(typa,typc) : typa=typc  'UPGRADE OPERAND
        endif
        '
      endif
      '
      a=0
      if xmode
        a=1
        nan=1
        varf=0
        typ=4
        mp=me
        wr=tmpvar()
        if op<=1
          wri=wr
        endif
      elseif op>1
        wr=tmpvar()
        a=1 'arrays index expr
      endif
      '
      if a
        '
        'NUMERIC ACCUM
        '=============
        '
        if typa>typc
          w1=cvtai(typc,typa)
          typc=typa  'UPGRADE ACCUMULATOR BEFORE PROCEDURE
        endif
        '
        'w5=tmpvar() : w6=tmpvar()
        'w1+=operi(2,typc,w5)
        'w2+=operi(2,typa,w6)+operi(1,typa,w5)+operi(op,typa,w6)
        '
        epfx+=wp+w2+operi(2,typa,wr)
        wp=operi(op,typc,wr)
        w2=""
        'epfx+=w1+wp+operi(2,typa,wr)
        'wt+=w2+operi(op,typc,wr)
        'skiplspace(s,i)
        'goto nextops
        '
      else 'op<=1
        typc=typa
      endif
      '
    endif
    '
    '---------
    doneprocs:
    '---------
    '
    wt+=w1+wp+w2
    uex or=1024 'SIGNAL TO USE FULL EXPRESSION
    skiplspace(s,i)
    goto nextops
    '
  endif 'varf>7
  '
  '
  'O2 INLINE CODE
  '==============
  '
  if wr="o2" 'inline opcodes
    wt+="o2 "+sp+captureblock(s,i,"")+ep
    typc=typx
    goto nextops
  endif
  '
  if wr="asm" 'inline assembler
    wt+=sp+captureblock(s,i,"")+ep
    typc=typx
    goto nextops
  endif
  '
  '
  'CORE MACROS
  '
  '===========
  floatmacros:
  '===========
  '
  if mc=-17
    uex or=1024 'SIGNAL TO USE FULL EXPRESSION
    b=ascn 'check for bracket later
    'w2="|fm "+hex(mp)+" "+wr+cr
    '
    if wr="pi"
      m=0
    else
      m=1
    endif
    '
    if typc<0x40
      if op>1
        wt+=cvtai(typc,0x68) 'UPGRADE ACCUM
      endif
      typc=0x68
    elseif typc<0x60 'FPU QUAD
      typc=0x68
    endif
    '
    typ=0x68 : typa=typ
    '
    'PI and any other FPU consts
    if (m=0)and(b<>lbr)
      wt+=mrcso(mp,1)+cr
      if op>1
        wt+=operi(op,typ,c127) 'NORMAL MATH OP
      endif
      goto nextops
    endif
    if b<>lbr
      w1=captsr(s,i)+")" 'WITH COMMAS
      inserts(s,w1,i)
      b=lbr : i--
    endif
    '
    'WITH BRACKETS 'sin(a)  sin(a*b)  atan(y,x)
    '
    i++
    if fpum>=0
      fpum++   ' FPU NESTING FROM CPU MODE
    elseif fpum<0
      fpum=1024 ' CPU MODE SWITCH TO FPU MODE
    endif
    n=1
    c=-mp   'FPU NESTING
    nstu.g=0 'NO TEMP VAR, NO PRECALC
    goto nestexp
  endif 'FLOAT MACROS mc=-17
  '
  '
  '========
  nestpush:
  '========
  '
  '
  '  #
  ' #  '=================
  ' #  NESTED EXPRESSIONS
  ' #  '=================
  '  #
  '
  if ascw=lbr
    '
    if irx
      irx++ 'NESTED EXPRESSION IN ARRAY
    endif
    uex or=2048 'USE FULL EXPRESSION FOR PARAMS
    'IGNOTE EMPTY BRACKETS
    if ascn=rbr
      i++
      goto oploop
    endif
    '
    'NESTED STRING EXPRESSIONS
    if isstr(typc)
      'ignore precedence brackets around string expression: (a+b)&(c+d)
      b=swd
      m=b 
      capture(s,m,b,a)
      mid(s,b-1)=" " 'strip right bracket
      goto oploop
    endif
    '
    c=0
    n=1
    if typc<typh
      if (fpum<=0)or(typc<0x40)
        w1=tmpvar() : w1="" : a=qme
        if op>1
          wtn(nst)=wt  'HOLD CURRENT CODE STREAM
          wt=""        'START FRESH CODE STREAM
          nstu.g=a     'TEMP VAR RECORD INDEX
        else
          nstu.g=-a    'TO LOAD NESTED RESULT
        endif
      endif
    endif
    goto nestexp 'PREPARE FOR NESTED EXPRESSION
  endif 'ascw=lbr
  '
  '
  '        #
  ' ####  #  ======
  ' #  #  #  ARRAYS
  ' ####  #  ======
  '        #
  '
  '
  if (ascn=lbr)and(ascw<>rbr)
    'ARRAY DOT MEMBERS
    'itr sub-members this.c[m].a[n] etc
    a=instr(ow,".") 'IMPLICIT THIS HAS BEEN MADE EXPLICIT PRIOR
    if a
      wc(nst)=mid(ow,a+1) 'MEMBER
      po(nst)=woff 'MEMBER OFFSET
    else
      wc(nst)=""
      po(nst)=0
    endif
    '
    if mp=0
      ert=32 : ers="Unidentified array or procedure"
      goto exitexpr
    endif
    '
    w1=""
    c=mp
    i++
    n=1 ' flag array params
    '
    '
    '======
    'ARRAYS
    '======
    '
    xmode=1
    pid=0 'SIB / postincdec
    nstu.g=0
    '
    'ARRAY ADDRESS
    '
    ixnd=ind  'INDIRECTION
    ixnt=indt 'ARRAY OF POINTERS
    ixns=""
    '
    if ixnd
      if ixnt=0
        if iszstra(typc)
          ixnt=1 'flag char**c
        endif
      endif
    endif
    '
    if ixnt 'ARRAY OF POINTERS
      '
      'SPLIT INDIRECTION PROCEDURE
      '
      ixns=splitderef(ixnd-ixnt) 'effectively splitting wpfx
      '
      'ARRAY FOR ASSIGNMENT OPERAND (OP=2)
      '
      if arf=2
        if (iszstra(typa)<>0)
          if not refaddr(ixns)
            ert=725 : ers="unable to get address"
          endif
        endif
      endif
      xmode=5 'FULL PRECALC INDEX
    endif  'ixnt
    '
    wmp=mp       'ARRAY RECORD INDEX
                 'PRIOR WVARF=VARF
    wra=wu       'ARRAY BASE OPERAND
    wpfxa=wpfx   'ARRAY BASE ADDRESS RESOLUTION
    wt+=wpfxa+"lea "+qesi+cm+wra+cr
    '
    'REFERENCING FOR ARRAY ATTRIBUTES
    wbx=wpfxa+"lea "+qecx+cm+wra+cr
    if wpfxa
      mid(wbx,1)="lea"
    endif
    '
    'QESI INDEX ACCUMULATOR
    '
  endif 'ascn=lbr
  '
  'ALL NESTINGS:
  '
  '=======
  nestexp:
  '=======
  '
  if n 'ARRAY PARAMS OR CORE FPU MACRO
    nstu.a=op   'OPERATOR
    nstu.b=typc 'ACCUMULATOR TYPE
    nstu.c=c    'ENTITY CODE
    nstu.d=cp   'COMPARATOR
    nstu.e=tp   'COMPARE TYPE
    nstu.f=ind  'INDIRECTION LEVEL
    nstu.h=omp  'LAST OBJECT
    nstu.i=noto 'NOT' FLAG
    nstu.k=typa 'OPERAND TYPE
    '
    if elsize
      nstu.j=elsize 'ELEMENT SIZE
    else
      nstu.j=drc(abs(c)).b 'VAR SIZE
    endif
    '
    if ixnt>0
      nstu.j=cpuw
    endif
    '
    if nst>=99
      ers="too many () nestings "
      ert=300 : goto xassigns
    endif
    copy @nstk(nst), @nstu, sizeof nstu
    nst++
    '
    '
    if typc=cpuw
      typc=0 'TYPC TAKES ON TYPA IDENTITY
    endif
    '
    if c>0 'ARRAY
      typc=0 'higher types do not arrive here
    elseif c<0 'FLOAT MACRO
      typc=0x68
    endif
    '
    cp=0 : tp=0 : noto=0 : op=1
    goto oploop 'PROCESS NESTED EXPRESSION
    '
  endif 'n  'ARRAY PARAMS OR CORE FPU MACRO

  '
  '
  '=======
  nestpop:
  '=======
  '
  '
  '
  ' #
  '  #  ==================================
  '  #  END OF NESTING OR ARRAY EXPRESSION
  '  #  ==================================
  ' #
  '
  ' NESTING STACK:
  '--------------------------------------------------------
  ' A  op   operation (-1 non) (0 or 1 mov)
  ' B  typc accumulator type
  ' C  c    array attributes locator / -ve intrinsics flag
  ' D  cp   conditional (flag) code
  ' E  tp   conditional L accummulator type
  ' F  ind  indirection level
  ' G  tmp   temp variable attributes locator
  ' H  omp  last object   
  ' I  noto 'not' flag
  ' J  elsize or varsize
  ' K  typa array var type
  '--------------------------------------------------------
  '
  if ascw=rbr
    '
    'MAKE COMPARISON IF CP INSIDE BRACKETS
    '-------------------------------------
    '
    if cp
      if isstr(typc)
        '
        'STRINGS
        a=typc and 15
        typc=0xc0+a
        '
        'STRING OPTIMIZATION
        'if (op<2)and((typc and 15)=1)and((tp and 15)=1)
        if op<2
          if usx
            'if isdstr(usx)
            '  wt+=logas
            'endif
            jn=0
          endif
        else
          wt+=operi(96,typc,qeax)+logas() 'CONCAT LOGICAL RESULT AFTER STRING COMPARE
        endif
        wt+=operi(cp,tp,w4)
        'usx=0
        '
      elseif typc<typh 'NON STRING PRIMITIVES
        '
        int ta=asc(wrp)
        if (op<2)and(tp<0x40)and(isn(ta)<>0)
          'DIRECT COMPARE NUMBER
          extractoperand(wt,wrp)
          decidecop(cp,tp)
          wt+="cmp "+identypes(tp)+w4+cm+wrp+cr+"set"+mid(cops,cp*4-63,3)+
          "al"+cr+"and "+qeax+",1"+cr
        elseif tp<>typc
          wt+=cvtai(typc,tp)+operi(cp,tp,w4) : typc=tp 'CONVERT TO LEFT SIDE TYPE
        else
          wt+=operi(cp,tp,w4)
        endif
        '
      endif
      '
      'if typc<typh
      '  'PRIMITIVES
      'endif
      typc=cpuw 'int type for logical result
    endif 'cp
    usx=0
    '
    'CHECK FOR EXCESS RIGHT BRACKETS
    '-------------------------------
    '
    if nst<1
      '
      'CHECK FOR RECURSIVE ASSIGNMENT BEFORE LOGGING AN ERROR
      '
      ers="Too many right param brackets" : ert=300
      goto xassigns
      '
    endif
    '
    'OBJECTS
    'if uex>=4096
    ' '
    'endif
    '
    '
    'CLOSE THE NESTING  (ACCUM-->OPERAND : POP ACCUM WITH OPERATOR / ARRAY BASE / FUNCTION
    '-----------------
    '
    typa=typc
    '
    ocp=cp
    nst--
    copy @nstu, @nstk(nst), sizeof nstu
    typc=nstu.b
    op=nstu.a
    c=nstu.c
    cp=nstu.d
    tp=nstu.e
    ind=nstu.f
    noto=nstu.i
    '
    '
    'DETERMINE OPERAND TYPE (whether array or result of nested expression)
    '
    if c>0
      typ=nstu.k : typa=typ
    else
      typ=typa 'same as typc
    endif
    '
    if typc=0
      typc=typ
    endif
    '
    '
    '=====================
    'DOT MEMBERS OF ARRAYS
    '=====================
    '
    if ascn=46
      '
      if asc(s,i+1)=62 '.>' derived from '->'
        i++
        'itr ind?
      endif
      '
      i++
      w1=tword(s,i)
      '
      'ACCUMULATE MEMBER EXPRESSION
      if wc(nst)<>""
        w1=wc(nst)+"."+w1
      endif
      '
      wc(nst)=w1
      '
      'IDENTIFY THE MEMBER
      '
      'READ THE MEMBER ATTRIBUTES
      '
      mp=nstu.c
      ow=mrcso(mp,0)+"."+w1 'VAR NAME EXCLUDING ARRAY SPEC
      'SUPPORTING DIRECT & INDIRECT MEMBERS
      a=-1
      findmember(w1,w2,a)
      '
      if a=0
        ers="Array member not found" : ert=500 : goto exitexpr
      endif
      '
      'INDIRECT MEMBERS
      if varf=3
        xmode=5              'FLAG FULL INDEX CALC
        'eg: mov edi,[edi+?woff]
        w2=memreg(qedi,woff) 'MEMBER OFFSET ADDED 
        memba=medi+w2+cr     '
        woff=0
      endif
      '
      m=woff         'OFFSET
      nstu.j=elsize  'LENGTH
      nstu.k=typ     'TYPE
      if indt
        nstu.j=cpuw
      endif
      v=varf        'OBJECT ATTRIBUTES (varf code)
      tye=typ
      typa=typ
      if op<2
        typc=typa
      endif
      '
      'ADD ELEMENT RELATIVE OFFSET TO THE OVERALL ARRAY OFFSET
      '
      skiplspace(s,i)
      '
      if ascn=91
        fixsqbr(s,i)
      endif
      '
      if nstu.j>0 'ELEMENT SIZE
        if v<=8   'EXCLUDE METHOD OFFSETS (this base)
          if wvarf=3
            a=m 'PARENT IS POINTER
            wvarf=0
          else
            a=m-po(nst) 'RELATIVE MEMBER OFFSET
          endif
          if a 'EXCLUDE OFFSET 0
            xoffs+=a 'DIRECT OFFSET ADJUSTMENT
            wt+="add "+qesi+cm+str(a)+cr
          endif
        endif
      endif
      '
      po(nst)=m
      '
      '=====================
      'SUBARRAYS   a(x).b(y)
      '=====================
      '
      'IS THERE A SUBARRAY
      '
      if varf<8
        '
        if ascn=91
          fixsqbr(s,i)
        endif
        '
        if ascn=lbr
          '
          'PLACE THE AMMENDED DESCRIPTION
          '
          'NEST IMPLICITLY
          copy @nstk(nst), @nstu, sizeof nstu
          nst++
          '
          'SKIP BRACKET
          '------------
          '
          i++ : skiplspace(s,i)
          '
          'SET ACCUM TO INTEGER TYPE WITH OP=LOAD
          '--------------------------------------
          '
          typc=cpuw : op=1
          '
          'RESUME EXPRESSION LOOP DIRECTLCY
          arcc=0 'no multidim
          goto oploop
          '
        endif
        '
      endif 'SUBARRAYS
      '
      '
      'RESOLVED FINAL OFFSET
      '
    endif 'DOT
    '
    '
    'ARRAY OFFSET CALC
    '=================
    '
    if c>0
      '
      if typx>=typh 'HIGHER TYPES
        if tye
          typx=tye 'CAST AS ELEMENT TYPE
        endif
      endif
      '
      if irx>1
        xmode=5 'ARRAY WITH NESTED INDEXER
      endif
      '
      'GET OPERAND
      '
      'wr/wg passed back to mword()
      'wt/wpfx passed back to mword()
      select xmode
      case 1,2 'DIRECT OFFSET
        wr=memregadj(wra,xoffs)
        wt=wpfxa 
      case 4 'SIB ENCODED INDEXING
        wr=memregadj(wra,xoffs)
        wt=xcalc
      case 5 'FULLY CALCULATED INDEXING
        w3=tmpvar()
        epfx+=wt+"mov "+w3+cm+qesi+cr 'STORE PRECALC
        wt=medi+w3+cr+ixns+memba      'READ PRECALC
        wr=pedi
      end select
      '
      goto endexpr 'ARRAY INDEXING COMPLETE
      '
    endif 'ARRAYS c>0
    '
    '
    '----------
    'INTRINSICS
    '==========
    '
    if c<0
      b=0x68 'ALWAYS FLOAT
      if isstr(typa)
        wt+=operi(96,typa,qeax)+logas() 'CONCAT AND LOG
      endif
      wt+=cvtai(typa,b)+mrcso(-c,1)+cr 'expandfmac(-c)
      typa=b 'TYPE CONVERSION + INTRINSIC
      if ert
        goto exitexpr
      endif
      '
      if isstr(typc) 'string accum
        wt+=cvtai(typa,typc)
        if (op>1)or(typx=0)
          wt+=logas() 'LOG AS TEMP STRING
        endif
        wt+=operi(op,typc,qeax)
        fpum=0
        goto postops
      endif
    endif 'INTRINSICS c<0
    '
    '
    'BOTH NESTED EXPRESSIONS AND INTRINSICS
    '======================================
    '
    'BITWISE NOT()
    '
    if noto
      w1=""
      wt+=operi(11,typa,w1)
      noto=0 'NOT
    endif
    '
    '
    'CHECK / TRANSFER ACCUM FROM FPU TO CPU OR VAL TO STRING
    '
    if fpum<=-1
      if isfpu(typc)
        wt+=cvtai(typc,cpuw)
        typc=cpuw : typa=cpuw
      endif
    endif
    '
    '
    'INDIRECTION *(A+B)
    '-----------
    '
    if ind
      if c=0
        for a=1 to ind
          wt+=operi(1,cpuw,peax) 'DEREFERENCE
        next
      endif
    endif
    '
    'STORE RESULT IN TEMP VAR (EXCEPT FOR STRINGS)
    '
    'CHECK FOR END OF NESTED EXPRESSION
    'LOOKAHEAD FOR NEXT OPERATOR (FOR LAZY JUMP)
    if nisxn
      d=identop(s,i,0)
      if op
        ctop++
      endif
      skiplspace(s,i)
    else
      d=0
    endif
    '
    if nst=0
      if (cnd<>0)and(d<>0)
        'opcn++
        if (d=33)or(d=71)
          'IF (A)AND(B) THEN ... always fail
          laz=chr(3)+"jz fwd _cnd"+cr
          lazn++
        elseif (d=34)or(d=72)
          'IF (A)OR(B) THEN .. always succeed
          laz=chr(3)+"jnz fwd _cnd"+cr
          lazn++
        endif
      endif
    else
      laz=""
    endif
    '
    lazt=""
    if lazn
      if nst=0
        lazt=chr(2)
      endif
    endif
    '
    if nstu.g>0
      '
      'STORE RESULT IN TEMP VAR AND REORGANISE CODE
      '
      w1=""
      w2=""
      b=typc
      w3=mrcso(nstu.g,1)
      '
      if isfloat(typa)
        typa=0x68
      endif
      if isfloat(typc)
        typc=0x68
      endif
      '
      if typa>typc
        w2=cvtai(typc,typa) 'UPGRADE ACCUM BEFORE
        b=typa
      elseif typc>typa
        w1=cvtai(typa,typc) 'UPGRADE OPERAND
      endif
      '
      'TO SUPPORT NESTED EXPRESSIONS
      '
      epfx+=wt+w1+laz+  'STORE NEST RESULT IN TEMP VAR (IN ADVANCE)
      lazt+operi(2,b,w3)
      wt=wtn(nst)+w2+lazt+operi(op,b,w3) 'OPERATE ON TEMP VAR
      wtn(nst)=""
      typc=b
      skiplspace(s,i)
      '
    elseif nstu.g<0
      'LOAD NESTED RESULT
      'USE TEMP VAR IF FURTHER OPS FOLLOW
      if d 'FURTHER OPS
        if isstr(typc)=0 'EXCLUDE STRINGS
          b=typc
          if isfloat(typc)
            if ocp 'NESTED COMPARE
              b=cpuw
            endif
          endif
          w3=mrcso(-nstu.g,1)
          epfx+=wt+laz
          if typx<typh
            epfx+=lazt+operi(2,b,w3)
            wt=lazt+operi(1,b,w3)
          else
            b=drc(-nstu.g).f and 0xffff
            epfx+=lazt+operi(1,b,w3)
          endif
          w3=""
        endif
      endif 'd
    elseif (fpum>0)and(op>1)
      wt+=operi(op,typc,c127) 'FPU OPERATIONS
    endif
    ocp=0
    if op<=1
      typc=typa
    endif
    nstu.g=0
    '
    '
    '=======
    postops:
    '=======
    '
    'INTRINSICS
    '
    if c<0
      if fpum<0
        fpum++    'REDUCE NESTING OF CPU INSTRINICS
      elseif fpum=1024
        fpum=-1 'REVERT TO CPU MODE
      elseif fpum>0
        fpum--    'REDUCE NESTING OF FPU INTRINSICS
      endif
    endif
    '
    if isstr(typc)
      op=qp 'CAT CONTINUITY
    endif
    goto nextops
    '
  endif ' ) RBR NESTPOP
  '
  ' #
  '  #   ###
  '  #   ### END
  '  #   ###
  ' #
  '
  '==========================
  cvtop: 'CONVERT AND OPERATE
  '==========================
  '
  '
  w1="" : b=0
  '
  'TO STRING TYPE
  '==============
  '
  if isstr(typa)
    '
    b=isq(ascw)
    '
    '
    'AUTOCONVERT ACCUM NUMBERS TO STRING
    '
    if typc<0xa0
      if op>1
        wt+=numtostr(typa,typc) 'CONVERT NUM ACCUM TO STRING ACCUM
        typc=typa
     else 'OP<=1
        typc=typa
      endif
    endif
    '
    '
    if isstr(typc)
      typc=upgradelen(typc,typa) 'UPGRADE STRING WIDTH
      if b=0
        goto ncvto
      endif
    endif
    '
    if b
      typc=typa
      wpfx="|qu "+wr+cr
      w1=wpfx+operi(op,typa,qeax) 'SGL
      goto xcvto
    endif
    '
  endif 'isstr typa
  '
  'TO NUMERIC TYPE
  '===============
  '
  if typc<0x80
    a=ascn
    w1+=wpfx+numoperation(wr,typa,typc) 'CAN UPGRADE OPERAND OR ACCUM TYPE
    ascn=a
    goto xcvto 
  endif
  '
  '
  '=====
  ncvto:
  '=====
  '
  w1+=wpfx+operi(op,typa,wr)
  
  '
  'DONE OPERATION
  '
  '=====
  xcvto:
  '=====
  '
  if fpum=-1
    w1+=cvtai(typc,cpuw) : typc=cpuw 'CONVERT TO CPU
  endif
  '
  '
  wt+=w1
  '
  '
  '============================
  ' 
  '      ###           ###
  '      ###              ##
  '  ###########         ##
  '  ###########       ##
  '      ###           ##
  '      ###           ##
  '
  '============================
  '
  '
  nextops:
  '=======
  '
  if ert
    goto exitexpr
  endif
  qp=op
  '
  if clbr
    if nst=0
      if ascw=rbr
        goto xassigns 'IF (A==B) ++C;
      endif
    endif
  endif
  '
  '
  'POST ++/-- postincdec
  '=====================
  '
  if (ascn=43)or(ascn=45)
    a=asc(s,i+1)
    if a=ascn
      if a=43
        pid=12
      else
        pid=13
      endif
      wt+=wpfx+operi(pid,typ,wr)
      i+=2 : skiplspace(s,i)
    endif
  endif
  '
  '
  '
  'CHECK FOR ASSIGNMENT OPERATOR
  '=============================
  '
  a=0
  b=asc(s,i+1)
  '
  if ascn=58
    if b=61
      i+=2 : a=2  ' := ASSIGN/COMPARE
    endif
  elseif ascn=61
    if b=61
      '           ' == COMPARE ONLY
    elseif casg
      i++ : a=2   ' =  ASSIGN/COMPARE WHEN IN C SYNTAX MODE #assign
    endif
  endif

  if a
    '
    '
    'EXAMPLE:
    '
    '  IF (A:=B+C) THEN ...
    '  IF (A:=F(B)) THEN ...
    '  A=B
    '  A(42)=B
    '
    'THESE ARE EVALUATED RECURSIVELY
    '
    if asxp=1
      wt=""
      w1="'ASSIGN:"+cr
    else
      'MULTISTORE: store but leave floats on fpu stack
      w1="'STORE:"+cr
      a=14
    endif
    w1+=wpfx+operi(a,typa,wr)
    'ASSIGNMENT PROCEDURE FOR DYNAMIC STRINGS
    if (typa>=0xe0)and(typa<0x100)
      a=asstrga 'GLOBAL STRING GC
      if drc(mp).d=0 'DIRECT
        w2=mid(mrcso(mp,1),3,3)
        if w2="bp-"
          a=asstrla 'LOCAL STRING GC
        endif
      endif
      if shd
        if a=asstrga
          w1+=cmt+asstrgc+cr
        else
          w1+=cmt+asstrlc+cr
        endif
      endif
      w1+=rtlo(a)
    endif
    '
    op=1
    'itr upgrade accum?
    if (nst<>0)
      typc=nstk(nst-1).b
    endif
    '
    w2=express(s,i,typa) 'RECURSE EXPRESSION
    wt+=w2+w1            'EXPRESSION+ASSIGNMENT
    '
    if isstr(typa)
      if typa>0xe0
        typa-=32 'USE DIRECT BSTR 0xC1..
      endif
    else 'not dynamic strings
      if typc<>typa
        wt+=cvtai(typa,typc)
        typa=typc
      endif
    endif
    '
    goto nextops
    '
  endif 'a assigns
  '
  '
  '
  'IS END OF EXPRESSION?
  '---------------------
  
  '   ###
  '  #####
  '   ####
  '     ##
  '    ##
  '   #
  '
  if nisxn
    goto nendof
  endif
  '
  'CHECK IF NOT NESTED
  '===================
  '
  if nsl=nst
    goto xassigns
  endif
  '
  'CHECK IF PART OF AN ARRAY INDEX
  '===============================
  '
  if nst
    int ell
    ell=0
    c=nstk(nst-1).c
    '
    'EXCLUDE NON-ARRRAY
    '
    if c<1
      goto xdimix  'EITHER INTRINSIC OR NESTED EXPRESSION
    endif
    '
    if ascn=44
      xmode=5
    endif
    '
    if arcn>1
      xmode=5
    endif
    '
    d=nst-1
    ell=nstk(d).j 'ELEMENT SIZE
    '
    if xmode=5
      goto dimix
    endif
    '
    if ell
      if (nan=0)and(op<=1)
        '
        'ADDING OFFSET DIRECTLY TO ADDRESS
        '
        b=ell*(dv-ixb) 'ADJUSTMENT FOR INDEXBASE
        xoffs+=b
        if b
          wt+="add "+qesi+cm+str(b)+cr 'PRE-EMPTIVE CODE for adding to index
        endif
        xmode=2
      else
        d=0 : m=0
        if (xmode<=2)and(typi>0)and(typi<0x40)and(ixnt=0)
          select ell
          case 1    : d=-1
          case 2    : d=-1
          case 4    : d=-1
          case 8    : d=-1
          case 16   : d=1
          case 32   : d=2
          case 64   : d=3
          case 128  : d=4
          case 256  : d=5
          case 3 to 127 : d=-2
          case 129 to 0x7fffffff : d=-3
          end select
        endif
        m=d
        if op>1
          d=0
        endif
        '
        'INDEXER AND IMMEDIATE OFFSET
        if (op=43)or(op=45)
          if (m=-1)or(m>0)
            if (ctop=1)and(nan=0)
              if op=43
                v=1
              else
                v=-1
              endif
              xoffs=xoffs+val(wr)*ell*v
              d=m
            endif
          endif
        endif
        '
        if d
          '
          'MAY USE A SIB ENCODING ONCE ONLY
          '
          'INDEXER TYPES
          w1="" : w2=""
          select typi
          case cpuw : w1="mov "+qesi+cm
          case 4    : w1="movsxd rsi," '64BIT / INT
          case 2    : w1="mov cx,"   : w2="movsx "+qesi+",cx"
          case 1    : w1="mov cl,"   : w2="movsx "+qesi+",cl"
          case 0x24 : w1="mov esi," 
          case 0x22 : w1="mov cx,"   : w2="movzx "+qesi+",cx"
          case 0x21 : w1="mov cl,"   : w2="movzx "+qesi+",cl"
          case else : ert=420 : ers="Indexing error" : goto exitexpr
          end select
          '
          xcalc=wpfxi
          if w1
            xcalc+=w1+wri+cr
          endif
          if w2
            xcalc+=w2+cr
          endif
          '
          xoffs=xoffs+ell*(-ixb) 'ADD INDEXBASE TO PRIOR OFFSETS
          '
          if pid
            if cnsterr() then return 0
            xcalc+=operi(pid,typi,wri) '++/-- POST INC/DEC
          endif
          '
          'INDEXER SCALING
          b=ell
          if d>0
            xcalc+="shl "+qesi+cm+str(d)+cr
            b=8
          elseif d=-2
            xcalc+="imul "+qesi+cm+qesi+cm+str(ell)+cr
            b=1
          elseif d=-3
            xcalc+="mov "+qecx+cm+str(ell)+cr+"imul "+qesi+cm+qecx+cr
            b=1
          endif
          xcalc+=wpfxa
          '
          'SIB ENCODING
          '
          if b>0
            w1="*"+str(b) 'SIB SCALER
          else
            w1=""
          endif
          int ta=asc(wra,2)
          if isn(ta)
            xcalc+="xor "+qedi+cm+qedi+cr
            'eg: [edi+esi*1+8] always '+' offset
            wra=aedi+"+"+qesi+w1+"+"+mid(wra,2) ' [n] absolute address
          else
            'eg: [ebp+esi*1-80] allowed "+" or '-' offset
            wra=left(wra,4)+"+"+qesi+w1+mid(wra,5)
          endif
          xmode=4
        else 'CALC OFFSET
          xmode=5 'ALWAYS USE FULL ENCODING
        endif 'd'
        '

        dimix: 'FULL PRE-EMPTIVE CALCS
        ==============================
        '
        w1=""
        '
        'BASE
        '
        if ixb
          if ixb=1
            w1+=operi(13,cpuw,qeax)     'DEC
          else
            w1+=operi(45,cpuw,str(ixb)) 'SUB
          endif
        endif
        '
        'SCALE
        '
        if ell
          select ell
            case 1    : b=0
            case 2    : b=1
            case 4    : b=2
            case 8    : b=3
            case 16   : b=4
            case else : b=0
          end select
          if b
            w1+=operi(74,cpuw,str(b)) 'SHIFT LEFT
          elseif ell>1
            w1+=operi(42,cpuw,str(ell)) 'MULTIPLY
          endif
        endif
        '
        wt+=cvtai(typc,cpuw)+w1
        typc=cpuw
        arcc++
        skiplspace(s,i)
        'DETECT MULTIDIM TERMS
        a=0
        if ascn=44
          a=1
        elseif arcc>1
          a=1 'to catch last term
        endif
        if a
          if arcc=1
            wta=tmpvar()
            wt+=wbx+"mov "+wta+cm+qecx+cr
            xmode=5
          endif 'arcc=1
          wt+=
          "mov "+qecx+cm+wta+cr+
          "imul "+memreg(qecx,-arcc*8-16)+cr
        endif 'multidim terms
        wt+="add "+qesi+cm+cpua+cr 'accumulate offset
      endif
    endif 'element size
    '
    typc=cpuw ' array index int 'INCREMENT TALLY
    c=0
    '
    '------
    xdimix:
    '======
    '
    '
    'CHECK FOR FURTHER TERMS
    '
    skiplspace(s,i)
    if ascn=44
      if c<0
        typc=0x68 'INTRINSIC FLOAT (17) READY FOR NEXT TERM
      endif
      i++
      skiplspace(s,i)
    endif
    '
    op=1
    goto oploop 'CONTINUE
    '
  endif 'NST
  '
  if ascn=rbr
    goto oploop
  else
    goto xassigns
  endif
  '
  'END OF ISXN() END OF EXPRESSION
  nendof:
  '
  '
  '        ##    ##
  '      ##        ##
  '    ##            ##
  '  ##                ##
  '    ##            ##
  '      ##        ##
  '        ##    ##

  'COMPARATORS = < > <= == >= <>
  '=============================
  '
  b=i+1
  a=identop(s,i,b)
  select a
  case 0
    op=0
    goto ncompar
  case 0x14 to 0x1f
    cp=a
    cpsh=mid(s,i,b-i)
    i=b
  'case 0x14 '== =
  'case 0x15 '<> !=
  'case 0x1c '<
  'case 0x1d '>=
  'case 0x1e '<=
  'case 0x1f '>
  case else 'all other ops
    op=a
    opsh=mid(s,i,b-i)
    i=b
    goto ncompar
  end select

  skiplspace(s,i)
  '
  if (cnd=1)or(cnd=-1)
    ctal++ 'count comparisons used in a conditional expression
  endif
  '
  'HIGHER TYPE COMPARE
  '
  if typc>=typh
    'STORE LEFT SIDE
    if findop(typc,"save",w2)
      newcleanvar(waccp,null,typc)
      hlex+=w2+"("+waccp+")"+cr
    else
      waccp=wacc
    endif
    op=0
    goto oploop
  endif
  '
  if isstr(typc)
    '
    'COMPARE STRINGS
    '
    'STRING OPTIMIZATION
    'if (qp<2)and((typc and 15)=1)
    if qp<2
      'DIRECT LOAD LEFT STRING
      if usx
        wt=wp
        if isdstr(usx)
          wt+=logas()
        endif
      else
        nstod=1
        typ=typa
        wt=makestrptrfun(wr) 'OVERWRITE PRIOR CAT CODE
        nstod=0
      endif 'usx
      jn=0
    else
      'CONCAT LEFT STRING
      typc=upgradelen(0xc1,typc)
      wt+=operi(96,typc,qeax)+_    'CONCATENATE
      logas()                    'MARK AS TEMP FOR DELETION
    endif
    usx=0
  endif 'COMPARE STRINGS
  '
  'IF PRIMITIVE THEN STACK THE LEFT HAND SIDE ACCUM VALUE
  '
  w2=""
  w4=""
  w3=wpfx
  tp=typc
  '
  'INTEGER COMPARISONS
  if tp<0x40
    a=asc(wr)
    a=isn(a) 'LEFT SIDE INTEGER LITERALS
    if (a<>0)and(qp<=1)
      goto stdcompare
    endif
    'NON-NESTED IF
    if (abs(cnd)=1)and(nst=0)
      int ai=i
      w1=tword(s,i)
      if (ascw=45)and(isn(ascn)<>0)
        w1+=tword(s,i) 'NEGATIVE NUMBER
      endif
      if (ascn=lbr)or(ascn=91)
        capture(s,m,i,0) : w1+=mid(s,m,i-m)
      endif
      '
      'END OF EXPRESSION
      d=isendofexpr(s,i)
      if d
        w2=pword(w1,1) 'EVALUATES ARRAYS
        a=0
        if (typ=typc)and(mc>=0)
          a=1
        endif
        if (mc=-31)or(a<>0) 'NO CONVERSION OR PROC
          '
          'POSSIBLE OPTIMISATION FOR NUMBER LITERALS TO GO HERE
          '
          if mc=-31
            if qp<=1
              a=extractoperand(wt,w4)
              if a 'DIRECT COMPARE WITH NUMBER
                wt=w3+"cmp "+identypes(a)+w4+cm+w2+cr
                if cnd=1
                  cp xor=1       'OPPOSITE LOGIC
                endif
                decidecop(cp,tp)
                wt+=mid(cops,cp*4-64,4)
                ctal=-16
                op=cp
                typ=tp
                typa=tp
                wr=w2
                wpfx=""
                goto endexpr
              endif
            endif
          endif
          '
          string wcm=""
          int ta
          ta=tp and 15
          'comparister
          select ta
            case 1 : wcm="al"
            case 2 : wcm="ax"
            case 4 : wcm="eax"
            case 8 : wcm="rax"
          end select
          w2=wcm+cm+w2    'EG: cmp eax,[ebp-16]
          '
          if dts<=0 'NO TEMP STRINGS TO FREE
            if cnd=1
              cp xor=1       'OPPOSITE LOGIC
            endif
            wt+=wpfx+operi(cp+112,tp,w2) '112 FOR DIRECT COMPARE & JUMP
            ctal=-16                     'FLAG FOR DIRECT JUMP
            op=cp
            typ=tp
            typa=tp
            wr=w2
            wpfx=""
            goto endexpr
          else 'FUNCTIONS PRODUCING TEMP STRINGS
            wt+=wpfx+operi(cp,tp,w2)
            op=1
            tp=0
            cp=0
            goto endexpr 'END OF EXPRESSION
          endif 'ctal etc
        endif
      endif
      i=ai
    endif 'NON-NESTED
    '
    if (qp<=1)and(w3="")and(wr<>")")and(typ=typc)and(pid=0)
      a=extractoperand(wt,w4)
      if a 'DIRECT COMPARE (NO PRELOAD)
        op=1
        skiplspace(s,i)
        goto oploop
      endif
    endif
    '
    stdcompare:
    '
    w2=cvta(typc,cpuw) 'fill temp bits / conversion
  endif 'CPU INTEGERS
  '
  'ALL PRIMITIVE TYPES
  '
  if isfpu(tp)=0
    w4=tmpvar()
    wt+=w2+operi(2,cpuw,w4)
  endif
  op=1
  goto oploop 'TO PROCESS RIGHT SIDE OF COMPARISON
  'END OF COMPARATORS
  '
  ncompar:
  '=======
  '
  skiplspace(s,i)
  '
  'IS END OF EXPRESSION?
  '
  ifendofx:
  =========
  if isendofexpr(s,i)
    if cnd
      if isfpu(typc)
        if cp=0
          wt+="fldz"+cr+"fcomip st1"+cr+"fstp st0"+cr+_
          "mov "+qeax+cm+"0"+cr+"jz fwd _cnd"+cr+"dec "+qeax+cr
        endif
      endif
      jmp fwd xassigns
    endif
    if ascn=0x74 't
      if wordahead(s,i)="to"
        i=nwd
        'conserve result ?
        w1=pword(s,i) 'changes typ
        if wpfx
          wt+="push "+qeax+cr+
          wpfx+"pop "+qeax+cr
        endif
        wt+=cvtai(typc,typ)+
        "|op 2 "+hex(typ)+" "+w1+cr
        goto ifendofx 'check for more
      endif
    endif
    jmp fwd xassigns
  endif
  '
  ''CHECK FOR NEXT OPERATOR
  '
  if op=0
    op=43
    opsh="+"
  else
    nextinstruct(s,i) 'EXPLICIT OPERATOR IGNORES COMMENTS AND LINE ENDS
    if (op=93)or(op=94)
      wt+=cvtai(typc,0x68)
      typc=0x68 'A^B power of
    endif
  endif
  '
  ctop++
  if cnd
    if nst=0
      opcn++
    endif
  endif
  '
  goto oploop
  '
  '
  xassigns:
  '========
  '
  if noto
    w1=""
    wt+=operi(11,typc,w1)
    noto=0 'NOT
  endif
  '
  'NO FURTHER OPERATOR SO
  'ASSIGN TO LEFT OR MAKE COMPARISON
  '
  'STRING ACCUM: join strings
  '--------------------------
  '
  if jn
    if funi
      lcl=1 : lcls=1
    endif
    if typc<0x80
      wt+=numtostr(typx,typc)
      typc=typx
    endif
    '
    'CONCATENATE NOW (OTHERWISE CONCAT ON ASSIGN)
    '
    tya1=typx
    if iszstra(tya1)=0 'exclude zstring variable assigns
      if typx
        typc=typx
      endif
      if typc<0x80
        typc=1 'STRING TO VAL CONVERSION LATER
      endif
      typc=upgradelen(0xc1,typc)
      wt+=operi(96,typc,qeax) 'CONCATENATE
      if (parx>0)or(typx<0x80)
        wt+=logas() 'mark as temp for deletion
      endif
    endif
  endif
  '
  '
  'NON NESTED COMPARATORS
  '
  if cp
    '
    ''HIGHER TYPE COMPARE
    if typc>=typh
      if findop(typc,cpsh,w2)
        newcleanvar(w5,null,4) 'BOOLEAN
        if savh
          hlex+=w2+"("+w5+cm+waccp+")"+cr
        else
          hlex+=w2+"("+w5+cm+waccp+cm+wacc+")"+cr
        endif
        wacc=w5
        rps=1
        skiplspace(s,i)
        typc=4
        typa=4
        if cnd
          hlex+="="+wacc+cr 'load to eax
        endif
       goto endexpr
      else
        ert=433 : ers="requires operator: "+cpsh
        goto exitexpr
     endif
    endif
    '
    'STRING COMARE OPTIMIZATION
    a=isstr(typc)
    if a
      if (op<2)and((typc and 15)=1)and((tp and 15)=1)
        a=instrevn(-1,wt,"|op 2 ") 'FIND 'SAVE TO TEMP'
        b=instr(a+1,wt,"|cv ") 'TO EXCLUDE CONVERSIONS
        if b=0
          typ=typa
          a=instr(a+1,wt,cr)+1
          if usx
            wt=left(wt,a)+wp
            if isdstr(usx)
              wt+=logas()
            endif
          else
            nstod=1
            wt=left(wt,a)+makestrptrfun(wr) 'REMOVE CAT CODE FOR DIRECT COMPARE
            nstod=0
            if dts>0
              dts-- 'NO TEMP STRING ON RIGHT SIDE
            endif
          endif
        endif
      endif
      'usx=0
      a=1
    endif 'isstr
    '
    'DIRECT JUMP (OPTIMISATION)
    'but not for strings (due to garbage collection call)
    '
    if (a=0)and(ctal=1)and(nst=0)and(dts<=0)
      if cnd=1
        cp xor=1 'OPPOSITE LOGIC
      endif
      cp+=0x70
      ctal=-16
    endif
    '
    wt+=cvtai(typc,tp)+operi(cp,tp,w4)
    'typc=tp
    typc=cpuw
    op=cp
    '
    if cnd=0
      typc=cpuw 'IIF EXPRESSION : A>B ? A : B
    endif
    '
  endif 'cp
  usx=0
  '
  '
  'PREPARE FOR ASSIGNMENT
  '
  if (typx<>0)and(cnd=0)
    if parx
      typa=typc 'ENSURE ANY 'convert' STICKS
    endif
    wt+=cvtai(typc,typx) : typc=typx 'CONVERT TO ASSIGNMENT TYPE
  endif
  '
  '
  endexpr: 'RECORD STATE AT END OF EXPRESSION
  '========
  '
  if lazn
    if opcn=lazn
      'REMOVE WT ASSIGNMENTS & OPERATIONS
      a=1
    else
      'REMOVE LAZY JUMPS
      a=0
    endif
    removemarked(epfx,chr(2),a)   'ASSIGNMENTS
    removemarked(wt,chr(2),a)     'OPERATIONS
    removemarked(epfx,chr(3),1-a) 'LAZY JUMPS
  endif
  '
  if hlex
    if nst
      if findop(typc,"save",w2)
        newcleanvar(wacc,null,typc)
        hlex+=w2+"("+wacc+")"+cr
      endif
    endif
    hiex+=hlex
    rps or=1
  endif
  '
  'RETURNING HIGHER ACCUM ADDRESS
  if uex>=4096
    accg=wacc
    wr=pword(wacc,1)
  endif
  '
  wg=wr 'global to carry wr
  '
  ascw=asc(wg)
  skiplspace(s,i)
  opg=op or uex : op=0
  'uex flag 'ALWAYS USE FULL EXPRESSION (not a variable)
  '
  if opg<2
    typg=typa
  else
    typg=typc
  endif
  if typu
    if isstr(typg)
      typg=(typg or typu) and 0xfffe
    endif
  endif
  '
  typ=typc
  '
  if nst<>nsl
    ert=438
    ers="expression nesting"
  endif
  return wt
  '
  exitexpr:
  '========
  '
  end function 'expressions
  '
  '
  '
  function arrayres(string*s, int*i, string*wr) as string
  =======================================================
  '
  int a,indi,opi,ocnstr
  int mpi,mci,typv,ni,varfi,cndi
  string wf,wri,sigi,sogi,oui
  '
  'SAVE STATE
  '
  mci=mc
  opi=op
  mpi=mp
  ocnstr=cnstr
  varfi=varf
  cndi=cnd
  oui=ou
  sigi=sig
  sogi=sog
  '
  op=-1
  typv=typ
  tye=0
  cnd=0
  cnstr=0
  arf=opi 'FLAG ARRAY OPERATOR (assign=2 etc)
  parx++
  indi=ind
  '
  if indi
    if cpoint
      wri=wr : wr=pedi
      ni=isptr(ou,1)
    endif
  endif
  wu=wr
  arcn++
  wf=express(s,i,typv) 'MAY BE RECURSIVE
  arcn--
  if indi
    if cpoint
      wpfx=""
      indiri(wri,ni+1)
      wf=wpfx+wf
    endif
  endif
  if varf
    if varf>10
      varf=10 'object offset resolved: this.obj[n].act
    endif
    varfi=varf 'pass back
  endif
  wr=wg 'set by express
  '
  parx--
  '
  typ=typv 'CHANGE TYPE IF ELEMENT
  '
  'RESTORE STATE
  '
  ind=indi
  op=opi
  cnstr=ocnstr
  mp=mpi
  mc=mci
  varf=varfi
  cnd=cndi
  sig=sigi
  sog=sogi
  ou=oui
  arf=-1 'set array resolution flag
  return wf
  '
  end function



  function namedparams(string *wr,*s, int *i,igb,*ct) as int
  ==========================================================
  int a,b,k,kk,kr,m,oo,sb,vf,mj
  string wd
  '
  vf=varf
  if vf=8
    m=mp : oo=1
  else 'vf>8
   m=drc(mp).a-typh : oo=-1
  endif
  '
  mj=m
  do
    dvm=""
    '
    kk=ascn
    if vf=8
      if mj
         mj=nextproc(mj,wd,0)
         oo=1
      else
        oo=0
      endif
      ascn=kk
    else 'vf<>8 METHODS
      findmember(wr,wd,oo) 'locate prior matching name (reverse order)
    endif
    ascn=kk
    '
    if oo=0
      exit do 'NO FURTHER FINDS
    endif
    ct++
    if dvm
      k=1
      sb=subsas(s,i,dvm,igb)
      if sb
        exit do   'SUCCESFUL SUBSTUTION
      endif
    endif
  loop
  '
  if k
    if sb=0
      ers="unable to match param names" : ert=106
      k=0
    endif
  endif
  '
  return k
  '
  end function
  '
  '
  '
  '====================================================================================
  '
  '
  '   ########    ########     #######     #######
  '   # PROCS #   #       #   # RECUR #   #       #
  '   #       #   #       #   #       #   #                   #
  '   #       #   #       #   #       #   #           ###########  CALL + EXPRESSIONS
  '   ########    ########    #       #   #                   #
  '   #           #   ##      #       #   #
  '   #           #     ##    #       #   #       #    
  '   #           #       ##   #######     #######
  '
  string owv 'byval return variable
  '
  function procedures(string*s, int*i, string*wr) as string
  =========================================================
  '
  ' predefine sig
  int mqo,mqp,typn,a,b,c,d,e,k,m,mj,ct,pb,pn,po,cc,qf,ofpu,igb,eqf,cbj
  int wff,tff,lid,vp,lvaf,stk,sti,px,cts,lv,lb,nsd
  string w1,w2,w3,w4,w5,w6,paramcode,wd,we,wp,wo,wf
  string sigs,sigd,rgst
  '
  'FUNCTION CALL
  '-------------
  '
  '
  lcl=1
  parx++
  w4=wr
  if w4="fwd"
    w4+=" "+mword(s,i)
  endif
  '
  '
  'RECURSION SUPPORT
  '-----------------
  '
  'procedures with parameters containing procedures
  '
  mqo=op
  mqp=mp
  typn=typ
  sigs=""
  vp=varf
  tff=toff
  stk=stkb
  a=0
  if asc(ow)=lbr
    wp=mrcso(mp,0)
  else
    wp=ow
  endif
  a=colom(strptr(wp),len(wp))
  if a
    nsd=a-2
    wp=mid(wp,a+1)
  endif
  w5=wpfx
  stkb=0
  rgst=regst
  '
  ct=drc(mp).a
  if ct>=typh
    if varf=8
      ct=-5 'FUNCTION TABLES
    endif
  endif
  lvaf=vaf : vaf=vp      'methods with parameters containing methods
  pb=pc                  'param stack index
  '
  '
  'itr linux calling conventions
  '
  'PROVISIONAL BEFORE SIGNATURE MATCHING
  cc=ccx
  '
  if ct=-4
    'UNPROTOTYPED CALLS
    nextproc(mp,w4,lb)
    cc=cco
    if lb>0
      w4=addlproc(lb,w4) 'GET VECTOR (OR CREATE IT)
    endif
  elseif ct=-17
    cc=17 'FPU CALL
  endif
  '

  if cc=0
    if cpuw=8
      cc=2 'MS64
    endif
  endif
  '
  '
  'RESOLVE ELEMENT NAME
  '--------------------
  '
  'IS CLIPPING FIRST PART OF NAME REQUIRED?
  '
  c=instr(wp,".")
  if c
    we=mid(wp,c+1)
  else
    we=wp
  endif
  '
  '
  '
  'LOOK AHEAD FOR LEFT BRACKET
  '---------------------------
  '
  a=i : nextinstruct(s,i)
  '
  if ascn=lbr
    igb=1 : i++    'IGNORE ( .. )
    nextinstruct(s,i)
  else
    i=a : skiplspace(s,i) 'RESTORE PRIOR POSITION
  endif
  '
  a=4
  select ascn
  case 41
    a=1 '()
    c=i : i+=1 : skiplspace(s,i)
    if (ascn=61)and(cnd=0)and(nst=0)
      eqf=1 : i++ : igb=0
    else
      i=c
    endif
    skiplspace(s,i)
  case 61 : eqf=1 : i++ : skiplspace(s,i) 'MARK ONE-PRAM PSEUDO-ASSIGN f=...
  case 91 : '[ drop thru
  case 44 :
  if igb=0 
    goto xparams ',
  endif
  case 43 : goto xparams '+
  case 47 : goto xparams '/
  case 92 : goto xparams '\
  case else
    if isendofexpr(s,i)
      a=1 'no params offered, possibly optional or default params
    else
      w1=wordahead(s,i) 'could be named param
      'SELECTED PARAM MODE? eg (b=4,c=5)
      if asc(s,nwd)=61
        if asc(s,nwd+1)<>61 'EXCLUDE ==
          a=2
        endif
      endif
    endif
  end select
  '
  'MACRO EXPANSION OF PARAM SETS
  '-----------------------------
  w1=wordahead(s,i)
  int ta=asc(w1)
  if isa(ta)
    m=lookupm(w1)
    if mp
      if drc(m).a=-18
        i=nwd
        wr=lomac(m,s,i) 'LOW LEVEL MACRO ONLY
        inserts(s,wr,i) : skiplspace(s,i)
      endif
    endif
  endif
  '
  '
  if a
    '
    b=namedparams(we,s,i,igb,cts)
    '
    if a=2
      if b=0
        if not ert
          ers="Default Params not available" : ert=110
        endif
      endif
    endif
    '
    if ert
      exit function
    endif
    '
    if b
      i++ : igb=1 'skip left bracket & will ignore right bracket
    endif
    if isxn
      if eqf=0
        goto xparams 'NO PARAMS PROVIDED
      endif
    endif
    '
  endif 'a
  '
  '=========================
  'PROCEDURE CALL PRODUCTION
  '=========================
  '
  'RECURSIVE:  PROC ----> EXPRESSIONS CONTAINING PROCS
  '
  '------------------------------------------------------------------
  '
  ' CALLING-CONVENTION -> PARAMS-REGS/STACK -> 
  '
  ' PARAMS -> EXPR + TYPE -> BUILD-SIG -> MATCH-SIG -> CONVERSIONS ->
  '
  ' BYVAL/BYREF -> TEMP-STORAGE ->
  '
  '
  ' CALL-DIRECT/INDIRECT/METHOD -> CLEANUPS -> COMPOSE
  '
  pdr++ 'PROCEDURE NESTING DEPTH COUNTER

  '
  'FOR UDTs PASSED BYVAL UNPROTOTYPED
  dprm=0
  if cpuw=8
    aprm[1]=0
    aprm[2]=0
    aprm[3]=0
    aprm[4]=0
  endif
  '
  do ' each param
    '
    if (ascn=123)or(ascn=125)
      exit do
    elseif (ascn=0x65)or(ascn=0x74)
      wah=wordahead(s,i)
      if idword(" then else elseif endif end to ",wah)
        exit do
      endif
    endif
    '
    'LOOSE TYPE IDENTITY
    '
    lid=0
    if (ascn=38)or(ascn=42)or(ascn=63)
      lid=1
      if ascn=38
        a=ascl(s,i+1)
        if (a=0x68)or(a=0x6f)
          lid=0 'avoiding &h &o
        endif
      endif
    endif
    '
    qf=0 : sog="a" : w1=""
    pc++    'PARAM COUNTER
    pn++    'PARAMETER NUMBER COUNTER
    po=pc    'RETAIN COUNTER DURING RECURSION
    ofpu=fpum 'RETAIN FPU FLAG
    sti=0    'param stack allocation increment
    '
    'CHECK FOR LOWER PROCEDURES AND MACROS
    '
    a=1
    select ct
    case 0,-4,-18,-19,-20
      a=0
    end select
    '
    '
    b=0 : c=48 : sog="" : w2=""
    op=0 : typg=0
    '
    if cc=17
      b=0x68 'FPU INTRINSICS
    endif
    '
    m=i : pex(pc)=captsx(s,i) : i=m 'SOURCE EXPRESSION
    owv=""
    wd=express(s,i,b)
    if ert
      goto xprocs
    endif
    '
    k=asc(wg)
    '
    if bvg 
      c=95 '_' BYVAL: TURN OFF TYPE MATCHING
    endif
    '
    'FPU CALLING CONVENTION OR OTHERWISE
    if cc=17 'FPU MACRO
      '
      w1=""
      '
    else 'cc<>17 (NOT FPU)
      '
      if typg=0
        typg=cpuw 'default type
      endif
      '
      'PRECALC PARAMS CONTAINING CALLS (RECURSIVE)
      '
      if opg>=4096
        epfx+=wd
        wd="lea "+qeax+cm+wg+cr 'accg
        opg=1
      elseif opg>=1024 'PROCEDURE PARAMS
        b=typg
        e=indt
        d=ascn
        if b>=0x80  'STRINGS AND HIGHER TYPE POINTERS
          b=cpuw
        elseif e  'RETURNING POINTER
          b=cpuw
          'typg=cpuw
        endif
        if owv
          epfx+=wd
          wg=owv
          opg=1
        else
          opg=1024
          w2=newtmpvar(typename(b))
          wg=mrcso(qme,1)
          w2=""
          epfx+=wd+operi(2,b,wg) 'PROCESS AND SAVE IN ADVANCE
        endif
        wd=operi(1,b,wg)
        ascn=d
        indt=e
        ind=indt
      endif 'OPG
      '
      if (a=0)and(opg<=1) 'UNPROTOTYPED
        if isstr(typg)
          dts--
          typ=typg
          makestrptr(wg)
        endif
        '
        if cpuw=4 '32BIT UNPROTOTYPED
          if (bvg=1)and(typg>=typh)
            b=cco : cco=cc
            if typg>=typh and bvg=0
              e=49
            else
              e=0
            endif
            w1=callcnv(pn,wg,e)
            cco=b
          else
            noprototype(wd,w1)
            w1=operi(4,typg,w1)
          endif
          if (typg and 8)=8
            sti=8
          else
            sti=cpuw
          endif
          stkb+=sti
          goto dparams
        endif
      endif
      '
      '
      if cpuw=8 '64BIT ALL TYPES
        w2=cpua
        if a=0 'UNPROTOTYPED
          if (bvg=1)and(typg>=typh)
            w2=wg
          else
            if opg<=1
              noprototype(wd,w2)
            endif
          endif
        endif
        '
        b=cco : cco=cc
        if typg>=typh and bvg=0
          e=49
        else
          e=0
        endif
        w1=callcnv(pn,w2,e)
        cco=b
        '
        if (cc=2)or(cc=3)
          if vaf>8
            b=1
          else
            b=0
          endif
          if pn+b>4
            sti=cpuw 'itr simd registers
          endif
        else
          sti=cpuw
        endif
      else 'cpuw=4
        b=typg
        if b>=typh
          b=cpuw
        endif
        if isfpu(b)
          w1=""
        else
          w1=qeax
        endif
        w1=operi(4,b,w1) 'DEFAULT
        sti=cpuw
      endif 'cpuw
      '
      stkb+=sti
    endif 'fpu / not fpu macro
    '
    if a=0
      goto dparams 'NO SIGNATURE
    endif
    '
    '---------------
    'BUILD SIGNATURE
    '===============
    '
    'to match with overloadable procs
    '
    'GENERAL TYPES
    '
    if (lid>0)and(opg<2)
      sog="sys"
    elseif typg<typh
      a=typg and 0x7fffffe0
      if a=0xc0
        a=typg+32
      else
        a=typg 'bstring gets labelled as string
      endif
      sog=typename(a)
      if sog=""
        sog="any"
      endif
    endif
    '
    a=opg and 0x3ff
    if a<2
      if (typg>=typh)or(ind>0)or(len(wpfx)<>0)
        if c<>95
          int g=asc(wg)
          if isq(g)
            'excluding o2 literal strings
          else
            c=49 'default byref
            'if ind
            '  if varf=3
            '    ind-=1
            '  endif
            '  c=48+ind
            'endif
            if asc(wpfx)=46
              'strptr etc
              if instr(wpfx,"._direct_")=1
                c=48
              endif
            endif
          endif
        endif
      endif
    endif
    '
    sigs+="#"+sog
    sigd+=chr(c)
    '
    '
    '
    dparams: 'bypass signature building for low level calls
    =======================================================
    '
    '
    if ert>0
      goto xparams
    endif
    '
    -----------------------------------------
    ' CAPTURE EXPRESSION TYPE CONVERSION CODE
    ' REFERENCING / DEREFERENCING CODE
    ' TEMP STORAGE
    =========================================
    '
    pc=po : fpum=ofpu ' RESTORES AFTER RECURSION
    '
    por(pc)=accg 'LAST TERM
    paw(pc)=wg   'LAST OPERAND
    pas(pc)=wd   'LAST EXPRESSION
    pat(pc)=typg 'LAST TYPE RETURNED
    pet(pc)=typg 'EFFECTIVE TYPE
    pao(pc)=opg  'LAST OPERATOR
    pav(pc)=w1   'DEFAULT COMPATIBILITY CODE (usually push eax)
    pax(pc)=wpfx 'INDIRECT
    pst(pc)=sti  'STACK INCREMENT
    '
    =============================
    nparams: 'CHECK END OF PARAMS
    =============================
    '
    '
    if iss(ascn)
      'RIGHT BRACKET CHECK AHEAD
      a=i : b=ascn : nextinstruct(s,i)
      if ascn<>rbr
        i=a : ascn=b : exit do
      endif
    endif
    '
    if ascn=44
      i++ : nextinstruct(s,i)
    endif
    '
    if ascn=rbr
      if (cnd=0)and(nst<2)
        a=i+1
        if wordahead(s,a)="="
          i=nwd
          igb=0  'itr err trap missing left bracket?
          continue do  'COMMAND FUNCTIONS
        endif
      endif
      exit do
    endif
    '
  '---------------
  loop 'NEXT PARAM
  '---------------
  '
  pdr--
  '
  '=======
  xparams:
  '=======
  '
  '
  pls="0"
  '
  if igb
    if ascn=rbr
      i++
    else
      ers="Missing right bracket" : ert=124 : exit function
    endif
  endif
  '
  pas(pc+1)="" 'CLEAR AFTER-CALL CODE
  skiplspace(s,i)
  '
  '
  if tranpass=1
    pc=pb
    goto xprocs 'NO PARAM MATCHING OR CALL ENCODING
  endif
  '
  'SIGNATURE MATCHING (typ is also identified)
  '-------------------------------------------
  '
  uk=1     'REQUIRE EXACT PARAM MATCHING
  typ=typn 'DEFAULT TYPE
  cco=cc   'PRESET CALLING CONVENTION
  mtyp=0   'CLEAR METATYPE
  '
  if (vp>8)or(ct=-5)or(ct=-16)
    '
    'whole signature matching
    '
    if sigs
      sigs+="@"+sigd ' 1/0 byref/byval
    else
      sigs="#@"
    endif
    '
    if vp=8
      if instr(wp,".")=0 
        uk or= 8 'REQUIRE PARAM MATCH FOR FUNCTIONS
      endif
    endif
    '
    '
    'MATCH FOR OVERLOADED PROCEDURES
    '-------------------------------
    '
    'FOR FUNCTIONS/SUBS/OPERATIONS (nextproc) AND METHODS (findmember)
    '
    if cts<=1
      uk or=6 'ALLOW ANY CONVERSION. NO OVERLOADING AVAILABLE
    endif
    mp=mqp
    '
    rmatchproc:
    '==========
    '
    mj=mqp
    w2=""
    m=0
    '
    a=uk and 8
    if a=0
      k=-1
    else
      k=1
    endif
    '
    do
      if a 'MATCH FUNCTIONS
        if mj
          mj=nextproc(mj,we,lb) 'returns prior proc
          k=2
          cc=cco
        else
          k=0 'end of proc overloads
        endif
      else 'MATCH METHODS
        findmember(we,wd,k)
        if k 
          if (varf=5)or(varf=6)
            k=0 'group header located
          else
            cc=cco 'calling convention
          endif
        endif
      endif
      '
      '
      if k=0
        exit do 'fail
      elseif sig=""
        exit do 'unprototyped
      endif
      '
      stkb=0 'FOR COMPAT SIG CDECL
      '
      if (typ>=typh)and(indt=0)
        coret=1 'CALLER ORIGINATED RETURN
      endif
      '
      mpfx="" 'precoding string
      '
      if compatsig(sigs,sig,pb)
        if ert
          goto xprocs
        endif
        exit do 'success
      else
        '
        'BUILD LIST OF OVERLOADED FUNCTIONS LIST
        '
        if (uk and 4)=4
          if sog="bstr"
            sog="string"
          endif
          if len(sog)=1
            sog=""
          endif
          if sog
            sog=" returns "+sog
          endif
          w3=splitsig(sig) 'remove indirection codes
          replace(w3,"#",",")
          w2+=wp+"("+mid(w3,2)+")"+sog+cr
        endif
      endif
    loop
    '
    '
    if k=0
      if (uk and 2)=0
        uk or=2 : goto rmatchproc 'TRY AGAIN ALLOWING LIMITED TYPE CONVERSIONS THIS TIME
      elseif (uk and 4)=0
        uk or=4 : goto rmatchproc 'TRY AGAIN ALLOWING NUMBER<->STRING CONVERSIONS
      endif
    endif
    '
    uk=0     'must be set to 0 when done
    wff=woff 'OFFSET
    '
    '
    '-------------------
    'MATCH UNSUCCESSFUL?
    '===================
    '
    if k=0
      ers="parameters mismatch for procedure "+wp+cr+_
      "params given : "+sigs+cr+cr+"OPTIONS:"+cr+w2+cr
      ert=13
    endif
    '
    matchok:
    '========
    '
    if ert
      goto xprocs
    endif
    '
    '
    cc=cco   '
    ct=-mtyp '0 IF A METHOD
    '
    if ct=-5
      if (lb>0)  'IMPORTED FUNCTIONS
        we=addlproc(lb,we) 'GET VECTOR (OR CREATE IT)
      endif
    endif
    if (ct=-5)or(ct=-16)
      '
      'FORMULATE CALL NAME
      '
      a=asc(we)
      if isn(a)
        w4="["+qebx+"+"+we+"]" 'GLOBAL VECTORED CALL
      elseif a=91
        w4=we 'VECTORED CALL
      else
        w4=we 'NAME WITH NAMESPACE
      endif
      '
      'IS CHAR WIDTH INFO REQUIRED? (built-in string functions only)
      '=============================================================
      '
      'if ct=-16
        if idword(" string ",wp)
          typg=pat(pb+2) 'check type of second param
        elseif idword(" space nuls stringbytes ",wp)
          if isstr(typn)
            typg=0xc0 or (typn and 15) 'the char width expected by the assignee
          else
            typg=0xc1 'ASSUME BYTE BSTRING
          endif
        elseif idword(" left mid mid_ ",wp)
          typg=pat(pb+1) 'check type of first param
        endif
        '
        if isstr(typg)
          a=typg and 15
          w5+="|ch "+chr(48+a)+cr 'calls charwidth(a) 'cast string param
        else
          a=0
        endif
        '
        if a
          if isstr(typ)
            typ=upgradelen(typ,a) 'cast string width according to a string param
          endif
        endif
      'endif 'ct=-16
    endif
    '
    skiplspace(s,i)
    '
  endif ' END OF SIG MATCHING
  '
  if ert
    goto xprocs
  endif
  '
  '
  '
  '
  ' #######
  ' # CALL # 
  ' #      #
  ' ####### 
  ' # METH #
  ' #      #
  ' #######
  '
  '
  'RESTORE STATE VARIABLES
  '
  varf=vp
  toff=tff
  woff=wff
  mp=mqp
  regst=rgst
  '
  'BUILD PARAMETER BLOCK
  '
  paramcode=buildparamblock(pb,cc)
  w1="" 'space allocate
  w2="" 'space disallocate
  a=instr(wp,".")+1 'supporting class members
  'wp original proc name (from ow)
  'w4 call vector or name
  'w5 wpfx
  if nsd
    nsp=drc(mqp).l 'namespace
  endif
  w3=w5+prepcall(wp,w4,mid(wp,a)+splitsig(sig),cc,pc-pb)
  '
  if typ>=typh
    if (indt=0)and(nobj=0)
      'ALLOCATE RETURN VAR
      m=typ
      newcleanvar(owa,w4,m)
      owv=w4
      '
      if (cc=2)or(cc=3)
        w6="lea rdx,"+w4+cr+
        "mov [rsp+8],rdx"+cr
      else
        w6="lea rdx,"+w4+cr+"push rdx"+cr
        if vaf<=8
          w6+="push 0"+cr
        endif
      endif
      w3=w6+w3
      wg=w4 'RETURNED OBJECT
      typ=m
    endif
  endif
  '
  '
  a=0 'temp storage value
  b=0
  '
  '
  'ALLOCATE SPACE FOR LOCAL TEMP STORAGE
  '
  if cpuw=8
    a-=tmpstk
  endif
  '
  if a<0
    w1="|sp "+str(a)+cr
  endif
  '
  'SPACE DISALLOCATION
  '
  b=0
  '
  if cc=1
    b=stkb  'CDECL STACK CLEANUP N BYTES
  endif
  '
  'ALSO DISCARD TEMP STORAGE
  '
  if cpuw=8
    b=tmpstk 'for reg spill zone ms64 calling convention
  endif
  '
  '
  if b
    w2="|sp "+str(b)+cr
  endif
  '
  'RELEASE TEMP STORAGE OFFSET (but not for statics)
  '
  '
  '======
  xprocs:
  '======
  '
  'FREE PARAM STACK
  '
  pc=pb : vaf=lvaf 'VARF
  stkb=stk 'PRIOR BYTES ON STACK
  '
  '
  coret=0
  parx--
  '
  return w1+paramcode+w3+w2
  '
  end function ' procedures
