go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

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 }