chore: 同步 TransPyV→ViperC 改名、new 表达式支持与定宽字面量/窄化适配
This commit is contained in:
1 parent
15f77da9d3
commit
23b47053d9
10 files changed
+10283
-10041
No files matched your search
+93
-2
@@ -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,含 行:列 + 源码片段 + 形态 +
|
||||
|
||||
Reference in new issue
Block a user