1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-08-13 19:52:52 +02:00

Refactor iterator-related opcodes (OpIterSkip, OpIterLimit) to fix operand handling and label resolution in vm, emitter, and disassembler. Update instruction formatting and improve disassembler output.

This commit is contained in:
Tim Voronov
2025-07-03 18:03:04 -04:00
parent a1e98c3c3c
commit 09df483164
3 changed files with 26 additions and 17 deletions

View File

@@ -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])

View File

@@ -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 ──────────────────────────────────────────────────────

View File

@@ -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])