marianoguerra/pure-py/ast does not have a README file

    Alias

    pub(all) struct Alias {
    name : String
    asname : String?
    span :
    Span

    } derive(Eq,
    Debug
    )

    Arg

    pub(all) struct Arg {
    arg : String
    annotation : Expr?
    span :
    Span

    } derive(Eq,
    Debug
    )

    Arguments

    pub(all) struct Arguments {
    posonlyargs : Array[Arg]
    args : Array[Arg]
    vararg : Arg?
    kwonlyargs : Array[Arg]
    kw_defaults : Array[Expr?]
    kwarg : Arg?
    defaults : Array[Expr]
    } derive(Eq,
    Debug
    )

    BoolOp

    pub(all) enum BoolOp {
    And
    Or
    } derive(Eq,
    Debug
    )

    BoolOp::name

    fn BoolOp::name(self : BoolOp) -> String

    BoolOp::symbol

    fn BoolOp::symbol(self : BoolOp) -> String

    CmpOp

    pub(all) enum CmpOp {
    Eq
    NotEq
    Lt
    LtE
    Gt
    GtE
    Is
    IsNot
    In
    NotIn
    } derive(Eq,
    Debug
    )

    CmpOp::name

    fn CmpOp::name(self : CmpOp) -> String

    CmpOp::symbol

    fn CmpOp::symbol(self : CmpOp) -> String

    Comprehension

    pub(all) struct Comprehension {
    target : Expr
    iter : Expr
    ifs : Array[Expr]
    is_async : Bool
    } derive(Eq,
    Debug
    )

    Constant

    pub(all) enum Constant {
    Int(
    BigInt
    )
    Float(Double)
    Complex(Double)
    Str(String)
    Bytes(Bytes)
    Bool(Bool)
    None
    Ellipsis
    } derive(Eq,
    Debug
    )

    A literal's value. Complex keeps only the imaginary part: a Python complex LITERAL is always 0+bj, and the sieve rejects it before anything needs the real part.

    Constant::to_literal

    fn Constant::to_literal(self : Constant) -> String

    A constant, exactly as Python's repr writes it.

    Constant::type_name

    fn Constant::type_name(self : Constant) -> String

    The name CPython's ast gives a constant's type -- what the sieve's "prohibited literal type: {T}" prints.

    ExceptHandler

    pub(all) struct ExceptHandler {
    type_ : Expr?
    name : String?
    body : Array[Stmt]
    span :
    Span

    } derive(Eq,
    Debug
    )

    Expr

    pub(all) enum Expr {
    BoolOp(op~ : BoolOp, values~ : Array[Expr], span~ :
    Span
    )
    NamedExpr(target~ : Expr, value~ : Expr, span~ :
    Span
    )
    BinOp(left~ : Expr, op~ : Operator, right~ : Expr, span~ :
    Span
    )
    UnaryOp(op~ : UnaryOp, operand~ : Expr, span~ :
    Span
    )
    Lambda(args~ : Arguments, body~ : Expr, span~ :
    Span
    )
    IfExp(cond~ : Expr, body~ : Expr, or_else~ : Expr, span~ :
    Span
    )
    Dict(keys~ : Array[Expr?], values~ : Array[Expr], span~ :
    Span
    )
    Set(elts~ : Array[Expr], span~ :
    Span
    )
    ListComp(elt~ : Expr, generators~ : Array[Comprehension], span~ :
    Span
    )
    SetComp(elt~ : Expr, generators~ : Array[Comprehension], span~ :
    Span
    )
    DictComp(key~ : Expr, value~ : Expr, generators~ : Array[Comprehension], span~ :
    Span
    )
    GeneratorExp(elt~ : Expr, generators~ : Array[Comprehension], span~ :
    Span
    )
    Await(value~ : Expr, span~ :
    Span
    )
    Yield(value~ : Expr?, span~ :
    Span
    )
    YieldFrom(value~ : Expr, span~ :
    Span
    )
    Compare(left~ : Expr, ops~ : Array[CmpOp], comparators~ : Array[Expr], span~ :
    Span
    )
    Call(func~ : Expr, args~ : Array[Expr], keywords~ : Array[Keyword], span~ :
    Span
    )
    JoinedStr(raw~ : String, parts~ : Array[FStringPart], span~ :
    Span
    )
    Constant(value~ : Constant, span~ :
    Span
    )
    Attribute(value~ : Expr, attr~ : String, ctx~ : ExprContext, span~ :
    Span
    )
    Subscript(value~ : Expr, slice~ : Expr, ctx~ : ExprContext, span~ :
    Span
    )
    Starred(value~ : Expr, ctx~ : ExprContext, span~ :
    Span
    )
    Name(id~ : String, ctx~ : ExprContext, span~ :
    Span
    )
    List(elts~ : Array[Expr], ctx~ : ExprContext, span~ :
    Span
    )
    Tuple(elts~ : Array[Expr], ctx~ : ExprContext, span~ :
    Span
    )
    Slice(lower~ : Expr?, upper~ : Expr?, step~ : Expr?, span~ :
    Span
    )
    } derive(Eq,
    Debug
    )

    Expr::attribute

    fn Expr::attribute(value : Expr, attr : String, ctx? : ExprContext) -> Expr

    Expr::bigint

    Expr::binop

    fn Expr::binop(left : Expr, op : Operator, right : Expr) -> Expr

    Expr::bool

    fn Expr::bool(b : Bool) -> Expr

    Expr::bool_op

    fn Expr::bool_op(op : BoolOp, values : Array[Expr]) -> Expr

    Expr::call

    fn Expr::call(func : Expr, args : Array[Expr], keywords? : Array[Keyword]) -> Expr

    Expr::compare

    fn Expr::compare(left : Expr, op : CmpOp, right : Expr) -> Expr

    Expr::dict

    fn Expr::dict(entries : Array[(Expr, Expr)]) -> Expr

    Expr::float

    fn Expr::float(d : Double) -> Expr

    Expr::if_exp

    fn Expr::if_exp(cond : Expr, body : Expr, or_else : Expr) -> Expr

    Expr::int

    fn Expr::int(n : Int) -> Expr

    Expr::kind_name

    fn Expr::kind_name(self : Expr) -> String

    Expr::lambda

    fn Expr::lambda(params : Array[String], body : Expr) -> Expr

    Expr::list

    fn Expr::list(elts : Array[Expr], ctx? : ExprContext) -> Expr

    Expr::name

    fn Expr::name(id : String, ctx? : ExprContext) -> Expr

    Constructors for a code generator.

    A generator builds a tree and prints it with write; it has no source, so it has no positions. Every builder here supplies @basic.nowhere and sensible defaults, so that Expr::call(Expr::name("print"), [Expr::str("hi")]) is a whole statement's worth of tree.

    The builders are also what keeps ast honest as a package a consumer can use alone: tools/embed-smoke.sh builds a program from them and checks that doing so links neither the lexer, the parser, the checker nor the evaluator.

    Expr::neg

    fn Expr::neg(e : Expr) -> Expr

    Expr::none

    fn Expr::none() -> Expr

    Expr::not_

    fn Expr::not_(e : Expr) -> Expr

    Expr::span

    Where an expression is.

    Expr::str

    fn Expr::str(s : String) -> Expr

    Expr::subscript

    fn Expr::subscript(value : Expr, slice : Expr, ctx? : ExprContext) -> Expr

    Expr::tuple

    fn Expr::tuple(elts : Array[Expr], ctx? : ExprContext) -> Expr

    ExprContext

    pub(all) enum ExprContext {
    Load
    Store
    Del
    } derive(Eq,
    Debug
    )

    ExprContext::name

    fn ExprContext::name(self : ExprContext) -> String

    FStringPart

    pub(all) enum FStringPart {
    Text(String)
    Hole(value~ : Expr, conversion~ : Char?, spec~ : String?)
    } derive(Eq,
    Debug
    )

    One piece of an f-string: literal text, or an interpolation.

    conversion is the r of f"{x!r}", and = for the f"{x=}" debug form, which has the same shape and the same decision behind it. spec is the >10 of f"{x:>10}", kept as source: it is a language of its own, and nothing here pretends to implement it.

    Keyword

    pub(all) struct Keyword {
    arg : String?
    value : Expr
    span :
    Span

    } derive(Eq,
    Debug
    )

    A keyword argument. arg of None is **kwargs.

    MatchCase

    pub(all) struct MatchCase {
    pattern : Pattern
    guard_ : Expr?
    body : Array[Stmt]
    } derive(Eq,
    Debug
    )

    Module

    The abstract syntax tree.

    It is CPython's, node for node and field for field, following Parser/Python.asdl for every construct PurePy needs to NAME -- to accept, or to reject with the right message. Being CPython's is the point: the reference checker walks CPython nodes, so a checker written against this tree can be put beside statements.py and read line for line, and the AST oracle can compare our dump against ast.dump over the whole suite.

    It is typed rather than stringly: operators, expression contexts and pattern kinds are enums, not strings.

    Five deliberate departures from Python.asdl, each earning its keep:

    • MatchSequence carries the bracket it was written with. The spec distinguishes a list pattern from a tuple pattern and CPython does not, so the reference recovers the bracket from the source text; this port records it where it is known, in the parser.
    • Async is a FLAG on FunctionDef, For and With, not three more node kinds. The sieve's message is async prohibited either way.
    • Constant is a typed enum, not a Python object. Complex and Bytes are arms so that the sieve can say "complex literals prohibited".
    • An f-string is JoinedStr with its text unparsed. The sieve rejects f-strings as not yet supported (#55); when that changes, the parts are parsed here and nothing else moves.
    • Positions are a Span of two Pos, and the column counts CODE POINTS. CPython's col_offset counts UTF-8 bytes; Source::byte_col converts, and only where a message in the reference's format needs it.

    Deliberately absent: type_comment, type_ignores, type_params, TemplateStr and Interpolation. PurePy is Python 3.12 and PEP 695 syntax is a syntax error here.

    Operator

    pub(all) enum Operator {
    Add
    Sub
    Mult
    MatMult
    Div
    Mod
    Pow
    LShift
    RShift
    BitOr
    BitXor
    BitAnd
    FloorDiv
    } derive(Eq,
    Debug
    )

    Operator::name

    fn Operator::name(self : Operator) -> String

    The name of the class CPython's ast uses for an operator, which is what its dump prints.

    Operator::symbol

    fn Operator::symbol(self : Operator) -> String

    The symbol a binary operator is written with -- what the sieve's "binary operator '{sym}' prohibited" prints.

    Pattern

    pub(all) enum Pattern {
    MatchValue(value~ : Expr, span~ :
    Span
    )
    MatchSingleton(value~ : Constant, span~ :
    Span
    )
    MatchSequence(kind~ : SeqKind, patterns~ : Array[Pattern], span~ :
    Span
    )
    MatchMapping(keys~ : Array[Expr], patterns~ : Array[Pattern], rest~ : String?, span~ :
    Span
    )
    MatchClass(cls~ : Expr, patterns~ : Array[Pattern], kwd_attrs~ : Array[String], kwd_patterns~ : Array[Pattern], span~ :
    Span
    )
    MatchStar(name~ : String?, span~ :
    Span
    )
    MatchAs(pattern~ : Pattern?, name~ : String?, span~ :
    Span
    )
    MatchOr(patterns~ : Array[Pattern], span~ :
    Span
    )
    } derive(Eq,
    Debug
    )

    Pattern::capture

    fn Pattern::capture(name : String) -> Pattern

    Pattern::constr

    fn Pattern::constr(cls : String, patterns : Array[Pattern], keywords? : Array[(String, Pattern)]) -> Pattern

    Pattern::kind_name

    fn Pattern::kind_name(self : Pattern) -> String

    Pattern::literal

    fn Pattern::literal(c : Constant) -> Pattern

    Pattern::sequence

    fn Pattern::sequence(kind : SeqKind, patterns : Array[Pattern]) -> Pattern

    Pattern::span

    Where a pattern is.

    Pattern::wildcard

    fn Pattern::wildcard() -> Pattern

    SeqKind

    pub(all) enum SeqKind {
    List
    Tuple
    } derive(Eq,
    Debug
    )

    Which bracket a sequence pattern was written with. CPython forgets; the spec distinguishes [p] from (p), and a bare case a, b: is a tuple.

    SeqKind::name

    fn SeqKind::name(self : SeqKind) -> String

    Stmt

    pub(all) enum Stmt {
    FunctionDef(name~ : String, args~ : Arguments, body~ : Array[Stmt], decorators~ : Array[Expr], returns~ : Expr?, is_async~ : Bool, span~ :
    Span
    )
    ClassDef(name~ : String, bases~ : Array[Expr], keywords~ : Array[Keyword], body~ : Array[Stmt], decorators~ : Array[Expr], span~ :
    Span
    )
    Return(value~ : Expr?, span~ :
    Span
    )
    Delete(targets~ : Array[Expr], span~ :
    Span
    )
    Assign(targets~ : Array[Expr], value~ : Expr, span~ :
    Span
    )
    AugAssign(target~ : Expr, op~ : Operator, value~ : Expr, span~ :
    Span
    )
    AnnAssign(target~ : Expr, annotation~ : Expr, value~ : Expr?, simple~ : Bool, span~ :
    Span
    )
    For(target~ : Expr, iter~ : Expr, body~ : Array[Stmt], or_else~ : Array[Stmt], is_async~ : Bool, span~ :
    Span
    )
    While(cond~ : Expr, body~ : Array[Stmt], or_else~ : Array[Stmt], span~ :
    Span
    )
    If(cond~ : Expr, body~ : Array[Stmt], or_else~ : Array[Stmt], span~ :
    Span
    )
    With(items~ : Array[WithItem], body~ : Array[Stmt], is_async~ : Bool, span~ :
    Span
    )
    Match(subject~ : Expr, cases~ : Array[MatchCase], span~ :
    Span
    )
    Raise(exc~ : Expr?, cause~ : Expr?, span~ :
    Span
    )
    Try(body~ : Array[Stmt], handlers~ : Array[ExceptHandler], or_else~ : Array[Stmt], finalbody~ : Array[Stmt], is_star~ : Bool, span~ :
    Span
    )
    Assert(cond~ : Expr, msg~ : Expr?, span~ :
    Span
    )
    Import(names~ : Array[Alias], span~ :
    Span
    )
    ImportFrom(module_name~ : String?, names~ : Array[Alias], level~ : Int, span~ :
    Span
    )
    Global(names~ : Array[String], span~ :
    Span
    )
    Nonlocal(names~ : Array[String], span~ :
    Span
    )
    ExprStmt(value~ : Expr, span~ :
    Span
    )
    Pass(span~ :
    Span
    )
    Break(span~ :
    Span
    )
    Continue(span~ :
    Span
    )
    } derive(Eq,
    Debug
    )

    Stmt::assign

    fn Stmt::assign(target : String, value : Expr) -> Stmt

    Stmt::dataclass

    fn Stmt::dataclass(name : String, fields : Array[String], base? : String) -> Stmt

    A PurePy dataclass: @dataclass on a class whose body is x: Any for each field, with an optional base class. That is the only class form PurePy accepts, so it is the only one the builder offers.

    Stmt::def_

    fn Stmt::def_(name : String, params : Array[String], body : Array[Stmt]) -> Stmt

    Stmt::expr_stmt

    fn Stmt::expr_stmt(e : Expr) -> Stmt

    Stmt::from_import

    fn Stmt::from_import(module_name : String, names : Array[String]) -> Stmt

    Stmt::if_

    fn Stmt::if_(cond : Expr, body : Array[Stmt], or_else? : Array[Stmt]) -> Stmt

    Stmt::import_

    fn Stmt::import_(names : Array[String]) -> Stmt

    Stmt::kind_name

    fn Stmt::kind_name(self : Stmt) -> String

    The name CPython's ast gives this node's class -- what the sieve's "unknown statement type: {T}" and "unknown expression type: {T}" print.

    Stmt::match_

    fn Stmt::match_(subject : Expr, cases : Array[MatchCase]) -> Stmt

    Stmt::pass

    fn Stmt::pass() -> Stmt

    Stmt::return_

    fn Stmt::return_(value? : Expr) -> Stmt

    Stmt::span

    Where a statement is.

    UnaryOp

    pub(all) enum UnaryOp {
    Invert
    Not
    UAdd
    USub
    } derive(Eq,
    Debug
    )

    UnaryOp::name

    fn UnaryOp::name(self : UnaryOp) -> String

    UnaryOp::symbol

    fn UnaryOp::symbol(self : UnaryOp) -> String

    WithItem

    pub(all) struct WithItem {
    context_expr : Expr
    optional_vars : Expr?
    } derive(Eq,
    Debug
    )

    arguments

    fn arguments(params : Array[String]) -> Arguments

    A plain parameter list: names, no defaults, no annotations, no stars.

    case_

    fn case_(pattern : Pattern, body : Array[Stmt], when? : Expr) -> MatchCase

    dump

    fn dump(m : Module, pos? : Bool) -> String

    The canonical dump of a tree.

    The format exists so that it can be implemented TWICE -- here and in tools/pyast_dump.py over CPython's ast -- and the two compared over every source in the suite. So it is defined precisely and kept dull:

    • One node per line, indented two spaces per level of nesting.
    • A node's line is its kind, then its scalar fields as name=value, in the order they are declared here (which is Python.asdl's order).
    • A field holding a node, an optional node or a list is a line of its own, name:, at the next level, with its contents below that. An absent optional is name: -; an empty list is name: with nothing under it.
    • Scalars: an identifier bare, an enumerated value by CPython's class name (Load, Add, Lt), a boolean as True/False, an integer in decimal, a string as Python's repr, a float as Python's repr, and an absent optional scalar as -.
    • With pos=true, a node's line ends with @l:c-l:c, the columns in CODE POINTS. The Python side converts col_offset from UTF-8 bytes.

    This is not ast.dump's format. ast.dump is a Python expression whose re-parsing is the only way to compare it structurally, and it renders a constant through Python's own repr of an arbitrary object. Defining our own costs one Python script and buys a line-oriented diff.

    module_of

    fn module_of(body : Array[Stmt]) -> Module

    Powered by MoonBit

    Site sourceReport issuePackagesBuild queueSkillsStatistics

    © 2026 mooncakes.io