feat(asm,err,typedef): 支持 __asm__/__llvmir__ 裸名与 typedef 语法糖;解析报错统一 Python 风格 traceback
CallGenCBuiltin/CallGenDispatch: __asm__/__llvmir__ 裸名调用,asminp/asmout/irinp/irout 与裸 ASM_DESCR。 AssignGenMixin: 支持 define NAME: T = V 形式的 CDefine 浮点值恢复;负浮点(-1e308)剥一层 UnaryOp(USub)。 Phase1Main/Phase2: AST 解析失败改调 GenApi.dump_parse_traceback(Traceback + File/行 + 源码行 + caret)。 TypeGenResolve/TypeGenCType: typedef 文本扫描统一支持 typedef 语法糖(builtins/库/单文件三处共用同一解析)。
This commit is contained in:
1 parent
a7af34bd7e
commit
676c19c362
7 files changed
+245
-171
No files matched your search
@@ -779,10 +779,12 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str,
|
|||||||
if tree_pv is None:
|
if tree_pv is None:
|
||||||
stdlib.free(src_buf_pv)
|
stdlib.free(src_buf_pv)
|
||||||
p1bpre_failed += 1
|
p1bpre_failed += 1
|
||||||
VLogger.error(
|
# 解析失败:改由 Python 风格 traceback 统一上报(Traceback + File/行 +
|
||||||
f"[Phase 1b-pre] {file_path_pv} | AST 解析失败"
|
# 源码行 + caret + SyntaxError: 消息;消息本身含 token 类型与前/后 token
|
||||||
f"(第 {ast.get_parse_err_line()} 行第 {ast.get_parse_err_col()} 列: "
|
# 附注,见 includes/ast/parser.vp 的 _record_parse_err_ctx),与单文件
|
||||||
f"{ast.get_parse_err_msg()})", "Phase1")
|
# 管线 BuildPipeline 同一条上报路径。
|
||||||
|
VLogger.error(f"[Phase 1b-pre] {file_path_pv} | AST 解析失败", "Phase1")
|
||||||
|
GenApi.dump_parse_traceback(file_path_pv)
|
||||||
continue
|
continue
|
||||||
pyi_buf_pv: bytes = stdlib.malloc(Phase1.PYI_BUF_SIZE)
|
pyi_buf_pv: bytes = stdlib.malloc(Phase1.PYI_BUF_SIZE)
|
||||||
if pyi_buf_pv is not None:
|
if pyi_buf_pv is not None:
|
||||||
|
|||||||
@@ -805,10 +805,12 @@ def RunMultiFileProject(mb: memhub.MemBuddy*,
|
|||||||
if tree_vp2 is None:
|
if tree_vp2 is None:
|
||||||
stdlib.free(src_buf_vp2)
|
stdlib.free(src_buf_vp2)
|
||||||
vpi_failed_p2 += 1
|
vpi_failed_p2 += 1
|
||||||
VLogger.error(
|
# 解析失败:改由 Python 风格 traceback 统一上报(Traceback + File/行 +
|
||||||
f"[Phase A-pre-vpi] {ent_vp2.Path} | AST 解析失败"
|
# 源码行 + caret + SyntaxError: 消息;消息本身含 token 类型与前/后 token
|
||||||
f"(第 {ast.get_parse_err_line()} 行第 {ast.get_parse_err_col()} 列: "
|
# 附注,见 includes/ast/parser.vp 的 _record_parse_err_ctx),与单文件
|
||||||
f"{ast.get_parse_err_msg()})", "PhaseA")
|
# 管线 BuildPipeline 同一条上报路径。
|
||||||
|
VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | AST 解析失败", "PhaseA")
|
||||||
|
GenApi.dump_parse_traceback(ent_vp2.Path)
|
||||||
continue
|
continue
|
||||||
pyi_buf_vp2: bytes = stdlib.malloc(PYI_BUF_SIZE_P2)
|
pyi_buf_vp2: bytes = stdlib.malloc(PYI_BUF_SIZE_P2)
|
||||||
if pyi_buf_vp2 is not None:
|
if pyi_buf_vp2 is not None:
|
||||||
|
|||||||
@@ -575,6 +575,21 @@ novirtual class AssignGenMixin:
|
|||||||
first_arg_cd: ast.AST* = cl_args_cd.get(0)
|
first_arg_cd: ast.AST* = cl_args_cd.get(0)
|
||||||
if first_arg_cd is not None and first_arg_cd.kind() == ast.ASTKind.Constant:
|
if first_arg_cd is not None and first_arg_cd.kind() == ast.ASTKind.Constant:
|
||||||
val_node = first_arg_cd
|
val_node = first_arg_cd
|
||||||
|
# 负浮点字面量(`define NAME: double = -1e308`):RHS 是
|
||||||
|
# UnaryOp(USub, Constant(CONST_FLOAT)),不是裸 Constant ⇒ 否则会落到下方的
|
||||||
|
# 整数提取,报"无法从表达式解析编译期常量"。此处只剥掉一层一元负号,把内层
|
||||||
|
# 浮点 Constant 交给浮点分支:浮点值一律由源文件文本恢复
|
||||||
|
# (_recover_cdefine_float 读原文,负号天然保留,不需在此取反)。
|
||||||
|
# 负整数不受影响(UnaryOp 继续落到 extract_cdefine_int_value,它本就认
|
||||||
|
# UnaryOp(USub, Constant)),故只拦 CONST_FLOAT 这一种内层形态。
|
||||||
|
if val_node is not None and val_node.kind() == ast.ASTKind.UnaryOp:
|
||||||
|
uu_cd: ast.UnaryOp* = ast.UnaryOp*(val_node)
|
||||||
|
if uu_cd is not None and uu_cd.op == OpKind.USub \
|
||||||
|
and uu_cd.operand is not None \
|
||||||
|
and uu_cd.operand.kind() == ast.ASTKind.Constant:
|
||||||
|
ic_cd: ast.Constant* = ast.Constant*(uu_cd.operand)
|
||||||
|
if ic_cd is not None and ic_cd.const_kind == ast.CONST_FLOAT:
|
||||||
|
val_node = uu_cd.operand
|
||||||
if val_node is not None and val_node.kind() == ast.ASTKind.Constant:
|
if val_node is not None and val_node.kind() == ast.ASTKind.Constant:
|
||||||
cn_fp: ast.Constant* = ast.Constant*(val_node)
|
cn_fp: ast.Constant* = ast.Constant*(val_node)
|
||||||
if cn_fp.const_kind == ast.CONST_STR:
|
if cn_fp.const_kind == ast.CONST_STR:
|
||||||
@@ -653,19 +668,36 @@ novirtual class AssignGenMixin:
|
|||||||
if pos < total_len:
|
if pos < total_len:
|
||||||
pos += 1
|
pos += 1
|
||||||
|
|
||||||
# 匹配行首的 "name",其后(跳过空格)必须是 ':' 或 '='
|
# `define NAME: T = V`(宏常量关键字形式):名字前有 "define " 前缀,
|
||||||
# (AnnAssign:`NAME: t.CDouble = 1.0`;无注解赋值:`NAME = 1.0`)
|
# 且行内没有 t.CDefine 文本(CDefine 标记来自关键字本身,见
|
||||||
if line_len < name_len + 1:
|
# parser.vp 的 _parse_define_const / _is_define_const)。故名字匹配
|
||||||
|
# 基准 ns 顺延到关键字之后的第一个非空白字符,并记下 is_define_line。
|
||||||
|
ns: sizet = line_start
|
||||||
|
is_define_line: int = 0
|
||||||
|
if line_len >= 8:
|
||||||
|
if buf[ns] == 'd' and buf[ns + 1] == 'e' and buf[ns + 2] == 'f' \
|
||||||
|
and buf[ns + 3] == 'i' and buf[ns + 4] == 'n' and buf[ns + 5] == 'e':
|
||||||
|
nb: sizet = ns + 6
|
||||||
|
while nb < line_start + line_len and (buf[nb] == ' ' or buf[nb] == '\t'):
|
||||||
|
nb += 1
|
||||||
|
# 后随空白才算关键字(避免匹配到 defineX 之类的标识符)
|
||||||
|
if nb > ns + 6:
|
||||||
|
is_define_line = 1
|
||||||
|
ns = nb
|
||||||
|
# 匹配行首(或 define 之后)的 "name",其后(跳过空格)必须是 ':' 或 '='
|
||||||
|
# (AnnAssign:`NAME: t.CDouble = 1.0`;无注解赋值:`NAME = 1.0`;
|
||||||
|
# 宏常量:`define NAME: double = 3.14`)
|
||||||
|
if ns + name_len + 1 > line_start + line_len:
|
||||||
continue
|
continue
|
||||||
match_ok: int = 1
|
match_ok: int = 1
|
||||||
ki: sizet
|
ki: sizet
|
||||||
for ki in range(name_len):
|
for ki in range(name_len):
|
||||||
if buf[line_start + ki] != name[ki]:
|
if buf[ns + ki] != name[ki]:
|
||||||
match_ok = 0
|
match_ok = 0
|
||||||
break
|
break
|
||||||
if match_ok == 0:
|
if match_ok == 0:
|
||||||
continue
|
continue
|
||||||
sep: sizet = line_start + name_len
|
sep: sizet = ns + name_len
|
||||||
while sep < line_start + line_len and buf[sep] == ' ':
|
while sep < line_start + line_len and buf[sep] == ' ':
|
||||||
sep += 1
|
sep += 1
|
||||||
if sep >= line_start + line_len:
|
if sep >= line_start + line_len:
|
||||||
@@ -673,8 +705,10 @@ novirtual class AssignGenMixin:
|
|||||||
if buf[sep] != ':' and buf[sep] != '=':
|
if buf[sep] != ':' and buf[sep] != '=':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# CDefine 路径要求行内出现 "t.CDefine";普通浮点全局路径跳过该检查
|
# CDefine 路径要求行内出现 "t.CDefine",或本行是 `define` 关键字形式
|
||||||
if require_cdefine != 0:
|
# (宏常量 `define NAME: T = V` 行内无 t.CDefine 文本);普通浮点全局
|
||||||
|
# 路径(require_cdefine=0)跳过该检查
|
||||||
|
if require_cdefine != 0 and is_define_line == 0:
|
||||||
has_cd: int = 0
|
has_cd: int = 0
|
||||||
ci: sizet = line_start + name_len + 1
|
ci: sizet = line_start + name_len + 1
|
||||||
while ci + 8 <= line_start + line_len:
|
while ci + 8 <= line_start + line_len:
|
||||||
|
|||||||
@@ -823,6 +823,9 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
|
|||||||
mod_nm2: ast.Name* = ast.Name*(at.value)
|
mod_nm2: ast.Name* = ast.Name*(at.value)
|
||||||
if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0:
|
if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "t") == 0:
|
||||||
return self._resolve_register(at.attr)
|
return self._resolve_register(at.attr)
|
||||||
|
# 裸名 ASM_DESCR.XXX:省去 t. 前缀的等价写法
|
||||||
|
if mod_nm2.id is not None and string.strcmp(mod_nm2.id, "ASM_DESCR") == 0:
|
||||||
|
return self._resolve_register(at.attr)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
# Constant: 字符串常量
|
# Constant: 字符串常量
|
||||||
@@ -844,9 +847,27 @@ class CallGenCBuiltin(CallGenBase.CallGenBase):
|
|||||||
|
|
||||||
|
|
||||||
def _asm_is_c_call(self, node: ast.Call*) -> str:
|
def _asm_is_c_call(self, node: ast.Call*) -> str:
|
||||||
"""检查 Call 节点是否是 c.XXX 调用,返回属性名或 None"""
|
"""检查 Call 节点是否是操作数标记内建调用,返回规范名或 None
|
||||||
|
|
||||||
|
支持两种等价写法(裸名写法省去 c. 前缀),裸名统一返回规范名,
|
||||||
|
使调用点的 string.strcmp 判定无需分支:
|
||||||
|
- 内联汇编:c.AsmInp/c.AsmOut ↔ asminp/asmout("AsmInp"/"AsmOut")
|
||||||
|
- LLVM IR:c.LInp/c.LOut ↔ irinp/irout("LInp"/"LOut")
|
||||||
|
"""
|
||||||
if node is None or node.func is None:
|
if node is None or node.func is None:
|
||||||
return None
|
return None
|
||||||
|
if node.func.kind() == ast.ASTKind.Name:
|
||||||
|
nm: ast.Name* = ast.Name*(node.func)
|
||||||
|
if nm.id is not None:
|
||||||
|
if string.strcmp(nm.id, "asminp") == 0:
|
||||||
|
return "AsmInp"
|
||||||
|
if string.strcmp(nm.id, "asmout") == 0:
|
||||||
|
return "AsmOut"
|
||||||
|
if string.strcmp(nm.id, "irinp") == 0:
|
||||||
|
return "LInp"
|
||||||
|
if string.strcmp(nm.id, "irout") == 0:
|
||||||
|
return "LOut"
|
||||||
|
return None
|
||||||
if node.func.kind() != ast.ASTKind.Attribute:
|
if node.func.kind() != ast.ASTKind.Attribute:
|
||||||
return None
|
return None
|
||||||
at: ast.Attribute* = ast.Attribute*(node.func)
|
at: ast.Attribute* = ast.Attribute*(node.func)
|
||||||
|
|||||||
@@ -104,6 +104,26 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
|||||||
translate_c_asm/translate_c_llvmir 成功处理 void 时返回 None,
|
translate_c_asm/translate_c_llvmir 成功处理 void 时返回 None,
|
||||||
若不加 hit_box 会被 translate_call 误判为"未命中"继续走外部函数路径。
|
若不加 hit_box 会被 translate_call 误判为"未命中"继续走外部函数路径。
|
||||||
"""
|
"""
|
||||||
|
# __asm__(...) / __llvmir__(...) 语法糖:裸名调用等价 c.Asm(...) / c.LLVMIR(...)
|
||||||
|
# (无 c. 前缀,无需 import c)。必须在 c.* Attribute 分支之前拦截:
|
||||||
|
# 裸名 cl.func 是 Name 而非 Attribute。
|
||||||
|
if func_name is not None and cl.func is not None and cl.func.kind() == ast.ASTKind.Name:
|
||||||
|
bare_nm: ast.Name* = ast.Name*(cl.func)
|
||||||
|
if bare_nm.id is not None and string.strcmp(bare_nm.id, "__asm__") == 0:
|
||||||
|
# 无输出(void)时 translate_c_asm 返回 None:置命中标记,
|
||||||
|
# 避免 translate_call 误判未命中继续走外部函数路径。
|
||||||
|
if hit_box is not None:
|
||||||
|
hit_box[0] = 1
|
||||||
|
return self.Gen.CallGenCBuiltin.translate_c_asm(pool, builder, mod, cl, trans)
|
||||||
|
if bare_nm.id is not None and string.strcmp(bare_nm.id, "__llvmir__") == 0:
|
||||||
|
# c.LLVMIR 总是无返回值(返回 None):置命中标记
|
||||||
|
if hit_box is not None:
|
||||||
|
hit_box[0] = 1
|
||||||
|
return self.Gen.CallGenCBuiltin.translate_c_llvmir(pool, builder, mod, cl, trans)
|
||||||
|
if bare_nm.id is not None and (string.strcmp(bare_nm.id, "irinp") == 0 or string.strcmp(bare_nm.id, "irout") == 0):
|
||||||
|
# irinp/irout 独立调用时返回 0(仅在 __llvmir__ 的 f-string 内有意义)
|
||||||
|
return llvmlite.ConstInt(pool, llvmlite.Int32(pool), 0, "0")
|
||||||
|
|
||||||
# 检测 c.Deref / c.DerefAs / c.Addr 等特殊调用(内联 IR,不生成 call)
|
# 检测 c.Deref / c.DerefAs / c.Addr 等特殊调用(内联 IR,不生成 call)
|
||||||
# 及 coro.* 协程库拦截(coro.coro_run 内联翻译,TPV-M1)
|
# 及 coro.* 协程库拦截(coro.coro_run 内联翻译,TPV-M1)
|
||||||
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
if cl.func is not None and cl.func.kind() == ast.ASTKind.Attribute:
|
||||||
|
|||||||
@@ -588,7 +588,7 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
|
|||||||
return count
|
return count
|
||||||
def register_ctypedef_from_source(self, pool: memhub.MemBuddy*,
|
def register_ctypedef_from_source(self, pool: memhub.MemBuddy*,
|
||||||
src: str) -> int:
|
src: str) -> int:
|
||||||
"""从源码文本逐行扫描注册 CTypedef(NAME: t.CTypedef = TYPE)
|
"""从源码文本逐行扫描注册 CTypedef(`typedef N = V` 或 `N: t.CTypedef = V`)
|
||||||
|
|
||||||
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
|
stdint.vp 崩溃根因修复:AST 字符串字段(attr/id)token 零拷贝指向
|
||||||
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
|
src_buf,跨阶段内容不稳定(悬空),ScanCTypedefDeclarations 读
|
||||||
@@ -608,54 +608,19 @@ class TypeGenCType(TypeGenBase.TypeGenBase):
|
|||||||
count: int = 0
|
count: int = 0
|
||||||
line_start: sizet = 0
|
line_start: sizet = 0
|
||||||
i: sizet = 0
|
i: sizet = 0
|
||||||
|
# 行解析缓冲("NAME\0VALUE\0"),整文件复用(register_ctypedef 内部自会复制)
|
||||||
|
td_buf: str = pool.alloc(320)
|
||||||
while i <= src_len:
|
while i <= src_len:
|
||||||
if i == src_len or src[i] == '\n':
|
if i == src_len or src[i] == '\n':
|
||||||
line_len: sizet = i - line_start
|
line_len: sizet = i - line_start
|
||||||
if line_len > 0:
|
if line_len > 0 and td_buf is not None:
|
||||||
# 找行内第一个 ':'(跳过注释行)
|
# 两种等价形态统一解析:语法糖 `typedef N = V`(builtins.vp 现用
|
||||||
j: sizet = 0
|
# 形态)与注解 `N: t.CTypedef = V`(stdint.vp 等库模块)。
|
||||||
found_colon: int = 0
|
if self.Gen.TypeGenResolve._parse_typedef_line(td_buf, src, line_start, line_len) != 0:
|
||||||
while j < line_len:
|
name_buf: str = td_buf
|
||||||
ch_c: char = src[line_start + j]
|
ty_buf: str = td_buf + string.strlen(td_buf) + 1
|
||||||
if ch_c == ':':
|
self.register_ctypedef(pool, name_buf, ty_buf)
|
||||||
found_colon = 1
|
count += 1
|
||||||
break
|
|
||||||
if ch_c == '#' or ch_c == '\r':
|
|
||||||
break
|
|
||||||
j += 1
|
|
||||||
if found_colon != 0:
|
|
||||||
# 左段 NAME(trim 尾随空格)
|
|
||||||
name_len: sizet = j
|
|
||||||
while name_len > 0 and src[line_start + name_len - 1] == ' ':
|
|
||||||
name_len -= 1
|
|
||||||
if name_len > 0 and name_len < 128:
|
|
||||||
# 右段必须含 "t.CTypedef"
|
|
||||||
rest: str = src + line_start + j + 1
|
|
||||||
if string.strstr(rest, "t.CTypedef") is not None:
|
|
||||||
# 提取 "=" 后的类型表达式(trim 空格)
|
|
||||||
eq_ptr: str = string.strstr(rest, "=")
|
|
||||||
if eq_ptr is not None:
|
|
||||||
# '=' 相对行首偏移;值段严格限定在行尾
|
|
||||||
# (line_len)内——防止跨行吞换行+后续行内容
|
|
||||||
eq_off: sizet = sizet(uint64(eq_ptr) - uint64(src)) - line_start
|
|
||||||
vs: sizet = eq_off + 1
|
|
||||||
while vs < line_len and src[line_start + vs] == ' ':
|
|
||||||
vs += 1
|
|
||||||
ve: sizet = line_len
|
|
||||||
while ve > vs and (src[line_start + ve - 1] == ' '
|
|
||||||
or src[line_start + ve - 1] == '\r'):
|
|
||||||
ve -= 1
|
|
||||||
if ve > vs:
|
|
||||||
vlen: sizet = ve - vs
|
|
||||||
name_buf: str = pool.alloc(name_len + 1)
|
|
||||||
ty_buf: str = pool.alloc(vlen + 1)
|
|
||||||
if name_buf is not None and ty_buf is not None:
|
|
||||||
string.strncpy(name_buf, src + line_start, name_len)
|
|
||||||
name_buf[name_len] = '\0'
|
|
||||||
string.strncpy(ty_buf, src + line_start + vs, vlen)
|
|
||||||
ty_buf[vlen] = '\0'
|
|
||||||
self.register_ctypedef(pool, name_buf, ty_buf)
|
|
||||||
count += 1
|
|
||||||
line_start = i + 1
|
line_start = i + 1
|
||||||
i += 1
|
i += 1
|
||||||
return count
|
return count
|
||||||
|
|||||||
@@ -882,6 +882,98 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
|||||||
if string.strncmp(buf + al_start, mod, mod_len) == 0:
|
if string.strncmp(buf + al_start, mod, mod_len) == 0:
|
||||||
return buf + tg_start
|
return buf + tg_start
|
||||||
return None
|
return None
|
||||||
|
def _parse_typedef_line(self, out_buf: str, buf: str,
|
||||||
|
line_start: sizet, line_len: sizet) -> int:
|
||||||
|
"""一行源码 → typedef 声明写入 out_buf("NAME\\0VALUE\\0"),返回 1/0
|
||||||
|
|
||||||
|
兼容两种等价形态(对齐 TPC TypeAnnotationResolver._parse_typedef_line):
|
||||||
|
- 语法糖 `typedef NAME = VALUE`(includes/builtins.vp 现用形态)
|
||||||
|
- 注解形态 `NAME: t.CTypedef = VALUE`(stdint.vp 等库模块)
|
||||||
|
只识别不注册;非法形态(缺 NAME / 缺 '=' / 缺 VALUE / 注释行)返回 0。
|
||||||
|
约束:NAME < 128、VALUE <= 190(out_buf 容量需 >= 320)。
|
||||||
|
"""
|
||||||
|
if buf is None or out_buf is None or line_len == 0:
|
||||||
|
return 0
|
||||||
|
lead: sizet = 0
|
||||||
|
while lead < line_len and (buf[line_start + lead] == ' ' or buf[line_start + lead] == '\t'):
|
||||||
|
lead += 1
|
||||||
|
if lead >= line_len or buf[line_start + lead] == '#':
|
||||||
|
return 0
|
||||||
|
name_s: sizet = 0
|
||||||
|
name_l: sizet = 0
|
||||||
|
vs: sizet = 0
|
||||||
|
is_sugar: int = 0
|
||||||
|
if lead + 8 <= line_len and buf[line_start + lead] == 't' \
|
||||||
|
and buf[line_start + lead + 1] == 'y' and buf[line_start + lead + 2] == 'p' \
|
||||||
|
and buf[line_start + lead + 3] == 'e' and buf[line_start + lead + 4] == 'd' \
|
||||||
|
and buf[line_start + lead + 5] == 'e' and buf[line_start + lead + 6] == 'f' \
|
||||||
|
and (buf[line_start + lead + 7] == ' ' or buf[line_start + lead + 7] == '\t'):
|
||||||
|
is_sugar = 1
|
||||||
|
if is_sugar != 0:
|
||||||
|
k: sizet = lead + 7
|
||||||
|
while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'):
|
||||||
|
k += 1
|
||||||
|
name_s = k
|
||||||
|
while k < line_len and buf[line_start + k] != ' ' and buf[line_start + k] != '\t' \
|
||||||
|
and buf[line_start + k] != '=' and buf[line_start + k] != '\r':
|
||||||
|
k += 1
|
||||||
|
name_l = k - name_s
|
||||||
|
while k < line_len and (buf[line_start + k] == ' ' or buf[line_start + k] == '\t'):
|
||||||
|
k += 1
|
||||||
|
if name_l == 0 or name_l >= 128:
|
||||||
|
return 0
|
||||||
|
if k >= line_len or buf[line_start + k] != '=':
|
||||||
|
return 0
|
||||||
|
if k + 1 < line_len and buf[line_start + k + 1] == '=':
|
||||||
|
return 0
|
||||||
|
vs = k + 1
|
||||||
|
else:
|
||||||
|
j: sizet = 0
|
||||||
|
fc: int = 0
|
||||||
|
while j < line_len:
|
||||||
|
ch: char = buf[line_start + j]
|
||||||
|
if ch == ':':
|
||||||
|
fc = 1
|
||||||
|
break
|
||||||
|
if ch == '#' or ch == '\r':
|
||||||
|
break
|
||||||
|
j += 1
|
||||||
|
if fc == 0:
|
||||||
|
return 0
|
||||||
|
name_l = j
|
||||||
|
while name_l > 0 and buf[line_start + name_l - 1] == ' ':
|
||||||
|
name_l -= 1
|
||||||
|
if name_l == 0 or name_l >= 128:
|
||||||
|
return 0
|
||||||
|
rest: str = buf + line_start + j + 1
|
||||||
|
if string.strstr(rest, "t.CTypedef") is None:
|
||||||
|
return 0
|
||||||
|
eq: str = string.strstr(rest, "=")
|
||||||
|
if eq is None:
|
||||||
|
return 0
|
||||||
|
vs = sizet(uint64(eq) - uint64(buf)) - line_start + 1
|
||||||
|
while vs < line_len and (buf[line_start + vs] == ' ' or buf[line_start + vs] == '\t'):
|
||||||
|
vs += 1
|
||||||
|
ve: sizet = line_len
|
||||||
|
while ve > vs and (buf[line_start + ve - 1] == ' ' or buf[line_start + ve - 1] == '\t' \
|
||||||
|
or buf[line_start + ve - 1] == '\r'):
|
||||||
|
ve -= 1
|
||||||
|
if ve <= vs:
|
||||||
|
return 0
|
||||||
|
vlen: sizet = ve - vs
|
||||||
|
if vlen > 190:
|
||||||
|
vlen = 190
|
||||||
|
ci: sizet = 0
|
||||||
|
while ci < name_l:
|
||||||
|
out_buf[ci] = buf[line_start + name_s + ci]
|
||||||
|
ci += 1
|
||||||
|
out_buf[name_l] = '\0'
|
||||||
|
ci = 0
|
||||||
|
while ci < vlen:
|
||||||
|
out_buf[name_l + 1 + ci] = buf[line_start + vs + ci]
|
||||||
|
ci += 1
|
||||||
|
out_buf[name_l + 1 + vlen] = '\0'
|
||||||
|
return 1
|
||||||
def _lookup_builtins_typedef(self, pool: memhub.MemBuddy*,
|
def _lookup_builtins_typedef(self, pool: memhub.MemBuddy*,
|
||||||
name: str) -> str:
|
name: str) -> str:
|
||||||
"""builtins 最后匹配:查 includes/builtins.vp 的 CTypedef 声明
|
"""builtins 最后匹配:查 includes/builtins.vp 的 CTypedef 声明
|
||||||
@@ -1005,73 +1097,42 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
|||||||
b_i: sizet = 0
|
b_i: sizet = 0
|
||||||
b_line_start: sizet = 0
|
b_line_start: sizet = 0
|
||||||
b_res: str = None
|
b_res: str = None
|
||||||
|
# 行解析缓冲("NAME\0VALUE\0"),整文件复用;需要保留的值当场复制到独立分配
|
||||||
|
# (register_ctypedef 内部自会复制,b_res 是唯一需要拷出的引用)。
|
||||||
|
b_td_buf: str = pool.alloc(320)
|
||||||
while b_i <= b_total:
|
while b_i <= b_total:
|
||||||
if b_i == b_total or b_buf[b_i] == '\n':
|
if b_i == b_total or b_buf[b_i] == '\n':
|
||||||
b_line_len: sizet = b_i - b_line_start
|
b_line_len: sizet = b_i - b_line_start
|
||||||
if b_line_len > 0:
|
if b_line_len > 0 and b_td_buf is not None:
|
||||||
# 找行内第一个 ':'(跳过注释行)
|
# 两种等价形态统一解析:语法糖 `typedef N = V` 与注解
|
||||||
b_j: sizet = 0
|
# `N: t.CTypedef = V`。builtins.vp 已改用语法糖形态,
|
||||||
b_found_colon: int = 0
|
# 只认注解形态会让本兜底表恒空 → 裸名退化为 %"{mod}.名"* 假结构体。
|
||||||
while b_j < b_line_len:
|
if self._parse_typedef_line(b_td_buf, b_buf, b_line_start, b_line_len) != 0:
|
||||||
b_ch: char = b_buf[b_line_start + b_j]
|
b_nb: str = b_td_buf
|
||||||
if b_ch == ':':
|
b_nl2: sizet = string.strlen(b_nb)
|
||||||
b_found_colon = 1
|
b_tb: str = b_td_buf + b_nl2 + 1
|
||||||
break
|
# 表内已存在(模块自身/import 注入)不覆盖
|
||||||
if b_ch == '#' or b_ch == '\r':
|
b_exist: str = self.Gen.TypeGenCType.lookup_ctypedef(b_nb)
|
||||||
break
|
if b_exist is None or self.Gen.TypeGenCType.CTypedefFound == 0:
|
||||||
b_j += 1
|
# 急切展开模块限定引用再注册(size_t:
|
||||||
if b_found_colon != 0:
|
# t.CTypedef = stdint.size_t → 注册 sizet),
|
||||||
# 左段 NAME(trim 尾随空格)
|
# 使表内直接持有最终类型表达式,下游查表即中
|
||||||
b_name_len: sizet = b_j
|
b_tb_x: str = self._expand_typedef_ref(pool, b_tb)
|
||||||
while b_name_len > 0 and b_buf[b_line_start + b_name_len - 1] == ' ':
|
if b_tb_x is not None:
|
||||||
b_name_len -= 1
|
self.Gen.TypeGenCType.register_ctypedef(pool, b_nb, b_tb_x)
|
||||||
if b_name_len > 0 and b_name_len < 128:
|
if string.strcmp(b_nb, name) == 0:
|
||||||
# 右段必须含 "t.CTypedef",提取 "=" 后的类型表达式
|
# 独立复制:b_td_buf 会被后续行覆盖
|
||||||
b_rest2: str = b_buf + b_line_start + b_j + 1
|
b_vl: sizet = string.strlen(b_tb)
|
||||||
if string.strstr(b_rest2, "t.CTypedef") is not None:
|
b_res = pool.alloc(b_vl + 1)
|
||||||
b_eq2: str = string.strstr(b_rest2, "=")
|
if b_res is not None:
|
||||||
if b_eq2 is not None:
|
string.strcpy(b_res, b_tb)
|
||||||
# '=' 相对行首偏移;值段严格限定在行尾
|
|
||||||
# (b_line_len)内——此前 strlen 跨行吞掉
|
|
||||||
# 换行+下一行注释(size_t: t.CTypedef =
|
|
||||||
# stdint.size_t 后跟 "# size_t: t.CTypedef =
|
|
||||||
# sizet" → 值含 "\n# ..." → 展开取到注释
|
|
||||||
# 里的 '.' → 模块名垃圾,main2.vp size_t 根因)
|
|
||||||
b_eq_off: sizet = sizet(uint64(b_eq2) - uint64(b_buf)) - b_line_start
|
|
||||||
b_vs: sizet = b_eq_off + 1
|
|
||||||
while b_vs < b_line_len and b_buf[b_line_start + b_vs] == ' ':
|
|
||||||
b_vs += 1
|
|
||||||
b_ve: sizet = b_line_len
|
|
||||||
while b_ve > b_vs and (b_buf[b_line_start + b_ve - 1] == ' '
|
|
||||||
or b_buf[b_line_start + b_ve - 1] == '\r'):
|
|
||||||
b_ve -= 1
|
|
||||||
if b_ve > b_vs:
|
|
||||||
b_vlen: sizet = b_ve - b_vs
|
|
||||||
b_nb: str = pool.alloc(b_name_len + 1)
|
|
||||||
b_tb: str = pool.alloc(b_vlen + 1)
|
|
||||||
if b_nb is not None and b_tb is not None:
|
|
||||||
string.strncpy(b_nb, b_buf + b_line_start, b_name_len)
|
|
||||||
b_nb[b_name_len] = '\0'
|
|
||||||
string.strncpy(b_tb, b_buf + b_line_start + b_vs, b_vlen)
|
|
||||||
b_tb[b_vlen] = '\0'
|
|
||||||
# 表内已存在(模块自身/import 注入)不覆盖
|
|
||||||
b_exist: str = self.Gen.TypeGenCType.lookup_ctypedef(b_nb)
|
|
||||||
if b_exist is None or self.Gen.TypeGenCType.CTypedefFound == 0:
|
|
||||||
# 急切展开模块限定引用再注册(size_t:
|
|
||||||
# t.CTypedef = stdint.size_t → 注册 sizet),
|
|
||||||
# 使表内直接持有最终类型表达式,下游查表即中
|
|
||||||
b_tb_x: str = self._expand_typedef_ref(pool, b_tb)
|
|
||||||
if b_tb_x is not None:
|
|
||||||
self.Gen.TypeGenCType.register_ctypedef(pool, b_nb, b_tb_x)
|
|
||||||
if string.strcmp(b_nb, name) == 0:
|
|
||||||
b_res = b_tb
|
|
||||||
b_line_start = b_i + 1
|
b_line_start = b_i + 1
|
||||||
b_i += 1
|
b_i += 1
|
||||||
# 置扫描完成标记:同文件内后续 miss 直接查表,不再重复读 builtins 源
|
# 置扫描完成标记:同文件内后续 miss 直接查表,不再重复读 builtins 源
|
||||||
self.Gen.TypeGenCType.BuiltinsTypedefScanned = 1
|
self.Gen.TypeGenCType.BuiltinsTypedefScanned = 1
|
||||||
# b_res 是 b_buf 内的切片(非副本),必须在 free 之前完成展开与诊断复制:
|
# b_res 已复制到 pool(非 b_buf 切片),展开与诊断复制仍须在 free(b_buf)
|
||||||
# _expand_typedef_ref 可能原样返回指向 b_buf 的指针,free 之后再读即
|
# 之前完成——_expand_typedef_ref 的中间结果可能引用 b_buf 之外的状态,
|
||||||
# heap-use-after-free(诊断字段还会长期持有该悬垂指针)。
|
# 且诊断字段须长期持有自有副本。
|
||||||
b_final_r: str = None
|
b_final_r: str = None
|
||||||
if b_res is not None:
|
if b_res is not None:
|
||||||
b_final_r = self._expand_typedef_ref(pool, b_res)
|
b_final_r = self._expand_typedef_ref(pool, b_res)
|
||||||
@@ -1209,64 +1270,33 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
|||||||
return None
|
return None
|
||||||
if m_read < LONG(BUF_L):
|
if m_read < LONG(BUF_L):
|
||||||
m_buf[sizet(m_read)] = 0
|
m_buf[sizet(m_read)] = 0
|
||||||
attr_len: sizet = string.strlen(attr)
|
|
||||||
m_total: sizet = string.strlen(m_buf)
|
m_total: sizet = string.strlen(m_buf)
|
||||||
m_i: sizet = 0
|
m_i: sizet = 0
|
||||||
m_ls: sizet = 0
|
m_ls: sizet = 0
|
||||||
m_res: str = None
|
m_res: str = None
|
||||||
|
# 行解析缓冲("NAME\0VALUE\0"),整文件复用;命中值复制到独立分配再保留
|
||||||
|
# (m_td_buf 会被后续行覆盖,而 m_res 要活到 free(m_buf) 之后)。
|
||||||
|
m_td_buf: str = pool.alloc(320)
|
||||||
# 全文件扫描(不再在首次命中处提前退出):既为该模块建立完整持久缓存,
|
# 全文件扫描(不再在首次命中处提前退出):既为该模块建立完整持久缓存,
|
||||||
# 又用与原实现相同的比较取 attr 的首次命中值(保证首次调用返回值不变)。
|
# 又用与原实现相同的比较取 attr 的首次命中值(保证首次调用返回值不变)。
|
||||||
while m_i <= m_total:
|
while m_i <= m_total:
|
||||||
if m_i == m_total or m_buf[m_i] == '\n':
|
if m_i == m_total or m_buf[m_i] == '\n':
|
||||||
m_line_len: sizet = m_i - m_ls
|
m_line_len: sizet = m_i - m_ls
|
||||||
if m_line_len > 0:
|
if m_line_len > 0 and m_td_buf is not None:
|
||||||
m_j: sizet = 0
|
# 两种等价形态统一解析:语法糖 `typedef N = V` 与注解
|
||||||
m_fc: int = 0
|
# `N: t.CTypedef = V`(库模块源两种形态都须识别)。
|
||||||
while m_j < m_line_len:
|
if self._parse_typedef_line(m_td_buf, m_buf, m_ls, m_line_len) != 0:
|
||||||
m_ch: char = m_buf[m_ls + m_j]
|
m_nb: str = m_td_buf
|
||||||
if m_ch == ':':
|
m_nl: sizet = string.strlen(m_nb)
|
||||||
m_fc = 1
|
m_tb: str = m_td_buf + m_nl + 1
|
||||||
break
|
# 写入持久缓存(首次遇到的名字为准)
|
||||||
if m_ch == '#' or m_ch == '\r':
|
self._register_lib_typedef_cache(m_real, m_nb, m_nl, m_tb)
|
||||||
break
|
# 原实现语义:attr 的首次匹配值
|
||||||
m_j += 1
|
if m_res is None and string.strcmp(m_nb, attr) == 0:
|
||||||
if m_fc != 0:
|
m_vl: sizet = string.strlen(m_tb)
|
||||||
m_nl: sizet = m_j
|
m_res = pool.alloc(m_vl + 1)
|
||||||
while m_nl > 0 and m_buf[m_ls + m_nl - 1] == ' ':
|
if m_res is not None:
|
||||||
m_nl -= 1
|
string.strcpy(m_res, m_tb)
|
||||||
m_rest: str = m_buf + m_ls + m_j + 1
|
|
||||||
if string.strstr(m_rest, "t.CTypedef") is not None:
|
|
||||||
m_eq: str = string.strstr(m_rest, "=")
|
|
||||||
if m_eq is not None:
|
|
||||||
# '=' 相对行首偏移;值段严格限定在行尾
|
|
||||||
# (m_line_len)内,防止跨行吞换行+后续内容
|
|
||||||
m_eq_off: sizet = sizet(uint64(m_eq) - uint64(m_buf)) - m_ls
|
|
||||||
m_vs: sizet = m_eq_off + 1
|
|
||||||
while m_vs < m_line_len and m_buf[m_ls + m_vs] == ' ':
|
|
||||||
m_vs += 1
|
|
||||||
m_ve: sizet = m_line_len
|
|
||||||
while m_ve > m_vs and (m_buf[m_ls + m_ve - 1] == ' '
|
|
||||||
or m_buf[m_ls + m_ve - 1] == '\r'):
|
|
||||||
m_ve -= 1
|
|
||||||
if m_ve > m_vs:
|
|
||||||
m_vlen: sizet = m_ve - m_vs
|
|
||||||
m_tb: str = pool.alloc(m_vlen + 1)
|
|
||||||
if m_tb is not None:
|
|
||||||
string.strncpy(m_tb, m_buf + m_ls + m_vs, m_vlen)
|
|
||||||
m_tb[m_vlen] = '\0'
|
|
||||||
# 写入持久缓存(首次遇到的名字为准)
|
|
||||||
self._register_lib_typedef_cache(m_real, m_buf + m_ls, m_nl, m_tb)
|
|
||||||
# 原实现语义:attr 的首次匹配值
|
|
||||||
if m_res is None and m_nl == attr_len:
|
|
||||||
m_nm_ok: int = 1
|
|
||||||
m_ki: sizet = 0
|
|
||||||
while m_ki < attr_len:
|
|
||||||
if m_buf[m_ls + m_ki] != attr[m_ki]:
|
|
||||||
m_nm_ok = 0
|
|
||||||
break
|
|
||||||
m_ki += 1
|
|
||||||
if m_nm_ok == 1:
|
|
||||||
m_res = m_tb
|
|
||||||
m_ls = m_i + 1
|
m_ls = m_i + 1
|
||||||
m_i += 1
|
m_i += 1
|
||||||
# 置该模块已扫描标记:同模块后续查询只查持久缓存表,不再重复读源
|
# 置该模块已扫描标记:同模块后续查询只查持久缓存表,不再重复读源
|
||||||
|
|||||||
Reference in new issue
Block a user