Reference overview¶
Concepts¶
Grammar: productions of fields. Each field has a shape, a sort and a role.
Shape: ONE, OPT, SEQ, or UNKNOWN when the source did not report it (ast._field_types supplies shapes from Python 3.13 on; earlier interpreters expose only names).
Sort: what a slot holds (another production, an identifier, or plain data).
Role: what the position does with what it holds. See Roles.
Namespace: which family of names a role is about. def(vals) and def(slots) keep a pass over SSA values away from a mutable slot, even though both fields hold the same type.
Condition: Present(field) or Absent(field), and nothing else. A field or a scope may carry one, so a role can depend on a sibling: import a.b binds a while import a.b as c binds c alone. Deliberately not a callable.
Trait: a free-form label on a production, for facts no field determines (pure, terminator).
The queries at a glance¶
| question | call |
|---|---|
| which fields bind a name? | positions(Kind.DEF, ns) |
| which read one? | operands(ns) |
| which introduce one? | definitions(ns) |
| which hold a bare identifier? | ident_slots(ns) |
| which does a traversal descend into? | children(prod) |
| which can actually appear? | concrete(base) |
| which carry a trait? | with_trait(name) |
| what does this node read? | reads(node, ns) |
| what does this node bind? | binds(node, ns) |
| which class builds this production? | constructor(name) |
| is the declaration well formed? | check() |
Static versus instance¶
positions, operands, definitions and ident_slots span every node of a production, so a conditionally-roled field is reported under both its roles. reads and binds take one node and apply the conditions.
A pass holding a node wants the second. Writing that walk inline is the sign a query is missing, which is how reads and binds came to exist.