debug.go (3285B)
1 package vm 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 ) 8 9 // ToString verifies all instructions in bytecode and returns an assmebly code instruction for it. 10 func ToString(b []byte) (string, error) { 11 buf := bytes.NewBuffer(nil) 12 n, err := ParseAll(b, buf) 13 if err != nil { 14 return "", err 15 } 16 logg.Tracef("", "bytes_written", n) 17 return buf.String(), nil 18 } 19 20 // ParseAll parses and verifies all instructions from bytecode. 21 // 22 // If writer is not nil, the parsed instruction as assembly code line string is written to it. 23 // 24 // Bytecode is consumed (and written) one instruction at a time. 25 // 26 // It fails on any parse error encountered before the bytecode EOF is reached. 27 func ParseAll(b []byte, w io.Writer) (int, error) { 28 var s string 29 var rs string 30 var rn int 31 running := true 32 for running { 33 op, bb, err := opSplit(b) 34 b = bb 35 if err != nil { 36 return rn, err 37 } 38 s = OpcodeString[op] 39 if s == "" { 40 return rn, fmt.Errorf("unknown opcode: %v", op) 41 } 42 43 switch op { 44 case CATCH: 45 r, n, m, bb, err := ParseCatch(b) 46 b = bb 47 if err == nil { 48 if w != nil { 49 vv := 0 50 if m { 51 vv = 1 52 } 53 if w != nil { 54 //rs = fmt.Sprintf("%s %s %v %v # invertmatch=%v\n", s, r, n, vv, m) 55 rs = fmt.Sprintf("%s %s %v %v\n", s, r, n, vv) 56 } 57 } 58 } 59 case CROAK: 60 n, m, bb, err := ParseCroak(b) 61 b = bb 62 if err == nil { 63 if w != nil { 64 vv := 0 65 if m { 66 vv = 1 67 } 68 //rs = fmt.Sprintf("%s %v %v # invertmatch=%v\n", s, n, vv, m) 69 rs = fmt.Sprintf("%s %v %v\n", s, n, vv) 70 } 71 } 72 case LOAD: 73 r, n, bb, err := ParseLoad(b) 74 b = bb 75 if err == nil { 76 if w != nil { 77 rs = fmt.Sprintf("%s %s %v\n", s, r, n) 78 } 79 } 80 case RELOAD: 81 r, bb, err := ParseReload(b) 82 b = bb 83 if err == nil { 84 if w != nil { 85 rs = fmt.Sprintf("%s %s\n", s, r) 86 } 87 } 88 case MAP: 89 r, bb, err := ParseMap(b) 90 b = bb 91 if err == nil { 92 if w != nil { 93 rs = fmt.Sprintf("%s %s\n", s, r) 94 } 95 } 96 case MOVE: 97 r, bb, err := ParseMove(b) 98 b = bb 99 if err == nil { 100 if w != nil { 101 rs = fmt.Sprintf("%s %s\n", s, r) 102 } 103 } 104 case INCMP: 105 r, v, bb, err := ParseInCmp(b) 106 b = bb 107 if err == nil { 108 if w != nil { 109 rs = fmt.Sprintf("%s %s %s\n", s, r, v) 110 } 111 } 112 case HALT: 113 b, err = ParseHalt(b) 114 rs = "HALT\n" 115 case MSINK: 116 b, err = ParseMSink(b) 117 rs = "MSINK\n" 118 case MOUT: 119 r, v, bb, err := ParseMOut(b) 120 b = bb 121 if err == nil { 122 if w != nil { 123 //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) 124 rs = fmt.Sprintf("%s %s %s\n", s, r, v) 125 } 126 } 127 case MNEXT: 128 r, v, bb, err := ParseMNext(b) 129 b = bb 130 if err == nil { 131 if w != nil { 132 //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) 133 rs = fmt.Sprintf("%s %s %s\n", s, r, v) 134 } 135 } 136 case MPREV: 137 r, v, bb, err := ParseMPrev(b) 138 b = bb 139 if err == nil { 140 if w != nil { 141 //rs = fmt.Sprintf("%s %s \"%s\"\n", s, r, v) 142 rs = fmt.Sprintf("%s %s %s\n", s, r, v) 143 } 144 } 145 } 146 if err != nil { 147 return rn, err 148 } 149 if w != nil { 150 n, err := io.WriteString(w, rs) 151 if err != nil { 152 return rn, err 153 } 154 rn += n 155 logg.Tracef("instruction debug write", "bytes", n, "instruction", s) 156 } 157 158 //rs += "\n" 159 if len(b) == 0 { 160 running = false 161 } 162 } 163 return rn, nil 164 }