FAILURE MAP
← Case archive

FA-90201 / Bytecode virtual machines / Open access

Generators: generator survives an uncaught throw · case 01

After throw() propagates out, next() resumes the dead frame and faults.

Verified by executionVariant 1 · 9 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

The unwinding path returns the exception without marking the generator finished.

VERIFIED REPAIR

An exception escaping the frame finishes the generator.

Unsuccessful approach: Clearing the handler stack still leaves the frame resumable.

Case contract

A generator frame runs body ops push v, pop, add, yield (pop and hand out a value, suspend), return (pop, finish with StopIteration value), try exc target / endtry (handler stack; handler "Exception" catches any thrown name). Commands: next (= send None) and send v resume; resuming a suspended frame pushes the sent value as the result of its yield; sending non-None to a never-started generator is ["TypeError"]; a finished generator answers ["StopIteration", None]. throw into a created or finished generator finishes it with ["raised", exc]; otherwise the innermost matching handler is jumped to, or the generator finishes and re-raises. close finishes the generator. Frame faults are ["vm-error"].

Why this case matters

Generator state transitions (created/suspended/done) and send/throw semantics are easy to get subtly wrong.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(body, commands):
    state = 'created'
    pc = 0
    stack = []
    handlers = []
    out = []
    def run(inject, exc):
        nonlocal pc, state
        if exc is not None:
            while handlers and handlers[-1][0] not in (exc, 'Exception'):
                handlers.pop()
            if not handlers:
                return ['raised', exc]
            pc = handlers.pop()[1]
        elif state == 'suspended':
            stack.append(inject)
        state = 'running'
        try:
            while True:
                ins = body[pc]
                op = ins[0]
                pc += 1
                if op == 'push':
                    stack.append(ins[1])
                elif op == 'pop':
                    stack.pop()
                elif op == 'add':
                    b = stack.pop()
                    a = stack.pop()
                    stack.append(a + b)
                elif op == 'yield':
                    state = 'suspended'
                    return ['yielded', stack.pop()]
                elif op == 'return':
                    state = 'done'
                    return ['StopIteration', stack.pop()]
                elif op == 'try':
                    handlers.append((ins[1], ins[2]))
                elif op == 'endtry':
                    handlers.pop()
        except (IndexError, TypeError):
            state = 'done'
            return ['vm-error']
    for cmd in commands:
        kind = cmd[0]
        if kind in ('next', 'send'):
            value = cmd[1] if kind == 'send' else None
            if state == 'done':
                out.append(['StopIteration', None])
            elif state == 'created' and value is not None:
                out.append(['TypeError'])
            else:
                out.append(run(value, None))
        elif kind == 'throw':
            if state == 'created' or state == 'done':
                state = 'done'
                out.append(['raised', cmd[1]])
            else:
                out.append(run(None, cmd[1]))
        else:
            state = 'done'
            out.append(['closed'])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 7], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['send', 0], ['next'], ['send', 1]]),
   [['TypeError'], ['yielded', 1], ['yielded', 11]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 6]]),
  ('yield hands out and removes the value',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 43],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 43], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 14], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 24], ['StopIteration', 7], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['send', 0], ['next'], ['send', 2]]),
   [['TypeError'], ['yielded', 1], ['yielded', 12]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 7]]),
  ('yield hands out and removes the value',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 13], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 44],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 44], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 21], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 31], ['StopIteration', 8], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['send', 0], ['next'], ['send', 3]]),
   [['TypeError'], ['yielded', 1], ['yielded', 13]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 8]]),
  ('yield hands out and removes the value',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 18], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 45],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 28], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 38], ['StopIteration', 9], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['send', 0], ['next'], ['send', 4]]),
   [['TypeError'], ['yielded', 1], ['yielded', 14]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 9]]),
  ('yield hands out and removes the value',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 23], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 46],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 46], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 35], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 10], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['send', 0], ['next'], ['send', 5]]),
   [['TypeError'], ['yielded', 1], ['yielded', 15]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 10]]),
  ('yield hands out and removes the value',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 28], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 47],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 47], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])]]
