execute performs an instruction cycle in the VM. acting on the instruction i in thread t.
(t *thread, i code.Instr)
| 334 | // execute performs an instruction cycle in the VM. acting on the instruction |
| 335 | // i in thread t. |
| 336 | func (v *VM) execute(t *thread, i code.Instr) { |
| 337 | // In normal operation, recover from panics, otherwise dump that state and repanic. |
| 338 | defer func() { |
| 339 | if r := recover(); r != nil { |
| 340 | if v.HardCrash { |
| 341 | fmt.Printf("panic in thread %#v at instr %q: %s\n", t, i, r) |
| 342 | panic(r) |
| 343 | } |
| 344 | v.errorf("panic in thread %#v at instr %q: %s", t, i, r) |
| 345 | v.terminate = true |
| 346 | } |
| 347 | }() |
| 348 | |
| 349 | switch i.Opcode { |
| 350 | case code.Bad: |
| 351 | panic("Invalid instruction. Aborting.") |
| 352 | |
| 353 | case code.Stop: |
| 354 | v.terminate = true |
| 355 | |
| 356 | case code.Match: |
| 357 | // match regex and store success |
| 358 | // Store the results in the operandth element of the stack, |
| 359 | // where i.opnd == the matched re index |
| 360 | index := i.Operand.(int) |
| 361 | t.matches[index] = v.re[index].FindStringSubmatch(v.input.Line) |
| 362 | t.Push(t.matches[index] != nil) |
| 363 | |
| 364 | case code.Smatch: |
| 365 | // match regex against item on the stack |
| 366 | index := i.Operand.(int) |
| 367 | line, err := t.PopString() |
| 368 | if err != nil { |
| 369 | v.errorf("+%v", err) |
| 370 | return |
| 371 | } |
| 372 | t.matches[index] = v.re[index].FindStringSubmatch(line) |
| 373 | t.Push(t.matches[index] != nil) |
| 374 | |
| 375 | case code.Cmp: |
| 376 | // Compare two elements on the stack. |
| 377 | // Set the match register based on the truthiness of the comparison. |
| 378 | // Operand contains the expected result. |
| 379 | b := t.Pop() |
| 380 | a := t.Pop() |
| 381 | |
| 382 | match, err := compare(a, b, i.Operand.(int)) |
| 383 | if err != nil { |
| 384 | v.errorf("%+v", err) |
| 385 | return |
| 386 | } |
| 387 | |
| 388 | t.Push(match) |
| 389 | |
| 390 | case code.Icmp: |
| 391 | b, berr := t.PopInt() |
| 392 | if berr != nil { |
| 393 | v.errorf("%+v", berr) |