library TVM_Disasm // simple TVM Disassembler "Lists.fif" include variable @vmlibs dictnew @vmlibs ! { 256 u@ dup @vmlibs @ 256 udict@ } : vmlib@ { 8 u@+ swap 2 = } : libspecial? variable 'disasm { 'disasm @ execute } : disasm // disassemble a slice { = } { swap 1+ -rot $| 1 $| nip -leading rot } while drop tuple } cond } : parse-op { dup "s-1" $= { drop "s(-1)" true } { dup "s-2" $= { drop "s(-2)" true } { dup 1 $| swap "x" $= { nip "x{" swap $+ +"}" true } { 2drop false } cond } cond } cond } : adj-op-arg { over count over <= { drop } { 2dup [] adj-op-arg { swap []= } { drop } cond } cond } : adj-arg[] { 1 adj-arg[] 2 adj-arg[] 3 adj-arg[] dup first dup `XCHG eq? { drop dup count 2 = { tpop swap "s0" , swap , } if } { dup `LSHIFT eq? { drop dup count 2 = stack-disasm? and { second `LSHIFT# swap pair } if } { dup `RSHIFT eq? { drop dup count 2 = stack-disasm? and { second `RSHIFT# swap pair } if } { drop } cond } cond } cond } : adjust-op variable @cp @cp 0! variable @curop variable @contX variable @contY variable @cdict { atom>$ type } : .atom { dup first .atom dup count 1 > { space 0 over count 2- { 1+ 2dup [] type .", " } swap times 1+ [] type } { drop } cond } : std-show-op { 0 over count 1- { 1+ 2dup [] type space } swap times drop first .atom } : stk-show-op { ."// LIB: " swap X. cr ref@ " cr } : show-cont-op { swap scont-swap ":<{" show-cont-bodyx scont-swap "" show-cont-bodyx .indent ."}>" cr } : show-cont2-op { @contX @ null? { "CONT" show-cont-op } ifnot } : flush-contX { @contY @ null? { scont-swap "CONT" show-cont-op scont-swap } ifnot } : flush-contY { flush-contY flush-contX } : flush-cont { @contX @ null? not } : have-cont? { @contY @ null? not } : have-cont2? { flush-contY @contY ! scont-swap } : save-cont-body { @cdict ! } : save-const-dict { @cdict null! } : flush-dict { @cdict @ null? not } : have-dict? { flush-cont .indent type .":<{" cr @curop @ ref@ " cr } : show-ref-op { flush-contY .indent rot type .":<{" cr @curop @ ref@ " cr } : show-cont-ref-op { flush-cont .indent swap type .":<{" cr @curop @ ref@+ " cr } : show-ref2-op { flush-cont first atom>$ dup 5 $| drop "DICTI" $= swap .indent type ." {" cr +indent @cdict @ @cdict null! unpair rot { swap .indent . ."=> <{" cr +indent disasm -indent .indent ."}>" cr true } swap ' idictforeach ' dictforeach cond drop -indent .indent ."}" cr } : show-const-dict-op ( `PUSHCONT `PUSHREFCONT ) constant @PushContL ( `REPEAT `UNTIL `IF `IFNOT `IFJMP `IFNOTJMP ) constant @CmdC1 ( `IFREF `IFNOTREF `IFJMPREF `IFNOTJMPREF `CALLREF `JMPREF ) constant @CmdR1 ( `DICTIGETJMP `DICTIGETJMPZ `DICTUGETJMP `DICTUGETJMPZ `DICTIGETEXEC `DICTUGETEXEC ) constant @JmpDictL { dup first `DICTPUSHCONST eq? { flush-cont @curop @ get-const-dict save-const-dict show-simple-op } { dup first @JmpDictL list-member? have-dict? and { flush-cont show-const-dict-op } { flush-dict dup first @PushContL list-member? { drop @curop @ get-cont-body save-cont-body } { dup first @CmdC1 list-member? have-cont? and { flush-contY first atom>$ .curop? show-cont-op } { dup first @CmdR1 list-member? { flush-cont first atom>$ dup $len 3 - $| drop .curop? show-ref-op } { dup first `WHILE eq? have-cont2? and { drop "WHILE" "}>DO<{" .curop? show-cont2-op } { dup first `IFELSE eq? have-cont2? and { drop "IF" "}>ELSE<{" .curop? show-cont2-op } { dup first dup `IFREFELSE eq? swap `IFELSEREF eq? or have-cont? and { first `IFREFELSE eq? "IF" "}>ELSE<{" rot .curop? show-cont-ref-op } { dup first `IFREFELSEREF eq? { drop "IF" "}>ELSE<{" .curop? show-ref2-op } { flush-cont show-simple-op } cond } cond } cond } cond } cond } cond } cond } cond } cond } : show-op { dup @cp @ (vmoplen) dup 0> { 65536 /mod swap sr@+ swap dup @cp @ (vmopdump) parse-op swap s> true } { drop false } cond } : fetch-one-op { { fetch-one-op } { swap @curop ! adjust-op show-op } while } : disasm-slice { { disasm-slice dup sbitrefs 1- or 0= } { ref@