tiny.python.syntax.ast
Defined in syntax.
A Python program in the package's subset parses into a syntax tree.
API (31)
Actions
Public operations.
Program.deinit: Frees every node of the tree at once by freeing the arena.
Types and contracts
Public types and contracts.
Assign: An assignment of a value to one name.Attribute: An attribute access: a value and the name after the dot.Binary: An arithmetic operator applied to two operands.BinaryOp: The three arithmetic operators of the subset:+,-and*.Call: A call: the called value and its arguments.Comparison: A chain of comparisons: a first operand, then each operator with its right operand.ComparisonOp: The ten comparison operators of the subset.ComparisonTerm: One operator of a comparison chain with the operand to its right.Delete: The target of adelstatement: one name, or one item selected by an index.Dict: A dictionary display: the key and value pairs between{and}.DictItem: One entry of a dictionary display: a key expression and a value expression.Expression: One expression, as a tagged union with one tag per kind of expression.ForStatement: Aforloop: the loop's name, the expression it takes items from, the body, and theelsebranch.Function: A function definition: its name, its parameter names and its body.IfStatement: Anifstatement: its condition, the body run when the condition is true, and theelsebranch.List: A list display: the item expressions between[and].Logical:andororapplied to two operands.LogicalOp: The two operators that evaluate their right operand only when needed.Program: The syntax tree of one program: its top-level statements and the arena that holds every node.Return: Areturnstatement and its optional value.Slice: The three bounds of a slice, each optional.Statement: One statement of the subset, as a tagged union with one tag per kind of statement.Subscript: A value followed by brackets that hold one index or a slice.SubscriptAssign: An assignment to one item selected by an index, such asxs[0] = 2ord["k"] = v.SubscriptDelete: The item adelremoves: a container and an index.SubscriptSelector: The contents of a subscript's brackets: one index expression or a slice.Tuple: A tuple: expressions separated by commas, or()for the empty tuple.Unary: An operator applied to one operand.UnaryOp: The two unary operators of the subset.WhileStatement: Awhileloop: its condition, its body and itselsebranch.
Source
Source: lib/python/src/syntax/ast.zig
zig
//! A Python program in the package's subset parses into a syntax tree. The program is a list of//! statements. Statements hold expressions and nested lists of statements. Each expression is a//! tree of operators and operands.//!//! The compiler walks the tree once to emit instructions, so every construct of the subset needs a//! node shape of its own that the compiler can tell apart. A program's tree has many small nodes,//! and all of them are freed together when the caller is done with the program.//!//! One tagged union, `Statement`, has a tag for each kind of statement. A second tagged union,//! `Expression`, has a tag for each kind of expression. So the compiler's switch over a node covers//! every construct. A child expression is a pointer to a constant node. A list of children is a//! constant slice. The parsed program, `Program`, owns one arena that holds every node and list.//! Names and string contents are slices of the source text, so the text has to outlive the tree.//!//! The `else` branch of `if`, `while` and `for` is a field named `otherwise`. When the source has//! no `else`, that field is empty. An `elif` is stored as an `if` statement that is the only//! statement of the previous `if`'s `otherwise` list.const std = @import("std");/// The syntax tree of one program: its top-level statements and the arena that holds every node./// `parse` builds it and `compile` reads it. The caller frees it with `deinit`.pub const Program = struct { /// The arena allocator that holds every statement, expression and list of the tree. `parse` /// creates it on the caller's allocator. `deinit` frees it. arena: std.heap.ArenaAllocator, /// The program's top-level statements in source order, allocated in the arena. statements: []const Statement, /// Frees every node of the tree at once by freeing the arena. The package's `execute` calls it /// as it returns, after the bytecode compiled from the tree is freed. The call leaves the /// program undefined. Every slice taken from the tree's lists is invalid afterward. The /// bytecode that `compile` builds borrows each function's parameter list from the arena, so the /// tree has to outlive that bytecode. The source text stays the caller's, and `deinit` leaves /// it alone. pub fn deinit(self: *Program) void { self.arena.deinit(); self.* = undefined; }};/// One statement of the subset, as a tagged union with one tag per kind of statement. The compiler/// switches on its tag to emit each statement's instructions. `parse` builds one for each statement/// of the program.pub const Statement = union(enum) { /// An expression statement: an expression evaluated for its value. At the top level, the value /// of the last one run becomes the program's result. Inside a function, the value is dropped. expression: *const Expression, /// An assignment to one name, such as `x = 1`. assign: Assign, /// An assignment to one item selected by an index, such as `xs[0] = 2`. subscript_assign: SubscriptAssign, /// A `del` statement for one name or one item selected by an index. delete: Delete, /// A `break` statement. The compiler rejects one outside a loop. break_stmt, /// A `continue` statement. The compiler rejects one outside a loop. continue_stmt, /// A `def` statement. The compiler accepts one at the top level alone. function: Function, /// A `for` loop. for_stmt: ForStatement, /// An `if` statement, whose `elif` and `else` parts are stored in its `otherwise` list. if_stmt: IfStatement, /// A `pass` statement, which the compiler skips. pass, /// A `return` statement, with or without a value. The compiler rejects one at the top level. return_stmt: Return, /// A `while` loop. while_stmt: WhileStatement,};/// An assignment of a value to one name. The compiler turns one into a store to the name. The/// target is a single name. `a, b = 1, 2` fails to parse with `UnexpectedToken`, because its left/// side is a tuple.pub const Assign = struct { /// The assigned name, a slice of the source text. name: []const u8, /// The expression whose value is assigned. value: *const Expression,};/// An assignment to one item selected by an index, such as `xs[0] = 2` or `d["k"] = v`. The/// compiler turns one into a store into a list or dictionary. A slice is never a target, so/// `xs[0:1] = [2]` fails to parse with `UnexpectedToken`.pub const SubscriptAssign = struct { /// The expression before the brackets, which gives the container. target: *const Expression, /// The expression inside the brackets. index: *const Expression, /// The expression whose value is stored. value: *const Expression,};/// The target of a `del` statement: one name, or one item selected by an index. The compiler turns/// one into the removal of a name or of an item. A `del` takes one target. For any other target, a/// slice included, parsing fails with `UnexpectedToken`.pub const Delete = union(enum) { /// The name to remove, a slice of the source text. name: []const u8, /// The item to remove from a container. subscript: SubscriptDelete,};/// The item a `del` removes: a container and an index. The compiler turns one, as in `del xs[0]`,/// into the removal of that item.pub const SubscriptDelete = struct { /// The expression before the brackets, which gives the container. target: *const Expression, /// The expression inside the brackets. index: *const Expression,};/// A function definition: its name, its parameter names and its body. The compiler turns each one/// into a separate block of bytecode bound to the function's name. Each parameter is a plain name./// A trailing comma after the last parameter is allowed.pub const Function = struct { /// The function's name, a slice of the source text. name: []const u8, /// The parameter names in order, each a slice of the source text. For a function without /// parameters, the list is empty. params: []const []const u8, /// The statements of the function's body in order. body: []const Statement,};/// A `for` loop: the loop's name, the expression it takes items from, the body, and the `else`/// branch. The compiler turns one into a loop that takes one item per pass from a list, tuple,/// string, range, dictionary or iterator. The loop's target is one name.pub const ForStatement = struct { /// The name bound to each item in turn, a slice of the source text. name: []const u8, /// The expression that gives the items. The iterable is one expression with no bare comma, so /// `for x in 1, 2:` fails to parse. iterable: *const Expression, /// The statements run for each item. body: []const Statement, /// The statements of the `else` branch. The branch runs once the loop has taken every item. /// When `break` ends the loop, the branch is skipped. When the loop has no `else`, the list is /// empty. otherwise: []const Statement,};/// An `if` statement: its condition, the body run when the condition is true, and the `else`/// branch. The compiler turns one into a test of the condition and a jump over the branch that does/// not run.pub const IfStatement = struct { /// The expression tested for truth. The condition is one expression with no bare comma. condition: *const Expression, /// The statements run when the condition is true. body: []const Statement, /// The statements run when the condition is false. For an `elif`, the list holds one `if` /// statement for the `elif` and its own branches. For an `else`, the list holds the `else` /// body. Without either, the list is empty. otherwise: []const Statement,};/// A `return` statement and its optional value. The compiler turns one into leaving the function/// with a value.pub const Return = struct { /// The returned expression. For a bare `return`, the field is `null`. A bare `return` returns /// `None`. value: ?*const Expression,};/// A `while` loop: its condition, its body and its `else` branch. The compiler turns one into a/// test at the top of each pass and a jump back.pub const WhileStatement = struct { /// The expression tested for truth before each pass. The condition is one expression with no /// bare comma. condition: *const Expression, /// The statements run on each pass while the condition is true. body: []const Statement, /// The statements of the `else` branch. The branch runs once the condition is false. When /// `break` ends the loop, the branch is skipped. When the loop has no `else`, the list is /// empty. otherwise: []const Statement,};/// One expression, as a tagged union with one tag per kind of expression. The compiler switches on/// its tag to emit the instructions that compute each value. `parse` allocates each node in the/// program's arena. A node points to its children as constant nodes.pub const Expression = union(enum) { /// The literal `None`. none, /// The literal `True` or `False`. boolean: bool, /// The value of an integer literal, as a signed 128-bit integer. The literal has no sign, so /// `-5` is unary minus applied to 5. integer: i128, /// The contents of a string literal: the bytes between the quotes, as a slice of the source /// text. A backslash stays in the bytes as written, with no escape decoding. string: []const u8, /// A name to look up, as a slice of the source text. name: []const u8, /// Unary minus or `not` applied to one operand. unary: Unary, /// `+`, `-` or `*` applied to two operands. binary: Binary, /// A chain of one or more comparisons, such as `a < b <= c`. comparison: Comparison, /// `and` or `or` applied to two operands. logical: Logical, /// A call of a function or method with its arguments. call: Call, /// An attribute access, such as `xs.append`. attribute: Attribute, /// A list display, such as `[1, x]`. list: List, /// A tuple: expressions separated by commas, or `()` for the empty tuple. tuple: Tuple, /// A dictionary display, such as `{"a": 1}`. dict: Dict, /// An index or a slice applied to a value, such as `xs[0]` or `xs[1:3]`. subscript: Subscript,};/// An operator applied to one operand. The compiler emits the operand's instructions and then one/// instruction for the operator.pub const Unary = struct { /// Which operator: unary minus or `not`. op: UnaryOp, /// The operand. operand: *const Expression,};/// The two unary operators of the subset. The compiler picks the instruction for a `Unary` node/// from it. The parser binds `not` more loosely than comparisons. The parser binds unary minus more/// tightly than `*`.pub const UnaryOp = enum { /// Unary minus, as in `-x`. Negating the smallest 128-bit integer fails with `IntegerOverflow` /// when the program runs. negate, /// `not`, which gives `True` when its operand is false and `False` otherwise. not,};/// An arithmetic operator applied to two operands. The compiler emits both operands' instructions,/// left first, and then one instruction for the operator. Operators of one precedence level group/// from the left, so `1 - 2 - 3` is `(1 - 2) - 3`.pub const Binary = struct { /// Which operator. op: BinaryOp, /// The left operand, evaluated first. left: *const Expression, /// The right operand. right: *const Expression,};/// The three arithmetic operators of the subset: `+`, `-` and `*`. The compiler picks the/// instruction for a `Binary` node from it. Integer results past the signed 128-bit range fail with/// `IntegerOverflow` when the program runs.pub const BinaryOp = enum { /// `+`: integer addition, or joining two strings, two lists or two tuples. add, /// `-`: integer subtraction. sub, /// `*`: integer multiplication, or a string, list or tuple repeated an integer number of times. /// The count can stand on either side of `*`. mul,};/// A chain of comparisons: a first operand, then each operator with its right operand. The compiler/// turns one chain into pairwise tests that stop at the first false one. `a < b < c` tests `a < b`/// and then `b < c`. Each operand is evaluated once. The parser builds one only when at least one/// operator follows the first operand.pub const Comparison = struct { /// The first operand of the chain. left: *const Expression, /// Each operator with its right operand, in source order. The slice holds at least one. terms: []const ComparisonTerm,};/// One operator of a comparison chain with the operand to its right. A `Comparison` holds one per/// operator of the chain. For the first term, the left operand is the chain's first operand. For/// every later term, the left operand is the previous term's right operand.pub const ComparisonTerm = struct { /// The comparison operator. op: ComparisonOp, /// The operand to the right of the operator. right: *const Expression,};/// The ten comparison operators of the subset. The compiler maps each tag to one comparison/// instruction.pub const ComparisonOp = enum { /// `==`. equal, /// `!=`. not_equal, /// `<`. less, /// `<=`. less_equal, /// `>`. greater, /// `>=`. greater_equal, /// `in`, a membership test: true when the right operand holds the left operand. contains, /// `not in`, the negated membership test. not_contains, /// `is`, an identity test. identical, /// `is not`, the negated identity test. not_identical,};/// `and` or `or` applied to two operands. The compiler turns one into a test of the left operand/// and a jump past the right one. The right operand is evaluated only when the left one does not/// decide the result. The result is the deciding operand's own value, so `0 and x` gives 0 and/// `None or 9` gives 9. A chain such as `a or b or c` groups from the left.pub const Logical = struct { /// Which operator. op: LogicalOp, /// The left operand, always evaluated. left: *const Expression, /// The right operand, evaluated only when the left one does not decide the result. right: *const Expression,};/// The two operators that evaluate their right operand only when needed. The compiler picks the/// jump pattern for a `Logical` node from it.pub const LogicalOp = enum { /// `and`: gives the left operand when it is false, and otherwise gives the right operand. and_op, /// `or`: gives the left operand when it is true, and otherwise gives the right operand. or_op,};/// A call: the called value and its arguments. The compiler emits the called value, then each/// argument in order, then one call instruction with the argument count. Each argument is one/// expression passed by position. A trailing comma after the last argument is allowed.pub const Call = struct { /// The expression that gives the function or method to call. target: *const Expression, /// The argument expressions in order. For a call without arguments, the list is empty. arguments: []const *const Expression,};/// An attribute access: a value and the name after the dot. The compiler turns one into an/// instruction that looks the name up on the value, so a method call such as `xs.append(1)` finds/// its method. When the program runs, the name resolves to one of the methods of a list or/// dictionary.pub const Attribute = struct { /// The expression before the dot. target: *const Expression, /// The name after the dot, as a slice of the source text. name: []const u8,};/// A list display: the item expressions between `[` and `]`. The compiler emits each item and then/// one instruction that builds a list of that many items.pub const List = struct { /// The item expressions in order. For `[]`, the list is empty. A trailing comma after the last /// item is allowed. items: []const *const Expression,};/// A tuple: expressions separated by commas, or `()` for the empty tuple. The compiler emits each/// item and then one instruction that builds a tuple of that many items. Parentheses around one/// expression with no comma only group it. `(1,)` is a tuple of one item.pub const Tuple = struct { /// The item expressions in order. For `()`, the list is empty. items: []const *const Expression,};/// A dictionary display: the key and value pairs between `{` and `}`. The compiler emits each key/// and value in order and then one instruction that builds a dictionary of that many entries.pub const Dict = struct { /// The entries in source order. For `{}`, the list is empty. A trailing comma after the last /// entry is allowed. When a key repeats, the later value replaces the earlier one at run time. items: []const DictItem,};/// One entry of a dictionary display: a key expression and a value expression. A `Dict` holds one/// per entry of the display.pub const DictItem = struct { /// The key expression, before the `:`. key: *const Expression, /// The value expression, after the `:`. value: *const Expression,};/// A value followed by brackets that hold one index or a slice. The compiler emits the value, then/// the index or the three slice bounds, then one instruction that reads the item or the slice.pub const Subscript = struct { /// The expression before the brackets. target: *const Expression, /// What the brackets hold: one index or a slice. selector: SubscriptSelector,};/// The contents of a subscript's brackets: one index expression or a slice. The compiler emits an/// index read or a slice read depending on its tag. A colon inside the brackets makes it a slice. A/// comma inside the brackets fails to parse with `ExpectedRightBracket`.pub const SubscriptSelector = union(enum) { /// The index expression, as in `xs[0]`. index: *const Expression, /// A slice, as in `xs[1:3]`. slice: Slice,};/// The three bounds of a slice, each optional. A `SubscriptSelector` holds one for a subscript with/// a colon. A bound left out is `null`, so every bound of `xs[:]` is `null`. The compiler passes/// `None` for each bound left out.pub const Slice = struct { /// The index of the first item taken. When the start is left out, as in `xs[:2]`, the field is /// `null`. start: ?*const Expression, /// The index the slice stops before. When the stop is left out, as in `xs[1:]`, the field is /// `null`. stop: ?*const Expression, /// The distance between the indexes taken. When the step is left out, as in `xs[1:3]` or /// `xs[1:3:]`, the field is `null`. step: ?*const Expression,};test "expression tags are stable" { const value = Expression{ .integer = 7 }; try std.testing.expectEqual(@as(i128, 7), value.integer);}Source: lib/python/src/syntax/root.zig:10
zig
pub const ast = @import("ast.zig");Audit
| Definitions | 32 |
|---|---|
| Public names | 36 |
| Members | 97 |
| Version | 26.7.0 |
| Revision | daab053ee433 |