Lab 02: AST & Bytecode

Objective

Understand Python's compilation pipeline: source → tokenizer → AST → bytecode → execution. Parse and transform AST nodes, inspect bytecode with dis, write an AST-based code analyser, and compile/execute dynamically generated code.

Background

Every Python program goes through: source text → tokenizeast.parse() → compiler → bytecode (.pyc). Knowing this pipeline lets you build linters, code generators, and even transpilers entirely within Python — no C extension needed.

Time

35 minutes

Prerequisites

  • Lab 01 (Metaprogramming)

Tools

  • Docker: zchencow/innozverse-python:latest


Lab Instructions

Step 1: Parsing & Inspecting the AST

💡 ast.walk(tree) yields every node in the AST depth-first. Each node type maps to a Python construct: FunctionDef for def, ClassDef for class, Call for function calls, BinOp for +/-/etc. The lineno attribute tells you exactly where in source the node came from.

📸 Verified Output:


Step 2: AST Visitor — Code Analyser

📸 Verified Output:


Steps 3–8: AST Transformer, Compile & Exec, dis Bytecode, Tokenizer, JIT-like Optimizer, Capstone

📸 Verified Output:


Summary

Tool
Purpose
Example

ast.parse(src)

Source → AST

tree = ast.parse('x = 1')

ast.walk(tree)

Traverse all nodes

for n in ast.walk(tree):

ast.NodeVisitor

Read-only traversal

Subclass + visit_NodeType

ast.NodeTransformer

Modify AST in-place

Return new node from visit_*

compile(tree, file, mode)

AST → bytecode

compile(tree, '<>','exec')

dis.dis(fn)

Disassemble to bytecode

Shows LOAD_FAST, CALL, etc.

eval(code, globals, locals)

Execute expression

Safe with empty __builtins__

tokenize

Source → token stream

Character-level analysis

Further Reading

Last updated