"""vast.nodes - 与 CPython 3.12 ast 完全同构的 AST 节点类 vast 是自研 Viper/Python 语法解析器,产出与标准库 ast 模块结构完全一致的 AST 树,从而使编译器侧 ``import vast as ast`` 后原有代码零修改。 本模块定义全部 131 个 AST 节点类(含遗留兼容类),字段/属性与 CPython 3.12 的 ``ast`` 模块逐一对应: - ``_fields``:节点结构字段(顺序与位置参数构造一致) - ``_attributes``:dump(include_attributes=True) 时随节点输出的位置属性 构造语义与 CPython 一致: - 位置参数按 ``_fields`` 顺序赋值,超出字段数抛 TypeError - 关键字参数按名赋值(实例为 __slots__ 紧凑布局,仅接受已声明字段) - 未传入的字段不设置属性(访问时 AttributeError,与 CPython 一致) """ from __future__ import annotations class AST: """所有 AST 节点的基类(与 ast.AST 同构)。""" # 空 __slots__:保证子类定义 __slots__ 后实例不携带 __dict__ # (基类若有 __dict__,子类 __slots__ 将失效) __slots__ = () _fields: tuple[str, ...] = () _attributes: tuple[str, ...] = () def __init__(self, *args: object, **kwargs: object) -> None: fields: tuple[str, ...] = self._fields if len(args) > len(fields): raise TypeError( f'{type(self).__name__} constructor takes at most ' f'{len(fields)} positional arguments' ) for name, val in zip(fields, args): setattr(self, name, val) for k, v in kwargs.items(): setattr(self, k, v) def __eq__(self, other: object) -> bool: """AST 节点按对象身份比较(与 CPython ast 一致)。""" return self is other # ============================================================================= # 节点定义表:字段表(含位置属性表),数据驱动生成全部节点类 # ============================================================================= _POS_ATTRS: tuple[str, ...] = ('lineno', 'col_offset', 'end_lineno', 'end_col_offset') # extern/export/define 软关键字标记(_ParseExternDef/_ParseExportDef/_ParseDefineDef # 写入,unparse 还原)。__slots__ 类无 __dict__,必须纳入槽位,否则 # node.Extern = True 抛 AttributeError。 _FUNC_ATTRS: tuple[str, ...] = _POS_ATTRS + ('Extern', 'Export', 'Define') # 类型注解修饰(由 Parser 直接写入注解节点,不再用 `T1 | T2` 组合表示): # Markers: ('const','volatile','static','export','extern','inline','state','define','typedef') # Attributes: ('section(".x")', 'aligned(16)', ...) # ByteOrder: '' | 'big' | 'little' # BitWidth: 0 = 非位域 _TYPE_ATTRS: tuple[str, ...] = _POS_ATTRS + ('Markers', 'Attributes', 'ByteOrder', 'BitWidth') _NODE_DEFS: dict[str, tuple[tuple[str, ...], tuple[str, ...]]] = { # ---- 模块/交互/表达式顶层 ---- 'Module': (('body', 'type_ignores'), ()), 'Interactive': (('body',), ()), 'Expression': (('body',), ()), 'FunctionType': (('argtypes', 'returns'), ()), 'Suite': ((), ()), # ---- 语句 ---- 'FunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS + _TYPE_ATTRS), 'AsyncFunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _FUNC_ATTRS + _TYPE_ATTRS), 'ClassDef': (('name', 'bases', 'keywords', 'body', 'decorator_list', 'type_params'), _POS_ATTRS), 'Return': (('value',), _POS_ATTRS), 'Delete': (('targets',), _POS_ATTRS), 'Assign': (('targets', 'value', 'type_comment'), _POS_ATTRS), 'AugAssign': (('target', 'op', 'value'), _POS_ATTRS), 'AnnAssign': (('target', 'annotation', 'value', 'simple'), _TYPE_ATTRS), 'For': (('target', 'iter', 'body', 'orelse', 'type_comment'), _POS_ATTRS), 'AsyncFor': (('target', 'iter', 'body', 'orelse', 'type_comment'), _POS_ATTRS), 'While': (('test', 'body', 'orelse'), _POS_ATTRS), 'If': (('test', 'body', 'orelse'), _POS_ATTRS), 'With': (('items', 'body', 'type_comment'), _POS_ATTRS), 'AsyncWith': (('items', 'body', 'type_comment'), _POS_ATTRS), 'Match': (('subject', 'cases', 'is_switch'), _POS_ATTRS), 'Raise': (('exc', 'cause'), _POS_ATTRS), 'Try': (('body', 'handlers', 'orelse', 'finalbody'), _POS_ATTRS), 'TryStar': (('body', 'handlers', 'orelse', 'finalbody'), _POS_ATTRS), 'Assert': (('test', 'msg'), _POS_ATTRS), 'Import': (('names',), _POS_ATTRS), 'ImportFrom': (('module', 'names', 'level'), _POS_ATTRS), 'Global': (('names',), _POS_ATTRS), 'Nonlocal': (('names',), _POS_ATTRS), 'Expr': (('value',), _POS_ATTRS), 'Pass': ((), _POS_ATTRS), 'Break': ((), _POS_ATTRS), 'Continue': ((), _POS_ATTRS), # ---- 表达式 ---- 'BoolOp': (('op', 'values'), _POS_ATTRS), 'NamedExpr': (('target', 'value'), _POS_ATTRS), 'BinOp': (('left', 'op', 'right'), _POS_ATTRS), 'UnaryOp': (('op', 'operand'), _POS_ATTRS), 'Lambda': (('args', 'body'), _POS_ATTRS), 'IfExp': (('test', 'body', 'orelse'), _POS_ATTRS), 'Dict': (('keys', 'values'), _POS_ATTRS), 'Set': (('elts',), _POS_ATTRS), 'ListComp': (('elt', 'generators'), _POS_ATTRS), 'SetComp': (('elt', 'generators'), _POS_ATTRS), 'DictComp': (('key', 'value', 'generators'), _POS_ATTRS), 'GeneratorExp': (('elt', 'generators'), _POS_ATTRS), 'Await': (('value',), _POS_ATTRS), 'Yield': (('value',), _POS_ATTRS), 'YieldFrom': (('value',), _POS_ATTRS), 'Compare': (('left', 'ops', 'comparators'), _POS_ATTRS), 'Call': (('func', 'args', 'keywords'), _TYPE_ATTRS), # Viper `new` 生命周期分配表达式(软关键字):new [描述符...] T(args)。 # Source/Life 为描述符整数(见 NEW_SRC_*/NEW_LIFE_*);memgr 为 `memgr(x)` 的 x # (无 memgr 描述符时为 None);func 是被构造的 callee(Name/Attribute/Subscript), # args 为构造实参列表(无括号时为 None)。 'New': (('Source', 'Life', 'memgr', 'func', 'args'), _POS_ATTRS), 'FormattedValue': (('value', 'conversion', 'format_spec'), _POS_ATTRS), 'JoinedStr': (('values',), _POS_ATTRS), 'Constant': (('value', 'kind'), _TYPE_ATTRS + ('int_width', 'int_unsigned')), 'Attribute': (('value', 'attr', 'ctx'), _TYPE_ATTRS), 'Subscript': (('value', 'slice', 'ctx'), _TYPE_ATTRS), 'Starred': (('value', 'ctx'), _POS_ATTRS), 'Name': (('id', 'ctx'), _TYPE_ATTRS), 'List': (('elts', 'ctx'), _POS_ATTRS), 'Tuple': (('elts', 'ctx'), _POS_ATTRS), 'Slice': (('lower', 'upper', 'step'), _POS_ATTRS), # ---- match 模式(PEP 634) ---- 'MatchValue': (('value',), _POS_ATTRS), 'MatchSingleton': (('value',), _POS_ATTRS), 'MatchSequence': (('patterns',), _POS_ATTRS), 'MatchMapping': (('keys', 'patterns', 'rest'), _POS_ATTRS), 'MatchClass': (('cls', 'patterns', 'kwd_attrs', 'kwd_patterns'), _POS_ATTRS), 'MatchStar': (('name',), _POS_ATTRS), 'MatchAs': (('pattern', 'name'), _POS_ATTRS), 'MatchOr': (('patterns',), _POS_ATTRS), # ---- 类型参数(PEP 695,仅声明性支持) ---- 'TypeVar': (('name', 'bound'), _POS_ATTRS), 'TypeVarTuple': (('name',), _POS_ATTRS), 'ParamSpec': (('name',), _POS_ATTRS), 'TypeAlias': (('name', 'type_params', 'value'), _POS_ATTRS), # ---- 复合辅助节点 ---- 'comprehension': (('target', 'iter', 'ifs', 'is_async'), ()), 'ExceptHandler': (('type', 'name', 'body'), _POS_ATTRS), 'arguments': (('posonlyargs', 'args', 'vararg', 'kwonlyargs', 'kw_defaults', 'kwarg', 'defaults'), ()), 'arg': (('arg', 'annotation', 'type_comment'), _TYPE_ATTRS), 'keyword': (('arg', 'value'), _POS_ATTRS), 'alias': (('name', 'asname'), _POS_ATTRS), 'withitem': (('context_expr', 'optional_vars'), ()), 'match_case': (('pattern', 'guard', 'body'), ()), 'TypeIgnore': (('lineno', 'tag'), ()), # ---- 运算符 / 上下文(无字段单例类) ---- 'Add': ((), ()), 'Sub': ((), ()), 'Mult': ((), ()), 'MatMult': ((), ()), 'Div': ((), ()), 'Mod': ((), ()), 'Pow': ((), ()), 'LShift': ((), ()), 'RShift': ((), ()), 'BitOr': ((), ()), 'BitXor': ((), ()), 'BitAnd': ((), ()), 'FloorDiv': ((), ()), 'Invert': ((), ()), 'Not': ((), ()), 'UAdd': ((), ()), 'USub': ((), ()), # Viper 扩展:单目解引用/取地址(*x / &x) 'Deref': ((), ()), 'AddrOf': ((), ()), 'Eq': ((), ()), 'NotEq': ((), ()), 'Lt': ((), ()), 'LtE': ((), ()), 'Gt': ((), ()), 'GtE': ((), ()), 'Is': ((), ()), 'IsNot': ((), ()), 'In': ((), ()), 'NotIn': ((), ()), 'And': ((), ()), 'Or': ((), ()), 'Load': ((), ()), 'Store': ((), ()), 'Del': ((), ()), 'AugLoad': ((), ()), 'AugStore': ((), ()), 'Param': ((), ()), 'Ellipsis': ((), _POS_ATTRS), # ---- 遗留兼容类(已废弃但保留,供 hasattr 检查) ---- 'Index': ((), ()), 'ExtSlice': ((), ()), # ---- 抽象类型占位(纯类型标注用,不实例化) ---- 'mod': ((), ()), 'stmt': ((), ()), 'expr': ((), ()), 'expr_context': ((), ()), 'boolop': ((), ()), 'operator': ((), ()), 'unaryop': ((), ()), 'cmpop': ((), ()), 'slice': ((), ()), 'pattern': ((), ()), 'type_ignore': ((), ()), 'type_param': ((), ()), 'excepthandler': ((), ()), } _DOCS: dict[str, str] = { 'FunctionDef': '函数定义节点(对应 def 语句)。', 'AsyncFunctionDef': '异步函数定义节点(对应 async def)。', 'ClassDef': '类定义节点(对应 class 语句)。', 'AnnAssign': '带注解的赋值节点(x: T = v)。', 'Constant': '常量节点(数字/字符串/bool/None/Ellipsis)。', 'Name': '名称节点(标识符引用,含 Load/Store/Del 上下文)。', 'Call': '函数调用节点。', 'BinOp': '二元运算节点。', 'Attribute': '属性访问节点(obj.attr)。', 'Subscript': '下标访问节点(obj[idx])。', 'arguments': '函数参数列表节点(含默认值、*args、**kwargs)。', 'alias': 'import 别名节点。', 'keyword': '关键字实参节点(f(x=1))。', 'withitem': 'with 语句上下文节点。', } # 类属性默认值(与 CPython 3.12 ast 节点一致): # dump 时"实例值为 None 且类默认值为 None"的字段会被跳过; # 无类默认值的字段(如 Constant.value)即使为 None 也会显示。 _CLASS_DEFAULTS: dict[str, dict[str, object]] = { 'AnnAssign': {'value': None}, 'Assert': {'msg': None}, 'Assign': {'type_comment': None}, 'AsyncFor': {'type_comment': None}, 'AsyncFunctionDef': {'returns': None, 'type_comment': None}, 'AsyncWith': {'type_comment': None}, 'Constant': {'kind': None}, 'ExceptHandler': {'type': None, 'name': None}, 'For': {'type_comment': None}, 'FormattedValue': {'format_spec': None}, 'FunctionDef': {'returns': None, 'type_comment': None}, 'ImportFrom': {'module': None, 'level': None}, 'match_case': {'guard': None}, 'MatchAs': {'pattern': None, 'name': None}, 'MatchMapping': {'rest': None}, 'MatchStar': {'name': None}, 'New': {'memgr': None, 'args': None}, 'Raise': {'exc': None, 'cause': None}, 'Return': {'value': None}, 'Slice': {'lower': None, 'upper': None, 'step': None}, 'TypeVar': {'bound': None}, 'With': {'type_comment': None}, 'Yield': {'value': None}, 'alias': {'asname': None}, 'arg': {'annotation': None, 'type_comment': None}, 'arguments': {'vararg': None, 'kwarg': None}, 'keyword': {'arg': None}, 'withitem': {'optional_vars': None}, } # 节点抽象基类映射(与 CPython 3.12 一致:expr/stmt/mod/operator/cmpop/...) # 节点类继承对应的抽象基类,使 isinstance(node, ast.expr) 等判断可用 _BASE_CLASS: dict[str, str] = { # stmt 'AnnAssign': 'stmt', 'Assert': 'stmt', 'Assign': 'stmt', 'AsyncFor': 'stmt', 'AsyncFunctionDef': 'stmt', 'AsyncWith': 'stmt', 'AugAssign': 'stmt', 'Break': 'stmt', 'ClassDef': 'stmt', 'Continue': 'stmt', 'Delete': 'stmt', 'Expr': 'stmt', 'For': 'stmt', 'FunctionDef': 'stmt', 'Global': 'stmt', 'If': 'stmt', 'Import': 'stmt', 'ImportFrom': 'stmt', 'Match': 'stmt', 'Nonlocal': 'stmt', 'Pass': 'stmt', 'Raise': 'stmt', 'Return': 'stmt', 'Try': 'stmt', 'TryStar': 'stmt', 'TypeAlias': 'stmt', 'While': 'stmt', 'With': 'stmt', # expr 'Attribute': 'expr', 'Await': 'expr', 'BinOp': 'expr', 'BoolOp': 'expr', 'Call': 'expr', 'Compare': 'expr', 'Constant': 'expr', 'Dict': 'expr', 'DictComp': 'expr', 'FormattedValue': 'expr', 'GeneratorExp': 'expr', 'IfExp': 'expr', 'JoinedStr': 'expr', 'Lambda': 'expr', 'List': 'expr', 'ListComp': 'expr', 'Name': 'expr', 'NamedExpr': 'expr', 'New': 'expr', 'Set': 'expr', 'SetComp': 'expr', 'Slice': 'expr', 'Starred': 'expr', 'Subscript': 'expr', 'Tuple': 'expr', 'UnaryOp': 'expr', 'Yield': 'expr', 'YieldFrom': 'expr', # mod 'Module': 'mod', 'Interactive': 'mod', 'Expression': 'mod', 'FunctionType': 'mod', 'Suite': 'mod', # operator 'Add': 'operator', 'Sub': 'operator', 'Mult': 'operator', 'MatMult': 'operator', 'Div': 'operator', 'Mod': 'operator', 'Pow': 'operator', 'LShift': 'operator', 'RShift': 'operator', 'BitOr': 'operator', 'BitXor': 'operator', 'BitAnd': 'operator', 'FloorDiv': 'operator', # unaryop 'Invert': 'unaryop', 'Not': 'unaryop', 'UAdd': 'unaryop', 'USub': 'unaryop', 'Deref': 'unaryop', 'AddrOf': 'unaryop', # boolop 'And': 'boolop', 'Or': 'boolop', # cmpop 'Eq': 'cmpop', 'NotEq': 'cmpop', 'Lt': 'cmpop', 'LtE': 'cmpop', 'Gt': 'cmpop', 'GtE': 'cmpop', 'Is': 'cmpop', 'IsNot': 'cmpop', 'In': 'cmpop', 'NotIn': 'cmpop', # expr_context 'Load': 'expr_context', 'Store': 'expr_context', 'Del': 'expr_context', 'AugLoad': 'expr_context', 'AugStore': 'expr_context', 'Param': 'expr_context', # slice 'Index': 'slice', 'ExtSlice': 'slice', # pattern 'MatchValue': 'pattern', 'MatchSingleton': 'pattern', 'MatchSequence': 'pattern', 'MatchMapping': 'pattern', 'MatchClass': 'pattern', 'MatchStar': 'pattern', 'MatchAs': 'pattern', 'MatchOr': 'pattern', # type_param / type_ignore 'TypeVar': 'type_param', 'TypeVarTuple': 'type_param', 'ParamSpec': 'type_param', 'TypeIgnore': 'type_ignore', # excepthandler 'ExceptHandler': 'excepthandler', } def _MakeNodeClass(name: str, fields: tuple[str, ...], attrs: tuple[str, ...]) -> type: """按字段表生成节点类(继承对应抽象基类)。""" # 特化 __init__:常见路径(全位置参数,vast_c 回退 Vectorcall 的主形态)按 # 字段索引直赋(unroll),避免 zip 迭代器 + 循环控制开销(PROF:_Init # 158 万次 29s 是最大纯 Python 热点)。语义与通用路径完全等价: # 位置参数按序设置前 n 个字段,kwargs 后设覆盖;越界同样抛 TypeError。 def _MakeInit(name: str, fields: tuple[str, ...]) -> object: n = len(fields) lines: list[str] = [ "def _Init(self: AST, *args: object, **kwargs: object) -> None:", " _set = object.__setattr__", " _n = len(args)", f" if _n > {n}:", f" raise TypeError(f'{name} constructor takes at most {n} positional arguments')", ] if n > 0: lines.append(" if _n:") for i in range(1, min(n, 8) + 1): assigns = "; ".join( f"_set(self, {fields[j]!r}, args[{j}])" for j in range(i)) lines.append(f" if _n == {i}:") lines.append(f" {assigns}") if n > 8: lines.append(" else:") lines.append(" for _i in range(_n):") lines.append(" _set(self, _F[_i], args[_i])") lines.append(" for _k, _v in kwargs.items():") lines.append(" _set(self, _k, _v)") ns: dict[str, object] = {"AST": AST, "_F": fields} exec("\n".join(lines), ns) return ns["_Init"] base_name: str | None = _BASE_CLASS.get(name) base_cls: type = globals()[base_name] if base_name else AST # __slots__ = 位置字段 + 位置属性(实例的全部属性名) slots: tuple[str, ...] = tuple(dict.fromkeys(fields + attrs)) ns: dict[str, object] = { '__init__': _MakeInit(name, fields), '__slots__': slots, '_fields': fields, '_attributes': attrs, # 字段默认值不能直接作为类属性(与同名 __slots__ 冲突), # 存入独立类属性供 dump 判断"值为 None 且默认值为 None"时跳过 '_node_defaults': dict(_CLASS_DEFAULTS.get(name, {})), '__module__': __name__, '__doc__': _DOCS.get(name, f'{name} AST 节点(与 ast.{name} 同构)。'), } cls: type = type(name, (base_cls,), ns) return cls # 动态生成全部节点类到本模块命名空间 # 抽象基类(mod/stmt/expr/...)在 _NODE_DEFS 末尾定义,但需先生成 _ABSTRACT_BASES: tuple[str, ...] = ( 'mod', 'stmt', 'expr', 'expr_context', 'boolop', 'operator', 'unaryop', 'cmpop', 'slice', 'pattern', 'type_ignore', 'type_param', 'excepthandler', ) for _name in _ABSTRACT_BASES: _fields, _attrs = _NODE_DEFS[_name] globals()[_name] = _MakeNodeClass(_name, _fields, _attrs) for _name, (_fields, _attrs) in _NODE_DEFS.items(): if _name in _ABSTRACT_BASES: continue globals()[_name] = _MakeNodeClass(_name, _fields, _attrs) # 显式别名:AnnAssign 已在表内;这里保证模块级 __all__ 完整性 __all__: list[str] = list(_NODE_DEFS.keys()) + ['AST']