KOS_OP_PUSH_FOREACH

  • Style: NOARG. Argument unused; break target is derived at runtime from the extent table (pop_pc + 1).

  • Stack: Pops iterable (TOS); creates iterator; pushes the FOREACH node, which owns its segment. Region loop result starts unset. ITER_NEXT uses the node’s iterator. Break target = extent.pop_pc + 1 (instruction after the matching POP_FOREACH).

  • Pushes: KOS_DYN_FOREACH (static extent KOS_EXT_FOREACH; node holds iterator and loop state).

  • Invariants: A KOS_EXT_FOREACH extent must exist at the PUSH_FOREACH PC; otherwise RuntimeError. Extent kind KOS_EXT_FOREACH.

  • Compiler form: Pre-compile arg = 0 (unused). Break target is not stored in the instruction; it is derived at runtime via kos_extent_find(KOS_EXT_FOREACH) → ext->pop_pc + 1.

Example: for x in [1,2,3]: body. Stack at entry: […, iterable]. Pool: 0 = [1,2,3].

index

opcode

arg

arg view

comment

0

CONST

0

0 ([1,2,3])

stack: […, iterable]

1

PUSH_FOREACH

0

0

pop iterable; push FOREACH region; break_pc = pop_pc+1 from extent table

2

ITER_NEXT

6

6 (-> 6)

next from region; else → 6. stack: […, x]

3

POP

1

1

body: consume x

4

JUMP

2

2 (-> 2)

loop back

5

POP_FOREACH

0

0

push loop result (None if unset)

6

LABEL

–

–

break / exhausted (= pop_pc+1)