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:
@@ -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])
|
||||
|
||||
|
@@ -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 ──────────────────────────────────────────────────────
|
||||
|
18
pkg/vm/vm.go
18
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])
|
||||
|
Reference in New Issue
Block a user