Master the fundamental concepts of cpython internals through this focused micro-challenge.
You have read the whole brief, and the concepts above stay free on every task. Writing and running the code needs a plan.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksThe \`dis\` module prints the opcodes CPython will execute. Pairing \`dis\` output with \`Python/compile.c\` and \`ceval.c\` is how you learn what the compiler actually emitted.
Each line shows offset, opcode name, and argument:
For example, \`def add(a, b): return a + b\` disassembles to loads of \`a\` and \`b\`, \`BINARY_OP\` or \`BINARY_ADD\`, then \`RETURN_VALUE\`.
Match opcodes to compiler phases:
Specialized opcodes in CPython 3.11+ replace generic forms for common patterns. When dis output shows `CACHE` lines, you are looking at the adaptive specialization machinery, not user bytecode.
This exercise asks you to disassemble sample functions and map opcodes to CPython source concepts. You will document how \`dis\` reveals the stack operations behind familiar Python syntax.
You will use the same mental model here when reading production interpreter source later in the track. Sketch one concrete input on paper, predict the outcome, then confirm with code. That discipline catches logic errors early and makes debugging far faster when you extend the implementation in follow-on tasks.
Build a mini CPython 3.8 compiler plus dis. Read Python functions, compile them to 3.8 bytecode with 3.8's rules for locals, globals, constants and jumps, and print the disassembly exactly as dis.dis does. Then print the code object's co_consts, co_varnames, co_names and co_stacksize.
One or more top-level def NAME(PARAMS): blocks, indented with spaces. Blank lines and # comments are allowed, and line numbers count every input line from 1.
Statements:
x = EXPRreturn [EXPR]EXPR (usually a call)if EXPR: ... [else: ...]while EXPR: ...passExpressions, from lowest to highest precedence:
< <= == != > >=);+ -;* // %;-;f(a, b) and parentheses.co_varnames. These use LOAD_FAST/STORE_FAST, even when a read comes before the assignment. Any other name is a global: LOAD_GLOBAL, collected in co_names by first use.co_consts[0] is None, and the others are added on first use without duplicates. Arithmetic on two constants, and unary minus on a constant, is folded at compile time (Python floor semantics for // and %). A division by a literal 0 is left unfolded.BINARY_ADD/SUBTRACT/MULTIPLY/FLOOR_DIVIDE/MODULO, UNARY_NEGATIVE, COMPARE_OP i with i indexing ('<','<=','==','!=','>','>='), CALL_FUNCTION argc after the callee and the arguments, POP_TOP after an expression statement, and RETURN_VALUE.test; POP_JUMP_IF_FALSE else; body; JUMP_FORWARD end; else: orelse; end:. Without else, the false jump goes straight past the body.top: test; POP_JUMP_IF_FALSE end; body; JUMP_ABSOLUTE top; end:.2i. POP_JUMP_IF_FALSE and JUMP_ABSOLUTE take absolute targets. JUMP_FORWARD takes a delta from the next instruction, shown as (to T).return, append LOAD_CONST None; RETURN_VALUE.cLoading…
Each instruction line follows dis:
>> for a jump target or 2 spaces, a space, and the offset in a width-4 field; (repr) for constants, names, comparisons and JUMP_FORWARD.Trailing spaces are dropped. Separate functions with a blank line, printed before each function after the first, even if that function then fails to compile. Print tuples Python-style: (None,) and ('n',).
A syntax error prints SyntaxError: line N: MSG and stops the whole run. Functions already printed stay printed. The messages are:
invalid syntaxexpected an indented blockunexpected indentunindent does not match any outer indentation levelduplicate argument in function definitionexpected 'def' at the top levelInput:
cLoading…
Output:
cLoading…
Hidden tests cover nested if/else with JUMP_FORWARD, constant folding (including a division by zero that is left alone), a local read before assignment, pass, a bare return, a while at the end of a function, and an indentation error.