DisassembleWriter takes a writer and writes opcodes to it.
(w io.Writer)
| 83 | |
| 84 | // DisassembleWriter takes a writer and writes opcodes to it. |
| 85 | func (program *Program) DisassembleWriter(w io.Writer) { |
| 86 | ip := 0 |
| 87 | for ip < len(program.Bytecode) { |
| 88 | pp := ip |
| 89 | op := program.Bytecode[ip] |
| 90 | arg := program.Arguments[ip] |
| 91 | ip += 1 |
| 92 | |
| 93 | code := func(label string) { |
| 94 | _, _ = fmt.Fprintf(w, "%v\t%v\n", pp, label) |
| 95 | } |
| 96 | jump := func(label string) { |
| 97 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t(%v)\n", pp, label, arg, ip+arg) |
| 98 | } |
| 99 | jumpBack := func(label string) { |
| 100 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t(%v)\n", pp, label, arg, ip-arg) |
| 101 | } |
| 102 | argument := func(label string) { |
| 103 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\n", pp, label, arg) |
| 104 | } |
| 105 | argumentWithInfo := func(label string, prefix string) { |
| 106 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, program.debugInfo[fmt.Sprintf("%s_%d", prefix, arg)]) |
| 107 | } |
| 108 | constant := func(label string) { |
| 109 | var c any |
| 110 | if arg < len(program.Constants) { |
| 111 | c = program.Constants[arg] |
| 112 | } else { |
| 113 | c = "out of range" |
| 114 | } |
| 115 | if name, ok := program.debugInfo[fmt.Sprintf("const_%d", arg)]; ok { |
| 116 | c = name |
| 117 | } |
| 118 | if r, ok := c.(*regexp.Regexp); ok { |
| 119 | c = r.String() |
| 120 | } |
| 121 | if field, ok := c.(*runtime.Field); ok { |
| 122 | c = fmt.Sprintf("{%v %v}", strings.Join(field.Path, "."), field.Index) |
| 123 | } |
| 124 | if method, ok := c.(*runtime.Method); ok { |
| 125 | c = fmt.Sprintf("{%v %v}", method.Name, method.Index) |
| 126 | } |
| 127 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, c) |
| 128 | } |
| 129 | builtinArg := func(label string) { |
| 130 | _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, builtin.Builtins[arg].Name) |
| 131 | } |
| 132 | |
| 133 | switch op { |
| 134 | case OpInvalid: |
| 135 | code("OpInvalid") |
| 136 | |
| 137 | case OpPush: |
| 138 | constant("OpPush") |
| 139 | |
| 140 | case OpInt: |
| 141 | argument("OpInt") |
| 142 |