for label, args, expected in cases[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: send values through two yields[['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]][['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]Passed
non-None send to a fresh generator[['TypeError'], ['yielded', 1], ['yielded', 11]][['TypeError'], ['yielded', 1], ['yielded', 11]]Passed
sending zero to a suspended generator[['yielded', 1], ['yielded', 10], ['StopIteration', 6]][['yielded', 1], ['yielded', 10], ['StopIteration', 6]]Passed
yield hands out and removes the value[['yielded', 1], ['StopIteration', 8], ['StopIteration', None]][['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]Passed
thrown exception caught by catch-all handler[['yielded', 1], ['yielded', 43], ['StopIteration', 0]][['yielded', 1], ['yielded', 43], ['StopIteration', 0]]Passed
uncaught throw finishes the generator[['yielded', 1], ['raised', 'KeyError'], ['vm-error']][['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]Failed
closing a fresh generator[['closed'], ['StopIteration', None]][['closed'], ['StopIteration', None]]Passed
closing a suspended generator[['yielded', 1], ['closed'], ['StopIteration', None]][['yielded', 1], ['closed'], ['StopIteration', None]]Passed
control: throw into a fresh generator[['raised', 'ValueError'], ['StopIteration', None]][['raised', 'ValueError'], ['StopIteration', None]]Passed

SHA-256 / cced5d97c847f516d789c70259bebc884c30da244f43a9b4940c5675f71876f2

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(body, commands):
    state = 'created'
    pc = 0
    stack = []
    handlers = []
    out = []
    def run(inject, exc):
        nonlocal pc, state
        if exc is not None:
            while handlers and handlers[-1][0] not in (exc, 'Exception'):
                handlers.pop()
            if not handlers:
                handlers.clear()
                return ['raised', exc]
            pc = handlers.pop()[1]
        elif state == 'suspended':
            stack.append(inject)
        state = 'running'
        try:
            while True:
                ins = body[pc]
                op = ins[0]
                pc += 1
                if op == 'push':
                    stack.append(ins[1])
                elif op == 'pop':
                    stack.pop()
                elif op == 'add':
                    b = stack.pop()
                    a = stack.pop()
                    stack.append(a + b)
                elif op == 'yield':
                    state = 'suspended'
                    return ['yielded', stack.pop()]
                elif op == 'return':
                    state = 'done'
                    return ['StopIteration', stack.pop()]
                elif op == 'try':
                    handlers.append((ins[1], ins[2]))
                elif op == 'endtry':
                    handlers.pop()
        except (IndexError, TypeError):
            state = 'done'
            return ['vm-error']
    for cmd in commands:
        kind = cmd[0]
        if kind in ('next', 'send'):
            value = cmd[1] if kind == 'send' else None
            if state == 'done':
                out.append(['StopIteration', None])
            elif state == 'created' and value is not None:
                out.append(['TypeError'])
            else:
                out.append(run(value, None))
        elif kind == 'throw':
            if state == 'created' or state == 'done':
                state = 'done'
                out.append(['raised', cmd[1]])
            else:
                out.append(run(None, cmd[1]))
        else:
            state = 'done'
            out.append(['closed'])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 7], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['send', 0], ['next'], ['send', 1]]),
   [['TypeError'], ['yielded', 1], ['yielded', 11]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 6]]),
  ('yield hands out and removes the value',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 43],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 43], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 14], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 24], ['StopIteration', 7], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['send', 0], ['next'], ['send', 2]]),
   [['TypeError'], ['yielded', 1], ['yielded', 12]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 7]]),
  ('yield hands out and removes the value',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 13], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 44],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 44], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 21], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 31], ['StopIteration', 8], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['send', 0], ['next'], ['send', 3]]),
   [['TypeError'], ['yielded', 1], ['yielded', 13]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 8]]),
  ('yield hands out and removes the value',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 18], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 45],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 28], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 38], ['StopIteration', 9], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['send', 0], ['next'], ['send', 4]]),
   [['TypeError'], ['yielded', 1], ['yielded', 14]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 9]]),
  ('yield hands out and removes the value',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 23], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 46],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 46], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 35], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 10], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['send', 0], ['next'], ['send', 5]]),
   [['TypeError'], ['yielded', 1], ['yielded', 15]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 10]]),
  ('yield hands out and removes the value',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 28], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 47],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 47], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])]]
