feat(tpc): 注解支持 C 风格指针后缀 T*(int* → int | t.CPtr 多级展开)

This commit is contained in:
TermiNexus committed 2026-08-28 08:01:03 +08:00
1 parent 0230385891
commit 63bc435723
4 files changed
+140 -33

No files matched your search

+55 -3
View File
@@ -1557,6 +1557,58 @@ def _parse_varargslist(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CP
return Arguments(ps.pool, args, vararg, kwarg, defaults, kw_defaults)
def _parse_type_ann(ps: Parser | t.CPtr) -> AST | t.CPtr:
"""解析类型注解,支持 C 风格指针后缀(* / **)。
int* → int | t.CPtr (i32*)
int** → (int | t.CPtr) | t.CPtr (i32**)
int****** → 6 层嵌套 (i32******)
_parse_test 会把后缀 '*' 消费为乘法(Mult)、'**' 消费为幂(Pow),
右操作数解析失败时产生 BinOp(op, right=None) 垃圾节点并 error_count+1
('int***' 形态为 BinOp(Pow, UnaryOp(Deref, None)),StarStar+Star)。
本函数回收该形态并恢复 error_count,再按层数嵌套构造 BinOp(BitOr, t.CPtr)。
"""
before_ec: t.CInt = ps.error_count
base: AST | t.CPtr = _parse_test(ps)
if base is None:
return None
ptr_level: t.CInt = 0
# 回收垃圾节点(_parse_test 对后缀 * / ** 的消费产物)
if base.kind() == ASTKind.BinOp:
gb: ast.BinOp | t.CPtr = (ast.BinOp | t.CPtr)(base)
if gb.op == OpKind.Mult and gb.right is None:
ptr_level += 1
base = gb.left
elif gb.op == OpKind.Pow:
if gb.right is None:
ptr_level += 2
base = gb.left
elif gb.right.kind() == ASTKind.UnaryOp:
gu: ast.UnaryOp | t.CPtr = (ast.UnaryOp | t.CPtr)(gb.right)
if gu.op == OpKind.Deref and gu.operand is None:
ptr_level += 3
base = gb.left
if ptr_level > 0:
ps.error_count = before_ec # 回收成功,恢复错误计数避免整文件解析失败
# 循环消费残留后缀('**' 是词法单 token 计 2 层,'*' 计 1 层)
while _match_op(ps, TokOp.StarStar):
_advance(ps)
ptr_level += 2
while _match_op(ps, TokOp.Star):
_advance(ps)
ptr_level += 1
# 嵌套构造 base | t.CPtr(n 层)
li_an: t.CInt = 0
while li_an < ptr_level:
cptr_an: AST | t.CPtr = Attribute(ps.pool,
Name(ps.pool, "t", ASTCtx.Load),
"CPtr", ASTCtx.Load)
base = BinOp(ps.pool, base, OpKind.BitOr, cptr_an)
li_an += 1
return base
def _parse_arg_def(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CPtr:
"""arg: TokenType.Name [':' annotation]"""
if _cur_type(ps) != TokenType.Name:
@@ -1569,7 +1621,7 @@ def _parse_arg_def(ps: Parser | t.CPtr, is_lambda: t.CInt = 0) -> AST | t.CPtr:
annotation: AST | t.CPtr = None
if is_lambda == 0:
if _accept_op(ps, TokOp.Colon):
annotation = _parse_test(ps)
annotation = _parse_type_ann(ps)
result: AST | t.CPtr = Arg(ps.pool, name_str, annotation)
_set_pos(result, lineno, col, 0, 0)
return result
@@ -1808,7 +1860,7 @@ def _parse_expr_stmt(ps: Parser | t.CPtr, first: AST | t.CPtr) -> AST | t.CPtr:
# annassign: target ':' annotation [= value]
if _match_op(ps, TokOp.Colon):
_advance(ps)
annotation: AST | t.CPtr = _parse_test(ps)
annotation: AST | t.CPtr = _parse_type_ann(ps)
value3: AST | t.CPtr = None
if _accept_op(ps, TokOp.Equal):
value3 = _parse_testlist(ps)
@@ -2312,7 +2364,7 @@ def _parse_funcdef(ps: Parser | t.CPtr, is_async: t.CInt) -> AST | t.CPtr:
_expect_op(ps, TokOp.RPar)
returns: AST | t.CPtr = None
if _accept_op(ps, TokOp.RArrow):
returns = _parse_test(ps)
returns = _parse_type_ann(ps)
if is_extern_fd:
# extern 声明:返回注解改写为 <原类型> | t.State,复用既有
# State/外部 C 函数识别路径(vpi 注解含 "State" → 定义端裸名 + 不生成函数体)
+28 -24
View File
@@ -18,7 +18,7 @@ if TYPE_CHECKING:
from lib.core.SymbolTable import SymbolTable
from lib.core.Handles.HandlesBase import CTypeInfo, CTypeHelper, BuiltinTypeMap
from lib.core.SymbolUtils import IsTModule, IsListAnnotation
from lib.core.SymbolUtils import IsTModule, IsListAnnotation, IsCPtrNode
from lib.includes import t as _t
from lib.includes.t import CTypeRegistry
@@ -60,17 +60,8 @@ class LLVMTypeMapper:
if returns_node is None:
return 'i32'
if isinstance(returns_node, ast.BinOp) and isinstance(returns_node.op, ast.BitOr):
left_str: str = self.get_llvm_type_str(returns_node.left)
right_str: str = self.get_llvm_type_str(returns_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
return left_str
# 统一走 CPtr 感知的联合解析(int | t.CPtr → i32*、str | t.CPtr → i8**)
return self._resolve_bitor(returns_node)
result: str = self.get_llvm_type_str(returns_node)
return result if result else 'i32'
@@ -79,17 +70,8 @@ class LLVMTypeMapper:
if annotation_node is None:
return 'i8*'
if isinstance(annotation_node, ast.BinOp) and isinstance(annotation_node.op, ast.BitOr):
left_str: str = self.get_llvm_type_str(annotation_node.left)
right_str: str = self.get_llvm_type_str(annotation_node.right)
if right_str and right_str.endswith('*'):
return right_str
if left_str and left_str.endswith('*'):
return left_str
if right_str and right_str not in ('i32', 'void', 'i64'):
return right_str
if left_str and left_str not in ('i32', 'void', 'i64'):
return left_str
return right_str if right_str else left_str
# 统一走 CPtr 感知的联合解析
return self._resolve_bitor(annotation_node)
result: str = self.get_llvm_type_str(annotation_node)
return result if result else 'i8*'
@@ -279,9 +261,21 @@ class LLVMTypeMapper:
return 'i32'
def _resolve_bitor(self, node: ast.BinOp) -> str:
"""解析 ast.BinOp(BitOr) 节点"""
"""解析 ast.BinOp(BitOr) 节点(CPtr 感知的指针层级叠加)。
T | t.CPtr 一侧为 t.CPtr 标记时,另一侧追加一层 '*':
int | t.CPtr → i32* (原逻辑误降级为 i8*)
str | t.CPtr → i8** (原逻辑误降级为 i8*)
(int | t.CPtr) | t.CPtr → i32**(嵌套递归叠加)
"""
left: str = self.get_llvm_type_str(node.left)
right: str = self.get_llvm_type_str(node.right)
left_is_cptr: bool = IsCPtrNode(node.left)
right_is_cptr: bool = IsCPtrNode(node.right)
if right_is_cptr:
return self._add_pointer_level(left)
if left_is_cptr:
return self._add_pointer_level(right)
if right and right.endswith('*'):
return right
if left and left.endswith('*'):
@@ -292,6 +286,16 @@ class LLVMTypeMapper:
return right
return left if left else right
def _add_pointer_level(self, ty: str) -> str:
"""给类型字符串追加一层指针 '*'(void/void* → i8*)。"""
if not ty:
return 'i8*'
if ty == 'void' or ty == 'void*':
return 'i8*'
if ty.endswith('*'):
return ty + '*'
return ty + '*'
def _resolve_call(self, node: ast.Call) -> str:
"""解析 ast.Call 节点"""
if isinstance(node.func, ast.Attribute):
+52 -1
View File
@@ -51,6 +51,9 @@ class TokenStream:
# 游标移动后 Idx 变化自然失配,无需显式失效。
self._PeekCacheIdx: int = -1
self._PeekCacheTok: Token | None = None
# 类型注解解析模式:为 True 时 '*' / '**' 按 C 风格指针后缀处理
# (int* → int | t.CPtr、int** → 嵌套两层),不按乘法/幂运算消费。
self._InTypeAnnotation: bool = False
# ------------------------------------------------------------------
# 游标操作
@@ -394,6 +397,8 @@ class ExprParserMixin(TokenStream):
tok: Token = self._Peek()
op_type: type | None = None
if tok.Type == OP:
if self._InTypeAnnotation and tok.Value == '*':
break # 注解模式:'*' 是 C 风格指针后缀标记,不按乘法处理
op_type = {'*': N.Mult, '/': N.Div, '//': N.FloorDiv,
'%': N.Mod, '@': N.MatMult}.get(tok.Value)
if op_type is None:
@@ -424,6 +429,8 @@ class ExprParserMixin(TokenStream):
start: Token = self._Peek()
base: N.expr = self._ParseAwaitPrimary()
if self._AtOp('**'):
if self._InTypeAnnotation:
return base # 注解模式:'**' 是 C 风格指针后缀标记(2 层),不按幂处理
self._Next()
exponent: N.expr = self._ParseFactor() # ** 右结合
node: N.BinOp = N.BinOp(left=base, op=N.Pow(), right=exponent)
@@ -1471,7 +1478,51 @@ class ExprParserMixin(TokenStream):
annotation: N.expr | None = None
if allow_annotation and self._AtOp(':'):
self._Next()
annotation = self.ParseExpr()
annotation = self._ParseTypeAnnotation()
a: N.arg = N.arg(arg=start.Value, annotation=annotation, type_comment=None)
self._FixLoc(a, start)
return a
def _ParseTypeAnnotation(self) -> N.expr:
"""解析类型注解,支持 C 风格指针后缀(* / **)。
注解模式开启后,'_ParseTerm'/'_ParsePower' 不再把 '*' / '**' 当
乘法/幂运算消费,而由本方法统一循环消费并展开为嵌套联合类型:
int* → int | t.CPtr (i32*)
int** → (int | t.CPtr) | t.CPtr (i32**)
int****** → 6 层嵌套 (i32******)
展开为 BinOp(BitOr) 链后,TPC/TPV 现有类型解析(TypeAnnotationResolver
的 PtrCount 相加、TPV TypeGenResolve 的递归 BinOp 分支)零改动即可
生成多级指针 LLVM 类型。
"""
saved_flag: bool = self._InTypeAnnotation
self._InTypeAnnotation = True
try:
expr: N.expr = self.ParseExpr()
finally:
self._InTypeAnnotation = saved_flag
if expr is None:
return None
# 循环消费 '*' / '**' 后缀('**' 是词法单 token,计 2 层)
while True:
tok: Token = self._Peek()
if tok.Type == OP and tok.Value == '*':
self._Next()
expr = self._MakePtrType(expr, tok)
elif tok.Type == OP and tok.Value == '**':
self._Next()
expr = self._MakePtrType(expr, tok)
expr = self._MakePtrType(expr, tok)
else:
break
return expr
def _MakePtrType(self, base: N.expr, tok: Token) -> N.expr:
"""构造一层指针包装:base | t.CPtr。"""
cptr: N.expr = N.Attribute(value=N.Name(id='t', ctx=N.Load()),
attr='CPtr', ctx=N.Load())
node: N.BinOp = N.BinOp(left=base, op=N.BitOr(), right=cptr)
self._FixLoc(node, tok)
return node
+5 -5
View File
@@ -259,7 +259,7 @@ class Parser(ExprParserMixin):
if self._At(NAME) and self._Peek(1).Type == OP and self._Peek(1).Value == ':':
name_tok: Token = self._Next()
self._Next() # ':'
annotation: N.expr = self.ParseExpr()
annotation: N.expr = self._ParseTypeAnnotation()
value: N.expr | None = None
if self._AtOp('='):
self._Next()
@@ -280,7 +280,7 @@ class Parser(ExprParserMixin):
return None
if self._AtOp(':') and isinstance(expr, (N.Name, N.Attribute, N.Subscript)):
self._Next()
annotation = self.ParseExpr()
annotation = self._ParseTypeAnnotation()
value = None
if self._AtOp('='):
self._Next()
@@ -531,7 +531,7 @@ class Parser(ExprParserMixin):
returns: N.expr | None = None
if self._AtOp('->'):
self._Next()
returns = self.ParseExpr()
returns = self._ParseTypeAnnotation()
self._ExpectOp(':')
body: list[N.stmt] = self._ParseSuite()
cls: type = N.AsyncFunctionDef if is_async else N.FunctionDef
@@ -567,7 +567,7 @@ class Parser(ExprParserMixin):
returns: N.expr | None = None
if self._AtOp('->'):
self._Next()
returns = self.ParseExpr()
returns = self._ParseTypeAnnotation()
body: list[N.stmt] = []
if self._AtOp(':'):
self._Next()
@@ -612,7 +612,7 @@ class Parser(ExprParserMixin):
returns: N.expr | None = None
if self._AtOp('->'):
self._Next()
returns = self.ParseExpr()
returns = self._ParseTypeAnnotation()
body: list[N.stmt] = []
if self._AtOp(':'):
self._Next()