( usage: cat file.tal | drifloon.rom > output.rom ) |10 @Console &vector $2 &read $1 &pad $4 &type $1 &write $1 &error $1 |000 @scope $30 @sublabel $30 @head $2 @length $2 @token $2 @halt $1 @scan $1 |100 @on-reset ( -> ) ;on-console .Console/vector DEO2 BRK @on-console ( -> ) .Console/read DEI DUP ?{ POP BRK } BRK ( @|loader ) @ ( chr -- ) ( normalize ) #20 GTHk [ JMP SWP POP ] ( join ) [ LIT &last-a 20 ] OVR ,&last-a STR ( skip ) DUP2 #2020 EQU2 ?&end #20 NEQ ?{ DUP [ LIT "[ ] EQU ?&skip DUP [ LIT "] ] EQU ?&skip DUP [ LIT "( ] EQU ? DUP [ LIT ") ] EQU ? } [ LIT &mute 01 ] ?{ &skip POP JMP2r } ( join ) [ LIT &last-b 20 ] OVR ,&last-b STR ( skip ) DUP2 #2020 EQU2 ?&end POP #00 [ LIT2 &ptr =input-buf ] STA2k INC2 ,&ptr STR2 &end ( chr last -- ) POP2 JMP2r @ ( chr -: ) [ LIT "( ] SUB ;/mute STA JMP2r ( @|assembly ) @ ( -: ) ;/ptr LDA2 INC2 ( ) DUP2 ;/ptr STA2 ( ) ;find-symbol/ptr STA2 ;input-buf #01 handle-pass ?exit #00 handle-pass ?exit @write-rom ( -- ) ;rom .length LDZ2 INC2 ADD2 ;rom/output &l ( -- ) LDAk #18 DEO INC2 NEQ2k ?&l POP2 POP2 ( >> ) @print-unused ( -- ) ;/ptr LDA2 ;find-symbol/ptr LDA2 &l ( -- ) INC2k INC2 LDA ?&>skip #0003 ADD2 LDAk [ LIT "A ] SUB #1a LTH ?&>skip DUP2 ;dict/reset scmp ?&>skip ;dict/unused DUP2 / #0a19 DEO &>skip scap/ INC2 GTH2k ?&l POP2 POP2 ( >> ) @print-summary ( -- ) ;dict/assembled .length LDZ2 #00ff SUB2 ;dict/bytes ;/count LDA2 ;dict/labels ;dict/end ( >> ) @exit ( -- ) [ LIT2 80 -halt ] LDZ ORA #0f DEO JMP2r @handle-pass ( scan -- err ) .scan STZ #0100 #00 ;Lambda/count STA ;dict/reset ;input-buf &w ( -- ) DUP2 .token STZ2 DUP2 .halt LDZ ?&end scap/ INC2 LDAk ?&w &end POP2 .halt LDZ JMP2r ( @|tokenizer ) @ ( t* -- ) LDAk ,&rune STR ;runes/end ;runes &l ( -- ) LDAk [ LIT &rune $1 ] NEQ ?{ NIP2 INC2 LDA2 ( * ) JMP2 } #0003 ADD2 GTH2k ?&l POP2 POP2 ( | non-runic ) is-hex ? is-opcode ? !lib/litjsi @lib &padabs INC2 get-any ! &padrel INC2 get-any .head LDZ2 ADD2 ! &toplab INC2 ! &sublab INC2 get-sublabel ! &litrel #80 &rawrel INC2 get-rel ! &litzep #80 &rawzep INC2 get-ref NIP ! &litabs #a0 &rawabs INC2 get-ref ! &litjci INC2 #20 ! &litjmi INC2 #40 ! &litjsi #60 ! &lithex INC2 ! &rawstr INC2 !/ &lambda POP2 !Lambda/pop &ignore JMP2r ( @|primitives ) @ ( str* -: ) LDAk INC2 & LDAk ? POP2 JMP2r @ ( str* -: ) find-opcode ! @ ( str* -: ) DUP2 slen NIP ( LIT ) DUP #04 EQU #50 SFT #80 ORA ! @ ( str* -: ) DUP2 slen NIP ( >> ) @ ( str* len -- ) DUP #02 NEQ ?{ POP shex NIP ! } #04 NEQ ?{ shex ! } POP2 ;err/number ! @ ( str* opc -: ) get-ref .head LDZ2 INC2 INC2 SUB2 ( >> ) @ ( short* -: ) SWP ( >> ) @ ( byte -: ) DUP .head LDZ2 INC2k STH2 ;rom ADD2 STA STH2r ( >> ) @ ( v* -: ) .head STZ2 JMP2r @ ( name* -- ) ;err #2019 DEO .token LDZ2 / ;dict/in .scope LDZ2 / [ LIT2 ". 19 ] DEO #0a19 DEO [ LIT2 01 -halt ] STZ JMP2r @ ( byte -- ) ?{ JMP2r } .scan LDZ ?{ JMP2r } .head LDZ2 ( ) DUP2 OVR ?{ ;err/zeropage } ( ) #8000 LTH2 ?{ ;err/length } .length STZ2 JMP2r ( @|labels ) @get-sublabel ( name* -- sublabel* ) DUP2 slen ;sublabel slen ADD2 #0030 LTH2 ?{ ;err/sublabel ! } [ LIT2 &ptr $2 ] ;sublabel JMP2r @ ( t* -- ) ( | copy scope until sublabel ) DUP2 [ LITr -scope ] &w ( -- ) LDAk [ LIT "/ ] EQU ?&end LDAk STHkr STZ INCr INC2 LDAk ?&w &end POP2 #00 STHr STZ ( | prepare sublabel pointer ) ;scope ;sublabel [ LIT2 "/ 00 ] ;sublabel scap/ ( ptr ) INC2k ,get-sublabel/ptr STR2 ( cap ) STA2 ( >> ) @ ( name* -: ) .scan LDZ ?{ POP2 JMP2r } is-hex ?&invalid is-opcode ?&invalid DUP2 find-symbol INC2 ORA ?¬-unique ( addr* ) .head LDZ2 [ LIT2 &ptr $2 ] STH2k INC2r INC2r STA2 ( refs ) #00 STH2kr INC2r STA ( name[] ) DUP2 STH2kr slen STH2r ADD2 INC2 ,&ptr STR2 [ LIT2 &count $2 ] INC2 ,&count STR2 JMP2r &invalid ( name* -- ) POP2 ;err/symbol ! ¬-unique ( name* -- ) POP2 ;err/duplicate ! @find-symbol ( name* -- * ) ,&t STR2 ;/ptr LDA2 [ LIT2 &ptr $2 ] &l ( -- ) EQU2k ?&end #0003 ADD2 DUP2 [ LIT2 &t $2 ] scmp ?&found scap/ INC2 GTH2k ?&l &end POP2 POP2 #ffff JMP2r &found ( symbols* -- * ) #0003 SUB2 NIP2 JMP2r @get-any ( str* -- value* ) is-hex ?shex !get-ref/eager @get-ref ( token* -- addr* ) LDAk [ LIT "{ ] NEQ ?{ POP2 Lambda/push } .scan LDZ ?&scan &eager ( -- ) LDAk [ LIT "& ] NEQ ?{ INC2 get-sublabel } LDAk [ LIT "/ ] NEQ ?{ INC2 get-sublabel } find-symbol INC2k #0000 EQU2 ?{ INC2k INC2 LDAk INC ROT ROT STA LDA2 &scan JMP2r } ;err/reference ! @get-rel ( label* -- distance ) get-ref .head LDZ2 INC2 INC2 SUB2 ( ) DUP2 #0080 ADD2 POP ?{ NIP JMP2r } ( ) .scan LDZ ?{ ;err/distance } POP2 #ff JMP2r @is-hex ( str* -- str* f ) DUP2 &w ( -- ) LDAk chex INC ?{ POP2 #00 JMP2r } INC2 LDAk ?&w POP2 #01 JMP2r @is-opcode ( str* -- str* f ) DUP2 find-opcode ?{ DUP2 ;opcodes/brk !scmp3 } #01 JMP2r @find-opcode ( name* -- byte ) DUP2 ,&t STR2 #2000 &l ( -- ) #00 OVR #03 MUL ;opcodes ADD2 [ LIT2 &t $2 ] scmp3 ?&on-found INC GTHk ?&l POP2 POP2 #00 JMP2r &on-found ( name* bounds* -- byte ) ( LITk ) NIP DUP #00 EQU #70 SFT ORA STH ( modes ) #0003 ADD2 &w ( -- ) LDAk ?{ POP2 STHr JMP2r } LDAk [ LIT "2 ] NEQ ?{ LITr 20 ORAr } LDAk [ LIT "k ] NEQ ?{ LITr 80 ORAr } LDAk [ LIT "r ] NEQ ?{ LITr 40 ORAr } INC2 !&w ( @|lambda ) @Lambda &push ( -- name* ) [ LIT &count $1 ] INCk ,&count STR DUP [ LIT2 &ptr =&buf ] INC2k ,&ptr STR2 STA ( >> ) &name ( id -- str* ) #21 ADD ,&id STR ;&sym JMP2r &pop ( -- ) ,&ptr LDR2 #0001 SUB2 LDAk Lambda/name ,&ptr STR2 JMP2r &sym cebb &id $2 ( @|stdlib ) @scap ( str* -: end* ) INC2 & LDAk ?scap JMP2r @slen ( str* -: len* ) DUP2 scap/ SWP2 SUB2 JMP2r @scmp ( a* b* -- f ) STH2 &l ( -- ) LDAk ?{ &d LDA LDAr STHr EQU JMP2r } LDAk LDAkr STHr NEQ ?&d INC2 INC2r !&l @scmp3 ( a* b* -- f ) STH2 LDAkr LDAk STHr NEQ ?{ INC2r INC2 } LDA2r LDA2 STH2r EQU2 JMP2r @chex ( c -: ) [ LIT "0 ] SUB DUP #0a LTH ?&>end #27 SUB DUP #10 LTH ?&>end POP #ff &>end JMP2r @shex ( str* -: value* ) [ LIT2r 0000 ] &w ( `i* -- ) ( acc ) [ LITr 40 ] SFT2r ( res ) LDAk chex [ LITr 00 ] STH ADD2r INC2 LDAk ?&w POP2 STH2r JMP2r @ ( str* -- ) #00 ROT ROT &w ( -- ) LDAk #20 GTH ?{ STAk } INC2 LDAk ?&w STA JMP2r @ ( src* dst* -: ) STH2 &w ( src* `dst* -- ) LDAk #00 STH2kr STA2 INC2r INC2 LDAk ?&w POP2 POP2r JMP2r @ ( str* -: ) LDAk #19 DEO INC2 & LDAk ? POP2 JMP2r @ ( short* -- ) #2710 [ LIT2r 00fb ] &w ( -- ) DIV2k #000a DIV2k MUL2 SUB2 SWPr EQUk OVR STHkr EQU AND ?{ DUP [ LIT "0 ] ADD #19 DEO INCr } POP2 #000a DIV2 SWPr INCr STHkr ?&w POP2r POP2 POP2 JMP2r ( @|assets ) @dict &unused "-- 20 "Unused: 20 $1 &reset "RESET $1 &assembled "Assembled 20 $1 &in 20 "in 20 $1 &bytes 20 "bytes( $1 &end "). 0a $1 &labels 20 "labels $1 @err "!! 20 "Error: 20 $1 &duplicate "Duplicate $1 &number "Number $1 &length "Length $1 &reference "Reference $1 &sublabel "Sublabel $1 &distance "Distance $1 &symbol "Symbol $1 &zeropage "Zero-page $1 @opcodes [ "LIT "INC "POP "NIP "SWP "ROT "DUP "OVR "EQU "NEQ "GTH "LTH "JMP "JCN "JSR "STH "LDZ "STZ "LDR "STR "LDA "STA "DEI "DEO "ADD "SUB "MUL "DIV "AND "ORA "EOR "SFT &brk "BRK ] @runes [ "| =lib/padabs "$ =lib/padrel "@ =lib/toplab "& =lib/sublab "# =lib/lithex "} =lib/lambda ", =lib/litrel "_ =lib/rawrel ". =lib/litzep "- =lib/rawzep "; =lib/litabs "= =lib/rawabs "? =lib/litjci "! =lib/litjmi "" =lib/rawstr "~ =lib/ignore ] &end @Lambda/buf $100 @input-buf $2000 |8000 @rom $100 &output