for label, args, expected in cases[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: send values through two yields[['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]][['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]Passed
non-None send to a fresh generator[['TypeError'], ['yielded', 1], ['yielded', 11]][['TypeError'], ['yielded', 1], ['yielded', 11]]Passed
sending zero to a suspended generator[['yielded', 1], ['yielded', 10], ['StopIteration', 6]][['yielded', 1], ['yielded', 10], ['StopIteration', 6]]Passed
yield hands out and removes the value[['yielded', 1], ['StopIteration', 8], ['StopIteration', None]][['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]Passed
thrown exception caught by catch-all handler[['yielded', 1], ['yielded', 43], ['StopIteration', 0]][['yielded', 1], ['yielded', 43], ['StopIteration', 0]]Passed
uncaught throw finishes the generator[['yielded', 1], ['raised', 'KeyError'], ['vm-error']][['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]Failed
closing a fresh generator[['closed'], ['StopIteration', None]][['closed'], ['StopIteration', None]]Passed
closing a suspended generator[['yielded', 1], ['closed'], ['StopIteration', None]][['yielded', 1], ['closed'], ['StopIteration', None]]Passed
control: throw into a fresh generator[['raised', 'ValueError'], ['StopIteration', None]][['raised', 'ValueError'], ['StopIteration', None]]Passed

SHA-256 / 359511c53c96cd3f4ba552cf2e3f63c3eccd176405144e541c756d394e964e90

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(body, commands):
    state = 'created'
    pc = 0
    stack = []
    handlers = []
    out = []
    def run(inject, exc):
        nonlocal pc, state
        if exc is not None:
            while handlers and handlers[-1][0] not in (exc, 'Exception'):
                handlers.pop()
            if not handlers:
                state = 'done'
                return ['raised', exc]
            pc = handlers.pop()[1]
        elif state == 'suspended':
            stack.append(inject)
        state = 'running'
        try:
            while True:
                ins = body[pc]
                op = ins[0]
                pc += 1
                if op == 'push':
                    stack.append(ins[1])
                elif op == 'pop':
                    stack.pop()
                elif op == 'add':
                    b = stack.pop()
                    a = stack.pop()
                    stack.append(a + b)
                elif op == 'yield':
                    state = 'suspended'
                    return ['yielded', stack.pop()]
                elif op == 'return':
                    state = 'done'
                    return ['StopIteration', stack.pop()]
                elif op == 'try':
                    handlers.append((ins[1], ins[2]))
                elif op == 'endtry':
                    handlers.pop()
        except (IndexError, TypeError):
            state = 'done'
            return ['vm-error']
    for cmd in commands:
        kind = cmd[0]
        if kind in ('next', 'send'):
            value = cmd[1] if kind == 'send' else None
            if state == 'done':
                out.append(['StopIteration', None])
            elif state == 'created' and value is not None:
                out.append(['TypeError'])
            else:
                out.append(run(value, None))
        elif kind == 'throw':
            if state == 'created' or state == 'done':
                state = 'done'
                out.append(['raised', cmd[1]])
            else:
                out.append(run(None, cmd[1]))
        else:
            state = 'done'
            out.append(['closed'])
    return out
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
cases = [[('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 7], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['send', 0], ['next'], ['send', 1]]),
   [['TypeError'], ['yielded', 1], ['yielded', 11]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 6]]),
  ('yield hands out and removes the value',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 43],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 43], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 5], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 6], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 14], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 24], ['StopIteration', 7], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['send', 0], ['next'], ['send', 2]]),
   [['TypeError'], ['yielded', 1], ['yielded', 12]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 7]]),
  ('yield hands out and removes the value',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 13], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 44],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 44], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 10], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 7], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 21], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 31], ['StopIteration', 8], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['send', 0], ['next'], ['send', 3]]),
   [['TypeError'], ['yielded', 1], ['yielded', 13]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 8]]),
  ('yield hands out and removes the value',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 18], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 45],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 15], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 8], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 28], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 38], ['StopIteration', 9], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['send', 0], ['next'], ['send', 4]]),
   [['TypeError'], ['yielded', 1], ['yielded', 14]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 9]]),
  ('yield hands out and removes the value',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 23], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 46],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 46], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 20], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 9], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])],
 [('regression: send values through two yields',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 35], ['next'], ['next']]),
   [['yielded', 1], ['yielded', 45], ['StopIteration', 10], ['StopIteration', None]]),
  ('non-None send to a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['send', 0], ['next'], ['send', 5]]),
   [['TypeError'], ['yielded', 1], ['yielded', 15]]),
  ('sending zero to a suspended generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['next'], ['send', 0], ['next']]),
   [['yielded', 1], ['yielded', 10], ['StopIteration', 10]]),
  ('yield hands out and removes the value',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['send', 3], ['next']]),
   [['yielded', 1], ['StopIteration', 28], ['StopIteration', None]]),
  ('thrown exception caught by catch-all handler',
   ([['try', 'Exception', 7],
     ['push', 1],
     ['yield'],
     ['pop'],
     ['endtry'],
     ['push', -1],
     ['return'],
     ['push', 47],
     ['yield'],
     ['pop'],
     ['push', 0],
     ['return']],
    [['next'], ['throw', 'ValueError'], ['next']]),
   [['yielded', 1], ['yielded', 47], ['StopIteration', 0]]),
  ('uncaught throw finishes the generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['throw', 'KeyError'], ['next']]),
   [['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]),
  ('closing a fresh generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['close'], ['next']]),
   [['closed'], ['StopIteration', None]]),
  ('closing a suspended generator',
   ([['push', 25], ['push', 1], ['yield'], ['add'], ['return']], [['next'], ['close'], ['next']]),
   [['yielded', 1], ['closed'], ['StopIteration', None]]),
  ('control: throw into a fresh generator',
   ([['push', 1], ['yield'], ['push', 10], ['add'], ['yield'], ['pop'], ['push', 10], ['return']],
    [['throw', 'ValueError'], ['next']]),
   [['raised', 'ValueError'], ['StopIteration', None]])]]
for label, args, expected in cases[N - 1]:
    check(label, solve(*args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
regression: send values through two yields[['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]][['yielded', 1], ['yielded', 17], ['StopIteration', 6], ['StopIteration', None]]Passed
non-None send to a fresh generator[['TypeError'], ['yielded', 1], ['yielded', 11]][['TypeError'], ['yielded', 1], ['yielded', 11]]Passed
sending zero to a suspended generator[['yielded', 1], ['yielded', 10], ['StopIteration', 6]][['yielded', 1], ['yielded', 10], ['StopIteration', 6]]Passed
yield hands out and removes the value[['yielded', 1], ['StopIteration', 8], ['StopIteration', None]][['yielded', 1], ['StopIteration', 8], ['StopIteration', None]]Passed
thrown exception caught by catch-all handler[['yielded', 1], ['yielded', 43], ['StopIteration', 0]][['yielded', 1], ['yielded', 43], ['StopIteration', 0]]Passed
uncaught throw finishes the generator[['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]][['yielded', 1], ['raised', 'KeyError'], ['StopIteration', None]]Passed
closing a fresh generator[['closed'], ['StopIteration', None]][['closed'], ['StopIteration', None]]Passed
closing a suspended generator[['yielded', 1], ['closed'], ['StopIteration', None]][['yielded', 1], ['closed'], ['StopIteration', None]]Passed
control: throw into a fresh generator[['raised', 'ValueError'], ['StopIteration', None]][['raised', 'ValueError'], ['StopIteration', None]]Passed

SHA-256 / f8a019999cd82806d62c44a3a1ff8aaf08de22e15580af70a42780f489ed07cb

Verification & scope

A deterministic, bounded teaching model of one bytecode virtual machine mechanism with a stipulated instruction encoding; it is not a production VM and claims no conformance to any real specification. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:51:24.527431+00:00.

Case digest / fb19b4131c63ae177fcdf964216d361bd7c9c3c0813334c2173d1d997470eccb