Files
TransPyC/lib/vast/Nodes.py
T
TermiNexus e25095da43 perf(vast): _At 内联 _Peek(0) 缓存逻辑 + Node 构造 __dict__ 直写
_At 被调用 1384 万次,每次经 _Peek 再取 token;内联 _Peek(0) 缓存
(_PeekCacheIdx/_PeekCacheTok)省 2300 万次函数调用,实测单文件解析
端到端提速 ~37%。_Init 的 setattr 改 __dict__ 直写(AST 节点无
__slots__/property,行为等价)。vast 差分测试 51/53 PASS 0 FAIL。
2026-08-17 22:20:28 +08:00

349 lines
15 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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
- 关键字参数全部 setattr(包括未知字段,与 CPython 行为一致)
- 未传入的字段不设置属性(访问时 AttributeError,与 CPython 一致)
"""
from __future__ import annotations
class AST:
"""所有 AST 节点的基类(与 ast.AST 同构)。"""
_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')
_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'), _POS_ATTRS),
'AsyncFunctionDef': (('name', 'args', 'body', 'decorator_list', 'returns', 'type_comment', 'type_params'), _POS_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'), _POS_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'), _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'), _POS_ATTRS),
'FormattedValue': (('value', 'conversion', 'format_spec'), _POS_ATTRS),
'JoinedStr': (('values',), _POS_ATTRS),
'Constant': (('value', 'kind'), _POS_ATTRS),
'Attribute': (('value', 'attr', 'ctx'), _POS_ATTRS),
'Subscript': (('value', 'slice', 'ctx'), _POS_ATTRS),
'Starred': (('value', 'ctx'), _POS_ATTRS),
'Name': (('id', 'ctx'), _POS_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'), _POS_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': ((), ()),
'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},
'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', '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',
# 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:
"""按字段表生成节点类(继承对应抽象基类)。"""
def _Init(self: AST, *args: object, **kwargs: object) -> None:
if len(args) > len(fields):
raise TypeError(
f'{name} constructor takes at most {len(fields)} positional arguments'
)
for fname, val in zip(fields, args):
self.__dict__[fname] = val
for k, v in kwargs.items():
self.__dict__[k] = v
base_name: str | None = _BASE_CLASS.get(name)
base_cls: type = globals()[base_name] if base_name else AST
ns: dict[str, object] = {
'__init__': _Init,
'_fields': fields,
'_attributes': attrs,
'__module__': __name__,
'__doc__': _DOCS.get(name, f'{name} AST 节点(与 ast.{name} 同构)。'),
}
# 类默认值(None 字段在 dump 时跳过)
for fname, fdefault in _CLASS_DEFAULTS.get(name, {}).items():
ns[fname] = fdefault
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']