#![allow(clippy::all)]
use super::*;
use crate::builtins::{PyGenericAlias, PyTuple, PyTupleRef, PyTypeRef, make_union};
use crate::common::ascii;
use crate::convert::ToPyObject;
use crate::function::FuncArgs;
use crate::types::Initializer;
macro_rules! impl_node {
(
#[pyclass(module = $_mod:literal, name = $_name:literal, base = $base:ty)]
$vis:vis struct $name:ident,
fields: [$($field:expr),* $(,)?],
attributes: [$($attr:expr),* $(,)?] $(,)?
) => {
#[pyclass(module = $_mod, name = $_name, base = $base)]
#[repr(transparent)]
$vis struct $name($base);
impl_base_node!($name, fields: [$($field),*], attributes: [$($attr),*]);
};
(
#[pyclass(module = $_mod:literal, name = $_name:literal, base = $base:ty)]
$vis:vis struct $name:ident,
fields: [$($field:expr),* $(,)?] $(,)?
) => {
impl_node!(
#[pyclass(module = $_mod, name = $_name, base = $base)]
$vis struct $name,
fields: [$($field),*],
attributes: [],
);
};
(
#[pyclass(module = $_mod:literal, name = $_name:literal, base = $base:ty)]
$vis:vis struct $name:ident,
attributes: [$($attr:expr),* $(,)?] $(,)?
) => {
impl_node!(
#[pyclass(module = $_mod, name = $_name, base = $base)]
$vis struct $name,
fields: [],
attributes: [$($attr),*],
);
};
(
#[pyclass(module = $_mod:literal, name = $_name:literal, base = $base:ty)]
$vis:vis struct $name:ident $(,)?
) => {
impl_node!(
#[pyclass(module = $_mod, name = $_name, base = $base)]
$vis struct $name,
fields: [],
attributes: [],
);
};
}
macro_rules! impl_base_node {
($name:ident) => {
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl $name {
#[pymethod]
fn __reduce__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
super::python::_ast::ast_reduce(zelf, vm)
}
#[pymethod]
fn __replace__(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
super::python::_ast::ast_replace(zelf, args, vm)
}
#[extend_class]
fn extend_class(ctx: &Context, class: &'static Py<PyType>) {
unsafe {
let flags = &class.slots.flags as *const crate::types::PyTypeFlags
as *mut crate::types::PyTypeFlags;
(*flags).remove(crate::types::PyTypeFlags::IMMUTABLETYPE);
}
class.set_attr(
identifier!(ctx, _attributes),
ctx.empty_tuple.clone().into(),
);
}
}
};
($name:ident, fields: [$($field:expr),*], attributes: [$($attr:expr),*]) => {
#[pyclass(flags(HAS_DICT, BASETYPE))]
impl $name {
#[pymethod]
fn __reduce__(zelf: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyTupleRef> {
super::python::_ast::ast_reduce(zelf, vm)
}
#[pymethod]
fn __replace__(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult {
super::python::_ast::ast_replace(zelf, args, vm)
}
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
unsafe {
let flags = &class.slots.flags as *const crate::types::PyTypeFlags
as *mut crate::types::PyTypeFlags;
(*flags).remove(crate::types::PyTypeFlags::IMMUTABLETYPE);
}
class.set_attr(
identifier!(ctx, _fields),
ctx.new_tuple(vec![
$(
ctx.new_str(ascii!($field)).into()
),*
])
.into(),
);
class.set_str_attr(
"__match_args__",
ctx.new_tuple(vec![
$(
ctx.new_str(ascii!($field)).into()
),*
]),
ctx,
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_tuple(vec![
$(
ctx.new_str(ascii!($attr)).into()
),*
])
.into(),
);
class.set_attr(
ctx.intern_str("_field_types"),
ctx.new_dict().into(),
);
}
}
};
}
#[pyclass(module = "_ast", name = "mod", base = NodeAst)]
pub(crate) struct NodeMod(NodeAst);
impl_base_node!(NodeMod);
impl_node!(
#[pyclass(module = "_ast", name = "Module", base = NodeMod)]
pub(crate) struct NodeModModule,
fields: ["body", "type_ignores"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Interactive", base = NodeMod)]
pub(crate) struct NodeModInteractive,
fields: ["body"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Expression", base = NodeMod)]
pub(crate) struct NodeModExpression,
fields: ["body"],
);
#[pyclass(module = "_ast", name = "stmt", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeStmt(NodeAst);
impl_base_node!(NodeStmt);
impl_node!(
#[pyclass(module = "_ast", name = "FunctionType", base = NodeMod)]
pub(crate) struct NodeModFunctionType,
fields: ["argtypes", "returns"],
);
impl_node!(
#[pyclass(module = "_ast", name = "FunctionDef", base = NodeStmt)]
pub(crate) struct NodeStmtFunctionDef,
fields: ["name", "args", "body", "decorator_list", "returns", "type_comment", "type_params"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = NodeStmt)]
pub(crate) struct NodeStmtAsyncFunctionDef,
fields: ["name", "args", "body", "decorator_list", "returns", "type_comment", "type_params"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "ClassDef", base = NodeStmt)]
pub(crate) struct NodeStmtClassDef,
fields: ["name", "bases", "keywords", "body", "decorator_list", "type_params"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Return", base = NodeStmt)]
pub(crate) struct NodeStmtReturn,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Delete", base = NodeStmt)]
pub(crate) struct NodeStmtDelete,
fields: ["targets"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Assign", base = NodeStmt)]
pub(crate) struct NodeStmtAssign,
fields: ["targets", "value", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "TypeAlias", base = NodeStmt)]
pub(crate) struct NodeStmtTypeAlias,
fields: ["name", "type_params", "value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "AugAssign", base = NodeStmt)]
pub(crate) struct NodeStmtAugAssign,
fields: ["target", "op", "value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "AnnAssign", base = NodeStmt)]
pub(crate) struct NodeStmtAnnAssign,
fields: ["target", "annotation", "value", "simple"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "For", base = NodeStmt)]
pub(crate) struct NodeStmtFor,
fields: ["target", "iter", "body", "orelse", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "AsyncFor", base = NodeStmt)]
pub(crate) struct NodeStmtAsyncFor,
fields: ["target", "iter", "body", "orelse", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "While", base = NodeStmt)]
pub(crate) struct NodeStmtWhile,
fields: ["test", "body", "orelse"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "If", base = NodeStmt)]
pub(crate) struct NodeStmtIf,
fields: ["test", "body", "orelse"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "With", base = NodeStmt)]
pub(crate) struct NodeStmtWith,
fields: ["items", "body", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "AsyncWith", base = NodeStmt)]
pub(crate) struct NodeStmtAsyncWith,
fields: ["items", "body", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Match", base = NodeStmt)]
pub(crate) struct NodeStmtMatch,
fields: ["subject", "cases"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Raise", base = NodeStmt)]
pub(crate) struct NodeStmtRaise,
fields: ["exc", "cause"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Try", base = NodeStmt)]
pub(crate) struct NodeStmtTry,
fields: ["body", "handlers", "orelse", "finalbody"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "TryStar", base = NodeStmt)]
pub(crate) struct NodeStmtTryStar,
fields: ["body", "handlers", "orelse", "finalbody"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Assert", base = NodeStmt)]
pub(crate) struct NodeStmtAssert,
fields: ["test", "msg"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Import", base = NodeStmt)]
pub(crate) struct NodeStmtImport,
fields: ["names"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "ImportFrom", base = NodeStmt)]
pub(crate) struct NodeStmtImportFrom,
fields: ["module", "names", "level"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Global", base = NodeStmt)]
pub(crate) struct NodeStmtGlobal,
fields: ["names"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Nonlocal", base = NodeStmt)]
pub(crate) struct NodeStmtNonlocal,
fields: ["names"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Expr", base = NodeStmt)]
pub(crate) struct NodeStmtExpr,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Pass", base = NodeStmt)]
pub(crate) struct NodeStmtPass,
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Break", base = NodeStmt)]
pub(crate) struct NodeStmtBreak,
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[pyclass(module = "_ast", name = "expr", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeExpr(NodeAst);
impl_base_node!(NodeExpr);
impl_node!(
#[pyclass(module = "_ast", name = "Continue", base = NodeStmt)]
pub(crate) struct NodeStmtContinue,
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "BoolOp", base = NodeExpr)]
pub(crate) struct NodeExprBoolOp,
fields: ["op", "values"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "NamedExpr", base = NodeExpr)]
pub(crate) struct NodeExprNamedExpr,
fields: ["target", "value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "BinOp", base = NodeExpr)]
pub(crate) struct NodeExprBinOp,
fields: ["left", "op", "right"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "UnaryOp", base = NodeExpr)]
pub(crate) struct NodeExprUnaryOp,
fields: ["op", "operand"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Lambda", base = NodeExpr)]
pub(crate) struct NodeExprLambda,
fields: ["args", "body"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "IfExp", base = NodeExpr)]
pub(crate) struct NodeExprIfExp,
fields: ["test", "body", "orelse"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Dict", base = NodeExpr)]
pub(crate) struct NodeExprDict,
fields: ["keys", "values"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Set", base = NodeExpr)]
pub(crate) struct NodeExprSet,
fields: ["elts"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "ListComp", base = NodeExpr)]
pub(crate) struct NodeExprListComp,
fields: ["elt", "generators"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "SetComp", base = NodeExpr)]
pub(crate) struct NodeExprSetComp,
fields: ["elt", "generators"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "DictComp", base = NodeExpr)]
pub(crate) struct NodeExprDictComp,
fields: ["key", "value", "generators"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "GeneratorExp", base = NodeExpr)]
pub(crate) struct NodeExprGeneratorExp,
fields: ["elt", "generators"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Await", base = NodeExpr)]
pub(crate) struct NodeExprAwait,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Yield", base = NodeExpr)]
pub(crate) struct NodeExprYield,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "YieldFrom", base = NodeExpr)]
pub(crate) struct NodeExprYieldFrom,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Compare", base = NodeExpr)]
pub(crate) struct NodeExprCompare,
fields: ["left", "ops", "comparators"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Call", base = NodeExpr)]
pub(crate) struct NodeExprCall,
fields: ["func", "args", "keywords"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "FormattedValue", base = NodeExpr)]
pub(crate) struct NodeExprFormattedValue,
fields: ["value", "conversion", "format_spec"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "JoinedStr", base = NodeExpr)]
pub(crate) struct NodeExprJoinedStr,
fields: ["values"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "TemplateStr", base = NodeExpr)]
pub(crate) struct NodeExprTemplateStr,
fields: ["values"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Interpolation", base = NodeExpr)]
pub(crate) struct NodeExprInterpolation,
fields: ["value", "str", "conversion", "format_spec"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[pyclass(module = "_ast", name = "Constant", base = NodeExpr)]
#[repr(transparent)]
pub(crate) struct NodeExprConstant(NodeExpr);
#[pyclass(flags(HAS_DICT, BASETYPE), with(Initializer))]
impl NodeExprConstant {
#[extend_class]
fn extend_class_with_fields(ctx: &Context, class: &'static Py<PyType>) {
// AST types are mutable (heap types, not IMMUTABLETYPE)
unsafe {
let flags = &class.slots.flags as *const crate::types::PyTypeFlags
as *mut crate::types::PyTypeFlags;
(*flags).remove(crate::types::PyTypeFlags::IMMUTABLETYPE);
}
class.set_attr(
identifier!(ctx, _fields),
ctx.new_tuple(vec![
ctx.new_str(ascii!("value")).into(),
ctx.new_str(ascii!("kind")).into(),
])
.into(),
);
class.set_str_attr(
"__match_args__",
ctx.new_tuple(vec![
ctx.new_str(ascii!("value")).into(),
ctx.new_str(ascii!("kind")).into(),
]),
ctx,
);
class.set_attr(
identifier!(ctx, _attributes),
ctx.new_tuple(vec![
ctx.new_str(ascii!("lineno")).into(),
ctx.new_str(ascii!("col_offset")).into(),
ctx.new_str(ascii!("end_lineno")).into(),
ctx.new_str(ascii!("end_col_offset")).into(),
])
.into(),
);
}
}
impl Initializer for NodeExprConstant {
type Args = FuncArgs;
fn slot_init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> {
<NodeAst as Initializer>::slot_init(zelf.clone(), args, vm)?;
// kind defaults to None if not provided
let dict = zelf.as_object().dict().unwrap();
if !dict.contains_key("kind", vm) {
dict.set_item("kind", vm.ctx.none(), vm)?;
}
Ok(())
}
fn init(_zelf: PyRef<Self>, _args: Self::Args, _vm: &VirtualMachine) -> PyResult<()> {
unreachable!("slot_init is defined")
}
}
impl_node!(
#[pyclass(module = "_ast", name = "Attribute", base = NodeExpr)]
pub(crate) struct NodeExprAttribute,
fields: ["value", "attr", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Subscript", base = NodeExpr)]
pub(crate) struct NodeExprSubscript,
fields: ["value", "slice", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Starred", base = NodeExpr)]
pub(crate) struct NodeExprStarred,
fields: ["value", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Name", base = NodeExpr)]
pub(crate) struct NodeExprName,
fields: ["id", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "List", base = NodeExpr)]
pub(crate) struct NodeExprList,
fields: ["elts", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Tuple", base = NodeExpr)]
pub(crate) struct NodeExprTuple,
fields: ["elts", "ctx"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[pyclass(module = "_ast", name = "expr_context", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeExprContext(NodeAst);
impl_base_node!(NodeExprContext);
impl_node!(
#[pyclass(module = "_ast", name = "Slice", base = NodeExpr)]
pub(crate) struct NodeExprSlice,
fields: ["lower", "upper", "step"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "Load", base = NodeExprContext)]
pub(crate) struct NodeExprContextLoad,
);
impl_node!(
#[pyclass(module = "_ast", name = "Store", base = NodeExprContext)]
pub(crate) struct NodeExprContextStore,
);
#[pyclass(module = "_ast", name = "boolop", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeBoolOp(NodeAst);
impl_base_node!(NodeBoolOp);
impl_node!(
#[pyclass(module = "_ast", name = "Del", base = NodeExprContext)]
pub(crate) struct NodeExprContextDel,
);
impl_node!(
#[pyclass(module = "_ast", name = "And", base = NodeBoolOp)]
pub(crate) struct NodeBoolOpAnd,
);
#[pyclass(module = "_ast", name = "operator", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeOperator(NodeAst);
impl_base_node!(NodeOperator);
impl_node!(
#[pyclass(module = "_ast", name = "Or", base = NodeBoolOp)]
pub(crate) struct NodeBoolOpOr,
);
impl_node!(
#[pyclass(module = "_ast", name = "Add", base = NodeOperator)]
pub(crate) struct NodeOperatorAdd,
);
impl_node!(
#[pyclass(module = "_ast", name = "Sub", base = NodeOperator)]
pub(crate) struct NodeOperatorSub,
);
impl_node!(
#[pyclass(module = "_ast", name = "Mult", base = NodeOperator)]
pub(crate) struct NodeOperatorMult,
);
impl_node!(
#[pyclass(module = "_ast", name = "MatMult", base = NodeOperator)]
pub(crate) struct NodeOperatorMatMult,
);
impl_node!(
#[pyclass(module = "_ast", name = "Div", base = NodeOperator)]
pub(crate) struct NodeOperatorDiv,
);
impl_node!(
#[pyclass(module = "_ast", name = "Mod", base = NodeOperator)]
pub(crate) struct NodeOperatorMod,
);
impl_node!(
#[pyclass(module = "_ast", name = "Pow", base = NodeOperator)]
pub(crate) struct NodeOperatorPow,
);
impl_node!(
#[pyclass(module = "_ast", name = "LShift", base = NodeOperator)]
pub(crate) struct NodeOperatorLShift,
);
impl_node!(
#[pyclass(module = "_ast", name = "RShift", base = NodeOperator)]
pub(crate) struct NodeOperatorRShift,
);
impl_node!(
#[pyclass(module = "_ast", name = "BitOr", base = NodeOperator)]
pub(crate) struct NodeOperatorBitOr,
);
impl_node!(
#[pyclass(module = "_ast", name = "BitXor", base = NodeOperator)]
pub(crate) struct NodeOperatorBitXor,
);
impl_node!(
#[pyclass(module = "_ast", name = "BitAnd", base = NodeOperator)]
pub(crate) struct NodeOperatorBitAnd,
);
#[pyclass(module = "_ast", name = "unaryop", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeUnaryOp(NodeAst);
impl_base_node!(NodeUnaryOp);
impl_node!(
#[pyclass(module = "_ast", name = "FloorDiv", base = NodeOperator)]
pub(crate) struct NodeOperatorFloorDiv,
);
impl_node!(
#[pyclass(module = "_ast", name = "Invert", base = NodeUnaryOp)]
pub(crate) struct NodeUnaryOpInvert,
);
impl_node!(
#[pyclass(module = "_ast", name = "Not", base = NodeUnaryOp)]
pub(crate) struct NodeUnaryOpNot,
);
impl_node!(
#[pyclass(module = "_ast", name = "UAdd", base = NodeUnaryOp)]
pub(crate) struct NodeUnaryOpUAdd,
);
#[pyclass(module = "_ast", name = "cmpop", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeCmpOp(NodeAst);
impl_base_node!(NodeCmpOp);
impl_node!(
#[pyclass(module = "_ast", name = "USub", base = NodeUnaryOp)]
pub(crate) struct NodeUnaryOpUSub,
);
impl_node!(
#[pyclass(module = "_ast", name = "Eq", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpEq,
);
impl_node!(
#[pyclass(module = "_ast", name = "NotEq", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpNotEq,
);
impl_node!(
#[pyclass(module = "_ast", name = "Lt", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpLt,
);
impl_node!(
#[pyclass(module = "_ast", name = "LtE", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpLtE,
);
impl_node!(
#[pyclass(module = "_ast", name = "Gt", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpGt,
);
impl_node!(
#[pyclass(module = "_ast", name = "GtE", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpGtE,
);
impl_node!(
#[pyclass(module = "_ast", name = "Is", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpIs,
);
impl_node!(
#[pyclass(module = "_ast", name = "IsNot", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpIsNot,
);
impl_node!(
#[pyclass(module = "_ast", name = "In", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpIn,
);
impl_node!(
#[pyclass(module = "_ast", name = "NotIn", base = NodeCmpOp)]
pub(crate) struct NodeCmpOpNotIn,
);
#[pyclass(module = "_ast", name = "excepthandler", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeExceptHandler(NodeAst);
impl_base_node!(NodeExceptHandler);
impl_node!(
#[pyclass(module = "_ast", name = "comprehension", base = NodeAst)]
pub(crate) struct NodeComprehension,
fields: ["target", "iter", "ifs", "is_async"],
);
impl_node!(
#[pyclass(module = "_ast", name = "ExceptHandler", base = NodeExceptHandler)]
pub(crate) struct NodeExceptHandlerExceptHandler,
fields: ["type", "name", "body"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "arguments", base = NodeAst)]
pub(crate) struct NodeArguments,
fields: ["posonlyargs", "args", "vararg", "kwonlyargs", "kw_defaults", "kwarg", "defaults"],
);
impl_node!(
#[pyclass(module = "_ast", name = "arg", base = NodeAst)]
pub(crate) struct NodeArg,
fields: ["arg", "annotation", "type_comment"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "keyword", base = NodeAst)]
pub(crate) struct NodeKeyword,
fields: ["arg", "value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "alias", base = NodeAst)]
pub(crate) struct NodeAlias,
fields: ["name", "asname"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "withitem", base = NodeAst)]
pub(crate) struct NodeWithItem,
fields: ["context_expr", "optional_vars"],
);
#[pyclass(module = "_ast", name = "pattern", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodePattern(NodeAst);
impl_base_node!(NodePattern);
impl_node!(
#[pyclass(module = "_ast", name = "match_case", base = NodeAst)]
pub(crate) struct NodeMatchCase,
fields: ["pattern", "guard", "body"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchValue", base = NodePattern)]
pub(crate) struct NodePatternMatchValue,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchSingleton", base = NodePattern)]
pub(crate) struct NodePatternMatchSingleton,
fields: ["value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchSequence", base = NodePattern)]
pub(crate) struct NodePatternMatchSequence,
fields: ["patterns"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchMapping", base = NodePattern)]
pub(crate) struct NodePatternMatchMapping,
fields: ["keys", "patterns", "rest"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchClass", base = NodePattern)]
pub(crate) struct NodePatternMatchClass,
fields: ["cls", "patterns", "kwd_attrs", "kwd_patterns"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchStar", base = NodePattern)]
pub(crate) struct NodePatternMatchStar,
fields: ["name"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "MatchAs", base = NodePattern)]
pub(crate) struct NodePatternMatchAs,
fields: ["pattern", "name"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[pyclass(module = "_ast", name = "type_ignore", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeTypeIgnore(NodeAst);
impl_base_node!(NodeTypeIgnore);
impl_node!(
#[pyclass(module = "_ast", name = "MatchOr", base = NodePattern)]
pub(crate) struct NodePatternMatchOr,
fields: ["patterns"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[pyclass(module = "_ast", name = "type_param", base = NodeAst)]
#[repr(transparent)]
pub(crate) struct NodeTypeParam(NodeAst);
impl_base_node!(NodeTypeParam);
impl_node!(
#[pyclass(module = "_ast", name = "TypeIgnore", base = NodeTypeIgnore)]
pub(crate) struct NodeTypeIgnoreTypeIgnore,
fields: ["lineno", "tag"],
);
impl_node!(
#[pyclass(module = "_ast", name = "TypeVar", base = NodeTypeParam)]
pub(crate) struct NodeTypeParamTypeVar,
fields: ["name", "bound", "default_value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "ParamSpec", base = NodeTypeParam)]
pub(crate) struct NodeTypeParamParamSpec,
fields: ["name", "default_value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
impl_node!(
#[pyclass(module = "_ast", name = "TypeVarTuple", base = NodeTypeParam)]
pub(crate) struct NodeTypeParamTypeVarTuple,
fields: ["name", "default_value"],
attributes: ["lineno", "col_offset", "end_lineno", "end_col_offset"],
);
#[derive(Clone, Copy)]
enum FieldType {
/// AST node type reference (e.g. "expr", "stmt")
Node(&'static str),
/// Built-in type reference (e.g. "str", "int", "object")
Builtin(&'static str),
/// list[NodeType] — Py_GenericAlias(list, node_type)
ListOf(&'static str),
/// list[BuiltinType] — Py_GenericAlias(list, builtin_type)
ListOfBuiltin(&'static str),
/// NodeType | None — Union[node_type, None]
Optional(&'static str),
/// BuiltinType | None — Union[builtin_type, None]
OptionalBuiltin(&'static str),
}
const FIELD_TYPES: &[(&str, &[(&str, FieldType)])] = &[
(
"Module",
&[
("body", FieldType::ListOf("stmt")),
("type_ignores", FieldType::ListOf("type_ignore")),
],
),
("Interactive", &[("body", FieldType::ListOf("stmt"))]),
("Expression", &[("body", FieldType::Node("expr"))]),
(
"FunctionType",
&[
("argtypes", FieldType::ListOf("expr")),
("returns", FieldType::Node("expr")),
],
),
(
"FunctionDef",
&[
("name", FieldType::Builtin("str")),
("args", FieldType::Node("arguments")),
("body", FieldType::ListOf("stmt")),
("decorator_list", FieldType::ListOf("expr")),
("returns", FieldType::Optional("expr")),
("type_comment", FieldType::OptionalBuiltin("str")),
("type_params", FieldType::ListOf("type_param")),
],
),
(
"AsyncFunctionDef",
&[
("name", FieldType::Builtin("str")),
("args", FieldType::Node("arguments")),
("body", FieldType::ListOf("stmt")),
("decorator_list", FieldType::ListOf("expr")),
("returns", FieldType::Optional("expr")),
("type_comment", FieldType::OptionalBuiltin("str")),
("type_params", FieldType::ListOf("type_param")),
],
),
(
"ClassDef",
&[
("name", FieldType::Builtin("str")),
("bases", FieldType::ListOf("expr")),
("keywords", FieldType::ListOf("keyword")),
("body", FieldType::ListOf("stmt")),
("decorator_list", FieldType::ListOf("expr")),
("type_params", FieldType::ListOf("type_param")),
],
),
("Return", &[("value", FieldType::Optional("expr"))]),
("Delete", &[("targets", FieldType::ListOf("expr"))]),
(
"Assign",
&[
("targets", FieldType::ListOf("expr")),
("value", FieldType::Node("expr")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"TypeAlias",
&[
("name", FieldType::Node("expr")),
("type_params", FieldType::ListOf("type_param")),
("value", FieldType::Node("expr")),
],
),
(
"AugAssign",
&[
("target", FieldType::Node("expr")),
("op", FieldType::Node("operator")),
("value", FieldType::Node("expr")),
],
),
(
"AnnAssign",
&[
("target", FieldType::Node("expr")),
("annotation", FieldType::Node("expr")),
("value", FieldType::Optional("expr")),
("simple", FieldType::Builtin("int")),
],
),
(
"For",
&[
("target", FieldType::Node("expr")),
("iter", FieldType::Node("expr")),
("body", FieldType::ListOf("stmt")),
("orelse", FieldType::ListOf("stmt")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"AsyncFor",
&[
("target", FieldType::Node("expr")),
("iter", FieldType::Node("expr")),
("body", FieldType::ListOf("stmt")),
("orelse", FieldType::ListOf("stmt")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"While",
&[
("test", FieldType::Node("expr")),
("body", FieldType::ListOf("stmt")),
("orelse", FieldType::ListOf("stmt")),
],
),
(
"If",
&[
("test", FieldType::Node("expr")),
("body", FieldType::ListOf("stmt")),
("orelse", FieldType::ListOf("stmt")),
],
),
(
"With",
&[
("items", FieldType::ListOf("withitem")),
("body", FieldType::ListOf("stmt")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"AsyncWith",
&[
("items", FieldType::ListOf("withitem")),
("body", FieldType::ListOf("stmt")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"Match",
&[
("subject", FieldType::Node("expr")),
("cases", FieldType::ListOf("match_case")),
],
),
(
"Raise",
&[
("exc", FieldType::Optional("expr")),
("cause", FieldType::Optional("expr")),
],
),
(
"Try",
&[
("body", FieldType::ListOf("stmt")),
("handlers", FieldType::ListOf("excepthandler")),
("orelse", FieldType::ListOf("stmt")),
("finalbody", FieldType::ListOf("stmt")),
],
),
(
"TryStar",
&[
("body", FieldType::ListOf("stmt")),
("handlers", FieldType::ListOf("excepthandler")),
("orelse", FieldType::ListOf("stmt")),
("finalbody", FieldType::ListOf("stmt")),
],
),
(
"Assert",
&[
("test", FieldType::Node("expr")),
("msg", FieldType::Optional("expr")),
],
),
("Import", &[("names", FieldType::ListOf("alias"))]),
(
"ImportFrom",
&[
("module", FieldType::OptionalBuiltin("str")),
("names", FieldType::ListOf("alias")),
("level", FieldType::OptionalBuiltin("int")),
],
),
("Global", &[("names", FieldType::ListOfBuiltin("str"))]),
("Nonlocal", &[("names", FieldType::ListOfBuiltin("str"))]),
("Expr", &[("value", FieldType::Node("expr"))]),
// -- expr --
(
"BoolOp",
&[
("op", FieldType::Node("boolop")),
("values", FieldType::ListOf("expr")),
],
),
(
"NamedExpr",
&[
("target", FieldType::Node("expr")),
("value", FieldType::Node("expr")),
],
),
(
"BinOp",
&[
("left", FieldType::Node("expr")),
("op", FieldType::Node("operator")),
("right", FieldType::Node("expr")),
],
),
(
"UnaryOp",
&[
("op", FieldType::Node("unaryop")),
("operand", FieldType::Node("expr")),
],
),
(
"Lambda",
&[
("args", FieldType::Node("arguments")),
("body", FieldType::Node("expr")),
],
),
(
"IfExp",
&[
("test", FieldType::Node("expr")),
("body", FieldType::Node("expr")),
("orelse", FieldType::Node("expr")),
],
),
(
"Dict",
&[
("keys", FieldType::ListOf("expr")),
("values", FieldType::ListOf("expr")),
],
),
("Set", &[("elts", FieldType::ListOf("expr"))]),
(
"ListComp",
&[
("elt", FieldType::Node("expr")),
("generators", FieldType::ListOf("comprehension")),
],
),
(
"SetComp",
&[
("elt", FieldType::Node("expr")),
("generators", FieldType::ListOf("comprehension")),
],
),
(
"DictComp",
&[
("key", FieldType::Node("expr")),
("value", FieldType::Node("expr")),
("generators", FieldType::ListOf("comprehension")),
],
),
(
"GeneratorExp",
&[
("elt", FieldType::Node("expr")),
("generators", FieldType::ListOf("comprehension")),
],
),
("Await", &[("value", FieldType::Node("expr"))]),
("Yield", &[("value", FieldType::Optional("expr"))]),
("YieldFrom", &[("value", FieldType::Node("expr"))]),
(
"Compare",
&[
("left", FieldType::Node("expr")),
("ops", FieldType::ListOf("cmpop")),
("comparators", FieldType::ListOf("expr")),
],
),
(
"Call",
&[
("func", FieldType::Node("expr")),
("args", FieldType::ListOf("expr")),
("keywords", FieldType::ListOf("keyword")),
],
),
(
"FormattedValue",
&[
("value", FieldType::Node("expr")),
("conversion", FieldType::Builtin("int")),
("format_spec", FieldType::Optional("expr")),
],
),
("JoinedStr", &[("values", FieldType::ListOf("expr"))]),
("TemplateStr", &[("values", FieldType::ListOf("expr"))]),
(
"Interpolation",
&[
("value", FieldType::Node("expr")),
("str", FieldType::Builtin("object")),
("conversion", FieldType::Builtin("int")),
("format_spec", FieldType::Optional("expr")),
],
),
(
"Constant",
&[
("value", FieldType::Builtin("object")),
("kind", FieldType::OptionalBuiltin("str")),
],
),
(
"Attribute",
&[
("value", FieldType::Node("expr")),
("attr", FieldType::Builtin("str")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"Subscript",
&[
("value", FieldType::Node("expr")),
("slice", FieldType::Node("expr")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"Starred",
&[
("value", FieldType::Node("expr")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"Name",
&[
("id", FieldType::Builtin("str")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"List",
&[
("elts", FieldType::ListOf("expr")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"Tuple",
&[
("elts", FieldType::ListOf("expr")),
("ctx", FieldType::Node("expr_context")),
],
),
(
"Slice",
&[
("lower", FieldType::Optional("expr")),
("upper", FieldType::Optional("expr")),
("step", FieldType::Optional("expr")),
],
),
(
"comprehension",
&[
("target", FieldType::Node("expr")),
("iter", FieldType::Node("expr")),
("ifs", FieldType::ListOf("expr")),
("is_async", FieldType::Builtin("int")),
],
),
(
"ExceptHandler",
&[
("type", FieldType::Optional("expr")),
("name", FieldType::OptionalBuiltin("str")),
("body", FieldType::ListOf("stmt")),
],
),
(
"arguments",
&[
("posonlyargs", FieldType::ListOf("arg")),
("args", FieldType::ListOf("arg")),
("vararg", FieldType::Optional("arg")),
("kwonlyargs", FieldType::ListOf("arg")),
("kw_defaults", FieldType::ListOf("expr")),
("kwarg", FieldType::Optional("arg")),
("defaults", FieldType::ListOf("expr")),
],
),
(
"arg",
&[
("arg", FieldType::Builtin("str")),
("annotation", FieldType::Optional("expr")),
("type_comment", FieldType::OptionalBuiltin("str")),
],
),
(
"keyword",
&[
("arg", FieldType::OptionalBuiltin("str")),
("value", FieldType::Node("expr")),
],
),
(
"alias",
&[
("name", FieldType::Builtin("str")),
("asname", FieldType::OptionalBuiltin("str")),
],
),
(
"withitem",
&[
("context_expr", FieldType::Node("expr")),
("optional_vars", FieldType::Optional("expr")),
],
),
(
"match_case",
&[
("pattern", FieldType::Node("pattern")),
("guard", FieldType::Optional("expr")),
("body", FieldType::ListOf("stmt")),
],
),
("MatchValue", &[("value", FieldType::Node("expr"))]),
("MatchSingleton", &[("value", FieldType::Builtin("object"))]),
(
"MatchSequence",
&[("patterns", FieldType::ListOf("pattern"))],
),
(
"MatchMapping",
&[
("keys", FieldType::ListOf("expr")),
("patterns", FieldType::ListOf("pattern")),
("rest", FieldType::OptionalBuiltin("str")),
],
),
(
"MatchClass",
&[
("cls", FieldType::Node("expr")),
("patterns", FieldType::ListOf("pattern")),
("kwd_attrs", FieldType::ListOfBuiltin("str")),
("kwd_patterns", FieldType::ListOf("pattern")),
],
),
("MatchStar", &[("name", FieldType::OptionalBuiltin("str"))]),
(
"MatchAs",
&[
("pattern", FieldType::Optional("pattern")),
("name", FieldType::OptionalBuiltin("str")),
],
),
("MatchOr", &[("patterns", FieldType::ListOf("pattern"))]),
// -- type_ignore --
(
"TypeIgnore",
&[
("lineno", FieldType::Builtin("int")),
("tag", FieldType::Builtin("str")),
],
),
(
"TypeVar",
&[
("name", FieldType::Builtin("str")),
("bound", FieldType::Optional("expr")),
("default_value", FieldType::Optional("expr")),
],
),
(
"ParamSpec",
&[
("name", FieldType::Builtin("str")),
("default_value", FieldType::Optional("expr")),
],
),
(
"TypeVarTuple",
&[
("name", FieldType::Builtin("str")),
("default_value", FieldType::Optional("expr")),
],
),
];
pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py<PyModule>) {
extend_module!(vm, module, {
"AST" => NodeAst::make_static_type(),
"mod" => NodeMod::make_static_type(),
"Module" => NodeModModule::make_static_type(),
"Interactive" => NodeModInteractive::make_static_type(),
"Expression" => NodeModExpression::make_static_type(),
"FunctionType" => NodeModFunctionType::make_static_type(),
"stmt" => NodeStmt::make_static_type(),
"FunctionDef" => NodeStmtFunctionDef::make_static_type(),
"AsyncFunctionDef" => NodeStmtAsyncFunctionDef::make_static_type(),
"ClassDef" => NodeStmtClassDef::make_static_type(),
"Return" => NodeStmtReturn::make_static_type(),
"Delete" => NodeStmtDelete::make_static_type(),
"Assign" => NodeStmtAssign::make_static_type(),
"TypeAlias" => NodeStmtTypeAlias::make_static_type(),
"AugAssign" => NodeStmtAugAssign::make_static_type(),
"AnnAssign" => NodeStmtAnnAssign::make_static_type(),
"For" => NodeStmtFor::make_static_type(),
"AsyncFor" => NodeStmtAsyncFor::make_static_type(),
"While" => NodeStmtWhile::make_static_type(),
"If" => NodeStmtIf::make_static_type(),
"With" => NodeStmtWith::make_static_type(),
"AsyncWith" => NodeStmtAsyncWith::make_static_type(),
"Match" => NodeStmtMatch::make_static_type(),
"Raise" => NodeStmtRaise::make_static_type(),
"Try" => NodeStmtTry::make_static_type(),
"TryStar" => NodeStmtTryStar::make_static_type(),
"Assert" => NodeStmtAssert::make_static_type(),
"Import" => NodeStmtImport::make_static_type(),
"ImportFrom" => NodeStmtImportFrom::make_static_type(),
"Global" => NodeStmtGlobal::make_static_type(),
"Nonlocal" => NodeStmtNonlocal::make_static_type(),
"Expr" => NodeStmtExpr::make_static_type(),
"Pass" => NodeStmtPass::make_static_type(),
"Break" => NodeStmtBreak::make_static_type(),
"Continue" => NodeStmtContinue::make_static_type(),
"expr" => NodeExpr::make_static_type(),
"BoolOp" => NodeExprBoolOp::make_static_type(),
"NamedExpr" => NodeExprNamedExpr::make_static_type(),
"BinOp" => NodeExprBinOp::make_static_type(),
"UnaryOp" => NodeExprUnaryOp::make_static_type(),
"Lambda" => NodeExprLambda::make_static_type(),
"IfExp" => NodeExprIfExp::make_static_type(),
"Dict" => NodeExprDict::make_static_type(),
"Set" => NodeExprSet::make_static_type(),
"ListComp" => NodeExprListComp::make_static_type(),
"SetComp" => NodeExprSetComp::make_static_type(),
"DictComp" => NodeExprDictComp::make_static_type(),
"GeneratorExp" => NodeExprGeneratorExp::make_static_type(),
"Await" => NodeExprAwait::make_static_type(),
"Yield" => NodeExprYield::make_static_type(),
"YieldFrom" => NodeExprYieldFrom::make_static_type(),
"Compare" => NodeExprCompare::make_static_type(),
"Call" => NodeExprCall::make_static_type(),
"FormattedValue" => NodeExprFormattedValue::make_static_type(),
"JoinedStr" => NodeExprJoinedStr::make_static_type(),
"TemplateStr" => NodeExprTemplateStr::make_static_type(),
"Interpolation" => NodeExprInterpolation::make_static_type(),
"Constant" => NodeExprConstant::make_static_type(),
"Attribute" => NodeExprAttribute::make_static_type(),
"Subscript" => NodeExprSubscript::make_static_type(),
"Starred" => NodeExprStarred::make_static_type(),
"Name" => NodeExprName::make_static_type(),
"List" => NodeExprList::make_static_type(),
"Tuple" => NodeExprTuple::make_static_type(),
"Slice" => NodeExprSlice::make_static_type(),
"expr_context" => NodeExprContext::make_static_type(),
"Load" => NodeExprContextLoad::make_static_type(),
"Store" => NodeExprContextStore::make_static_type(),
"Del" => NodeExprContextDel::make_static_type(),
"boolop" => NodeBoolOp::make_static_type(),
"And" => NodeBoolOpAnd::make_static_type(),
"Or" => NodeBoolOpOr::make_static_type(),
"operator" => NodeOperator::make_static_type(),
"Add" => NodeOperatorAdd::make_static_type(),
"Sub" => NodeOperatorSub::make_static_type(),
"Mult" => NodeOperatorMult::make_static_type(),
"MatMult" => NodeOperatorMatMult::make_static_type(),
"Div" => NodeOperatorDiv::make_static_type(),
"Mod" => NodeOperatorMod::make_static_type(),
"Pow" => NodeOperatorPow::make_static_type(),
"LShift" => NodeOperatorLShift::make_static_type(),
"RShift" => NodeOperatorRShift::make_static_type(),
"BitOr" => NodeOperatorBitOr::make_static_type(),
"BitXor" => NodeOperatorBitXor::make_static_type(),
"BitAnd" => NodeOperatorBitAnd::make_static_type(),
"FloorDiv" => NodeOperatorFloorDiv::make_static_type(),
"unaryop" => NodeUnaryOp::make_static_type(),
"Invert" => NodeUnaryOpInvert::make_static_type(),
"Not" => NodeUnaryOpNot::make_static_type(),
"UAdd" => NodeUnaryOpUAdd::make_static_type(),
"USub" => NodeUnaryOpUSub::make_static_type(),
"cmpop" => NodeCmpOp::make_static_type(),
"Eq" => NodeCmpOpEq::make_static_type(),
"NotEq" => NodeCmpOpNotEq::make_static_type(),
"Lt" => NodeCmpOpLt::make_static_type(),
"LtE" => NodeCmpOpLtE::make_static_type(),
"Gt" => NodeCmpOpGt::make_static_type(),
"GtE" => NodeCmpOpGtE::make_static_type(),
"Is" => NodeCmpOpIs::make_static_type(),
"IsNot" => NodeCmpOpIsNot::make_static_type(),
"In" => NodeCmpOpIn::make_static_type(),
"NotIn" => NodeCmpOpNotIn::make_static_type(),
"comprehension" => NodeComprehension::make_static_type(),
"excepthandler" => NodeExceptHandler::make_static_type(),
"ExceptHandler" => NodeExceptHandlerExceptHandler::make_static_type(),
"arguments" => NodeArguments::make_static_type(),
"arg" => NodeArg::make_static_type(),
"keyword" => NodeKeyword::make_static_type(),
"alias" => NodeAlias::make_static_type(),
"withitem" => NodeWithItem::make_static_type(),
"match_case" => NodeMatchCase::make_static_type(),
"pattern" => NodePattern::make_static_type(),
"MatchValue" => NodePatternMatchValue::make_static_type(),
"MatchSingleton" => NodePatternMatchSingleton::make_static_type(),
"MatchSequence" => NodePatternMatchSequence::make_static_type(),
"MatchMapping" => NodePatternMatchMapping::make_static_type(),
"MatchClass" => NodePatternMatchClass::make_static_type(),
"MatchStar" => NodePatternMatchStar::make_static_type(),
"MatchAs" => NodePatternMatchAs::make_static_type(),
"MatchOr" => NodePatternMatchOr::make_static_type(),
"type_ignore" => NodeTypeIgnore::make_static_type(),
"TypeIgnore" => NodeTypeIgnoreTypeIgnore::make_static_type(),
"type_param" => NodeTypeParam::make_static_type(),
"TypeVar" => NodeTypeParamTypeVar::make_static_type(),
"ParamSpec" => NodeTypeParamParamSpec::make_static_type(),
"TypeVarTuple" => NodeTypeParamTypeVarTuple::make_static_type(),
});
populate_field_types(vm, module);
populate_singletons(vm, module);
force_ast_module_name(vm, module);
populate_repr(vm, module);
}
fn populate_field_types(vm: &VirtualMachine, module: &Py<PyModule>) {
let list_type: PyTypeRef = vm.ctx.types.list_type.to_owned();
let none_type: PyObjectRef = vm.ctx.types.none_type.to_owned().into();
let resolve_builtin = |name: &str| -> PyObjectRef {
let ty: &Py<PyType> = match name {
"str" => vm.ctx.types.str_type,
"int" => vm.ctx.types.int_type,
"object" => vm.ctx.types.object_type,
"bool" => vm.ctx.types.bool_type,
_ => unreachable!("unknown builtin type: {name}"),
};
ty.to_owned().into()
};
// Resolve an AST node type name by looking it up from the module
let resolve_node = |name: &str| -> PyObjectRef {
module
.get_attr(vm.ctx.intern_str(name), vm)
.unwrap_or_else(|_| panic!("AST node type '{name}' not found in module"))
};
let field_types_attr = vm.ctx.intern_str("_field_types");
let annotations_attr = vm.ctx.intern_str("__annotations__");
let empty_dict: PyObjectRef = vm.ctx.new_dict().into();
for &(class_name, fields) in FIELD_TYPES {
if fields.is_empty() {
continue;
}
let class = module
.get_attr(class_name, vm)
.unwrap_or_else(|_| panic!("AST class '{class_name}' not found in module"));
let dict = vm.ctx.new_dict();
for &(field_name, ref field_type) in fields {
let type_obj = match field_type {
FieldType::Node(name) => resolve_node(name),
FieldType::Builtin(name) => resolve_builtin(name),
FieldType::ListOf(name) => {
let elem = resolve_node(name);
let args = PyTuple::new_ref(vec![elem], &vm.ctx);
PyGenericAlias::new(list_type.clone(), args, false, vm).to_pyobject(vm)
}
FieldType::ListOfBuiltin(name) => {
let elem = resolve_builtin(name);
let args = PyTuple::new_ref(vec![elem], &vm.ctx);
PyGenericAlias::new(list_type.clone(), args, false, vm).to_pyobject(vm)
}
FieldType::Optional(name) => {
let base = resolve_node(name);
let union_args = PyTuple::new_ref(vec![base, none_type.clone()], &vm.ctx);
make_union(&union_args, vm).expect("failed to create union type")
}
FieldType::OptionalBuiltin(name) => {
let base = resolve_builtin(name);
let union_args = PyTuple::new_ref(vec![base, none_type.clone()], &vm.ctx);
make_union(&union_args, vm).expect("failed to create union type")
}
};
dict.set_item(vm.ctx.intern_str(field_name), type_obj, vm)
.expect("failed to set field type");
}
let dict_obj: PyObjectRef = dict.into();
if let Some(type_obj) = class.downcast_ref::<PyType>() {
type_obj.set_attr(field_types_attr, dict_obj.clone());
type_obj.set_attr(annotations_attr, dict_obj);
// Set None as class-level default for optional fields.
// When ast_type_init skips optional fields, the instance
// inherits None from the class (init_types in Python-ast.c).
let none = vm.ctx.none();
for &(field_name, ref field_type) in fields {
if matches!(
field_type,
FieldType::Optional(_) | FieldType::OptionalBuiltin(_)
) {
type_obj.set_attr(vm.ctx.intern_str(field_name), none.clone());
}
}
}
}
// CPython sets __annotations__ for all built-in AST node classes, even
// when _field_types is an empty dict (e.g., operators, Load/Store/Del).
for (_name, value) in &module.dict() {
let Some(type_obj) = value.downcast_ref::<PyType>() else {
continue;
};
if let Some(field_types) = type_obj.get_attr(field_types_attr) {
type_obj.set_attr(annotations_attr, field_types);
}
}
// Base AST classes (e.g., expr, stmt) should still expose __annotations__.
const BASE_AST_TYPES: &[&str] = &[
"mod",
"stmt",
"expr",
"expr_context",
"boolop",
"operator",
"unaryop",
"cmpop",
"excepthandler",
"pattern",
"type_ignore",
"type_param",
];
for &class_name in BASE_AST_TYPES {
let class = module
.get_attr(class_name, vm)
.unwrap_or_else(|_| panic!("AST class '{class_name}' not found in module"));
let Some(type_obj) = class.downcast_ref::<PyType>() else {
continue;
};
if type_obj.get_attr(field_types_attr).is_none() {
type_obj.set_attr(field_types_attr, empty_dict.clone());
}
if type_obj.get_attr(annotations_attr).is_none() {
type_obj.set_attr(annotations_attr, empty_dict.clone());
}
}
}
fn populate_singletons(vm: &VirtualMachine, module: &Py<PyModule>) {
let instance_attr = vm.ctx.intern_str("_instance");
const SINGLETON_TYPES: &[&str] = &[
// expr_context
"Load", "Store", "Del", // boolop
"And", "Or", // operator
"Add", "Sub", "Mult", "MatMult", "Div", "Mod", "Pow", "LShift", "RShift", "BitOr",
"BitXor", "BitAnd", "FloorDiv", // unaryop
"Invert", "Not", "UAdd", "USub", // cmpop
"Eq", "NotEq", "Lt", "LtE", "Gt", "GtE", "Is", "IsNot", "In", "NotIn",
];
for &class_name in SINGLETON_TYPES {
let class = module
.get_attr(class_name, vm)
.unwrap_or_else(|_| panic!("AST class '{class_name}' not found in module"));
let Some(type_obj) = class.downcast_ref::<PyType>() else {
continue;
};
let instance = vm
.ctx
.new_base_object(type_obj.to_owned(), Some(vm.ctx.new_dict()));
type_obj.set_attr(instance_attr, instance);
}
}
fn force_ast_module_name(vm: &VirtualMachine, module: &Py<PyModule>) {
let ast_name = vm.ctx.new_str("ast");
for (_name, value) in &module.dict() {
let Some(type_obj) = value.downcast_ref::<PyType>() else {
continue;
};
type_obj.set_attr(identifier!(vm, __module__), ast_name.clone().into());
}
}
fn populate_repr(_vm: &VirtualMachine, module: &Py<PyModule>) {
for (_name, value) in &module.dict() {
let Some(type_obj) = value.downcast_ref::<PyType>() else {
continue;
};
type_obj
.slots
.repr
.store(Some(super::python::_ast::ast_repr));
}
}