debug.go (5443B)
1 package vm 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 ) 8 9 type ParseHandler struct { 10 Catch func(string, uint32, bool) error 11 Croak func(uint32, bool) error 12 Load func(string, uint32) error 13 Reload func(string) error 14 Map func(string) error 15 Move func(string) error 16 Halt func() error 17 InCmp func(string, string) error 18 MOut func(string, string) error 19 MSink func() error 20 MNext func(string, string) error 21 MPrev func(string, string) error 22 cur string 23 n int 24 w io.Writer 25 } 26 27 func NewParseHandler() *ParseHandler { 28 return &ParseHandler{} 29 } 30 31 func (ph *ParseHandler) Length() int { 32 return ph.n 33 } 34 35 func (ph *ParseHandler) WithDefaultHandlers() *ParseHandler { 36 ph.Catch = ph.catch 37 ph.Croak = ph.croak 38 ph.Load = ph.load 39 ph.Reload = ph.reload 40 ph.Map = ph.maph 41 ph.Move = ph.move 42 ph.Halt = ph.halt 43 ph.InCmp = ph.incmp 44 ph.MOut = ph.mout 45 ph.MSink = ph.msink 46 ph.MNext = ph.mnext 47 ph.MPrev = ph.mprev 48 return ph 49 } 50 51 func (ph *ParseHandler) WithWriter(w io.Writer) *ParseHandler { 52 ph.w = w 53 return ph 54 } 55 56 // TODO: output op sym 57 func (ph *ParseHandler) flush() error { 58 if ph.w != nil { 59 n, err := io.WriteString(ph.w, ph.cur) 60 if err != nil { 61 return err 62 } 63 ph.n += n 64 ph.cur = "" 65 //logg.Tracef("instruction debug write", "bytes", n, "instruction", s) 66 logg.Tracef("instruction debug write", "bytes", n) 67 } 68 return nil 69 } 70 71 func (ph *ParseHandler) catch(sym string, flag uint32, inv bool) error { 72 s := OpcodeString[CATCH] 73 vv := 0 74 if inv { 75 vv = 1 76 } 77 ph.cur = fmt.Sprintf("%s %s %v %v\n", s, sym, flag, vv) 78 return nil 79 } 80 81 func (ph *ParseHandler) croak(flag uint32, inv bool) error { 82 s := OpcodeString[CROAK] 83 vv := 0 84 if inv { 85 vv = 1 86 } 87 ph.cur = fmt.Sprintf("%s %v %v\n", s, flag, vv) 88 return nil 89 } 90 91 func (ph *ParseHandler) load(sym string, length uint32) error { 92 s := OpcodeString[LOAD] 93 ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, length) 94 return nil 95 } 96 97 func (ph *ParseHandler) reload(sym string) error { 98 s := OpcodeString[RELOAD] 99 ph.cur = fmt.Sprintf("%s %s\n", s, sym) 100 return nil 101 } 102 103 func (ph *ParseHandler) maph(sym string) error { 104 s := OpcodeString[MAP] 105 ph.cur = fmt.Sprintf("%s %s\n", s, sym) 106 return nil 107 } 108 109 func (ph *ParseHandler) move(sym string) error { 110 s := OpcodeString[MOVE] 111 ph.cur = fmt.Sprintf("%s %s\n", s, sym) 112 return nil 113 } 114 115 func (ph *ParseHandler) incmp(sym string, sel string) error { 116 s := OpcodeString[INCMP] 117 ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, sel) 118 return nil 119 } 120 121 func (ph *ParseHandler) halt() error { 122 s := OpcodeString[HALT] 123 ph.cur = fmt.Sprintf("%s\n", s) 124 return nil 125 } 126 127 func (ph *ParseHandler) msink() error { 128 s := OpcodeString[MSINK] 129 ph.cur = fmt.Sprintf("%s\n", s) 130 return nil 131 } 132 133 func (ph *ParseHandler) mout(sym string, sel string) error { 134 s := OpcodeString[MOUT] 135 ph.cur = fmt.Sprintf("%s %s %v\n", s, sym, sel) 136 return nil 137 } 138 139 func (ph *ParseHandler) mnext(sym string, sel string) error { 140 s := OpcodeString[MNEXT] 141 ph.cur = fmt.Sprintf("%s %s %s\n", s, sym, sel) 142 return nil 143 } 144 145 func (ph *ParseHandler) mprev(sym string, sel string) error { 146 s := OpcodeString[MPREV] 147 ph.cur = fmt.Sprintf("%s %s %s\n", s, sym, sel) 148 return nil 149 } 150 151 // ToString verifies all instructions in bytecode and returns an assmebly code instruction for it. 152 func (ph *ParseHandler) ToString(b []byte) (string, error) { 153 buf := bytes.NewBuffer(nil) 154 ph = ph.WithWriter(buf) 155 n, err := ph.ParseAll(b) 156 if err != nil { 157 return "", err 158 } 159 logg.Tracef("", "bytes_written", n) 160 return buf.String(), nil 161 } 162 163 // ParseAll parses and verifies all instructions from bytecode. 164 // 165 // If writer is not nil, the parsed instruction as assembly code line string is written to it. 166 // 167 // Bytecode is consumed (and written) one instruction at a time. 168 // 169 // It fails on any parse error encountered before the bytecode EOF is reached. 170 func (ph *ParseHandler) ParseAll(b []byte) (int, error) { 171 var s string 172 running := true 173 for running { 174 op, bb, err := opSplit(b) 175 b = bb 176 if err != nil { 177 return ph.Length(), err 178 } 179 s = OpcodeString[op] 180 if s == "" { 181 return ph.Length(), fmt.Errorf("unknown opcode: %v", op) 182 } 183 184 switch op { 185 case CATCH: 186 r, n, m, bb, err := ParseCatch(b) 187 b = bb 188 if err == nil { 189 err = ph.Catch(r, n, m) 190 } 191 case CROAK: 192 n, m, bb, err := ParseCroak(b) 193 b = bb 194 if err == nil { 195 err = ph.Croak(n, m) 196 } 197 case LOAD: 198 r, n, bb, err := ParseLoad(b) 199 b = bb 200 if err == nil { 201 err = ph.Load(r, n) 202 } 203 case RELOAD: 204 r, bb, err := ParseReload(b) 205 b = bb 206 if err == nil { 207 err = ph.Reload(r) 208 } 209 case MAP: 210 r, bb, err := ParseMap(b) 211 b = bb 212 if err == nil { 213 err = ph.Map(r) 214 } 215 case MOVE: 216 r, bb, err := ParseMove(b) 217 b = bb 218 if err == nil { 219 err = ph.Move(r) 220 } 221 case INCMP: 222 r, v, bb, err := ParseInCmp(b) 223 b = bb 224 if err == nil { 225 err = ph.InCmp(r, v) 226 } 227 case HALT: 228 b, err = ParseHalt(b) 229 if err == nil { 230 err = ph.Halt() 231 } 232 case MSINK: 233 b, err = ParseMSink(b) 234 if err == nil { 235 err = ph.MSink() 236 } 237 case MOUT: 238 r, v, bb, err := ParseMOut(b) 239 b = bb 240 if err == nil { 241 err = ph.MOut(r, v) 242 } 243 case MNEXT: 244 r, v, bb, err := ParseMNext(b) 245 b = bb 246 if err == nil { 247 err = ph.MNext(r, v) 248 } 249 case MPREV: 250 r, v, bb, err := ParseMPrev(b) 251 b = bb 252 if err == nil { 253 err = ph.MPrev(r, v) 254 } 255 } 256 if err != nil { 257 return ph.Length(), err 258 } 259 ph.flush() 260 261 //rs += "\n" 262 if len(b) == 0 { 263 running = false 264 } 265 } 266 return ph.Length(), nil 267 }