1def myfunc(alist):2 return len(alist)NAMENAMEOPNAMEOP1// C: int add(int a, int b)2// { return a + b; }30b000020 add w0, w1, w04d65f03c0 retReturnCallName lenName alistCPUPython VM1RESUME 02LOAD_GLOBAL 1 (len + NULL)3LOAD_FAST 0 (alist)4CALL 15RETURN_VALUEreturnlen(alist)op
Front end: source text, tokens and the syntax treeBack ends: machine code and the CPU, or bytecode and the Python VMTiles: tokens, code, bytecode instructions and machine instructions on the moveBack: the source text and the row of tokens. Middle: the machine-code card and the syntax tree. Front: the CPU, the Python VM and the bytecode card. Lexing cuts return len(alist) into five tokens; parsing builds the tree Return, Call, Name len, Name alist. A compiler turns a tree into machine code the CPU runs directly; CPython turns it into bytecode that its VM runs one instruction at a time; a JIT compiles the hot code while the program runs. The bytecode is CPython 3.13's, as in the dis documentation. Bytecode changes between versions: CPython 3.14 prints LOAD_FAST_BORROW instead of LOAD_FAST. (len + NULL) means LOAD_GLOBAL also pushes a NULL that CALL uses.

Text to tree

  1. A program starts as source code: plain text a person typed. The CPU cannot run text. A compiler or an interpreter turns it into something that can run, and both begin with the same two jobs.

Compile ahead of time

Bytecode and a VM

JIT and trade-offs

What happens

;; step 1/10 · source
source code   plain text in a file
  1  def myfunc(alist):
  2      return len(alist)

the CPU only runs machine code (numbers),
so another program must translate the text:
  1  lexing    text   -> tokens
  2  parsing   tokens -> syntax tree
  3  then machine code, bytecode, or a JIT

The bytecode is CPython 3.13's, as in the dis documentation. Bytecode changes between versions: CPython 3.14 prints LOAD_FAST_BORROW instead of LOAD_FAST. (len + NULL) means LOAD_GLOBAL also pushes a NULL that CALL uses. The machine code is Apple clang 21 -O2 output for int add(int a, int b) { return a + b; } on arm64. For x86-64 the same compiler writes lea eax, [rdi + rsi] and ret. The C and Python examples are different functions.