@outcounter:   0
@incounter:    0
@number:       0
@numberstate:  0

@labeltable:   0
@labelindex:   0
@pointertable: 0
@pointerindex: 0
; allocated variables
0 0 0 0
0 0 0 0

Psh &init Jmp ; change to rjp(17)
  @printself ; prints everything after address 1000
Psh usercode(1000)
@quineloop
Dup Lds
; checksum
Dup Psh 5 Lds Add Psh 5 Str
; print number and comma
Psh -100 Str
Psh 44 Psh -101 Str
Psh 1 Add
; jump to end if done printing
Dup Psh &outcounter Lds
sUb iBz Not Psh &endquine Cjp
; restart
Psh &quineloop Jmp
@endquine
; print program length and "checksum"
Psh &printnewline cllF
Psh 999 sUb Psh -100 Str Psh &printnewline cllF
Psh 5 Lds Psh -100 Str Psh &printnewline cllF
Hlt

  @init
; fix variables
Psh 1000 Dup Psh &outcounter Str Psh &incounter Str
Psh 0 Dup Psh &number Str Psh &numberstate Str
; find end of program
Psh 1000
@tableloop
Dup Lds
Not
Psh &endtableloop Cjp
Psh 1000 Add ; u can lower this later
Psh &tableloop Jmp
@endtableloop
Psh 1 Add
Dup
Dup Psh &labeltable Str Psh &labelindex Str
Psh 1000 Add ; 500 labels
Dup Psh &pointertable Str Psh &pointerindex Str
Psh 65 Psh -101 Str Psh &printnewline cllF

  @start
Psh &getchar cllF
  @switchchar
Dup Psh &isnull cllF Psh &secondpass Cjp
Dup Psh &isat cllF Psh &parselabel Cjp
Dup Psh &isampersand cllF Psh &parsepointer Cjp
Dup Psh &issemicolon cllF Psh &parsecomment Cjp
Dup Psh &isminus cllF Psh &parsenumber Cjp
Dup Psh &isdigit cllF Psh &parsenumber Cjp
Dup Psh &isupperletter cllF Psh &parseopcode Cjp
popV Psh &start Jmp

  @isnull
Not Ret
  @isat
Psh at(64) sUb Not Ret
  @isampersand
Psh ampersand(38) sUb Not Ret
  @issemicolon
Psh semicolon(59) sUb Not Ret
  @isminus
Psh minus(45) sUb Not Ret
  @isdigit
Dup
Psh digitzero(48) sUb iBz Not
sWp Psh digitzero+ten(58) sUb iBz
Mul
Ret
  @isupperletter
Dup
Psh uppera(65) sUb iBz Not
sWp Psh uppera+twentysix(91) sUb iBz
Mul
Ret
  @islowerletter
Dup
Psh lowera(97) sUb iBz Not
sWp Psh lowera+twentysix(123) sUb iBz
Mul
Ret

  @parselabel
popV Psh 0
@lblloop
Psh &getchar cllF Dup
Psh &islowerletter cllF Not Psh &endlblloop Cjp
Psh lowera(97) sUb
sWp Psh 26 Mul Add
Psh &lblloop Jmp
@endlblloop
sWp
Psh &labelindex Lds Str
Psh &labelindex Lds Psh 1 Add
Psh &outcounter Lds
Psh 1000 sUb
ovrK Str
Psh 1 Add Psh &labelindex Str
Psh &switchchar Jmp

  @parsepointer
popV Psh 0
@ptrloop
Psh &getchar cllF Dup
Psh &islowerletter cllF Not Psh &endptrloop Cjp
Psh lowera(97) sUb
sWp Psh 26 Mul Add
Psh &ptrloop Jmp
@endptrloop
sWp
Psh &pointerindex Lds Str
Psh &pointerindex Lds Psh 1 Add
Psh &outcounter Lds ovrK Str
Psh 1 Add Psh &pointerindex Str
Psh -0 Psh &writeinstruction cllF
Psh &switchchar Jmp

  @parsecomment
popV
Psh &getchar cllF
Dup
Psh &isnull cllF
ovrK Psh 10 sUb Not
Add
Psh &switchchar Cjp
Psh &parsecomment Jmp

  @parsenumber
Dup Psh &isminus cllF Dup Not Psh &storesign Cjp
; change minus to zero
sWp Psh 3 Add sWp
@storesign
Not Psh 2 Mul Psh 1 sUb ; conver bool to sign
Psh &numberstate Str
@numberloop
Psh 48 sUb
Psh &number Lds
Psh 10 Mul Add
Psh &number Str
Psh &getchar cllF
Dup Psh &isdigit cllF Psh &numberloop Cjp
; write number
Psh &number Lds Psh &numberstate Lds
Mul Psh &writeinstruction cllF
Psh 0 Dup Psh &number Str Psh &numberstate Str
Psh &switchchar Jmp

  @parseopcode
Psh uppera(65) sUb
Psh &opcodetable Add Lds
Psh &writeinstruction cllF
Psh &start Jmp

  @opcodetable
add ibz cjp dup rjp cll rot hlt     jmp ovr lds mul
a09 b14 c16 d03 e17 f19 g06 h21 i-1 j15 k05 l07 m11

not nop psh rcj ret str     sub pop swp
n13 o00 p01 q18 r20 s08 t-1 u10 v02 w04 x-1 y-1 z-1

  @getchar
Psh &incounter Lds
Dup Lds
sWp
; increment by one
Psh 1 Add Psh &incounter Str
Ret

  @printnewline
Psh 10 Psh -101 Str Ret

  @writeinstruction
Psh &outcounter Lds sWp ovrK Str
Psh 1 Add Psh &outcounter Str
Ret

  @secondpass


  @jumpuser
popV Psh &printself Jmp
Psh usercode(1000) Jmp
