diff --git a/pkg/asm/disassembler.go b/pkg/asm/disassembler.go index 6f3643b0..2292fba3 100644 --- a/pkg/asm/disassembler.go +++ b/pkg/asm/disassembler.go @@ -41,7 +41,7 @@ func collectLabels(bytecode []vm.Instruction) map[int]string { for _, instr := range bytecode { switch instr.Opcode { - case vm.OpJump, vm.OpJumpIfFalse, vm.OpJumpIfTrue: + case vm.OpJump, vm.OpJumpIfFalse, vm.OpJumpIfTrue, vm.OpIterNext, vm.OpIterSkip, vm.OpIterLimit: target := int(instr.Operands[0]) if _, ok := labels[target]; !ok { labels[target] = fmt.Sprintf("@L%d", counter) @@ -77,9 +77,12 @@ func disasmLine(ip int, instr vm.Instruction, p *vm.Program, labels map[int]stri case vm.OpJump: out = fmt.Sprintf("%d: %s %s", ip, opcode, labelOrAddr(int(ops[0]), labels)) - case vm.OpJumpIfTrue, vm.OpJumpIfFalse: + case vm.OpJumpIfTrue, vm.OpJumpIfFalse, vm.OpIterNext: out = fmt.Sprintf("%d: %s %s %s", ip, opcode, labelOrAddr(int(ops[0]), labels), ops[1]) + case vm.OpIterSkip, vm.OpIterLimit: + out = fmt.Sprintf("%d: %s %s %s %s", ip, opcode, labelOrAddr(int(ops[0]), labels), ops[1], ops[2]) + case vm.OpReturn: out = fmt.Sprintf("%d: %s R%d", ip, opcode, ops[0]) diff --git a/pkg/compiler/internal/core/emitter_helpers.go b/pkg/compiler/internal/core/emitter_helpers.go index 2109ccc2..d6d8a76d 100644 --- a/pkg/compiler/internal/core/emitter_helpers.go +++ b/pkg/compiler/internal/core/emitter_helpers.go @@ -25,15 +25,23 @@ func (e *Emitter) EmitIterValue(dst, iterator vm.Operand) { } func (e *Emitter) EmitIterSkip(state, count vm.Operand, label Label) { - e.EmitABx(vm.OpIterSkip, state, count, jumpPlaceholder) + e.instructions = append(e.instructions, vm.Instruction{ + Opcode: vm.OpIterSkip, + Operands: [3]vm.Operand{jumpPlaceholder, state, count}, + }) + pos := len(e.instructions) - 1 - e.addLabelRef(pos, 2, label) + e.addLabelRef(pos, 0, label) } -func (e *Emitter) EmitIterLimit(state, count vm.Operand, jump Label) { - e.EmitABx(vm.OpIterLimit, state, count, jumpPlaceholder) +func (e *Emitter) EmitIterLimit(state, count vm.Operand, label Label) { + e.instructions = append(e.instructions, vm.Instruction{ + Opcode: vm.OpIterLimit, + Operands: [3]vm.Operand{jumpPlaceholder, state, count}, + }) + pos := len(e.instructions) - 1 - e.addLabelRef(pos, 2, jump) + e.addLabelRef(pos, 0, label) } // ─── Value & Memory ────────────────────────────────────────────────────── diff --git a/pkg/vm/vm.go b/pkg/vm/vm.go index d8685c85..0a8e6895 100644 --- a/pkg/vm/vm.go +++ b/pkg/vm/vm.go @@ -461,25 +461,23 @@ loop: iterator := reg[src1].(*internal.Iterator) reg[dst] = iterator.Key() case OpIterSkip: - state := runtime.ToIntSafe(ctx, reg[dst]) - threshold := runtime.ToIntSafe(ctx, reg[src1]) - jump := int(src2) + state := runtime.ToIntSafe(ctx, reg[src1]) + threshold := runtime.ToIntSafe(ctx, reg[src2]) if state < threshold { state++ - reg[dst] = state - vm.pc = jump + reg[src1] = state + vm.pc = int(dst) } case OpIterLimit: - state := runtime.ToIntSafe(ctx, reg[dst]) - threshold := runtime.ToIntSafe(ctx, reg[src1]) - jump := int(src2) + state := runtime.ToIntSafe(ctx, reg[src1]) + threshold := runtime.ToIntSafe(ctx, reg[src2]) if state < threshold { state++ - reg[dst] = state + reg[src1] = state } else { - vm.pc = jump + vm.pc = int(dst) } case OpStream: observable, eventName, options, err := vm.castSubscribeArgs(reg[dst], reg[src1], reg[src2])