chore: 同步 TransPyV→ViperC 改名、new 表达式支持与定宽字面量/窄化适配

This commit is contained in:
TermiNexus committed 2026-10-12 20:59:39 +08:00
1 parent 15f77da9d3
commit 23b47053d9
10 files changed
+10283 -10041

No files matched your search

+93 -2
View File
@@ -23,6 +23,30 @@ from lib.vast.Tokenizer import (
)
# ---------------------------------------------------------------------------
# `new [描述符...] T(args)` 生命周期分配表达式(与 ViperC includes/ast/exprs.vp
# 的 NEW_SRC_*/NEW_LIFE_* 同值)。TPC 侧同样按 VPC 口径解析成 New 节点,语义落地
# 由 Handles 负责(见 HandlesExprCall._HandleNewExprLlvm)。
# ---------------------------------------------------------------------------
NEW_SRC_DEFAULT = 0
NEW_SRC_STACK = 1
NEW_SRC_HEAP = 2
NEW_SRC_MEMGR = 3
NEW_LIFE_DEFAULT = 0
NEW_LIFE_SLIFE = 1
NEW_LIFE_HLIFE = 2
# `new` 之后的普通名不能是这些保留字(它们在 vast 里也是 NAME token)。
# 缺此判据时 `for new in x:` 会被误判为 new 表达式(`in` 紧随其后)。
_NEW_NEXT_RESERVED: frozenset[str] = frozenset({
'in', 'is', 'and', 'or', 'not', 'if', 'else', 'elif', 'for', 'while',
'lambda', 'await', 'yield', 'return', 'pass', 'break', 'continue',
'import', 'from', 'as', 'with', 'try', 'except', 'finally', 'raise',
'def', 'class', 'global', 'nonlocal', 'del', 'assert', 'match', 'case',
'True', 'False', 'None',
})
def _JoinConstParts(parts: list[object]) -> str | bytes:
"""拼接连续字符串字面量值(str 或 bytes,与 CPython 语义一致)。"""
if not parts:
@@ -705,6 +729,58 @@ class ExprParserMixin(TokenStream):
# ==================================================================
# 原子表达式
# ==================================================================
def _ParseNewExpr(self) -> N.expr:
"""`new [hlife|slife] [stack|heap|memgr(x)] T(args)`(软关键字,与 VPC 同口径)。
描述符顺序无关、各轴最多一次;T 走主表达式(Name/Attribute/Subscript + 调用
trailer),若解析结果本身是 Call(`T(args)`)则拆成 func/args,否则 args=None。
结果恒为 T*(语义在 Handles 侧落地:取存储 + 构造)。
"""
start: Token = self._Next() # 吃掉 `new`
src: int = NEW_SRC_DEFAULT
life: int = NEW_LIFE_DEFAULT
memgr: N.expr | None = None
while True:
tok: Token = self._Peek()
if tok.Type != NAME:
break
v: str = tok.Value
if v == 'hlife':
self._Next()
life = NEW_LIFE_HLIFE
continue
if v == 'slife':
self._Next()
life = NEW_LIFE_SLIFE
continue
if v == 'stack':
self._Next()
src = NEW_SRC_STACK
continue
if v == 'heap':
self._Next()
src = NEW_SRC_HEAP
continue
if v == 'memgr':
self._Next()
self._ExpectOp('(')
self._SkipNL()
memgr = self.ParseExpr()
self._SkipNL()
self._ExpectOp(')')
src = NEW_SRC_MEMGR
continue
break
callee: N.expr = self._ParsePrimary()
func: N.expr = callee
args: list[N.expr] | None = None
if isinstance(callee, N.Call):
func = callee.func
args = callee.args
node: N.New = N.New(Source=src, Life=life, memgr=memgr, func=func, args=args)
self._FixLoc(node, start)
return node
def _ParseAtom(self) -> N.expr:
self._SkipNL()
tok: Token = self._Peek()
@@ -713,6 +789,10 @@ class ExprParserMixin(TokenStream):
if tok.Type in (STRING, FSTRING):
return self._ParseStringConcat()
if tok.Type == NAME:
if tok.Value == 'new':
nxt: Token = self._Peek(1)
if nxt.Type == NAME and nxt.Value not in _NEW_NEXT_RESERVED:
return self._ParseNewExpr()
if tok.Value in ('True', 'False', 'None'):
self._Next()
node: N.Constant = N.Constant(value={'True': True, 'False': False, 'None': None}[tok.Value], kind=None)
@@ -744,6 +824,13 @@ class ExprParserMixin(TokenStream):
def _ParseNumber(self) -> N.Constant:
tok: Token = self._Next()
text: str = tok.Value
# 显式宽度后缀(_int<N>/_uint<N>/_i<N>/_u<N>):先从文本里剥掉再解析数值
width: int = getattr(tok, 'IntWidth', 0)
unsigned: int = getattr(tok, 'IntUnsigned', 0)
if width > 0:
cut: int = text.rfind('_')
if cut > 0:
text = text[:cut]
try:
if text.lower().endswith('j'):
num: object = complex(text[:-1].replace('_', ''))
@@ -757,6 +844,10 @@ class ExprParserMixin(TokenStream):
# 无法解析:保留原字符串(理论上不会发生)
num = text
node: N.Constant = N.Constant(value=num, kind=None)
if width > 0:
# 显式宽度随节点带走,由 codegen 做「不截断」严格校验
node.int_width = width
node.int_unsigned = unsigned
self._FixLoc(node, tok)
return node
@@ -1605,8 +1696,8 @@ class ExprParserMixin(TokenStream):
int** → (int | t.CPtr) | t.CPtr (i32**)
int****** → 6 层嵌套 (i32******)
展开为 BinOp(BitOr) 链后,TPC/TPV 现有类型解析(TypeAnnotationResolver
的 PtrCount 相加、TPV TypeGenResolve 的递归 BinOp 分支)零改动即可
展开为 BinOp(BitOr) 链后,TPC/VPC 现有类型解析(TypeAnnotationResolver
的 PtrCount 相加、VPC TypeGenResolve 的递归 BinOp 分支)零改动即可
生成多级指针 LLVM 类型。
无法解析的后缀形态**响亮失败**(SyntaxError,含 行:列 + 源码片段 + 形态 +