refactor: rawptr[T] -> T*(R14)+ 修 REnum 前向占位未就地填充
R14:rawptr[X] -> X*(56 文件 / 834 行改动);保留 6 处 rawptr[t.CPtr](存纯裸指针的规范例外)。 修复:class X(t.REnum) 的变体字段写成自引用 X* 时,字段解析在变体扫描期经 ensure_forward_class 建了一个 opaque 前向占位;末尾 register_struct 按 Ty 指针去重会再建第二个同名 entry,而 find_struct 取首个(占位,0 字段)→ X.__sizeof__() == 0,报「已注册但大小为 0(字段链表未填充)」。改为注册前若命中同模块前向占位则就地填充(与 ensure_forward_class 文档口径一致)。TPC 无此问题,属 TPV 侧缺口。 验证:自举三重重编 SUCCESS;全量 77/77 顺序回归通过(修复前卡在 LLvmLiteTest)。
This commit is contained in:
1 parent
aeb4e8e54c
commit
cd55a7e214
56 files changed
+834
-822
No files matched your search
@@ -124,7 +124,7 @@ def WriteCallSidecar(temp_dir: str, sha1: str, text: str) -> int:
|
||||
if vpath is None:
|
||||
VLogger.error(f"--traceback: .vpcall 路径构造失败(sha1={sha1}),终止编译", "TRACEBACK")
|
||||
return 1
|
||||
vf: rawptr[fileio.File] = fileio.File(vpath, fileio.MODE.W)
|
||||
vf: fileio.File* = fileio.File(vpath, fileio.MODE.W)
|
||||
if vf.closed:
|
||||
VLogger.error(f"--traceback: 写出 .vpcall 失败(无法打开 {vpath}),终止编译", "TRACEBACK")
|
||||
stdlib.free(vpath)
|
||||
@@ -146,10 +146,10 @@ def _tb_basename_is_traceback(file_path: str) -> int:
|
||||
|
||||
# TranslateFileGetTrans - translate one file and return a Translator (caller dumps IR).
|
||||
# File -> AST -> .vpi -> LLVM IR; includes use loose scoping, user files strict (local + imports).
|
||||
def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, current_package: str = None, declare_only: int = 0, temp_dir: str = None, pre_allow_dep_inject: int = 0) -> rawptr[HandlesTranslator.Translator]:
|
||||
def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, current_package: str = None, declare_only: int = 0, temp_dir: str = None, pre_allow_dep_inject: int = 0) -> HandlesTranslator.Translator*:
|
||||
"""Translate one file and return a Translator (caller dumps IR); None on failure."""
|
||||
if file_path is None: return None
|
||||
f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed: return None
|
||||
# read_all's capacity includes the terminator (reads cap-1 bytes max) and silently
|
||||
# truncates longer files; reject by size first, else parsing gets confusing syntax errors.
|
||||
@@ -195,13 +195,13 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, c
|
||||
td_len_vpi: sizet = len(temp_dir)
|
||||
pyi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_vpi, sha1_val, "vpi")
|
||||
if pyi_path is not None:
|
||||
pf: rawptr[fileio.File] = fileio.File(pyi_path, fileio.MODE.W)
|
||||
pf: fileio.File* = fileio.File(pyi_path, fileio.MODE.W)
|
||||
if not pf.closed:
|
||||
pf.write(pyi_buf, pyi_pos)
|
||||
pf.close()
|
||||
stdlib.free(pyi_path)
|
||||
stdlib.free(pyi_buf)
|
||||
tr: rawptr[HandlesTranslator.Translator] = mb.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
tr: HandlesTranslator.Translator* = mb.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
tr.__before_init__()
|
||||
tr.__init__()
|
||||
tr.ModuleSha1 = sha1_val
|
||||
@@ -212,7 +212,7 @@ def TranslateFileGetTrans(mb: memhub.MemBuddy*, file_path: str, sha1_val: str, c
|
||||
tr._pre_allow_dep_inject = pre_allow_dep_inject
|
||||
# P2: reuse the global gen singleton (created by App/main.vp); create it as a fallback
|
||||
# when unregistered (defensive for direct-call paths).
|
||||
gen: rawptr[GenGenerator.Generator] = GenGenerator._g_gen
|
||||
gen: GenGenerator.Generator* = GenGenerator._g_gen
|
||||
if gen is None:
|
||||
gen = mb.alloc(GenGenerator.Generator.__sizeof__())
|
||||
if gen is None:
|
||||
@@ -344,7 +344,7 @@ def write_ir_to_file(ir_buf: bytes, ir_len: sizet, output_dir: str, module_name:
|
||||
if path is None: return 1
|
||||
|
||||
# open the file for writing
|
||||
f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.W)
|
||||
f: fileio.File* = fileio.File(path, fileio.MODE.W)
|
||||
if f.closed: return 1
|
||||
|
||||
written: int64 = f.write(ir_buf, ir_len)
|
||||
@@ -543,7 +543,7 @@ def _phase2_write_cmd(cmd: str) -> None:
|
||||
"""--phase2command mode: append the command to the bat file without executing it."""
|
||||
global _phase2_bat_init
|
||||
if _phase2_cmd_path is None or cmd is None: return
|
||||
f: rawptr[fileio.File] = fileio.File(_phase2_cmd_path, fileio.MODE.A)
|
||||
f: fileio.File* = fileio.File(_phase2_cmd_path, fileio.MODE.A)
|
||||
if f.closed:
|
||||
VLogger.error("phase2command: bat 打开失败", "phase2cmd")
|
||||
return
|
||||
@@ -662,7 +662,7 @@ def run_llc_parallel(tasks: bytes, task_count: int, max_threads: int) -> int:
|
||||
# spawn this batch
|
||||
for j in range(batch_n):
|
||||
tsk: LlcTask* = (LlcTask*)(uint64(tasks) + sizet(batch_start + j) * slot_size)
|
||||
th: rawptr[vthreading.Thread] = vthreading.Thread(_llc_task_worker, t.CPtr(tsk))
|
||||
th: vthreading.Thread* = vthreading.Thread(_llc_task_worker, t.CPtr(tsk))
|
||||
th.start()
|
||||
# Read the handle right after start() (the Thread object's stack slot may be
|
||||
# reused; reading self.handle at join could see a cleared/overwritten value).
|
||||
@@ -844,7 +844,7 @@ def link_obj_to_exe(output_dir: str, module_name: str, linker_cmd: str, linker_f
|
||||
_phase2_write_cmd(cmd)
|
||||
return 0
|
||||
|
||||
result: rawptr[subprocess.CompletedProcess] = subprocess.run(cmd, True, True)
|
||||
result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True)
|
||||
if result is None:
|
||||
VLogger.error("subprocess.run 返回 None", "link")
|
||||
return 1
|
||||
@@ -877,7 +877,7 @@ def asm_to_obj(asm_path: str, sha1_val: str, output_dir: str, triple: str) -> in
|
||||
_phase2_write_cmd(cmd)
|
||||
return 0
|
||||
|
||||
result: rawptr[subprocess.CompletedProcess] = subprocess.run(cmd, True, True)
|
||||
result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True)
|
||||
if result is None:
|
||||
VLogger.error("llvm-mc subprocess.run 返回 None", "asm")
|
||||
return 1
|
||||
@@ -1006,7 +1006,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_cmd: str, link
|
||||
if _phase2_cmd_path is not None:
|
||||
_phase2_write_cmd(cmd)
|
||||
return 0
|
||||
result: rawptr[subprocess.CompletedProcess] = subprocess.run(cmd, True, True)
|
||||
result: subprocess.CompletedProcess* = subprocess.run(cmd, True, True)
|
||||
if result is None:
|
||||
VLogger.error("subprocess.run 返回 None", "link")
|
||||
return 1
|
||||
@@ -1418,7 +1418,7 @@ def _tb_read_pe_layout(mb: memhub.MemBuddy*, exe_path: str) -> TbPeLayout*:
|
||||
"""Read (ImageBase, SizeOfImage, .text RVA) from the PE headers."""
|
||||
lay: TbPeLayout* = TbPeLayout()
|
||||
if lay is None: return None
|
||||
f: rawptr[fileio.File] = fileio.File(exe_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(exe_path, fileio.MODE.R)
|
||||
if f.closed: return lay
|
||||
HEAD: sizet = 4096
|
||||
head: bytes = mb.alloc(HEAD)
|
||||
@@ -1811,7 +1811,7 @@ def _tb_cp_add_fr(mb: memhub.MemBuddy*, cp: TbCallParse*, sym: str, file: str, d
|
||||
|
||||
def _tb_read_whole(mb: memhub.MemBuddy*, path: str) -> str:
|
||||
"""Read the whole file into a NUL-terminated string; None on failure."""
|
||||
f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(path, fileio.MODE.R)
|
||||
if f.closed: return None
|
||||
sz: LONGLONG = f.size()
|
||||
if sz < 0:
|
||||
@@ -1984,7 +1984,7 @@ def _tb_run_objdump(mb: memhub.MemBuddy*, exe_path: str) -> str:
|
||||
VLogger.error("--traceback: objdump 命令缓冲分配失败,终止编译", "TRACEBACK")
|
||||
return None
|
||||
viperlib.snprintf(cmd, cl, "llvm-objdump -d \"%s\"", exe_path)
|
||||
res: rawptr[subprocess.CompletedProcess] = subprocess.run(cmd, True, True)
|
||||
res: subprocess.CompletedProcess* = subprocess.run(cmd, True, True)
|
||||
if res is None or res.returncode != 0:
|
||||
rc: int = -1
|
||||
if res is not None: rc = res.returncode
|
||||
@@ -2109,7 +2109,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
VLogger.error("--traceback: dwarfdump 命令缓冲分配失败,终止编译", "TRACEBACK")
|
||||
return 1
|
||||
viperlib.snprintf(cmd, cmd_len, "llvm-dwarfdump --debug-line --debug-info \"%s\"", exe_path)
|
||||
res: rawptr[subprocess.CompletedProcess] = subprocess.run(cmd, True, True)
|
||||
res: subprocess.CompletedProcess* = subprocess.run(cmd, True, True)
|
||||
if res is None or res.returncode != 0:
|
||||
rc: int = -1
|
||||
if res is not None: rc = res.returncode
|
||||
@@ -2351,7 +2351,7 @@ def WriteStackMap(mb: memhub.MemBuddy*, exe_path: str) -> int:
|
||||
VLogger.error("--traceback: 旁文件路径缓冲分配失败,终止编译", "TRACEBACK")
|
||||
return 1
|
||||
viperlib.snprintf(map_path, map_len, "%s.stackmap", exe_path)
|
||||
mf: rawptr[fileio.File] = fileio.File(map_path, fileio.MODE.W)
|
||||
mf: fileio.File* = fileio.File(map_path, fileio.MODE.W)
|
||||
if mf.closed:
|
||||
VLogger.error(f"--traceback: 写出旁文件失败(无法打开 {map_path}),终止编译", "TRACEBACK")
|
||||
return 1
|
||||
|
||||
@@ -32,7 +32,7 @@ import lib.core.Gen.DebugInfoGen as DebugInfoGen
|
||||
|
||||
# _InjectedCreatesCycle - cycle check before auto-injecting a container module
|
||||
# (_list/_dict); a hit (e.g. memhub<->_list) skips injection to avoid a Phase A deadlock.
|
||||
def _InjectedCreatesCycle(entry: rawptr[IncludesScanner.FileEntry], mod_name: str) -> int:
|
||||
def _InjectedCreatesCycle(entry: IncludesScanner.FileEntry*, mod_name: str) -> int:
|
||||
"""Return 1 if injecting mod_name into the current module would create a cycle"""
|
||||
if entry is None or entry.RelPath is None or mod_name is None: return 0
|
||||
inj_sha1: str = StubMergerStore.LookupSha1ByModName(mod_name)
|
||||
@@ -120,7 +120,7 @@ def _RewriteDepsTxt(temp_dir: str, sha1: str, deps_str: str) -> None:
|
||||
td_len: sizet = string.strlen(temp_dir)
|
||||
dpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "deps.txt")
|
||||
if dpath is None: return
|
||||
df: rawptr[fileio.File] = fileio.File(dpath, fileio.MODE.W)
|
||||
df: fileio.File* = fileio.File(dpath, fileio.MODE.W)
|
||||
if not df.closed:
|
||||
dl: sizet = string.strlen(deps_str)
|
||||
if dl > 0: df.write(deps_str, dl)
|
||||
@@ -179,12 +179,12 @@ def _BreakContainerCyclesInDeps(temp_dir: str) -> int:
|
||||
|
||||
# _BuildReachableResult - rebuild the reachable FileEntry list from the Sha1Store.
|
||||
# Only incdir-nonempty (includes) entries enter result; App entries would cause duplicate symbols.
|
||||
def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> rawptr[IncludesScanner.ScanResult]:
|
||||
def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> IncludesScanner.ScanResult*:
|
||||
"""Build the reachable FileEntry list from the Sha1Store (reachable includes only)"""
|
||||
if mb is None: return None
|
||||
store_count: sizet = sizet(StubMerger._sha1_store_count)
|
||||
if store_count <= 0 or StubMerger._sha1_store_arr is None: return None
|
||||
result: rawptr[IncludesScanner.ScanResult] = IncludesScanner.create_scan_result(mb)
|
||||
result: IncludesScanner.ScanResult* = IncludesScanner.create_scan_result(mb)
|
||||
if result is None: return None
|
||||
entry_size: sizet = IncludesScanner.FileEntry.__sizeof__()
|
||||
i: sizet
|
||||
@@ -195,7 +195,7 @@ def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> rawptr[Inc
|
||||
iidx: sizet = sizet(i) * StubMerger.MAX_INC_DIR_LEN
|
||||
if StubMerger._sha1_store_incdir[iidx] == '\0': continue
|
||||
eaddr: uint64 = uint64(result.Entries) + uint64(result.Count) * entry_size
|
||||
entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](eaddr)
|
||||
entry: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(eaddr)
|
||||
if entry is None: continue
|
||||
# Deep-copy SHA1 (store slot is 17 bytes)
|
||||
sha1_buf: bytes = stdlib.malloc(17)
|
||||
@@ -244,7 +244,7 @@ def _BuildReachableResult(mb: memhub.MemBuddy*, includes_dir: str) -> rawptr[Inc
|
||||
|
||||
# ============================================================
|
||||
# RunPhase1 - scan the includes dir; translate and split stubs only when missing.
|
||||
def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawptr[VLogger.Logger]) -> int:
|
||||
def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: VLogger.Logger*) -> int:
|
||||
"""Phase1: scan the includes directory and translate/generate stubs on demand"""
|
||||
if includes_dir is None or temp_dir is None:
|
||||
VLogger.error("includes_dir 或 temp_dir 为空,无法运行 Phase1", "Phase1")
|
||||
@@ -296,7 +296,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
|
||||
# Build the reachable FileEntry list from the Sha1Store; 1a/1b-pre/1b iterate result
|
||||
# (non-empty incdir = includes). use_reachable filtering is idempotent.
|
||||
result: rawptr[IncludesScanner.ScanResult] = _BuildReachableResult(mb, includes_dir)
|
||||
result: IncludesScanner.ScanResult* = _BuildReachableResult(mb, includes_dir)
|
||||
if result is None:
|
||||
VLogger.error("可达 FileEntry 列表构建失败,终止编译", "Phase1")
|
||||
return 1
|
||||
@@ -399,7 +399,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
|
||||
# ============================================================
|
||||
# Phase 1a-pre-generic-all: pre-register all includes' generic templates before mark1.
|
||||
full_scan_g: rawptr[IncludesScanner.ScanResult] = IncludesScanner.scan_includes(mb, includes_dir)
|
||||
full_scan_g: IncludesScanner.ScanResult* = IncludesScanner.scan_includes(mb, includes_dir)
|
||||
if full_scan_g is not None: Phase1Scan._PreRegisterAllGenericTemplates(mb, full_scan_g)
|
||||
else: Phase1Scan._PreRegisterAllGenericTemplates(mb, result)
|
||||
|
||||
@@ -422,7 +422,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
if od_ptr is not None: file_idx = od_ptr[0]
|
||||
|
||||
entry_addr_r: uint64 = uint64(result.Entries) + file_idx * entry_size
|
||||
entry_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr_r)
|
||||
entry_r: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(entry_addr_r)
|
||||
if entry_r is None:
|
||||
p1a_fl += 1
|
||||
continue
|
||||
@@ -448,7 +448,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
|
||||
# Read file contents
|
||||
file_path_r: str = entry_r.Path
|
||||
f_r: rawptr[fileio.File] = fileio.File(file_path_r, fileio.MODE.R)
|
||||
f_r: fileio.File* = fileio.File(file_path_r, fileio.MODE.R)
|
||||
if f_r.closed:
|
||||
p1a_fl += 1
|
||||
continue
|
||||
@@ -492,7 +492,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
t_fa1: uint64 = w32.win32base.GetTickCount64()
|
||||
|
||||
# Create Translator with _declare_only=1 (register struct/enum/union)
|
||||
tr_r: rawptr[HandlesTranslator.Translator] = HandlesTranslator.Translator()
|
||||
tr_r: HandlesTranslator.Translator* = HandlesTranslator.Translator()
|
||||
if tr_r is None:
|
||||
stdlib.free(src_buf_r)
|
||||
p1a_fl += 1
|
||||
@@ -563,7 +563,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
t_pv0: uint64 = w32.win32base.GetTickCount64()
|
||||
for i_pv in range(result.Count):
|
||||
entry_addr_pv: uint64 = uint64(result.Entries) + i_pv * entry_size
|
||||
entry_pv: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr_pv)
|
||||
entry_pv: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(entry_addr_pv)
|
||||
if entry_pv is None or entry_pv.Sha1 is None:
|
||||
p1bpre_failed += 1
|
||||
continue
|
||||
@@ -578,7 +578,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
p1bpre_failed += 1
|
||||
VLogger.error(f"[Phase 1b-pre] {entry_pv.Path} | vpi 路径生成失败", "Phase1")
|
||||
continue
|
||||
vf_pv: rawptr[fileio.File] = fileio.File(vpi_path_pv, fileio.MODE.R)
|
||||
vf_pv: fileio.File* = fileio.File(vpi_path_pv, fileio.MODE.R)
|
||||
if not vf_pv.closed:
|
||||
vf_pv.close()
|
||||
stdlib.free(vpi_path_pv)
|
||||
@@ -586,7 +586,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
stdlib.free(vpi_path_pv)
|
||||
# Read the file, parse the AST, generate the vpi
|
||||
file_path_pv: str = entry_pv.Path
|
||||
f_pv: rawptr[fileio.File] = fileio.File(file_path_pv, fileio.MODE.R)
|
||||
f_pv: fileio.File* = fileio.File(file_path_pv, fileio.MODE.R)
|
||||
if f_pv.closed:
|
||||
p1bpre_failed += 1
|
||||
VLogger.error(f"[Phase 1b-pre] {file_path_pv} | 无法打开源文件", "Phase1")
|
||||
@@ -634,7 +634,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
if pyi_pos_pv > 0:
|
||||
pyi_path_pv: str = StubMergerCollect._sliced_path(temp_dir, dir_len_pv, sha1_pv, "vpi")
|
||||
if pyi_path_pv is not None:
|
||||
pf_pv: rawptr[fileio.File] = fileio.File(pyi_path_pv, fileio.MODE.W)
|
||||
pf_pv: fileio.File* = fileio.File(pyi_path_pv, fileio.MODE.W)
|
||||
if not pf_pv.closed:
|
||||
pf_pv.write(pyi_buf_pv, pyi_pos_pv)
|
||||
pf_pv.close()
|
||||
@@ -681,7 +681,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
od_ptr_b: t.CPtr = (int*)(od_addr_b)
|
||||
if od_ptr_b is not None: file_idx_b = od_ptr_b[0]
|
||||
entry_addr: uint64 = uint64(result.Entries) + sizet(file_idx_b) * entry_size
|
||||
entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr)
|
||||
entry: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(entry_addr)
|
||||
if entry is None:
|
||||
failed += 1
|
||||
continue
|
||||
@@ -714,7 +714,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
force_translate: int = 0
|
||||
vpi_path_1b: str = StubMergerCollect._sliced_path(temp_dir, dir_len, sha1, "vpi")
|
||||
if vpi_path_1b is not None:
|
||||
vf_1b: rawptr[fileio.File] = fileio.File(vpi_path_1b, fileio.MODE.R)
|
||||
vf_1b: fileio.File* = fileio.File(vpi_path_1b, fileio.MODE.R)
|
||||
if not vf_1b.closed:
|
||||
vbuf_1b: bytes = stdlib.malloc(1048576)
|
||||
if vbuf_1b is not None:
|
||||
@@ -743,13 +743,13 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
VLogger.info(f"含 class 定义,强制翻译: {rp}(sha1={sha1})", "Phase1")
|
||||
else:
|
||||
# Skip already-existing stubs (on-demand translation)
|
||||
sf: rawptr[fileio.File] = fileio.File(stub_path, fileio.MODE.R)
|
||||
sf: fileio.File* = fileio.File(stub_path, fileio.MODE.R)
|
||||
if not sf.closed:
|
||||
sf.close()
|
||||
# Check that text.ll exists too (vtable scan needs it)
|
||||
text_path: str = StubMergerCollect._sliced_path(temp_dir, dir_len, sha1, "text.ll")
|
||||
if text_path is not None:
|
||||
tf: rawptr[fileio.File] = fileio.File(text_path, fileio.MODE.R)
|
||||
tf: fileio.File* = fileio.File(text_path, fileio.MODE.R)
|
||||
if not tf.closed:
|
||||
tf.close()
|
||||
# The sidecar ({sha1}.meta) and online FULL artifact ({sha1}.full.ll) must also exist;
|
||||
@@ -757,7 +757,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
meta_path_1b: str = StubMergerCollect._sliced_path(temp_dir, dir_len, sha1, "meta")
|
||||
meta_ok_1b: int = 0
|
||||
if meta_path_1b is not None:
|
||||
mf_chk: rawptr[fileio.File] = fileio.File(meta_path_1b, fileio.MODE.R)
|
||||
mf_chk: fileio.File* = fileio.File(meta_path_1b, fileio.MODE.R)
|
||||
if not mf_chk.closed:
|
||||
mf_chk.close()
|
||||
meta_ok_1b = 1
|
||||
@@ -765,7 +765,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
full_path_1b: str = StubMergerCollect._sliced_path(temp_dir, dir_len, sha1, "full.ll")
|
||||
full_ok_1b: int = 0
|
||||
if full_path_1b is not None:
|
||||
ff_chk: rawptr[fileio.File] = fileio.File(full_path_1b, fileio.MODE.R)
|
||||
ff_chk: fileio.File* = fileio.File(full_path_1b, fileio.MODE.R)
|
||||
if not ff_chk.closed:
|
||||
ff_chk.close()
|
||||
full_ok_1b = 1
|
||||
@@ -790,7 +790,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
|
||||
# Read file contents
|
||||
file_path: str = entry.Path
|
||||
f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(file_path, fileio.MODE.R)
|
||||
if f is None:
|
||||
VLogger.error(f"无法打开(f=None): {file_path}", "Phase1")
|
||||
failed += 1
|
||||
@@ -850,7 +850,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
# is only a fallback when the vpi is missing.
|
||||
vpi_path_1b: str = StubMergerCollect._sliced_path(temp_dir, dir_len, sha1, "vpi")
|
||||
if vpi_path_1b is not None:
|
||||
vf_1b: rawptr[fileio.File] = fileio.File(vpi_path_1b, fileio.MODE.R)
|
||||
vf_1b: fileio.File* = fileio.File(vpi_path_1b, fileio.MODE.R)
|
||||
vpi_exists_1b: int = 0
|
||||
if not vf_1b.closed:
|
||||
vf_1b.close()
|
||||
@@ -860,7 +860,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
if pyi_buf is not None:
|
||||
pyi_pos: sizet = StubConverter._GeneratePyiFromAst(mb, tree, entry.Path, pyi_buf, Phase1.PYI_BUF_SIZE)
|
||||
if pyi_pos > 0:
|
||||
pf_1b: rawptr[fileio.File] = fileio.File(vpi_path_1b, fileio.MODE.W)
|
||||
pf_1b: fileio.File* = fileio.File(vpi_path_1b, fileio.MODE.W)
|
||||
if not pf_1b.closed:
|
||||
pf_1b.write(pyi_buf, pyi_pos)
|
||||
pf_1b.close()
|
||||
@@ -868,7 +868,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
stdlib.free(vpi_path_1b)
|
||||
|
||||
# Translate AST -> LLVM IR
|
||||
tr: rawptr[HandlesTranslator.Translator] = HandlesTranslator.Translator()
|
||||
tr: HandlesTranslator.Translator* = HandlesTranslator.Translator()
|
||||
if tr is None:
|
||||
stdlib.free(src_buf)
|
||||
failed += 1
|
||||
@@ -934,7 +934,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
dir_len_p1: sizet = string.strlen(temp_dir)
|
||||
stub_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "stub.ll")
|
||||
if stub_path_p1 is not None:
|
||||
sf_p1: rawptr[fileio.File] = fileio.File(stub_path_p1, fileio.MODE.W)
|
||||
sf_p1: fileio.File* = fileio.File(stub_path_p1, fileio.MODE.W)
|
||||
if not sf_p1.closed:
|
||||
sf_p1.write(stub_buf, stub_len)
|
||||
sf_p1.close()
|
||||
@@ -955,7 +955,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
# save text.ll
|
||||
text_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "text.ll")
|
||||
if text_path_p1 is not None:
|
||||
tf_p1: rawptr[fileio.File] = fileio.File(text_path_p1, fileio.MODE.W)
|
||||
tf_p1: fileio.File* = fileio.File(text_path_p1, fileio.MODE.W)
|
||||
if not tf_p1.closed:
|
||||
tf_p1.write(text_buf, text_len)
|
||||
tf_p1.close()
|
||||
@@ -973,7 +973,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
full_len_p1: sizet = string.strlen(full_buf_p1)
|
||||
full_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "full.ll")
|
||||
if full_path_p1 is not None:
|
||||
ff_p1: rawptr[fileio.File] = fileio.File(full_path_p1, fileio.MODE.W)
|
||||
ff_p1: fileio.File* = fileio.File(full_path_p1, fileio.MODE.W)
|
||||
if not ff_p1.closed:
|
||||
ff_p1.write(full_buf_p1, full_len_p1)
|
||||
ff_p1.close()
|
||||
@@ -995,7 +995,7 @@ def RunPhase1(mb: memhub.MemBuddy*, includes_dir: str, temp_dir: str, log: rawpt
|
||||
# save dependencies(_imported_modules) for Phase B
|
||||
deps_path_p1: str = StubMergerCollect._sliced_path(temp_dir, dir_len_p1, sha1, "deps.txt")
|
||||
if deps_path_p1 is not None:
|
||||
df_p1: rawptr[fileio.File] = fileio.File(deps_path_p1, fileio.MODE.W)
|
||||
df_p1: fileio.File* = fileio.File(deps_path_p1, fileio.MODE.W)
|
||||
if not df_p1.closed:
|
||||
if tr._imported_modules is not None:
|
||||
dl: sizet = string.strlen(tr._imported_modules)
|
||||
|
||||
@@ -40,7 +40,7 @@ import lib.core.Gen.GenApi as GenApi
|
||||
|
||||
# _ScanClassInheritance - pre-scan includes files, parse ASTs and collect ClassDef
|
||||
# names/parent names into flat byte arrays; returns the class count (-1 on failure).
|
||||
def _ScanClassInheritance(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResult], reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, generic_file_indices: t.CPtr, generic_file_count_box: t.CPtr) -> int:
|
||||
def _ScanClassInheritance(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, generic_file_indices: t.CPtr, generic_file_count_box: t.CPtr) -> int:
|
||||
"""Pre-scan includes files and collect class inheritance info."""
|
||||
if result is None: return -1
|
||||
# The three flat buffers are mb.alloc'ed by the caller; a NULL buffer would make
|
||||
@@ -55,7 +55,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.S
|
||||
# info (keeping all ASTs alive until mark1 would OOM the 1GB main pool).
|
||||
scan_mark: sizet = mb.mark()
|
||||
entry_addr: uint64 = uint64(result.Entries) + i * entry_size
|
||||
entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr)
|
||||
entry: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(entry_addr)
|
||||
if entry is None or entry.Sha1 is None: continue
|
||||
|
||||
sha1_e: str = entry.Sha1
|
||||
@@ -69,7 +69,7 @@ def _ScanClassInheritance(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.S
|
||||
|
||||
# read the file
|
||||
file_path: str = entry.Path
|
||||
f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed: continue
|
||||
|
||||
# read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated
|
||||
@@ -219,7 +219,7 @@ def _BufHasGenericFuncMarker(buf: bytes, blen: sizet) -> int:
|
||||
return 0
|
||||
# _PreRegisterAllGenericTemplates - pre-register includes generic templates before
|
||||
# mark1 so the lazy tables survive later resets; parses only marker-matched files.
|
||||
def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResult]) -> int:
|
||||
def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*) -> int:
|
||||
"""Pre-register generic templates from all includes files and return the count."""
|
||||
if result is None or mb is None: return 0
|
||||
perm: memhub.MemBuddy* = CompilerFactory.factory.PermPool
|
||||
@@ -228,11 +228,11 @@ def _PreRegisterAllGenericTemplates(mb: memhub.MemBuddy*, result: rawptr[Include
|
||||
handled_count: int = 0
|
||||
for i in range(result.Count):
|
||||
entry_addr_pg: uint64 = uint64(result.Entries) + i * p1e_size
|
||||
entry_pg: rawptr[IncludesScanner.FileEntry] = (rawptr[IncludesScanner.FileEntry])(entry_addr_pg)
|
||||
entry_pg: IncludesScanner.FileEntry* = (IncludesScanner.FileEntry*)(entry_addr_pg)
|
||||
if entry_pg is None or entry_pg.Sha1 is None: continue
|
||||
# read the file
|
||||
file_path_pg: str = entry_pg.Path
|
||||
f_pg: rawptr[fileio.File] = fileio.File(file_path_pg, fileio.MODE.R)
|
||||
f_pg: fileio.File* = fileio.File(file_path_pg, fileio.MODE.R)
|
||||
if f_pg.closed: continue
|
||||
# read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated
|
||||
if f_pg.size() >= Phase1.SRC_BUF_SIZE:
|
||||
@@ -355,7 +355,7 @@ def _ScanTreeForContainers(node: ast.AST*, need_list_box: t.CPtr, need_dict_box:
|
||||
nk_s: sizet = len(cl_kws_s)
|
||||
i_k2: sizet
|
||||
for i_k2 in range(nk_s):
|
||||
kw_s: rawptr[ast.Keyword] = rawptr[ast.Keyword](cl_kws_s.get(i_k2))
|
||||
kw_s: ast.Keyword* = ast.Keyword*(cl_kws_s.get(i_k2))
|
||||
if kw_s is not None: _ScanTreeForContainers(kw_s.value, need_list_box, need_dict_box, depth + 1)
|
||||
elif k_s == ast.ASTKind.Assign:
|
||||
asn_s: ast.Assign* = ast.Assign*(node)
|
||||
@@ -402,13 +402,13 @@ def _ScanTreeForContainers(node: ast.AST*, need_list_box: t.CPtr, need_dict_box:
|
||||
uop_s: ast.UnaryOp* = ast.UnaryOp*(node)
|
||||
_ScanTreeForContainers(uop_s.operand, need_list_box, need_dict_box, depth + 1)
|
||||
elif k_s == ast.ASTKind.Expr:
|
||||
ex_s: rawptr[ast.Expr] = rawptr[ast.Expr](node)
|
||||
ex_s: ast.Expr* = ast.Expr*(node)
|
||||
_ScanTreeForContainers(ex_s.value, need_list_box, need_dict_box, depth + 1)
|
||||
elif k_s == ast.ASTKind.Return:
|
||||
rt_s: rawptr[ast.Return] = rawptr[ast.Return](node)
|
||||
rt_s: ast.Return* = ast.Return*(node)
|
||||
_ScanTreeForContainers(rt_s.value, need_list_box, need_dict_box, depth + 1)
|
||||
elif k_s == ast.ASTKind.Compare:
|
||||
cp_s: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cp_s: ast.Compare* = ast.Compare*(node)
|
||||
_ScanTreeForContainers(cp_s.left, need_list_box, need_dict_box, depth + 1)
|
||||
cps_s: list[ast.AST*]* = cp_s.comparators
|
||||
if cps_s is not None:
|
||||
@@ -416,7 +416,7 @@ def _ScanTreeForContainers(node: ast.AST*, need_list_box: t.CPtr, need_dict_box:
|
||||
i_c2: sizet
|
||||
for i_c2 in range(nc_s): _ScanTreeForContainers(cps_s.get(i_c2), need_list_box, need_dict_box, depth + 1)
|
||||
elif k_s == ast.ASTKind.BoolOp:
|
||||
bo_s: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo_s: ast.BoolOp* = ast.BoolOp*(node)
|
||||
bvs_s: list[ast.AST*]* = bo_s.values
|
||||
if bvs_s is not None:
|
||||
nv_s: sizet = len(bvs_s)
|
||||
|
||||
@@ -32,7 +32,7 @@ import lib.Phase.Phase1 as Phase1
|
||||
|
||||
# _TopoSortFiles - topologically sort files by class inheritance (Kahn).
|
||||
# Builds a "file SHA1 -> dependency SHA1 set" map, computes in-degrees (parent-file first), then outputs the order; returns 0 or -1.
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResult], reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, class_count: int, out_order: t.CPtr, out_count: t.CPtr, temp_dir: str, td_len_ts: sizet) -> int:
|
||||
def _TopoSortFiles(mb: memhub.MemBuddy*, result: IncludesScanner.ScanResult*, reachable_set: str, reachable_count: int, use_reachable: int, sha1_set: str, set_count: int, class_names_buf: bytes, parent_names_buf: bytes, def_sha1s_buf: bytes, class_count: int, out_order: t.CPtr, out_count: t.CPtr, temp_dir: str, td_len_ts: sizet) -> int:
|
||||
"""Topologically sort files by class inheritance and import dependencies."""
|
||||
if result is None or out_order is None or out_count is None: return -1
|
||||
|
||||
@@ -64,7 +64,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResu
|
||||
# sha1 -> file_index map (simple linear search; file count is small)
|
||||
for i in range(result.Count):
|
||||
entry_addr: uint64 = uint64(result.Entries) + i * entry_size
|
||||
entry: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](entry_addr)
|
||||
entry: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(entry_addr)
|
||||
if entry is None or entry.Sha1 is None: continue
|
||||
|
||||
sha1_e: str = entry.Sha1
|
||||
@@ -206,7 +206,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResu
|
||||
target_sha1: str = file_sha1s_buf + fi * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r: uint64 = uint64(result.Entries) + ri * entry_size
|
||||
ent_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](ea_r)
|
||||
ent_r: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(ea_r)
|
||||
if ent_r is not None and ent_r.Sha1 is not None:
|
||||
if string.strcmp(ent_r.Sha1, target_sha1) == 0:
|
||||
# Write into the output index array
|
||||
@@ -287,7 +287,7 @@ def _TopoSortFiles(mb: memhub.MemBuddy*, result: rawptr[IncludesScanner.ScanResu
|
||||
target_sha1_2: str = file_sha1s_buf + fi_a2 * Phase1.SHA1_LEN
|
||||
for ri in range(result.Count):
|
||||
ea_r2: uint64 = uint64(result.Entries) + ri * entry_size
|
||||
ent_r2: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](ea_r2)
|
||||
ent_r2: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(ea_r2)
|
||||
if ent_r2 is not None and ent_r2.Sha1 is not None:
|
||||
if string.strcmp(ent_r2.Sha1, target_sha1_2) == 0:
|
||||
out_idx_addr2: uint64 = uint64(out_order) + out_idx * 4
|
||||
|
||||
@@ -218,7 +218,7 @@ def _PreRegisterAppGenericTemplates(mb: memhub.MemBuddy*, entries: SrcFileEntry*
|
||||
ent_pa: SrcFileEntry* = (SrcFileEntry*)(ea_pa)
|
||||
if ent_pa is None or ent_pa.Path is None or ent_pa.Sha1 is None: continue
|
||||
# Read the file
|
||||
f_pa: rawptr[fileio.File] = fileio.File(ent_pa.Path, fileio.MODE.R)
|
||||
f_pa: fileio.File* = fileio.File(ent_pa.Path, fileio.MODE.R)
|
||||
if f_pa.closed: continue
|
||||
# read_all's capacity includes the terminator (reads at most cap-1 bytes); longer files are truncated
|
||||
if f_pa.size() >= SRC_BUF_SIZE:
|
||||
@@ -382,7 +382,7 @@ def _PhaseATextLLExists(temp_dir: str, td_len: sizet, sha1: str) -> int:
|
||||
if temp_dir is None or td_len == 0 or sha1 is None or string.strlen(sha1) < 2: return 0
|
||||
tpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "text.ll")
|
||||
if tpath is None: return 0
|
||||
tf: rawptr[fileio.File] = fileio.File(tpath, fileio.MODE.R)
|
||||
tf: fileio.File* = fileio.File(tpath, fileio.MODE.R)
|
||||
exists: int = 0
|
||||
if not tf.closed:
|
||||
tf.close()
|
||||
@@ -407,7 +407,7 @@ def _PhaseADumpNode(temp_dir: str, td_len: sizet, sha1: str, depth: int, prefix:
|
||||
# Fallback: read {temp_dir}/{prefix}/{sha1}.deps.txt (Phase1 already wrote it for includes)
|
||||
dpath: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "deps.txt")
|
||||
if dpath is not None:
|
||||
df: rawptr[fileio.File] = fileio.File(dpath, fileio.MODE.R)
|
||||
df: fileio.File* = fileio.File(dpath, fileio.MODE.R)
|
||||
if not df.closed:
|
||||
deps = stdlib.malloc(PA_DEPS_MAX_STR)
|
||||
if deps is not None:
|
||||
@@ -508,7 +508,7 @@ def _PhaseADumpFailGraph(temp_dir: str, td_len: sizet, path: str, sha1: str) ->
|
||||
stdio.fflush(None)
|
||||
|
||||
|
||||
def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, output_dir: str, cc_cmd: str, cc_flags: str, linker_cmd: str, linker_flags: str, linker_output: str, includes_binary_dir: str, includes_dir: str, do_phase1: int, do_phase2: int, log: rawptr[VLogger.Logger], args: rawptr[argparse.ParsedArgs], linker_static_libs: str = None, linker_dynamic_libs: str = None) -> int:
|
||||
def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, output_dir: str, cc_cmd: str, cc_flags: str, linker_cmd: str, linker_flags: str, linker_output: str, includes_binary_dir: str, includes_dir: str, do_phase1: int, do_phase2: int, log: VLogger.Logger*, args: argparse.ParsedArgs*, linker_static_libs: str = None, linker_dynamic_libs: str = None) -> int:
|
||||
"""Compile a multi-file project; return 0 on success, non-zero on failure"""
|
||||
if source_dir is None:
|
||||
VLogger.error("source_dir 为空", "project")
|
||||
@@ -576,7 +576,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
map_path_am: bytes = stdlib.malloc(td_len_am + 32)
|
||||
if map_path_am is not None:
|
||||
viperlib.snprintf(map_path_am, td_len_am + 32, "%s/_sha1_map.txt", temp_dir)
|
||||
mf: rawptr[fileio.File] = fileio.File(map_path_am, fileio.MODE.A)
|
||||
mf: fileio.File* = fileio.File(map_path_am, fileio.MODE.A)
|
||||
line_am: bytes = stdlib.malloc(512)
|
||||
# First fill the in-memory store (no file I/O), then write _sha1_map.txt
|
||||
app_filled: int = 0
|
||||
@@ -627,7 +627,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
vpi_failed_p2 += 1
|
||||
VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | vpi 路径生成失败", "PhaseA")
|
||||
continue
|
||||
vf_vp2: rawptr[fileio.File] = fileio.File(vpi_path_vp2, fileio.MODE.R)
|
||||
vf_vp2: fileio.File* = fileio.File(vpi_path_vp2, fileio.MODE.R)
|
||||
if not vf_vp2.closed:
|
||||
vf_vp2.close()
|
||||
stdlib.free(vpi_path_vp2)
|
||||
@@ -635,7 +635,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
stdlib.free(vpi_path_vp2)
|
||||
# Read the source -> parse the AST -> generate the vpi (rel_path = ent_vp2.Path: vpi content does
|
||||
# not depend on it; it is only used for fatal_error attribution, pointing at this source file)
|
||||
f_vp2: rawptr[fileio.File] = fileio.File(ent_vp2.Path, fileio.MODE.R)
|
||||
f_vp2: fileio.File* = fileio.File(ent_vp2.Path, fileio.MODE.R)
|
||||
if f_vp2.closed:
|
||||
vpi_failed_p2 += 1
|
||||
VLogger.error(f"[Phase A-pre-vpi] {ent_vp2.Path} | 无法打开源文件", "PhaseA")
|
||||
@@ -683,7 +683,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
if pyi_pos_vp2 > 0:
|
||||
pyi_path_vp2: str = StubMergerCollect._sliced_path(temp_dir, td_len_vpa, ent_vp2.Sha1, "vpi")
|
||||
if pyi_path_vp2 is not None:
|
||||
pf_vp2: rawptr[fileio.File] = fileio.File(pyi_path_vp2, fileio.MODE.W)
|
||||
pf_vp2: fileio.File* = fileio.File(pyi_path_vp2, fileio.MODE.W)
|
||||
if not pf_vp2.closed:
|
||||
pf_vp2.write(pyi_buf_vp2, pyi_pos_vp2)
|
||||
pf_vp2.close()
|
||||
@@ -750,7 +750,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
if full_path_pre is None: continue
|
||||
viperlib.snprintf(full_path_pre, incdir_len_pre + rel_len_pre + 2, "%s/%s", incdir_pre, inc_rel_pre)
|
||||
pkg_inc_pre: str = GenApi.compute_package_from_relpath(mb, inc_rel_pre)
|
||||
tr_inc_pre: rawptr[HandlesTranslator.Translator] = BuildPipeline.TranslateFileGetTrans(mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1)
|
||||
tr_inc_pre: HandlesTranslator.Translator* = BuildPipeline.TranslateFileGetTrans(mb, full_path_pre, inc_sha1_pre, pkg_inc_pre, 1)
|
||||
stdlib.free(full_path_pre)
|
||||
if tr_inc_pre is not None:
|
||||
# Record this file's deps (for convergence diagnostics; stdlib table survives reset)
|
||||
@@ -793,7 +793,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
pkg_pre = GenApi.compute_package_from_relpath(mb, rel_path_pre)
|
||||
# App pre-registration passes pre_allow_dep_inject=1: imports and dep vpi injection happen at
|
||||
# declaration time so field annotations share Phase A's context (else struct layouts diverge).
|
||||
tr_pre: rawptr[HandlesTranslator.Translator] = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1, None, 1)
|
||||
tr_pre: HandlesTranslator.Translator* = BuildPipeline.TranslateFileGetTrans(mb, ent_pre.Path, ent_pre.Sha1, pkg_pre, 1, None, 1)
|
||||
if tr_pre is None: VLogger.error(f"预注册失败: {ent_pre.Path}", "PhaseA")
|
||||
# OOM cleanup: free this App file's transient pre-registration data
|
||||
mb.reset_to(mark2)
|
||||
@@ -846,7 +846,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
if string.strlen(ent.Path) > src_dir_len_pa + 1:
|
||||
rel_path_pa: str = ent.Path + src_dir_len_pa + 1
|
||||
pkg_pa = GenApi.compute_package_from_relpath(mb, rel_path_pa)
|
||||
tr_a: rawptr[HandlesTranslator.Translator] = BuildPipeline.TranslateFileGetTrans(mb, ent.Path, ent.Sha1, pkg_pa, 0, temp_dir)
|
||||
tr_a: HandlesTranslator.Translator* = BuildPipeline.TranslateFileGetTrans(mb, ent.Path, ent.Sha1, pkg_pa, 0, temp_dir)
|
||||
# Timing point 1: translate returned
|
||||
t_pa1: uint64 = w32.win32base.GetTickCount64()
|
||||
if tr_a is None:
|
||||
@@ -894,7 +894,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
# Save stub.ll (sliced path: temp_dir/{sha1 prefix}/{sha1}.stub.ll)
|
||||
stub_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "stub.ll")
|
||||
if stub_path_a is not None:
|
||||
sf_a: rawptr[fileio.File] = fileio.File(stub_path_a, fileio.MODE.W)
|
||||
sf_a: fileio.File* = fileio.File(stub_path_a, fileio.MODE.W)
|
||||
if not sf_a.closed:
|
||||
sf_a.write(stub_buf_a, stub_len_a)
|
||||
sf_a.close()
|
||||
@@ -910,7 +910,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
# Save text.ll (sliced path)
|
||||
text_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "text.ll")
|
||||
if text_path_a is not None:
|
||||
tf_a: rawptr[fileio.File] = fileio.File(text_path_a, fileio.MODE.W)
|
||||
tf_a: fileio.File* = fileio.File(text_path_a, fileio.MODE.W)
|
||||
if not tf_a.closed:
|
||||
tf_a.write(text_buf_a, text_len_a)
|
||||
tf_a.close()
|
||||
@@ -927,7 +927,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
full_len_a: sizet = string.strlen(full_buf_a)
|
||||
full_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "full.ll")
|
||||
if full_path_a is not None:
|
||||
ffa: rawptr[fileio.File] = fileio.File(full_path_a, fileio.MODE.W)
|
||||
ffa: fileio.File* = fileio.File(full_path_a, fileio.MODE.W)
|
||||
if not ffa.closed:
|
||||
ffa.write(full_buf_a, full_len_a)
|
||||
ffa.close()
|
||||
@@ -944,7 +944,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
# Save dependencies (_imported_modules) for Phase B (sliced path)
|
||||
deps_path_a: str = StubMergerCollect._sliced_path(temp_dir, td_len_pa, ent.Sha1, "deps.txt")
|
||||
if deps_path_a is not None:
|
||||
df_a: rawptr[fileio.File] = fileio.File(deps_path_a, fileio.MODE.W)
|
||||
df_a: fileio.File* = fileio.File(deps_path_a, fileio.MODE.W)
|
||||
if not df_a.closed:
|
||||
if tr_a._imported_modules is not None:
|
||||
dl_a: sizet = string.strlen(tr_a._imported_modules)
|
||||
@@ -1057,7 +1057,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
if llc_ir_path is None:
|
||||
VLogger.error("llc 输入路径构造失败", "PhaseB")
|
||||
sys.exit(1)
|
||||
tslot: rawptr[BuildPipeline.LlcTask] = rawptr[BuildPipeline.LlcTask](uint64(llc_tasks) + sizet(llc_task_count) * BuildPipeline.LlcTask.__sizeof__())
|
||||
tslot: BuildPipeline.LlcTask* = BuildPipeline.LlcTask*(uint64(llc_tasks) + sizet(llc_task_count) * BuildPipeline.LlcTask.__sizeof__())
|
||||
if BuildPipeline.init_llc_task(tslot, llc_ir_path, output_dir, ent.Sha1, cc_cmd, cc_flags) != 0:
|
||||
VLogger.error(f"llc 任务构造失败: {ent.Path}", "PhaseB")
|
||||
sys.exit(1)
|
||||
@@ -1103,7 +1103,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
# Free the llc tasks (command strings + records)
|
||||
ti: int = 0
|
||||
while ti < llc_task_count:
|
||||
tfree: rawptr[BuildPipeline.LlcTask] = rawptr[BuildPipeline.LlcTask](uint64(llc_tasks) + sizet(ti) * BuildPipeline.LlcTask.__sizeof__())
|
||||
tfree: BuildPipeline.LlcTask* = BuildPipeline.LlcTask*(uint64(llc_tasks) + sizet(ti) * BuildPipeline.LlcTask.__sizeof__())
|
||||
BuildPipeline.free_llc_task(tfree)
|
||||
ti += 1
|
||||
stdlib.free(llc_tasks)
|
||||
@@ -1270,7 +1270,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
if string.strlen(src_fp_mi) > inc_dir_len_mi + 1:
|
||||
inc_rel_mi2: str = src_fp_mi + inc_dir_len_mi + 1
|
||||
inc_pkg_mi = GenApi.compute_package_from_relpath(mb, inc_rel_mi2)
|
||||
tr_mi: rawptr[HandlesTranslator.Translator] = BuildPipeline.TranslateFileGetTrans(mb, src_fp_mi, inc_sha1_mi, inc_pkg_mi)
|
||||
tr_mi: HandlesTranslator.Translator* = BuildPipeline.TranslateFileGetTrans(mb, src_fp_mi, inc_sha1_mi, inc_pkg_mi)
|
||||
if tr_mi is not None:
|
||||
# PBP IR buffer: same as PHASE_A_IR_SIZE (parser.vp's text.ll >1MB truncation root cause)
|
||||
PBP_IR_SIZE: sizet = 8388608
|
||||
@@ -1283,7 +1283,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
inc_stub_len: sizet = string.strlen(inc_stub_buf)
|
||||
inc_stub_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "stub.ll")
|
||||
if inc_stub_path is not None:
|
||||
isf: rawptr[fileio.File] = fileio.File(inc_stub_path, fileio.MODE.W)
|
||||
isf: fileio.File* = fileio.File(inc_stub_path, fileio.MODE.W)
|
||||
if not isf.closed:
|
||||
isf.write(inc_stub_buf, inc_stub_len)
|
||||
isf.close()
|
||||
@@ -1296,7 +1296,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
inc_text_len: sizet = string.strlen(inc_text_buf)
|
||||
inc_text_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "text.ll")
|
||||
if inc_text_path is not None:
|
||||
itf: rawptr[fileio.File] = fileio.File(inc_text_path, fileio.MODE.W)
|
||||
itf: fileio.File* = fileio.File(inc_text_path, fileio.MODE.W)
|
||||
if not itf.closed:
|
||||
itf.write(inc_text_buf, inc_text_len)
|
||||
itf.close()
|
||||
@@ -1311,7 +1311,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
inc_full_len: sizet = string.strlen(inc_full_buf)
|
||||
inc_full_path: str = StubMergerCollect._sliced_path(temp_dir, td_len_mi, inc_sha1_mi, "full.ll")
|
||||
if inc_full_path is not None:
|
||||
ifff: rawptr[fileio.File] = fileio.File(inc_full_path, fileio.MODE.W)
|
||||
ifff: fileio.File* = fileio.File(inc_full_path, fileio.MODE.W)
|
||||
if not ifff.closed:
|
||||
ifff.write(inc_full_buf, inc_full_len)
|
||||
ifff.close()
|
||||
@@ -1338,19 +1338,19 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
diag_stub_ex: int = 0
|
||||
diag_text_ex: int = 0
|
||||
if diag_full is not None:
|
||||
df_diag_f: rawptr[fileio.File] = fileio.File(diag_full, fileio.MODE.R)
|
||||
df_diag_f: fileio.File* = fileio.File(diag_full, fileio.MODE.R)
|
||||
if not df_diag_f.closed:
|
||||
diag_full_ex = 1
|
||||
df_diag_f.close()
|
||||
stdlib.free(diag_full)
|
||||
if diag_stub is not None:
|
||||
df_diag_s: rawptr[fileio.File] = fileio.File(diag_stub, fileio.MODE.R)
|
||||
df_diag_s: fileio.File* = fileio.File(diag_stub, fileio.MODE.R)
|
||||
if not df_diag_s.closed:
|
||||
diag_stub_ex = 1
|
||||
df_diag_s.close()
|
||||
stdlib.free(diag_stub)
|
||||
if diag_text is not None:
|
||||
df_diag_t: rawptr[fileio.File] = fileio.File(diag_text, fileio.MODE.R)
|
||||
df_diag_t: fileio.File* = fileio.File(diag_text, fileio.MODE.R)
|
||||
if not df_diag_t.closed:
|
||||
diag_text_ex = 1
|
||||
df_diag_t.close()
|
||||
@@ -1466,7 +1466,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
obj_path_pc: str = StubMergerCollect._sliced_path(includes_binary_dir, ibd_len_pc, rsha1_pc, "obj")
|
||||
if obj_path_pc is not None:
|
||||
# Check whether the .obj file exists
|
||||
cf_pc: rawptr[fileio.File] = fileio.File(obj_path_pc, fileio.MODE.R)
|
||||
cf_pc: fileio.File* = fileio.File(obj_path_pc, fileio.MODE.R)
|
||||
if not cf_pc.closed:
|
||||
cf_pc.close()
|
||||
# The .obj exists; append to final_obj_paths
|
||||
@@ -1514,7 +1514,7 @@ def RunMultiFileProject(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str, ou
|
||||
VLogger.info("phase2command 模式:跳过 --run(exe 尚未链接)", "phase2cmd")
|
||||
elif args.get_bool("run"):
|
||||
VLogger.info(f"执行: {exe_path}", "run")
|
||||
rp: rawptr[subprocess.CompletedProcess] = subprocess.run(exe_path, False, False)
|
||||
rp: subprocess.CompletedProcess* = subprocess.run(exe_path, False, False)
|
||||
if rp is not None: VLogger.info(f"退出码: {rp.returncode}", "run")
|
||||
else:
|
||||
VLogger.error("链接失败", "PhaseC")
|
||||
|
||||
@@ -14,7 +14,7 @@ import w32.fileio as fileio
|
||||
# Config - project configuration
|
||||
|
||||
# Global mbuddy pointer
|
||||
_mbuddy: rawptr[memhub.MemManager]
|
||||
_mbuddy: memhub.MemManager*
|
||||
|
||||
# Config values (loaded from project.vpj); default None/0: callers must guard with `is not None` (else garbage pointer crash)
|
||||
SourceDir: str = None
|
||||
@@ -56,7 +56,7 @@ def Load_project_config(path: str) -> int:
|
||||
if _mbuddy is None: return 1
|
||||
|
||||
# Open file
|
||||
f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(path, fileio.MODE.R)
|
||||
if f is None: return 1
|
||||
if f.closed: return 1
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ def compute_sha1(pool: memhub.MemBuddy*, content: str) -> str:
|
||||
if content is None or pool is None: return None
|
||||
|
||||
# ctx is stack-allocated (alloca); no heap allocation needed
|
||||
ctx: rawptr[hashlib.sha1] = hashlib.sha1()
|
||||
ctx: hashlib.sha1* = hashlib.sha1()
|
||||
if ctx is None: return None
|
||||
|
||||
# Compute the digest
|
||||
@@ -87,7 +87,7 @@ def JoinPath(a: str, b: str) -> str:
|
||||
def read_file_to_buf(path: str, buf_size: sizet) -> bytes:
|
||||
"""Read a whole file into a null-terminated malloc buffer, or None."""
|
||||
if path is None or buf_size <= 0: return None
|
||||
sf: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R)
|
||||
sf: fileio.File* = fileio.File(path, fileio.MODE.R)
|
||||
if sf.closed: return None
|
||||
buf: bytes = stdlib.malloc(buf_size)
|
||||
if buf is None:
|
||||
|
||||
@@ -241,7 +241,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
|
||||
# Compare: comparison expressions (MAX_SIZE > 512 / val == 1).
|
||||
# == != < <= > >= match TPC; unknown ops emit " ? ".
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp_t: rawptr[ast.Compare] = rawptr[ast.Compare](annot)
|
||||
cmp_t: ast.Compare* = ast.Compare*(annot)
|
||||
pos = _PyiTypeStr(buf, buf_size, pos, cmp_t.left, depth + 1)
|
||||
ops_ct: list[int]* = (list[int]*)(cmp_t.ops)
|
||||
cmps_ct: list[ast.AST*]* = cmp_t.comparators
|
||||
@@ -264,7 +264,7 @@ def _PyiTypeStr(buf: bytes, buf_size: sizet, pos: sizet, annot: ast.AST*, depth:
|
||||
# BoolOp: boolean ops (ENABLED and MAX_SIZE > 0 / A or B).
|
||||
# Matches TPC: and -> " and ", or -> " or ".
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bool_t: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](annot)
|
||||
bool_t: ast.BoolOp* = ast.BoolOp*(annot)
|
||||
vals_bt: list[ast.AST*]* = bool_t.values
|
||||
if vals_bt is not None:
|
||||
vn_bt: sizet = len(vals_bt)
|
||||
|
||||
@@ -809,7 +809,7 @@ def _ensure_vpi_ret_annot_loaded(src_sha1: str, temp_dir: str) -> int:
|
||||
vpi_path[td_len + 3] = '/'
|
||||
string.strcpy(vpi_path + td_len + 4, src_sha1)
|
||||
string.strcpy(vpi_path + td_len + 4 + sha1_len, ".vpi")
|
||||
f: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
stdlib.free(vpi_path)
|
||||
return 0
|
||||
@@ -879,7 +879,7 @@ def _ensure_vpi_param_annot_loaded(src_sha1: str, temp_dir: str) -> int:
|
||||
vpi_path[td_len + 3] = '/'
|
||||
string.strcpy(vpi_path + td_len + 4, src_sha1)
|
||||
string.strcpy(vpi_path + td_len + 4 + sha1_len, ".vpi")
|
||||
f: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
stdlib.free(vpi_path)
|
||||
return 0
|
||||
@@ -1450,7 +1450,7 @@ def _vpi_register_typedef_closure(pool: memhub.MemBuddy*, import_mods: str, temp
|
||||
vpi_path_r[td_len + 3] = '/'
|
||||
string.strcpy(vpi_path_r + td_len + 4, sha1_r)
|
||||
string.strcpy(vpi_path_r + td_len + 4 + 16, ".vpi")
|
||||
f_r: rawptr[fileio.File] = fileio.File(vpi_path_r, fileio.MODE.R)
|
||||
f_r: fileio.File* = fileio.File(vpi_path_r, fileio.MODE.R)
|
||||
if f_r.closed:
|
||||
stdlib.free(vpi_path_r)
|
||||
continue
|
||||
@@ -1570,7 +1570,7 @@ def _ParseVpiIntoModuleImpl(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, v
|
||||
if pool is None or mod is None or vpi_path is None or trans is None: return 0
|
||||
|
||||
# 1. read the .vpi file
|
||||
f: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if f.closed: return 0
|
||||
vpi_buf: bytes = stdlib.malloc(VPI_READ_BUF_SIZE)
|
||||
if vpi_buf is None:
|
||||
@@ -1934,7 +1934,7 @@ def _ensure_dep_vpi_injected(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
|
||||
if path_i is None: return 0
|
||||
if sub_len_i > 0: viperlib.snprintf(path_i, path_len_i, "%s/%s/%s.vpi", temp_dir, sub_i, dep_sha1)
|
||||
else: viperlib.snprintf(path_i, path_len_i, "%s/%s.vpi", temp_dir, dep_sha1)
|
||||
vf_i: rawptr[fileio.File] = fileio.File(path_i, fileio.MODE.R)
|
||||
vf_i: fileio.File* = fileio.File(path_i, fileio.MODE.R)
|
||||
if vf_i.closed:
|
||||
stdlib.free(path_i)
|
||||
return 0
|
||||
@@ -2058,7 +2058,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
|
||||
# REPL (ReplStubLayoutMode): if this class is already driven by the {sha1}.meta path, yield to it:
|
||||
# mark visible if registered, defer if the base is pending, skip if the layout is untrusted.
|
||||
if ReplStubLayoutMode != 0:
|
||||
se: rawptr[ReplStubClass] = _repl_stub_find(_repl_stub_key(pool, src_sha1, real_name))
|
||||
se: ReplStubClass* = _repl_stub_find(_repl_stub_key(pool, src_sha1, real_name))
|
||||
if se is not None and se.State != _REPL_SS_EMPTY:
|
||||
if se.State == _REPL_SS_PENDING: _repl_stub_try(se, mod)
|
||||
if se.State == _REPL_SS_OK: GenApi.add_visible_struct(pool, real_name)
|
||||
@@ -2117,11 +2117,11 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
|
||||
# the source module hit an empty struct and raise InternalCompilerError, so do not register.
|
||||
if field_count == 0: return 0
|
||||
# 4. build the ParamNode list
|
||||
first_node_c: rawptr[mlirlite.ParamNode] = None
|
||||
prev_node_c: rawptr[mlirlite.ParamNode] = None
|
||||
first_node_c: mlirlite.ParamNode* = None
|
||||
prev_node_c: mlirlite.ParamNode* = None
|
||||
for fi_c in range(field_count):
|
||||
fty_c: mlirlite.LLVMType* = (mlirlite.LLVMType*)(field_types_buf[fi_c])
|
||||
pnode_c: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
pnode_c: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if pnode_c is None: continue
|
||||
string.memset(pnode_c, 0, mlirlite.ParamNode.__sizeof__())
|
||||
pnode_c.Ty = fty_c
|
||||
@@ -2153,7 +2153,7 @@ def _inject_class_struct_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModul
|
||||
# fill_fwd) so register_struct's Ty-pointer dedup works and the StructTable does not overflow.
|
||||
if fill_fwd_c != 0 and existing_c is not None and existing_c.Ty is not None:
|
||||
fwd_name_c: str = mlirlite.get_struct_name(existing_c.Ty)
|
||||
fwd_fields_c: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty_c)
|
||||
fwd_fields_c: mlirlite.ParamNode* = mlirlite.get_struct_fields(struct_ty_c)
|
||||
fwd_fc_c: int = mlirlite.get_struct_fcount(struct_ty_c)
|
||||
*existing_c.Ty = mlirlite.LLVMType.Struct(fwd_fields_c, fwd_fc_c, fwd_name_c)
|
||||
struct_ty_c = existing_c.Ty
|
||||
@@ -2701,7 +2701,7 @@ def _repl_stub_path(sha1: str, ext: str) -> str:
|
||||
def _repl_stub_readtext(path: str) -> str:
|
||||
"""Read stub text (stdlib.malloc, caller frees); None if missing or over the size cap."""
|
||||
if path is None: return None
|
||||
f: rawptr[fileio.File] = fileio.File(path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(path, fileio.MODE.R)
|
||||
if f is None or f.closed: return None
|
||||
sz: sizet = f.size()
|
||||
if sz <= 0 or sz >= _REPL_STUB_TXT_CAP:
|
||||
@@ -2808,39 +2808,39 @@ def ReplStubLayoutBegin(temp_dir: str) -> int:
|
||||
return 0
|
||||
|
||||
|
||||
def _repl_stub_at(i: int) -> rawptr[ReplStubClass]:
|
||||
def _repl_stub_at(i: int) -> ReplStubClass*:
|
||||
"""Return the i-th class-table entry, or None."""
|
||||
if ReplStubTable is None or i < 0 or i >= ReplStubCount: return None
|
||||
addr: sizet = ReplStubTable[i]
|
||||
if addr == 0: return None
|
||||
return rawptr[ReplStubClass](uint64(addr))
|
||||
return ReplStubClass*(uint64(addr))
|
||||
|
||||
|
||||
def _repl_stub_find(key: str) -> rawptr[ReplStubClass]:
|
||||
def _repl_stub_find(key: str) -> ReplStubClass*:
|
||||
"""Look up a class-table entry by "<sha1>.<class name>"; None if not found."""
|
||||
if key is None: return None
|
||||
i: int
|
||||
for i in range(ReplStubCount):
|
||||
e: rawptr[ReplStubClass] = _repl_stub_at(i)
|
||||
e: ReplStubClass* = _repl_stub_at(i)
|
||||
if e is None or e.Key is None: continue
|
||||
if string.strcmp(e.Key, key) == 0: return e
|
||||
return None
|
||||
|
||||
|
||||
def _repl_stub_find_base(e: rawptr[ReplStubClass], bi: int) -> rawptr[ReplStubClass]:
|
||||
def _repl_stub_find_base(e: ReplStubClass*, bi: int) -> ReplStubClass*:
|
||||
"""Find a base-class entry: same-module SHA1 exact match first, then first bare-name match."""
|
||||
if e is None or e.Bases is None or bi < 0 or bi >= e.BaseCount: return None
|
||||
pname: str = rawptr(e.Bases[bi])
|
||||
if pname is None: return None
|
||||
i: int
|
||||
for i in range(ReplStubCount):
|
||||
pe: rawptr[ReplStubClass] = _repl_stub_at(i)
|
||||
pe: ReplStubClass* = _repl_stub_at(i)
|
||||
if pe is None or pe.ClassName is None: continue
|
||||
if string.strcmp(pe.ClassName, pname) != 0: continue
|
||||
if e.Sha1 is not None and pe.Sha1 is not None:
|
||||
if string.strcmp(pe.Sha1, e.Sha1) == 0: return pe
|
||||
for i in range(ReplStubCount):
|
||||
pe2: rawptr[ReplStubClass] = _repl_stub_at(i)
|
||||
pe2: ReplStubClass* = _repl_stub_at(i)
|
||||
if pe2 is None or pe2.ClassName is None: continue
|
||||
if string.strcmp(pe2.ClassName, pname) == 0: return pe2
|
||||
return None
|
||||
@@ -2883,7 +2883,7 @@ def _repl_stub_deco_flags(deco_list: list[ast.AST*]*) -> int:
|
||||
return flags
|
||||
|
||||
|
||||
def _repl_stub_is_virtual(e: rawptr[ReplStubClass], mi: int, first: rawptr[ReplStubClass]) -> int:
|
||||
def _repl_stub_is_virtual(e: ReplStubClass*, mi: int, first: ReplStubClass*) -> int:
|
||||
"""Return whether this class's mi-th method goes into the vtable."""
|
||||
if e is None or e.MethodFlags is None or mi < 0 or mi >= e.MethodCount: return 0
|
||||
mf: int = int(e.MethodFlags[mi])
|
||||
@@ -2896,7 +2896,7 @@ def _repl_stub_is_virtual(e: rawptr[ReplStubClass], mi: int, first: rawptr[ReplS
|
||||
return 0
|
||||
|
||||
|
||||
def _repl_stub_warn_refuse(e: rawptr[ReplStubClass], why: str, a: int, b: int) -> None:
|
||||
def _repl_stub_warn_refuse(e: ReplStubClass*, why: str, a: int, b: int) -> None:
|
||||
"""Warn on a criterion rejection: stub field count a differs from flattened+vtable inference b."""
|
||||
global ReplStubWarnLeft, ReplStubRefused
|
||||
ReplStubRefused += 1
|
||||
@@ -2905,7 +2905,7 @@ def _repl_stub_warn_refuse(e: rawptr[ReplStubClass], why: str, a: int, b: int) -
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可信 ⇒ 明确拒绝(原因=判据拒绝:%s;" "存根字段数=%d ≠ 展平字段数+虚表位=%d)。该类字段访问被明确拒绝" "(方法调用不受影响)\n", e.Sha1, e.ClassName, why, a, b)
|
||||
|
||||
|
||||
def _repl_stub_warn_nodata(e: rawptr[ReplStubClass], cause: int) -> None:
|
||||
def _repl_stub_warn_nodata(e: ReplStubClass*, cause: int) -> None:
|
||||
"""Warn on a missing-data refusal: no comparison was possible, so print the data sources instead."""
|
||||
global ReplStubWarnLeft, ReplStubRefused
|
||||
global ReplStubRefusedNoStub, ReplStubRefusedNoClass
|
||||
@@ -2928,7 +2928,7 @@ def _repl_stub_warn_nodata(e: rawptr[ReplStubClass], cause: int) -> None:
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『判据拒绝』:" "meta %s.meta 存在但其中没有键 %s 的 `STRUCT … FIELDS n / OPAQUE` 记录;" "meta 字段数=未找到 / 推断字段数=未计算 ⇒ 『未做比较』)。该类字段访问" "被拒绝(方法调用不受影响);若该类确实定义于该模块,说明 meta 陈旧/" "不完整,请重建\n", e.Sha1, e.ClassName, e.Sha1, e.Key)
|
||||
|
||||
|
||||
def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) -> None:
|
||||
def _repl_stub_warn_parent(e: ReplStubClass*, detail: str, pname: str) -> None:
|
||||
"""Warn on an upstream-no-data refusal: the base layout is unavailable or unregistered."""
|
||||
global ReplStubWarnLeft, ReplStubRefused, ReplStubRefusedParent
|
||||
ReplStubRefused += 1
|
||||
@@ -2938,7 +2938,7 @@ def _repl_stub_warn_parent(e: rawptr[ReplStubClass], detail: str, pname: str) ->
|
||||
stdio.printf("includes 类布局: %s.%s 布局不可用 ⇒ 明确拒绝(原因=『上游无数据』:%s," "父类=%s;父类字段与虚表位无法展平 ⇒ 本类未做字段数比较)。该类字段访问" "被拒绝(方法调用不受影响)\n", e.Sha1, e.ClassName, detail, pname)
|
||||
|
||||
|
||||
def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
def _repl_stub_try(e: ReplStubClass*, mod: mlirlite.LLVMModule*) -> int:
|
||||
"""Validate and register the full layout from the stub: 1=registered / 0=base pending / -1=refused."""
|
||||
global ReplStubOk, ReplStubVtOk, ReplStubWarnLeft
|
||||
if e is None: return -1
|
||||
@@ -2952,7 +2952,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
# (1) base classes must be ready (not ready -> defer; refused -> this layout is untrusted)
|
||||
bi: int
|
||||
for bi in range(e.BaseCount):
|
||||
pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi)
|
||||
pe: ReplStubClass* = _repl_stub_find_base(e, bi)
|
||||
if pe is None: return 0
|
||||
if pe.State == _REPL_SS_PENDING: return 0
|
||||
if pe.State == _REPL_SS_REFUSED:
|
||||
@@ -2965,7 +2965,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
e.State = _REPL_SS_REFUSED
|
||||
_repl_stub_warn_parent(e, "父类的字段类型未全部解析(其字段数不完整)", pe.ClassName)
|
||||
return -1
|
||||
first: rawptr[ReplStubClass] = None
|
||||
first: ReplStubClass* = None
|
||||
if e.BaseCount > 0: first = _repl_stub_find_base(e, 0)
|
||||
# (2) HasVTable (transcribed from ClassGenBase._detect_vtable_status)
|
||||
hv: int = 0
|
||||
@@ -2978,7 +2978,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
# (3) field flattening (base fields first + own fields, deduped by short name, first wins)
|
||||
cn: int = 0
|
||||
for bi in range(e.BaseCount):
|
||||
pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi)
|
||||
pe: ReplStubClass* = _repl_stub_find_base(e, bi)
|
||||
fi: int
|
||||
for fi in range(pe.Count):
|
||||
if cn >= _REPL_STUB_FIELD_MAX: break
|
||||
@@ -3009,7 +3009,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
vn: int = 0
|
||||
if hv == 1:
|
||||
for bi in range(e.BaseCount):
|
||||
pe: rawptr[ReplStubClass] = _repl_stub_find_base(e, bi)
|
||||
pe: ReplStubClass* = _repl_stub_find_base(e, bi)
|
||||
vi: int
|
||||
for vi in range(pe.VtCount):
|
||||
if vn >= _REPL_STUB_VT_MAX: break
|
||||
@@ -3041,10 +3041,10 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
total: int = cn + hv
|
||||
i8_ptr: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
|
||||
if i8_ptr is None: return 0
|
||||
first_node: rawptr[mlirlite.ParamNode] = None
|
||||
prev_node: rawptr[mlirlite.ParamNode] = None
|
||||
first_node: mlirlite.ParamNode* = None
|
||||
prev_node: mlirlite.ParamNode* = None
|
||||
if hv == 1:
|
||||
nd0: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
nd0: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if nd0 is None: return 0
|
||||
string.memset(nd0, 0, mlirlite.ParamNode.__sizeof__())
|
||||
nd0.Ty = i8_ptr
|
||||
@@ -3054,7 +3054,7 @@ def _repl_stub_try(e: rawptr[ReplStubClass], mod: mlirlite.LLVMModule*) -> int:
|
||||
for fi2 in range(cn):
|
||||
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(e.Types[fi2])
|
||||
if fty is None: continue
|
||||
nd: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
nd: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if nd is None: continue
|
||||
string.memset(nd, 0, mlirlite.ParamNode.__sizeof__())
|
||||
nd.Ty = fty
|
||||
@@ -3116,7 +3116,7 @@ def _repl_stub_add_class(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, cd:
|
||||
key: str = _repl_stub_key(pool, sha1, cd.name)
|
||||
if key is None: return 0
|
||||
if _repl_stub_find(key) is not None: return 0
|
||||
e: rawptr[ReplStubClass] = pool.alloc(ReplStubClass.__sizeof__())
|
||||
e: ReplStubClass* = pool.alloc(ReplStubClass.__sizeof__())
|
||||
if e is None: return 0
|
||||
string.memset(e, 0, ReplStubClass.__sizeof__())
|
||||
e.Key = key
|
||||
@@ -3287,21 +3287,21 @@ def ReplStubLayoutFinish() -> int:
|
||||
prog: int = 0
|
||||
i: int
|
||||
for i in range(ReplStubCount):
|
||||
e: rawptr[ReplStubClass] = _repl_stub_at(i)
|
||||
e: ReplStubClass* = _repl_stub_at(i)
|
||||
if e is None or e.State != _REPL_SS_PENDING: continue
|
||||
if _repl_stub_try(e, None) != 0: prog += 1
|
||||
if prog == 0: break
|
||||
# still not ready -> the base was never registered (missing stub/refused): explicitly refuse
|
||||
i2: int
|
||||
for i2 in range(ReplStubCount):
|
||||
e2: rawptr[ReplStubClass] = _repl_stub_at(i2)
|
||||
e2: ReplStubClass* = _repl_stub_at(i2)
|
||||
if e2 is None or e2.State != _REPL_SS_PENDING: continue
|
||||
e2.State = _REPL_SS_REFUSED
|
||||
# find the still-unready base class name (to identify the upstream)
|
||||
pbad: str = "(未定位)"
|
||||
bi2: int
|
||||
for bi2 in range(e2.BaseCount):
|
||||
peb: rawptr[ReplStubClass] = _repl_stub_find_base(e2, bi2)
|
||||
peb: ReplStubClass* = _repl_stub_find_base(e2, bi2)
|
||||
if peb is not None and peb.State == _REPL_SS_OK: continue
|
||||
if peb is not None and peb.ClassName is not None: pbad = peb.ClassName
|
||||
break
|
||||
|
||||
@@ -97,11 +97,11 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
# 1. App scan (skipped when app_deps is non-empty; use the caller-provided initial queue directly)
|
||||
if app_deps is None or app_deps[0] == '\0':
|
||||
VLogger.info("App 扫描:解析 source_dir 的 import 依赖", "Reachable")
|
||||
scan_res_r: rawptr[IncludesScanner.ScanResult] = IncludesScanner.scan_includes(mb, source_dir)
|
||||
scan_res_r: IncludesScanner.ScanResult* = IncludesScanner.scan_includes(mb, source_dir)
|
||||
if scan_res_r is not None:
|
||||
es_r: sizet = IncludesScanner.FileEntry.__sizeof__()
|
||||
for e_i_r in range(scan_res_r.Count):
|
||||
e_r: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(scan_res_r.Entries) + uint64(e_i_r) * es_r)
|
||||
e_r: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(uint64(scan_res_r.Entries) + uint64(e_i_r) * es_r)
|
||||
if e_r is None or e_r.Path is None: continue
|
||||
# File-level mark: reclaim the AST right after parsing (keeping all App ASTs resident would OOM)
|
||||
app_mark: sizet = mb.mark()
|
||||
@@ -116,7 +116,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
tokens: ast.Token* = ast.tokenize(lx)
|
||||
tree = ast.parse_tokens(mb, tokens)
|
||||
if tree is not None:
|
||||
tr: rawptr[HandlesTranslator.Translator] = HandlesTranslator.Translator()
|
||||
tr: HandlesTranslator.Translator* = HandlesTranslator.Translator()
|
||||
if tr is not None:
|
||||
tr._declare_only = 2
|
||||
# Source package name from RelPath (relative to source_dir, supports subdirs),
|
||||
@@ -397,7 +397,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
stdlib.free(wl_pos)
|
||||
mb.reset_to(scan_mark_r)
|
||||
return -1
|
||||
tr_r2: rawptr[HandlesTranslator.Translator] = HandlesTranslator.Translator()
|
||||
tr_r2: HandlesTranslator.Translator* = HandlesTranslator.Translator()
|
||||
if tr_r2 is None:
|
||||
stdlib.free(abs_path)
|
||||
stdlib.free(rel_path)
|
||||
@@ -448,7 +448,7 @@ def _BuildReachableSha1Set(mb: memhub.MemBuddy*, source_dir: str, temp_dir: str,
|
||||
td_len_w: sizet = string.strlen(temp_dir)
|
||||
deps_path_w: str = StubMergerCollect._sliced_path(temp_dir, td_len_w, sha1_r2, "deps.txt")
|
||||
if deps_path_w is not None:
|
||||
df_w: rawptr[fileio.File] = fileio.File(deps_path_w, fileio.MODE.W)
|
||||
df_w: fileio.File* = fileio.File(deps_path_w, fileio.MODE.W)
|
||||
if not df_w.closed:
|
||||
dl_w: sizet = string.strlen(deps_r2)
|
||||
if dl_w > 0: df_w.write(deps_r2, dl_w)
|
||||
@@ -500,7 +500,7 @@ def LoadFullIR(temp_dir: str, sha1: str, out_buf: bytes, out_size: sizet) -> siz
|
||||
td_len: sizet = string.strlen(temp_dir)
|
||||
p: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1, "full.ll")
|
||||
if p is None: return 0
|
||||
f: rawptr[fileio.File] = fileio.File(p, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(p, fileio.MODE.R)
|
||||
stdlib.free(p)
|
||||
out_buf[0] = '\0'
|
||||
if f.closed: return 0
|
||||
@@ -516,7 +516,7 @@ def LoadFullIR(temp_dir: str, sha1: str, out_buf: bytes, out_size: sizet) -> siz
|
||||
|
||||
# LoadDepVpiIntoModule - load dependency modules' .vpi files and inject their declares into the current module.
|
||||
# Call after Import handling and before translate_children; returns the number of successfully loaded .vpi files.
|
||||
def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, imported_modules: str, from_imports: str, temp_dir: str, trans: rawptr[HandlesTranslator.Translator]) -> int:
|
||||
def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, imported_modules: str, from_imports: str, temp_dir: str, trans: HandlesTranslator.Translator*) -> int:
|
||||
"""Load dependency modules' .vpi files and inject their declares into the current module."""
|
||||
if pool is None or mod is None or temp_dir is None or trans is None: return 0
|
||||
if imported_modules is None: return 0
|
||||
@@ -564,7 +564,7 @@ def LoadDepVpiIntoModule(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, impo
|
||||
vpi_path: str = StubMergerCollect._sliced_path(temp_dir, td_len, sha1_val, "vpi")
|
||||
if vpi_path is not None:
|
||||
# Check that the .vpi file exists (is readable)
|
||||
vf: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
vf: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if not vf.closed:
|
||||
vf.close()
|
||||
# Parse the .vpi via VpiReader and inject declares (the error context frame is kept by the caller HandlesTranslator)
|
||||
|
||||
@@ -87,7 +87,7 @@ def _is_in_sha1_set(sha1: str, sha1_set: str, set_count: int) -> int:
|
||||
return 0
|
||||
# WriteIncludesSha1Map - write includes scan results to _sha1_map.txt (human-readable debug output only).
|
||||
# Internally the in-memory store filled by PopulateSha1MapStore is used; returns 0 on success, non-zero on failure.
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, scan_result: rawptr[IncludesScanner.ScanResult], filter_set: str, filter_count: int) -> int:
|
||||
def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, scan_result: IncludesScanner.ScanResult*, filter_set: str, filter_count: int) -> int:
|
||||
"""Write the includes scan result to _sha1_map.txt (human-readable debug output)."""
|
||||
if temp_dir is None or scan_result is None: return 1
|
||||
|
||||
@@ -98,7 +98,7 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, scan_result: rawpt
|
||||
viperlib.snprintf(map_path, dir_len + 32, "%s/_sha1_map.txt", temp_dir)
|
||||
|
||||
# Open the file for writing (CREATE_ALWAYS)
|
||||
f: rawptr[fileio.File] = fileio.File(map_path, fileio.MODE.W)
|
||||
f: fileio.File* = fileio.File(map_path, fileio.MODE.W)
|
||||
if f.closed: return 1
|
||||
|
||||
# Write each include entry: {sha1}:includes/{rel_path}\n
|
||||
@@ -111,7 +111,7 @@ def WriteIncludesSha1Map(mb: memhub.MemBuddy*, temp_dir: str, scan_result: rawpt
|
||||
written_count: int = 0
|
||||
for i in range(scan_result.Count):
|
||||
ea_w: uint64 = uint64(scan_result.Entries) + i * entry_size_w
|
||||
ent_w: rawptr[IncludesScanner.FileEntry] = (rawptr[IncludesScanner.FileEntry])(ea_w)
|
||||
ent_w: IncludesScanner.FileEntry* = (IncludesScanner.FileEntry*)(ea_w)
|
||||
if ent_w is None or ent_w.Sha1 is None or ent_w.RelPath is None: continue
|
||||
# When a filter set is provided, write only its entries
|
||||
if filter_set is not None and filter_count > 0:
|
||||
|
||||
@@ -126,7 +126,7 @@ def NotePlainImport(pool: memhub.MemBuddy*, ctx: ImportCtx*, name: str, asname:
|
||||
|
||||
# PopulateSha1MapStore - build sha1 -> module_name map from ScanResult.Entries into the global store.
|
||||
# Memory via stdlib.malloc (global, not freed with mbuddy). Returns entry count, -1 on failure.
|
||||
def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int:
|
||||
def PopulateSha1MapStore(scan_result: IncludesScanner.ScanResult*) -> int:
|
||||
"""Populate the global SHA1 store from a scan result; returns the entry count or -1"""
|
||||
if scan_result is None: return -1
|
||||
# free the old store
|
||||
@@ -149,7 +149,7 @@ def PopulateSha1MapStore(scan_result: rawptr[IncludesScanner.ScanResult]) -> int
|
||||
for i in range(scan_result.Count):
|
||||
if StubMerger._sha1_store_count >= StubMerger.MAX_INCLUDES: VLogger.error("includes SHA1 存储超上限,终止", "StubMerger")
|
||||
ea: uint64 = uint64(scan_result.Entries) + i * entry_size_p
|
||||
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](ea)
|
||||
ent: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(ea)
|
||||
if ent is None or ent.Sha1 is None or ent.RelPath is None:
|
||||
p_bad += 1
|
||||
continue
|
||||
|
||||
@@ -191,7 +191,7 @@ novirtual class AssignGenMixin:
|
||||
if name is None: return None
|
||||
fp: str = self.Gen.TypeGenResolve.get_current_file()
|
||||
if fp is None: return None
|
||||
f: rawptr[fileio.File] = fileio.File(fp, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(fp, fileio.MODE.R)
|
||||
if f.closed: return None
|
||||
BUF_SZ: sizet = 1048576
|
||||
buf: bytes = stdlib.malloc(BUF_SZ)
|
||||
@@ -397,7 +397,7 @@ novirtual class AssignGenMixin:
|
||||
self.RecoverFound = 0
|
||||
fp: str = self.Gen.TypeGenResolve.get_current_file()
|
||||
if fp is None or name is None or out is None: return 0
|
||||
f: rawptr[fileio.File] = fileio.File(fp, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(fp, fileio.MODE.R)
|
||||
if f.closed: return 0
|
||||
BUF_SZ: sizet = 1048576
|
||||
buf: bytes = stdlib.malloc(BUF_SZ)
|
||||
@@ -869,7 +869,7 @@ novirtual class AssignGenMixin:
|
||||
"""Translate an augmented assignment statement (x += 1)."""
|
||||
if node is None: return 0
|
||||
|
||||
aug: rawptr[ast.AugAssign] = rawptr[ast.AugAssign](node)
|
||||
aug: ast.AugAssign* = ast.AugAssign*(node)
|
||||
if aug is None: return 0
|
||||
|
||||
target: ast.AST* = aug.target
|
||||
@@ -1375,7 +1375,7 @@ novirtual class AssignGenMixin:
|
||||
|
||||
# REPL session variable: annotated declaration at fragment entry goes to the session slot
|
||||
if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
rp_e: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_ensure_entry(trans, nm.id, aa)
|
||||
rp_e: GenTypes.ReplVarEntry* = self.Gen.VarGen.repl_ensure_entry(trans, nm.id, aa)
|
||||
if rp_e is not None:
|
||||
self.Gen.VarGen.repl_try_annassign(trans, nm.id, aa.annotation, aa.value, aa)
|
||||
return 0
|
||||
@@ -1823,7 +1823,7 @@ novirtual class AssignGenMixin:
|
||||
if asg_slot is not None and asg_slot.Ty is not None: asg_target_ty = asg_slot.Ty.Pointee
|
||||
elif trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
# REPL: a typed session variable also uses its slot type as the target type
|
||||
asg_re: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, asg_nm0.id)
|
||||
asg_re: GenTypes.ReplVarEntry* = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, asg_nm0.id)
|
||||
if asg_re is not None and asg_re.Kind != GenTypes.REPL_KIND_UNTYPED: asg_target_ty = self.Gen.VarGen.repl_slot_ty(pool, asg_re)
|
||||
rhs_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, asgn.value, None, 0, trans, asg_target_ty)
|
||||
if rhs_val is None:
|
||||
@@ -2159,7 +2159,7 @@ novirtual class AssignGenMixin:
|
||||
|
||||
# REPL session variable: a Name target at fragment entry defines/assigns the session slot
|
||||
if trans.ReplCtx is not None and self.Gen.VarGen.repl_in_frag_entry_scope(trans) != 0:
|
||||
rp_entry: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_ensure_entry(trans, nm.id, target)
|
||||
rp_entry: GenTypes.ReplVarEntry* = self.Gen.VarGen.repl_ensure_entry(trans, nm.id, target)
|
||||
if rp_entry is not None:
|
||||
self.Gen.VarGen.repl_try_assign(trans, nm.id, rhs_val, asgn.value, node)
|
||||
continue
|
||||
|
||||
+113
-114
@@ -87,7 +87,6 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
cnt: int = 0
|
||||
if ags.args is None: return 0
|
||||
bn: sizet = len(ags.args)
|
||||
i: sizet = 0
|
||||
for i in range(bn):
|
||||
a0: ast.AST* = ags.args.get(i)
|
||||
if a0 is None: continue
|
||||
@@ -137,13 +136,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if stmt is None or trans._coro_uses_sleep != 0: return
|
||||
sk: int = stmt.kind()
|
||||
if sk == ast.ASTKind.If:
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](stmt)
|
||||
ifn: ast.If* = ast.If*(stmt)
|
||||
self._scan_sleep_expr(trans, ifn.test)
|
||||
self._scan_sleep_stmts(trans, stmt.children)
|
||||
self._scan_sleep_stmts(trans, ifn.orelse)
|
||||
return
|
||||
if sk == ast.ASTKind.While:
|
||||
whn: rawptr[ast.While] = rawptr[ast.While](stmt)
|
||||
whn: ast.While* = ast.While*(stmt)
|
||||
self._scan_sleep_expr(trans, whn.test)
|
||||
self._scan_sleep_stmts(trans, stmt.children)
|
||||
self._scan_sleep_stmts(trans, whn.orelse)
|
||||
@@ -167,7 +166,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self._scan_sleep_stmts(trans, trn.finalbody)
|
||||
return
|
||||
if sk == ast.ASTKind.Return:
|
||||
rv: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rv: ast.Return* = ast.Return*(stmt)
|
||||
self._scan_sleep_expr(trans, rv.value)
|
||||
return
|
||||
if sk == ast.ASTKind.AnnAssign:
|
||||
@@ -179,7 +178,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self._scan_sleep_expr(trans, as_.value)
|
||||
return
|
||||
if sk == ast.ASTKind.Expr:
|
||||
e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
e: ast.Expr* = ast.Expr*(stmt)
|
||||
self._scan_sleep_expr(trans, e.value)
|
||||
return
|
||||
|
||||
@@ -215,7 +214,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self._scan_sleep_expr(trans, u.operand)
|
||||
return
|
||||
if k == ast.ASTKind.Compare:
|
||||
cm: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cm: ast.Compare* = ast.Compare*(node)
|
||||
self._scan_sleep_expr(trans, cm.left)
|
||||
if cm.comparators is not None:
|
||||
nb2: sizet = len(cm.comparators)
|
||||
@@ -223,14 +222,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
for j2 in range(nb2): self._scan_sleep_expr(trans, cm.comparators.get(j2))
|
||||
return
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo.values is not None:
|
||||
nb3: sizet = len(bo.values)
|
||||
j3: sizet = 0
|
||||
for j3 in range(nb3): self._scan_sleep_expr(trans, bo.values.get(j3))
|
||||
return
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
self._scan_sleep_expr(trans, ie.test)
|
||||
self._scan_sleep_expr(trans, ie.body)
|
||||
self._scan_sleep_expr(trans, ie.orelse)
|
||||
@@ -245,7 +244,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self._scan_sleep_expr(trans, sb.slice)
|
||||
return
|
||||
if k == ast.ASTKind.Await:
|
||||
aw: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw: ast.Await* = ast.Await*(node)
|
||||
self._scan_sleep_expr(trans, aw.value)
|
||||
return
|
||||
|
||||
@@ -260,13 +259,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if stmt is None: return
|
||||
sk: int = stmt.kind()
|
||||
if sk == ast.ASTKind.If:
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](stmt)
|
||||
ifn: ast.If* = ast.If*(stmt)
|
||||
if ifn.test is not None: self._scan_expr(trans, ifn.test)
|
||||
self._scan_stmts(trans, stmt.children)
|
||||
self._scan_stmts(trans, ifn.orelse)
|
||||
return
|
||||
if sk == ast.ASTKind.While:
|
||||
whn: rawptr[ast.While] = rawptr[ast.While](stmt)
|
||||
whn: ast.While* = ast.While*(stmt)
|
||||
if whn.test is not None: self._scan_expr(trans, whn.test)
|
||||
self._scan_stmts(trans, stmt.children)
|
||||
self._scan_stmts(trans, whn.orelse)
|
||||
@@ -308,11 +307,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self._scan_stmts(trans, tr2.finalbody)
|
||||
return
|
||||
if sk == ast.ASTKind.Raise:
|
||||
rz: rawptr[ast.Raise] = rawptr[ast.Raise](stmt)
|
||||
rz: ast.Raise* = ast.Raise*(stmt)
|
||||
if rz.exc is not None: self._scan_expr(trans, rz.exc)
|
||||
return
|
||||
if sk == ast.ASTKind.Return:
|
||||
rv: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rv: ast.Return* = ast.Return*(stmt)
|
||||
if rv.value is not None: self._scan_expr(trans, rv.value)
|
||||
return
|
||||
if sk == ast.ASTKind.Break or sk == ast.ASTKind.Continue: return
|
||||
@@ -337,7 +336,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if as_.value is not None: self._scan_expr(trans, as_.value)
|
||||
return
|
||||
if sk == ast.ASTKind.Expr:
|
||||
e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
e: ast.Expr* = ast.Expr*(stmt)
|
||||
if e.value is not None: self._scan_expr(trans, e.value)
|
||||
return
|
||||
# other statement types: fail fast at translation
|
||||
@@ -348,7 +347,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Await:
|
||||
# M3: await coro_sleep suspends via the wake slot, not __await_N (state id only)
|
||||
aw_s: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw_s: ast.Await* = ast.Await*(node)
|
||||
if self._expr_await_is_sleep(aw_s) != 0:
|
||||
trans._coro_await_count = trans._coro_await_count + 1
|
||||
return
|
||||
@@ -376,7 +375,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if u.operand is not None: self._scan_expr(trans, u.operand)
|
||||
return
|
||||
if k == ast.ASTKind.Compare:
|
||||
cm: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cm: ast.Compare* = ast.Compare*(node)
|
||||
if cm.left is not None: self._scan_expr(trans, cm.left)
|
||||
if cm.comparators is not None:
|
||||
nb2: sizet = len(cm.comparators)
|
||||
@@ -384,14 +383,14 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
for j2 in range(nb2): self._scan_expr(trans, cm.comparators.get(j2))
|
||||
return
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo.values is not None:
|
||||
nb3: sizet = len(bo.values)
|
||||
j3: sizet = 0
|
||||
for j3 in range(nb3): self._scan_expr(trans, bo.values.get(j3))
|
||||
return
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
self._scan_expr(trans, ie.test)
|
||||
self._scan_expr(trans, ie.body)
|
||||
self._scan_expr(trans, ie.orelse)
|
||||
@@ -430,12 +429,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if stmt is None: return 0
|
||||
sk2: int = stmt.kind()
|
||||
if sk2 == ast.ASTKind.If:
|
||||
ifn2: rawptr[ast.If] = rawptr[ast.If](stmt)
|
||||
ifn2: ast.If* = ast.If*(stmt)
|
||||
if ifn2.test is not None and self._find_expr_await(ifn2.test) is not None: return 1
|
||||
if self._stmts_deep_await(stmt.children) != 0: return 1
|
||||
return self._stmts_deep_await(ifn2.orelse)
|
||||
if sk2 == ast.ASTKind.While:
|
||||
whn2: rawptr[ast.While] = rawptr[ast.While](stmt)
|
||||
whn2: ast.While* = ast.While*(stmt)
|
||||
if whn2.test is not None and self._find_expr_await(whn2.test) is not None: return 1
|
||||
if self._stmts_deep_await(stmt.children) != 0: return 1
|
||||
return self._stmts_deep_await(whn2.orelse)
|
||||
@@ -514,12 +513,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return
|
||||
if sk == ast.ASTKind.If:
|
||||
self._collect_locals_stmts(trans, stmt.children)
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](stmt)
|
||||
ifn: ast.If* = ast.If*(stmt)
|
||||
self._collect_locals_stmts(trans, ifn.orelse)
|
||||
return
|
||||
if sk == ast.ASTKind.While:
|
||||
self._collect_locals_stmts(trans, stmt.children)
|
||||
whn: rawptr[ast.While] = rawptr[ast.While](stmt)
|
||||
whn: ast.While* = ast.While*(stmt)
|
||||
self._collect_locals_stmts(trans, whn.orelse)
|
||||
return
|
||||
if sk == ast.ASTKind.For:
|
||||
@@ -567,8 +566,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
trans._coro_local_base = 5 + nparams
|
||||
trans._coro_extra_base = trans._coro_local_base + nlocals
|
||||
total: int = 5 + nparams + nlocals + nextra
|
||||
head: rawptr[mlirlite.ParamNode] = None
|
||||
prev: rawptr[mlirlite.ParamNode] = None
|
||||
head: mlirlite.ParamNode* = None
|
||||
prev: mlirlite.ParamNode* = None
|
||||
fi: int = 0
|
||||
for fi in range(total):
|
||||
fty: mlirlite.LLVMType* = i32_ty
|
||||
@@ -577,7 +576,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
tidx: int = fi - trans._coro_extra_base
|
||||
if tidx < nextra and trans._coro_extra_types is not None:
|
||||
if trans._coro_extra_types[tidx] == 2: fty = i64_ty
|
||||
pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
pnode: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if pnode is None: continue
|
||||
string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__())
|
||||
pnode.Ty = fty
|
||||
@@ -622,7 +621,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
cur_count: int = trans._func_count
|
||||
if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, cur_count, cname_buf2, func, 1024, None, 0, 0, trans.Pool) == 0: trans._func_count = cur_count + 1
|
||||
|
||||
entry: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry is None: return 0
|
||||
builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
|
||||
if builder is None: return 0
|
||||
@@ -644,9 +643,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
zero64: mlirlite.Value* = mlirlite.const_int64(pool, 0)
|
||||
empty_cond: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, pool_head, zero64)
|
||||
if empty_cond is None: return 0
|
||||
hit_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.hit")
|
||||
miss_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.miss")
|
||||
join_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "pool.join")
|
||||
hit_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "pool.hit")
|
||||
miss_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "pool.miss")
|
||||
join_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "pool.join")
|
||||
if hit_bb is None or miss_bb is None or join_bb is None: return 0
|
||||
mlirlite.build_cond_br(builder, empty_cond, miss_bb, hit_bb)
|
||||
# hit: pop from pool (first 8 bytes are next)
|
||||
@@ -750,7 +749,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if self.Gen.CallGenLeafKit.add_func_to_table(funcs_ptr, cur_count, rname_buf, func, 1024, None, 0, 1, trans.Pool) == 0:
|
||||
trans._func_count = cur_count + 1
|
||||
|
||||
entry: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry is None: return 0
|
||||
builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
|
||||
if builder is None: return 0
|
||||
@@ -829,7 +828,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# state value + exit block
|
||||
state_val: mlirlite.Value* = mlirlite.build_load(builder, i32_ty, state_ptr)
|
||||
exit_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.exit")
|
||||
exit_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.exit")
|
||||
if exit_bb is None: return 0
|
||||
|
||||
# save resume context (shared by await suspension / resume blocks)
|
||||
@@ -857,17 +856,17 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
state_bbs: sizet* = pool.alloc(nseg * 8)
|
||||
if state_bbs is None: return 0
|
||||
trans._coro_state_bbs = state_bbs
|
||||
sw_head: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_tail: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_head: mlirlite.SwitchCase* = None
|
||||
sw_tail: mlirlite.SwitchCase* = None
|
||||
sw_count: int = 0
|
||||
bb_name: str = pool.alloc(32)
|
||||
si: int = 0
|
||||
for si in range(nseg):
|
||||
if bb_name is not None: viperlib.snprintf(bb_name, 32, "state%d", si)
|
||||
sbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_name)
|
||||
sbb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_name)
|
||||
if sbb is None: continue
|
||||
state_bbs[si] = sizet(sbb)
|
||||
sc: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, mlirlite.const_int32(pool, si), sbb)
|
||||
sc: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, mlirlite.const_int32(pool, si), sbb)
|
||||
if sc is not None:
|
||||
if sw_head is None:
|
||||
sw_head = sc
|
||||
@@ -882,7 +881,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# Set trans._cur_builder/_cur_func here; later position_at_end reuse the same builder object.
|
||||
trans._cur_func = func
|
||||
trans._cur_builder = builder
|
||||
seg_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](state_bbs[0])
|
||||
seg_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(state_bbs[0])
|
||||
mlirlite.position_at_end(builder, seg_bb)
|
||||
self._handle_segment(trans, builder, pool, mod, fd.children)
|
||||
# body fell through -> implicit return (ret=0 + done=1 + br exit)
|
||||
@@ -954,7 +953,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
else:
|
||||
# Expr(await ...): no target slot (discard return), clear stale slot
|
||||
trans._coro_await_slot = None
|
||||
aw_node: rawptr[ast.Await] = self._get_await_value(stmt)
|
||||
aw_node: ast.Await* = self._get_await_value(stmt)
|
||||
call_name: str = None
|
||||
if aw_node is not None: call_name = self._extract_await_call_name(aw_node)
|
||||
if call_name is not None and self.is_async_func(trans, call_name) != 0: self._emit_await(builder, pool, mod, trans, aw_node, call_name)
|
||||
@@ -975,7 +974,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# ============================================================
|
||||
# M2: coroutine If (awaits inside branches suspend/resume in place)
|
||||
def _handle_coro_if(self, trans: HT.Translator*, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, stmt: ast.AST*):
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](stmt)
|
||||
ifn: ast.If* = ast.If*(stmt)
|
||||
if ifn is None or ifn.test is None: return
|
||||
if self._find_expr_await(ifn.test) is not None:
|
||||
err_b: str = pool.alloc(256)
|
||||
@@ -987,11 +986,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if cond is None: return
|
||||
cond1: mlirlite.Value* = self._normalize_cond(builder, pool, mod, cond, trans)
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
then_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.then")
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.end")
|
||||
then_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.then")
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.end")
|
||||
has_else: int = 0
|
||||
if ifn.orelse is not None and len(ifn.orelse) > 0: has_else = 1
|
||||
else_bb: rawptr[mlirlite.BasicBlock] = None
|
||||
else_bb: mlirlite.BasicBlock* = None
|
||||
if has_else != 0: else_bb = mlirlite.create_block(pool, func, "coro.else")
|
||||
if cond1 is None or then_bb is None or merge_bb is None: return
|
||||
mlirlite.build_cond_br(builder, cond1, then_bb, else_bb if else_bb is not None else merge_bb)
|
||||
@@ -1009,7 +1008,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# ============================================================
|
||||
# M2: coroutine While (condition block + body; awaits in the body suspend/resume in place)
|
||||
def _handle_coro_while(self, trans: HT.Translator*, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, stmt: ast.AST*):
|
||||
whn: rawptr[ast.While] = rawptr[ast.While](stmt)
|
||||
whn: ast.While* = ast.While*(stmt)
|
||||
if whn is None: return
|
||||
if whn.test is not None and self._find_expr_await(whn.test) is not None:
|
||||
err_c: str = pool.alloc(256)
|
||||
@@ -1018,13 +1017,13 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self.Gen.TypeGenErr.fatal_error(stmt, err_c, "SyntaxError")
|
||||
return
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wcond")
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wbody")
|
||||
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wend")
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.wcond")
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.wbody")
|
||||
after_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.wend")
|
||||
if cond_bb is None or body_bb is None or after_bb is None: return
|
||||
# break/continue targets (M2, single level)
|
||||
prev_break: rawptr[mlirlite.BasicBlock] = trans._coro_break_bb
|
||||
prev_cont: rawptr[mlirlite.BasicBlock] = trans._coro_continue_bb
|
||||
prev_break: mlirlite.BasicBlock* = trans._coro_break_bb
|
||||
prev_cont: mlirlite.BasicBlock* = trans._coro_continue_bb
|
||||
trans._coro_break_bb = after_bb
|
||||
trans._coro_continue_bb = cond_bb
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
@@ -1049,7 +1048,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
"""Hoist all nested awaits in a statement to top-level temporaries in DFS order"""
|
||||
guard: int = 0
|
||||
while True:
|
||||
aw_node: rawptr[ast.Await] = self._extract_first_await(stmt)
|
||||
aw_node: ast.Await* = self._extract_first_await(stmt)
|
||||
if aw_node is None: break
|
||||
if guard >= HT.MAX_CORO_VARS: break
|
||||
guard = guard + 1
|
||||
@@ -1070,11 +1069,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# ============================================================
|
||||
# Nested-await detection / extraction / replacement (DFS order matches pre-scan)
|
||||
def _stmt_has_await(self, stmt: ast.AST*) -> int:
|
||||
aw: rawptr[ast.Await] = self._extract_first_await(stmt)
|
||||
aw: ast.Await* = self._extract_first_await(stmt)
|
||||
if aw is not None: return 1
|
||||
return 0
|
||||
|
||||
def _extract_first_await(self, stmt: ast.AST*) -> rawptr[ast.Await]:
|
||||
def _extract_first_await(self, stmt: ast.AST*) -> ast.Await*:
|
||||
"""Return the first Await node in a statement (DFS field order), or None"""
|
||||
if stmt is None: return None
|
||||
sk: int = stmt.kind()
|
||||
@@ -1085,63 +1084,63 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
as_: ast.Assign* = ast.Assign*(stmt)
|
||||
return self._find_expr_await(as_.value)
|
||||
if sk == ast.ASTKind.Expr:
|
||||
e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
e: ast.Expr* = ast.Expr*(stmt)
|
||||
return self._find_expr_await(e.value)
|
||||
if sk == ast.ASTKind.Return:
|
||||
rv: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rv: ast.Return* = ast.Return*(stmt)
|
||||
return self._find_expr_await(rv.value)
|
||||
return None
|
||||
|
||||
def _find_expr_await(self, node: ast.AST*) -> rawptr[ast.Await]:
|
||||
def _find_expr_await(self, node: ast.AST*) -> ast.Await*:
|
||||
"""DFS the expression tree for the first Await"""
|
||||
if node is None: return None
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.Await: return rawptr[ast.Await](node)
|
||||
if k == ast.ASTKind.Await: return ast.Await*(node)
|
||||
if k == ast.ASTKind.BinOp:
|
||||
b: ast.BinOp* = ast.BinOp*(node)
|
||||
r: rawptr[ast.Await] = self._find_expr_await(b.left)
|
||||
r: ast.Await* = self._find_expr_await(b.left)
|
||||
if r is not None: return r
|
||||
return self._find_expr_await(b.right)
|
||||
if k == ast.ASTKind.Call:
|
||||
cl: ast.Call* = ast.Call*(node)
|
||||
if cl.func is not None:
|
||||
r2: rawptr[ast.Await] = self._find_expr_await(cl.func)
|
||||
r2: ast.Await* = self._find_expr_await(cl.func)
|
||||
if r2 is not None: return r2
|
||||
if cl.args is not None:
|
||||
nb: sizet = len(cl.args)
|
||||
j: sizet = 0
|
||||
for j in range(nb):
|
||||
r3: rawptr[ast.Await] = self._find_expr_await(cl.args.get(j))
|
||||
r3: ast.Await* = self._find_expr_await(cl.args.get(j))
|
||||
if r3 is not None: return r3
|
||||
return None
|
||||
if k == ast.ASTKind.UnaryOp:
|
||||
u: ast.UnaryOp* = ast.UnaryOp*(node)
|
||||
return self._find_expr_await(u.operand)
|
||||
if k == ast.ASTKind.Compare:
|
||||
cm: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
r4: rawptr[ast.Await] = self._find_expr_await(cm.left)
|
||||
cm: ast.Compare* = ast.Compare*(node)
|
||||
r4: ast.Await* = self._find_expr_await(cm.left)
|
||||
if r4 is not None: return r4
|
||||
if cm.comparators is not None:
|
||||
nb2: sizet = len(cm.comparators)
|
||||
j2: sizet = 0
|
||||
for j2 in range(nb2):
|
||||
r5: rawptr[ast.Await] = self._find_expr_await(cm.comparators.get(j2))
|
||||
r5: ast.Await* = self._find_expr_await(cm.comparators.get(j2))
|
||||
if r5 is not None: return r5
|
||||
return None
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo.values is not None:
|
||||
nb3: sizet = len(bo.values)
|
||||
j3: sizet = 0
|
||||
for j3 in range(nb3):
|
||||
r6: rawptr[ast.Await] = self._find_expr_await(bo.values.get(j3))
|
||||
r6: ast.Await* = self._find_expr_await(bo.values.get(j3))
|
||||
if r6 is not None: return r6
|
||||
return None
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
r7: rawptr[ast.Await] = self._find_expr_await(ie.test)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
r7: ast.Await* = self._find_expr_await(ie.test)
|
||||
if r7 is not None: return r7
|
||||
r8: rawptr[ast.Await] = self._find_expr_await(ie.body)
|
||||
r8: ast.Await* = self._find_expr_await(ie.body)
|
||||
if r8 is not None: return r8
|
||||
return self._find_expr_await(ie.orelse)
|
||||
if k == ast.ASTKind.Attribute:
|
||||
@@ -1149,7 +1148,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return self._find_expr_await(at.value)
|
||||
if k == ast.ASTKind.Subscript:
|
||||
sb: ast.Subscript* = ast.Subscript*(node)
|
||||
r9: rawptr[ast.Await] = self._find_expr_await(sb.value)
|
||||
r9: ast.Await* = self._find_expr_await(sb.value)
|
||||
if r9 is not None: return r9
|
||||
return self._find_expr_await(sb.slice)
|
||||
return None
|
||||
@@ -1167,11 +1166,11 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if as_.value is not None: return self._replace_expr_await(pool, as_.value, temp_name)
|
||||
return 0
|
||||
if sk == ast.ASTKind.Expr:
|
||||
e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
e: ast.Expr* = ast.Expr*(stmt)
|
||||
if e.value is not None: return self._replace_expr_await(pool, e.value, temp_name)
|
||||
return 0
|
||||
if sk == ast.ASTKind.Return:
|
||||
rv: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rv: ast.Return* = ast.Return*(stmt)
|
||||
if rv.value is not None: return self._replace_expr_await(pool, rv.value, temp_name)
|
||||
return 0
|
||||
return 0
|
||||
@@ -1221,7 +1220,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.Compare:
|
||||
cm: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cm: ast.Compare* = ast.Compare*(node)
|
||||
r6: int = self._replace_expr_await(pool, cm.left, temp_name)
|
||||
if r6 == 1: return 1
|
||||
if r6 == 2:
|
||||
@@ -1238,7 +1237,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo.values is not None:
|
||||
nb3: sizet = len(bo.values)
|
||||
j3: sizet = 0
|
||||
@@ -1250,7 +1249,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return 1
|
||||
return 0
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
r9: int = self._replace_expr_await(pool, ie.test, temp_name)
|
||||
if r9 == 1: return 1
|
||||
if r9 == 2:
|
||||
@@ -1306,12 +1305,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
|
||||
# ============================================================
|
||||
# Resume-block lookup (state{N} from the pre-built array)
|
||||
def _get_state_bb(self, trans: HT.Translator*, state_no: int) -> rawptr[mlirlite.BasicBlock]:
|
||||
def _get_state_bb(self, trans: HT.Translator*, state_no: int) -> mlirlite.BasicBlock*:
|
||||
if trans is None or trans._coro_state_bbs is None: return None
|
||||
if state_no < 0 or state_no >= trans._coro_nseg: return None
|
||||
# state_bbs holds block pointers (sizet): index it, never take an element address,
|
||||
# or position lands on an invalid block and the IR chain corrupts (RenumberSSA crash).
|
||||
return rawptr[mlirlite.BasicBlock](trans._coro_state_bbs[state_no])
|
||||
return mlirlite.BasicBlock*(trans._coro_state_bbs[state_no])
|
||||
|
||||
def _lookup_coro_frame_by_trans(self, trans: HT.Translator*) -> mlirlite.LLVMType*:
|
||||
"""Return the frame type of the current coroutine, looked up from the registered frames"""
|
||||
@@ -1333,7 +1332,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
|
||||
if node is None or trans is None or trans._coro_wake_ptr is None: return mlirlite.const_int32(pool, 0)
|
||||
ms_val: mlirlite.Value* = mlirlite.const_int64(pool, 0)
|
||||
aw_s: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw_s: ast.Await* = ast.Await*(node)
|
||||
if aw_s.value is not None and aw_s.value.kind() == ast.ASTKind.Call:
|
||||
cl_s: ast.Call* = ast.Call*(aw_s.value)
|
||||
if cl_s.args is not None and len(cl_s.args) > 0:
|
||||
@@ -1354,7 +1353,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
st_v_s: mlirlite.Value* = mlirlite.const_int32(pool, new_state_s)
|
||||
mlirlite.build_store(builder, st_v_s, trans._coro_state_ptr)
|
||||
mlirlite.build_br(builder, trans._coro_exit_bb)
|
||||
resume_bb_s: rawptr[mlirlite.BasicBlock] = self._get_state_bb(trans, new_state_s)
|
||||
resume_bb_s: mlirlite.BasicBlock* = self._get_state_bb(trans, new_state_s)
|
||||
if resume_bb_s is not None: mlirlite.position_at_end(builder, resume_bb_s)
|
||||
return mlirlite.const_int32(pool, 0)
|
||||
|
||||
@@ -1364,7 +1363,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
"""Handle raise inside a coroutine: store the exception code/message, then jump to the handler or exit"""
|
||||
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
|
||||
exc_code: mlirlite.Value* = mlirlite.const_int32(pool, 1)
|
||||
rz: rawptr[ast.Raise] = rawptr[ast.Raise](stmt)
|
||||
rz: ast.Raise* = ast.Raise*(stmt)
|
||||
if rz is not None and rz.exc is not None:
|
||||
code: int = self._resolve_raise_code(pool, rz.exc)
|
||||
if code != 0:
|
||||
@@ -1378,7 +1377,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if trans._coro_exc_ptr is not None: mlirlite.build_store(builder, exc_code, trans._coro_exc_ptr)
|
||||
# jump to try/except or terminate
|
||||
if trans._coro_try_stack_count > 0:
|
||||
tbb_r: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](trans._coro_try_stack[trans._coro_try_stack_count - 1])
|
||||
tbb_r: mlirlite.BasicBlock* = mlirlite.BasicBlock*(trans._coro_try_stack[trans._coro_try_stack_count - 1])
|
||||
mlirlite.build_br(builder, tbb_r)
|
||||
else:
|
||||
done_r: mlirlite.Value* = mlirlite.const_int32(pool, 1)
|
||||
@@ -1426,8 +1425,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self.Gen.TypeGenErr.fatal_error(stmt, err_t, "SyntaxError")
|
||||
return
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
except_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_except")
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_merge")
|
||||
except_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.try_except")
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.try_merge")
|
||||
if except_bb is None or merge_bb is None: return
|
||||
# push the try stack
|
||||
if trans._coro_try_stack_count < HT.MAX_CORO_TRY:
|
||||
@@ -1456,12 +1455,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
viperlib.snprintf(exc_name, 64, "coro.except_%d", hi)
|
||||
check_bbs[hi + 1] = sizet(mlirlite.create_block(pool, func, chk_name))
|
||||
handler_bbs[hi] = sizet(mlirlite.create_block(pool, func, exc_name))
|
||||
unmatched_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.try_reraise")
|
||||
unmatched_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.try_reraise")
|
||||
codes_buf: int* = pool.alloc(256)
|
||||
# per handler: the check chain
|
||||
for hi in range(nhandlers):
|
||||
h_node: ast.AST* = tr.handlers.get(hi)
|
||||
check_bb: rawptr[mlirlite.BasicBlock] = (rawptr[mlirlite.BasicBlock])(check_bbs[hi])
|
||||
check_bb: mlirlite.BasicBlock* = (mlirlite.BasicBlock*)(check_bbs[hi])
|
||||
mlirlite.position_at_end(builder, check_bb)
|
||||
catch_all: int = 0
|
||||
ncodes: int = 0
|
||||
@@ -1472,10 +1471,10 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
ename: str = self._exception_type_name(pool, hd.type)
|
||||
if ename is not None and string.strcmp(ename, "Exception") == 0: catch_all = 1
|
||||
else: ncodes = self.Gen.ClassGenBase.collect_descendant_codes(ename, codes_buf, 64)
|
||||
next_check: rawptr[mlirlite.BasicBlock] = None
|
||||
if hi + 1 < nhandlers: next_check = rawptr[mlirlite.BasicBlock](check_bbs[hi + 1])
|
||||
next_check: mlirlite.BasicBlock* = None
|
||||
if hi + 1 < nhandlers: next_check = mlirlite.BasicBlock*(check_bbs[hi + 1])
|
||||
else: next_check = unmatched_bb
|
||||
handler_bb: rawptr[mlirlite.BasicBlock] = (rawptr[mlirlite.BasicBlock])(handler_bbs[hi])
|
||||
handler_bb: mlirlite.BasicBlock* = (mlirlite.BasicBlock*)(handler_bbs[hi])
|
||||
if catch_all != 0: mlirlite.build_br(builder, handler_bb)
|
||||
else:
|
||||
match_cond: mlirlite.Value* = None
|
||||
@@ -1494,7 +1493,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# ---- each except handler ----
|
||||
for hi in range(nhandlers):
|
||||
h_node2: ast.AST* = tr.handlers.get(hi)
|
||||
handler_bb2: rawptr[mlirlite.BasicBlock] = (rawptr[mlirlite.BasicBlock])(handler_bbs[hi])
|
||||
handler_bb2: mlirlite.BasicBlock* = (mlirlite.BasicBlock*)(handler_bbs[hi])
|
||||
mlirlite.position_at_end(builder, handler_bb2)
|
||||
if h_node2 is not None:
|
||||
hd2: ast.ExceptHandler* = ast.ExceptHandler*(h_node2)
|
||||
@@ -1536,9 +1535,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
self.Gen.TypeGenErr.fatal_error(stmt, err_f, "SyntaxError")
|
||||
return
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
fin_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin")
|
||||
fin_exc_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin_exc")
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fin_merge")
|
||||
fin_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fin")
|
||||
fin_exc_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fin_exc")
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fin_merge")
|
||||
if fin_bb is None or fin_exc_bb is None or merge_bb is None: return
|
||||
# push the try stack (exceptions jump to finally)
|
||||
if trans._coro_try_stack_count < HT.MAX_CORO_TRY:
|
||||
@@ -1595,12 +1594,12 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
mlirlite.build_store(builder, end_val, len_slot)
|
||||
# loop structure
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fcond")
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fbody")
|
||||
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.fend")
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fcond")
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fbody")
|
||||
after_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.fend")
|
||||
if cond_bb is None or body_bb is None or after_bb is None: return
|
||||
prev_break: rawptr[mlirlite.BasicBlock] = trans._coro_break_bb
|
||||
prev_cont: rawptr[mlirlite.BasicBlock] = trans._coro_continue_bb
|
||||
prev_break: mlirlite.BasicBlock* = trans._coro_break_bb
|
||||
prev_cont: mlirlite.BasicBlock* = trans._coro_continue_bb
|
||||
trans._coro_break_bb = after_bb
|
||||
trans._coro_continue_bb = cond_bb
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
@@ -1713,8 +1712,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
resume_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rn_buf, 0)
|
||||
if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: continue
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
loop_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "gather.loop")
|
||||
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "gather.after")
|
||||
loop_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "gather.loop")
|
||||
after_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "gather.after")
|
||||
if loop_bb is None or after_bb is None: continue
|
||||
mlirlite.build_br(builder, loop_bb)
|
||||
mlirlite.position_at_end(builder, loop_bb)
|
||||
@@ -1759,7 +1758,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
args_head: mlirlite.Value* = None
|
||||
args_tail: mlirlite.Value* = None
|
||||
args_count: int = 0
|
||||
aw_n: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw_n: ast.Await* = ast.Await*(node)
|
||||
if aw_n.value is not None and aw_n.value.kind() == ast.ASTKind.Call:
|
||||
cl_a: ast.Call* = ast.Call*(aw_n.value)
|
||||
if cl_a.args is not None:
|
||||
@@ -1789,8 +1788,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
child_exc_ptr: mlirlite.Value* = mlirlite.build_gep_struct(builder, child_frame_ty, i32_ty, child, 3)
|
||||
child_exc: mlirlite.Value* = mlirlite.build_load(builder, i32_ty, child_exc_ptr)
|
||||
zero32_x: mlirlite.Value* = mlirlite.const_int32(pool, 0)
|
||||
exc_ok_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, "coro.ok")
|
||||
exc_bad_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, "coro.exc")
|
||||
exc_ok_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, trans._cur_func, "coro.ok")
|
||||
exc_bad_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, trans._cur_func, "coro.exc")
|
||||
if exc_ok_bb is None or exc_bad_bb is None: return mlirlite.const_int32(pool, 0)
|
||||
exc_cond: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, child_exc, zero32_x)
|
||||
mlirlite.build_cond_br(builder, exc_cond, exc_ok_bb, exc_bad_bb)
|
||||
@@ -1802,7 +1801,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
child_msg: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_a, child_msg_ptr)
|
||||
mlirlite.build_store(builder, child_msg, trans._coro_msg_ptr)
|
||||
if trans._coro_try_stack_count > 0:
|
||||
tbb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](trans._coro_try_stack[trans._coro_try_stack_count - 1])
|
||||
tbb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(trans._coro_try_stack[trans._coro_try_stack_count - 1])
|
||||
mlirlite.build_br(builder, tbb)
|
||||
else:
|
||||
done_x: mlirlite.Value* = mlirlite.const_int32(pool, 1)
|
||||
@@ -1819,7 +1818,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
mlirlite.build_store(builder, st_v, trans._coro_state_ptr)
|
||||
mlirlite.build_br(builder, trans._coro_exit_bb)
|
||||
# resume block state{new_state}: position immediately (pre-built case; translation continues)
|
||||
resume_bb: rawptr[mlirlite.BasicBlock] = self._get_state_bb(trans, new_state)
|
||||
resume_bb: mlirlite.BasicBlock* = self._get_state_bb(trans, new_state)
|
||||
if resume_bb is not None: mlirlite.position_at_end(builder, resume_bb)
|
||||
return child_ret
|
||||
|
||||
@@ -1853,9 +1852,9 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
resume_mangled: str = self.Gen.FuncGenBase._mangle_func_name(trans, rn_buf, 0)
|
||||
if self.Gen.CallGenBase.find_func_in_module(mod, resume_mangled) is None: return mlirlite.const_int32(pool, 0)
|
||||
|
||||
loop_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.loop")
|
||||
check_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.check")
|
||||
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.after")
|
||||
loop_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.loop")
|
||||
check_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.check")
|
||||
after_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.after")
|
||||
if loop_bb is None or check_bb is None or after_bb is None: return mlirlite.const_int32(pool, 0)
|
||||
mlirlite.build_br(builder, loop_bb)
|
||||
mlirlite.position_at_end(builder, loop_bb)
|
||||
@@ -1876,8 +1875,8 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
not_wake_r: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_EQ, wake_v_r, mlirlite.const_int64(pool, 0))
|
||||
due_r: mlirlite.Value* = mlirlite.build_icmp(builder, mlirlite.ICMP_UGE, now_v_r, wake_v_r)
|
||||
cont_r: mlirlite.Value* = mlirlite.build_or(builder, not_wake_r, due_r)
|
||||
wsleep_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wsleep")
|
||||
wdue_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "coro.wdue")
|
||||
wsleep_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.wsleep")
|
||||
wdue_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "coro.wdue")
|
||||
mlirlite.build_cond_br(builder, cont_r, wdue_bb, wsleep_bb)
|
||||
mlirlite.position_at_end(builder, wsleep_bb)
|
||||
sleep_one: mlirlite.Value* = mlirlite.const_int32(pool, 1)
|
||||
@@ -1987,7 +1986,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
# Segment-translation helpers
|
||||
def _emit_coro_return(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, trans: HT.Translator*, stmt: ast.AST*) -> None:
|
||||
"""Special-case Return inside a coroutine: store the return slot, set done, and branch to exit"""
|
||||
rv_node: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rv_node: ast.Return* = ast.Return*(stmt)
|
||||
ret_val: mlirlite.Value* = None
|
||||
if rv_node is not None and rv_node.value is not None:
|
||||
if rv_node.value.kind() != ast.ASTKind.Await: ret_val = self.Gen.ExprGen.translate_value(builder, pool, mod, rv_node.value, None, 0, trans)
|
||||
@@ -1997,7 +1996,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
mlirlite.build_store(builder, done_one, trans._coro_done_ptr)
|
||||
mlirlite.build_br(builder, trans._coro_exit_bb)
|
||||
|
||||
def _expr_await_is_sleep(self, aw: rawptr[ast.Await]) -> int:
|
||||
def _expr_await_is_sleep(self, aw: ast.Await*) -> int:
|
||||
"""Return whether an Await target is coro_sleep (Name or coro.coro_sleep)"""
|
||||
if aw is None or aw.value is None: return 0
|
||||
if aw.value.kind() != ast.ASTKind.Call: return 0
|
||||
@@ -2023,7 +2022,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
if as_.value is not None and as_.value.kind() == ast.ASTKind.Await:
|
||||
if as_.targets is not None and len(as_.targets) == 1: return 1
|
||||
elif sk == ast.ASTKind.Expr:
|
||||
e: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
e: ast.Expr* = ast.Expr*(stmt)
|
||||
if e.value is not None and e.value.kind() == ast.ASTKind.Await: return 1
|
||||
return 0
|
||||
|
||||
@@ -2045,22 +2044,22 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
|
||||
return tn2.id
|
||||
return None
|
||||
|
||||
def _get_await_value(self, stmt: ast.AST*) -> rawptr[ast.Await]:
|
||||
def _get_await_value(self, stmt: ast.AST*) -> ast.Await*:
|
||||
"""Return the Await value node of a segment-tail statement, or None"""
|
||||
if stmt is None: return None
|
||||
sk: int = stmt.kind()
|
||||
if sk == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
|
||||
if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](aa.value)
|
||||
if aa.value is not None and aa.value.kind() == ast.ASTKind.Await: return ast.Await*(aa.value)
|
||||
elif sk == ast.ASTKind.Assign:
|
||||
as_: ast.Assign* = ast.Assign*(stmt)
|
||||
if as_.value is not None and as_.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](as_.value)
|
||||
if as_.value is not None and as_.value.kind() == ast.ASTKind.Await: return ast.Await*(as_.value)
|
||||
elif sk == ast.ASTKind.Expr:
|
||||
ex: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
if ex.value is not None and ex.value.kind() == ast.ASTKind.Await: return rawptr[ast.Await](ex.value)
|
||||
ex: ast.Expr* = ast.Expr*(stmt)
|
||||
if ex.value is not None and ex.value.kind() == ast.ASTKind.Await: return ast.Await*(ex.value)
|
||||
return None
|
||||
|
||||
def _extract_await_call_name(self, aw_node: rawptr[ast.Await]) -> str:
|
||||
def _extract_await_call_name(self, aw_node: ast.Await*) -> str:
|
||||
"""Extract the async function name or coro_sleep from an Await call, or None"""
|
||||
if aw_node is None or aw_node.value is None: return None
|
||||
if aw_node.value.kind() == ast.ASTKind.Call:
|
||||
|
||||
@@ -16,7 +16,7 @@ novirtual class BaseGenMixin:
|
||||
Module: mlirlite.LLVMModule* # Current LLVM module
|
||||
Builder: mlirlite.IRBuilder* # Current IRBuilder
|
||||
# Symbol / function tables
|
||||
SymTab: rawptr[GenTypes.SymbolTable]
|
||||
SymTab: GenTypes.SymbolTable*
|
||||
Funcs: GenTypes.FuncEntry*
|
||||
FuncCount: int
|
||||
# Import / module info
|
||||
|
||||
@@ -152,7 +152,7 @@ novirtual class CallGenBase:
|
||||
if buf is None:
|
||||
stdlib.free(vpi_path)
|
||||
return None
|
||||
vf: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
vf: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
stdlib.free(vpi_path)
|
||||
if vf.closed:
|
||||
stdlib.free(buf)
|
||||
@@ -1142,7 +1142,7 @@ novirtual class CallGenBase:
|
||||
stdlib.free(subdir_buf)
|
||||
|
||||
# read text.ll by actual size (a fixed buffer would truncate large modules); 64MB cap
|
||||
tf: rawptr[fileio.File] = fileio.File(path_buf, fileio.MODE.R)
|
||||
tf: fileio.File* = fileio.File(path_buf, fileio.MODE.R)
|
||||
if tf.closed:
|
||||
stdlib.free(path_buf)
|
||||
return None
|
||||
|
||||
@@ -679,11 +679,11 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
return ""
|
||||
|
||||
|
||||
def _asm_get_operand(self, base: rawptr[GenTypes.AsmOperand], idx: int) -> rawptr[GenTypes.AsmOperand]:
|
||||
def _asm_get_operand(self, base: GenTypes.AsmOperand*, idx: int) -> GenTypes.AsmOperand*:
|
||||
"""Return a pointer to operand idx in the operand array."""
|
||||
entry_size: sizet = GenTypes.AsmOperand.__sizeof__()
|
||||
entry_addr: uint64 = uint64(base) + idx * entry_size
|
||||
return rawptr[GenTypes.AsmOperand](entry_addr)
|
||||
return GenTypes.AsmOperand*(entry_addr)
|
||||
|
||||
|
||||
def _asm_is_c_call(self, node: ast.Call*) -> str:
|
||||
@@ -717,7 +717,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
return 0
|
||||
|
||||
|
||||
def _asm_add_operand(self, operands: rawptr[GenTypes.AsmOperand], count: int, val: mlirlite.Value*, constraint: str, is_output: int) -> int:
|
||||
def _asm_add_operand(self, operands: GenTypes.AsmOperand*, count: int, val: mlirlite.Value*, constraint: str, is_output: int) -> int:
|
||||
"""Append an operand, dedup by value and direction, and return the new count."""
|
||||
if count >= ASM_MAX_OPERANDS: return count
|
||||
# fail-fast: AsmInp/AsmOut operands must not carry SHA1-mangled symbols;
|
||||
@@ -726,9 +726,9 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
if self._asm_name_is_mangled(val.Name) != 0: self.Gen.TypeGenErr.fatal_error(None, f"__asm__ 操作数(AsmInp/AsmOut)不允许带 SHA1 混淆头的符号 '{val.Name}',请将对应函数/全局定义标记为 t.CExport(裸名)", "TypeError")
|
||||
if val is not None:
|
||||
for ei in range(count):
|
||||
eop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, ei)
|
||||
eop: GenTypes.AsmOperand* = self._asm_get_operand(operands, ei)
|
||||
if eop is not None and eop.Value == val and eop.IsOutput == is_output: return count
|
||||
op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, count)
|
||||
op: GenTypes.AsmOperand* = self._asm_get_operand(operands, count)
|
||||
op.Value = val
|
||||
# Default constraint: AsmInp(reg) with one arg has no descr, causing an
|
||||
# llc mismatch. Input defaults to "r", output to "=r".
|
||||
@@ -749,7 +749,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
|
||||
# Allocate the operand array
|
||||
operand_size: sizet = GenTypes.AsmOperand.__sizeof__()
|
||||
operands: rawptr[GenTypes.AsmOperand] = pool.alloc(operand_size * ASM_MAX_OPERANDS)
|
||||
operands: GenTypes.AsmOperand* = pool.alloc(operand_size * ASM_MAX_OPERANDS)
|
||||
if operands is None: return None
|
||||
string.memset(operands, 0, operand_size * ASM_MAX_OPERANDS)
|
||||
|
||||
@@ -788,7 +788,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
tk: int = tmpl_node.kind()
|
||||
|
||||
if tk == ast.ASTKind.JoinedStr:
|
||||
js: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](tmpl_node)
|
||||
js: ast.JoinedStr* = ast.JoinedStr*(tmpl_node)
|
||||
jvalues: list[ast.AST*]* = js.values
|
||||
if jvalues is not None:
|
||||
jvlen: sizet = len(jvalues)
|
||||
@@ -798,7 +798,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
pk: int = part.kind()
|
||||
|
||||
if pk == ast.ASTKind.FormattedValue:
|
||||
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part)
|
||||
fv: ast.FormattedValue* = ast.FormattedValue*(part)
|
||||
fexpr: ast.AST* = fv.value
|
||||
if fexpr is None or fexpr.kind() != ast.ASTKind.Call: continue
|
||||
fcall: ast.Call* = ast.Call*(fexpr)
|
||||
@@ -879,7 +879,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
if keywords is not None:
|
||||
kwlen: sizet = len(keywords)
|
||||
for ki in range(kwlen):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
|
||||
kw: ast.Keyword* = ast.Keyword*(keywords.get(ki))
|
||||
if kw is None or kw.arg is None or kw.value is None: continue
|
||||
kwk: int = kw.value.kind()
|
||||
|
||||
@@ -976,7 +976,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
input_count: int = 0
|
||||
first_output_idx: int = -1
|
||||
for oi2 in range(operand_count):
|
||||
op2: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi2)
|
||||
op2: GenTypes.AsmOperand* = self._asm_get_operand(operands, oi2)
|
||||
if op2.IsOutput != 0:
|
||||
if first_output_idx < 0: first_output_idx = oi2
|
||||
output_count += 1
|
||||
@@ -994,7 +994,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
out_pn_n: int = 0
|
||||
out_seq: int = 0
|
||||
for oi5 in range(operand_count):
|
||||
op5: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi5)
|
||||
op5: GenTypes.AsmOperand* = self._asm_get_operand(operands, oi5)
|
||||
if op5 is None or op5.IsOutput == 0: continue
|
||||
pty5: mlirlite.LLVMType* = None
|
||||
# Prefer the type cached in order at collection, then fall back to reading the slot
|
||||
@@ -1013,7 +1013,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
self.Gen.TypeGenErr.fatal_error(cl, "__asm__ 输出操作数类型缺失(变量 alloca 类型退化)", "TypeError")
|
||||
ret_ty = mlirlite.Int32(pool)
|
||||
else:
|
||||
out_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, first_output_idx)
|
||||
out_op: GenTypes.AsmOperand* = self._asm_get_operand(operands, first_output_idx)
|
||||
out_pt: mlirlite.LLVMType* = None
|
||||
# Prefer the element type cached at collection, then fall back to reading the slot
|
||||
if out_ret_ty_first is not None: out_pt = out_ret_ty_first
|
||||
@@ -1034,7 +1034,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
case mlirlite.LLVMType.Void():
|
||||
ret_re: mlirlite.LLVMType* = None
|
||||
for re_i in range(operand_count):
|
||||
re_op: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, re_i)
|
||||
re_op: GenTypes.AsmOperand* = self._asm_get_operand(operands, re_i)
|
||||
if re_op is None or re_op.IsOutput == 0: continue
|
||||
if re_op.Value is not None and re_op.Value.Ty is not None and re_op.Value.Ty.Pointee != 0:
|
||||
ret_re = re_op.Value.Ty.Pointee
|
||||
@@ -1053,13 +1053,13 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
new_idx: int = 0
|
||||
# Outputs first
|
||||
for oi3 in range(operand_count):
|
||||
op3: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi3)
|
||||
op3: GenTypes.AsmOperand* = self._asm_get_operand(operands, oi3)
|
||||
if op3.IsOutput != 0:
|
||||
new_order[new_idx] = oi3
|
||||
new_idx += 1
|
||||
# Then inputs
|
||||
for oi4 in range(operand_count):
|
||||
op4: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, oi4)
|
||||
op4: GenTypes.AsmOperand* = self._asm_get_operand(operands, oi4)
|
||||
if op4.IsOutput == 0:
|
||||
new_order[new_idx] = oi4
|
||||
new_idx += 1
|
||||
@@ -1071,7 +1071,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
if tmpl_node is not None:
|
||||
tk2: int = tmpl_node.kind()
|
||||
if tk2 == ast.ASTKind.JoinedStr:
|
||||
js2: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](tmpl_node)
|
||||
js2: ast.JoinedStr* = ast.JoinedStr*(tmpl_node)
|
||||
jvalues2: list[ast.AST*]* = js2.values
|
||||
if jvalues2 is not None:
|
||||
jvlen2: sizet = len(jvalues2)
|
||||
@@ -1104,7 +1104,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
first_const: int = 1
|
||||
for ci2 in range(operand_count):
|
||||
orig_i: int = new_order[ci2]
|
||||
cop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_i)
|
||||
cop: GenTypes.AsmOperand* = self._asm_get_operand(operands, orig_i)
|
||||
cons_val: str = cop.Constraint
|
||||
if cons_val is None: cons_val = "r"
|
||||
|
||||
@@ -1138,7 +1138,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
first_arg: int = 1
|
||||
for ai3 in range(operand_count):
|
||||
orig_i2: int = new_order[ai3]
|
||||
aop: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_i2)
|
||||
aop: GenTypes.AsmOperand* = self._asm_get_operand(operands, orig_i2)
|
||||
if aop.IsOutput != 0: continue
|
||||
aval: mlirlite.Value* = aop.Value
|
||||
if aval is None or aval.Ty is None or aval.Name is None: continue
|
||||
@@ -1199,7 +1199,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
out_emit_idx: int = 0
|
||||
for oi_out in range(operand_count):
|
||||
orig_o: int = new_order[oi_out]
|
||||
oo: rawptr[GenTypes.AsmOperand] = self._asm_get_operand(operands, orig_o)
|
||||
oo: GenTypes.AsmOperand* = self._asm_get_operand(operands, orig_o)
|
||||
if oo is None or oo.IsOutput == 0: continue
|
||||
if output_count > 1:
|
||||
# Multi-output: extractvalue index out_emit_idx, then store
|
||||
@@ -1249,7 +1249,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
tk: int = first_arg.kind()
|
||||
|
||||
if tk == ast.ASTKind.JoinedStr:
|
||||
js: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](first_arg)
|
||||
js: ast.JoinedStr* = ast.JoinedStr*(first_arg)
|
||||
jvalues: list[ast.AST*]* = js.values
|
||||
if jvalues is not None:
|
||||
jvlen: sizet = len(jvalues)
|
||||
@@ -1264,7 +1264,7 @@ novirtual class CallGenCBuiltin(CallGenBase.CallGenBase):
|
||||
if cn.str_val is not None: self._asm_append_cstr(text, LLVMIR_TEMPLATE_BUF, cn.str_val)
|
||||
|
||||
elif pk == ast.ASTKind.FormattedValue:
|
||||
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part)
|
||||
fv: ast.FormattedValue* = ast.FormattedValue*(part)
|
||||
fexpr: ast.AST* = fv.value
|
||||
if fexpr is None: continue
|
||||
# Detect c.LInp / c.LOut
|
||||
|
||||
@@ -976,7 +976,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
if pname_k is not None:
|
||||
ki_k: int
|
||||
for ki_k in range(kwc):
|
||||
kw_k: rawptr[ast.Keyword] = rawptr[ast.Keyword](kw_calls.get(ki_k))
|
||||
kw_k: ast.Keyword* = ast.Keyword*(kw_calls.get(ki_k))
|
||||
if kw_k is None or kw_k.arg is None or kw_k.value is None: continue
|
||||
if self._kwarg_name_matches(kw_k.arg, pname_k) == 1:
|
||||
arg_node_k = kw_k.value
|
||||
@@ -1599,7 +1599,7 @@ novirtual class CallGenCall(CallGenBase.CallGenBase):
|
||||
# packed (@c.Attribute(t.attr.packed)) structs have no field padding:
|
||||
# offset = sum of preceding field sizes (LLVM packed struct layout).
|
||||
is_packed_fb: int = entry.IsPacked
|
||||
cur_fb: rawptr[mlirlite.ParamNode] = fields
|
||||
cur_fb: mlirlite.ParamNode* = fields
|
||||
i_fb: int = 0
|
||||
while cur_fb is not None and i_fb < field_index:
|
||||
if cur_fb.Ty is not None:
|
||||
|
||||
@@ -387,7 +387,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
new_arg_count += 1
|
||||
# keyword args are also passed to __new__
|
||||
for nki in range(kw_count):
|
||||
nkw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(nki))
|
||||
nkw: ast.Keyword* = ast.Keyword*(keywords.get(nki))
|
||||
if nkw is None or nkw.value is None: continue
|
||||
nkw_av: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, nkw.value, None, 0, trans)
|
||||
if nkw_av is not None:
|
||||
@@ -420,7 +420,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
init_arg_count += 1
|
||||
# keyword args (appended at the end, in order of appearance)
|
||||
for ki_init in range(kw_count):
|
||||
kw_init: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki_init))
|
||||
kw_init: ast.Keyword* = ast.Keyword*(keywords.get(ki_init))
|
||||
if kw_init is None or kw_init.value is None: continue
|
||||
kw_av_init: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, kw_init.value, None, 0, trans)
|
||||
if kw_av_init is not None:
|
||||
@@ -459,7 +459,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
kw_sha1: str = None
|
||||
if kw_entry is not None: kw_sha1 = kw_entry.ModuleSha1
|
||||
for ki in range(kw_count):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
|
||||
kw: ast.Keyword* = ast.Keyword*(keywords.get(ki))
|
||||
if kw is None or kw.arg is None or kw.value is None: continue
|
||||
fe: GenTypes.FieldEntry* = self.Gen.StructGen.lookup_field_by_class(class_name, kw.arg, kw_sha1, kw, trans._from_imports)
|
||||
if fe is None:
|
||||
@@ -731,7 +731,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if ag_kw.arg is None: return -1
|
||||
ki_kw: sizet
|
||||
for ki_kw in range(kw_count):
|
||||
kw_tp: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki_kw))
|
||||
kw_tp: ast.Keyword* = ast.Keyword*(keywords.get(ki_kw))
|
||||
if kw_tp is None or kw_tp.arg is None or kw_tp.value is None: continue
|
||||
if string.strcmp(kw_tp.arg, ag_kw.arg) == 0: return int(ki_kw)
|
||||
return -1
|
||||
@@ -818,7 +818,7 @@ novirtual class CallGenCtor(CallGenBase.CallGenBase):
|
||||
if kw_count > 0:
|
||||
ki_slot: sizet
|
||||
for ki_slot in range(kw_count):
|
||||
kw_slot: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki_slot))
|
||||
kw_slot: ast.Keyword* = ast.Keyword*(keywords.get(ki_slot))
|
||||
if kw_slot is None or kw_slot.arg is None or kw_slot.value is None: continue
|
||||
slot_kw: int = self._ctor_init_arg_slot_by_name(tmpl_name, kw_slot.arg)
|
||||
if slot_kw >= 32:
|
||||
|
||||
@@ -103,7 +103,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
# Keyword arg: locate by template param name (positional wins; -1 if slot taken)
|
||||
kwi: int = self._generic_func_kw_arg_index(template_fd, slot, cl.keywords, int(can))
|
||||
if kwi >= 0:
|
||||
kwn: rawptr[ast.Keyword] = rawptr[ast.Keyword](cl.keywords.get(sizet(kwi)))
|
||||
kwn: ast.Keyword* = ast.Keyword*(cl.keywords.get(sizet(kwi)))
|
||||
if kwn is not None and kwn.value is not None: ta = self.Gen.ClassGenGeneric._infer_generic_func_type_arg(pool, kwn.value, tpl_name, trans)
|
||||
if ta is None and ctx_args is not None and sizet(tpi) < len(ctx_args): ta = ctx_args.get(tpi)
|
||||
if ta is None:
|
||||
@@ -143,7 +143,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
kn: sizet = len(keywords)
|
||||
ki: sizet
|
||||
for ki in range(kn):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
|
||||
kw: ast.Keyword* = ast.Keyword*(keywords.get(ki))
|
||||
if kw is None or kw.arg is None: continue
|
||||
if string.strcmp(kw.arg, ag.arg) == 0: return int(ki)
|
||||
return -1
|
||||
@@ -1046,7 +1046,7 @@ novirtual class CallGenDispatch(CallGenBase.CallGenBase):
|
||||
if rp_at.value.kind() == ast.ASTKind.Name:
|
||||
rp_nm: ast.Name* = ast.Name*(rp_at.value)
|
||||
if rp_nm.id is not None:
|
||||
rp_ent: rawptr[GenTypes.ReplVarEntry] = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, rp_nm.id)
|
||||
rp_ent: GenTypes.ReplVarEntry* = self.Gen.VarGen.repl_find_entry(trans.ReplCtx, rp_nm.id)
|
||||
if rp_ent is not None:
|
||||
rp_val: mlirlite.Value* = None
|
||||
if rp_ent.TyTag == GenTypes.REPL_TY_STRUCT:
|
||||
|
||||
@@ -174,9 +174,9 @@ novirtual class CallGenFd(CallGenBase.CallGenBase):
|
||||
fd_bb_buf2: str = pool.alloc(64)
|
||||
if fd_bb_buf2 is None: continue
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.skip.%d", vtc2)
|
||||
fd_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
|
||||
fd_skip_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
|
||||
viperlib.snprintf(fd_bb_buf2, 64, "fd.inject.%d", vtc2)
|
||||
fd_inject_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
|
||||
fd_inject_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, cur_func, fd_bb_buf2)
|
||||
if fd_skip_bb is None or fd_inject_bb is None: continue
|
||||
mlirlite.build_cond_br(builder, fd_cmp, fd_inject_bb, fd_skip_bb)
|
||||
# inject block: bitcast + GEP + store, then jump back to skip
|
||||
|
||||
@@ -161,9 +161,9 @@ novirtual class CallGenLeafKit(CallGenCBuiltin.CallGenCBuiltin):
|
||||
bb_buf_g: str = pool.alloc(64)
|
||||
if bb_buf_g is None: return result
|
||||
viperlib.snprintf(bb_buf_g, 64, "eh.err.%d", lc_g)
|
||||
err_bb_g: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
|
||||
err_bb_g: mlirlite.BasicBlock* = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
|
||||
viperlib.snprintf(bb_buf_g, 64, "eh.ok.%d", lc_g)
|
||||
ok_bb_g: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
|
||||
ok_bb_g: mlirlite.BasicBlock* = mlirlite.create_block(pool, cur_func_g, bb_buf_g)
|
||||
if err_bb_g is None or ok_bb_g is None: return result
|
||||
mlirlite.build_cond_br(builder, is_err_g, err_bb_g, ok_bb_g)
|
||||
# err block
|
||||
|
||||
@@ -536,7 +536,7 @@ novirtual class CallGenLib(CallGenBase.CallGenBase):
|
||||
param_name: str = mlirlite.param_get_name(cur_param)
|
||||
if param_name is not None:
|
||||
for ki in range(kw_count):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(ki))
|
||||
kw: ast.Keyword* = ast.Keyword*(keywords.get(ki))
|
||||
if kw is None or kw.arg is None or kw.value is None: continue
|
||||
if self.Gen.CallGenCall._kwarg_name_matches(kw.arg, param_name) == 1:
|
||||
arg_val = self.Gen.ExprGen.translate_value(builder, pool, mod, kw.value, None, 0, trans, param_ty)
|
||||
|
||||
@@ -333,7 +333,7 @@ novirtual class CallGenMixin(CallGenBase.CallGenBase):
|
||||
# and infer from it (order-independent; returns -1 if the slot is positional).
|
||||
kwi_bare: int = self.Gen.CallGenCtor._find_ctor_type_param_kw_arg_index(func_name, tp_bare.get(tpi_bare), keywords, kw_count, int(can))
|
||||
if kwi_bare >= 0:
|
||||
kwn_bare: rawptr[ast.Keyword] = rawptr[ast.Keyword](keywords.get(sizet(kwi_bare)))
|
||||
kwn_bare: ast.Keyword* = ast.Keyword*(keywords.get(sizet(kwi_bare)))
|
||||
if kwn_bare is not None and kwn_bare.value is not None: ta_bare = self.Gen.CallGenCtor._infer_generic_ctor_type_arg(pool, kwn_bare.value, func_name, trans)
|
||||
if ta_bare is None and ctx_args_bare is not None:
|
||||
# [C1] The annotation already gives type args (e.g. s: Stack[int] = Stack()): specialize with them.
|
||||
|
||||
@@ -59,9 +59,9 @@ novirtual class CallGenVt(CallGenBase.CallGenBase):
|
||||
vt_bb_buf3: str = pool.alloc(64)
|
||||
if vt_bb_buf3 is None: return 0
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.copy.%d", vtc3)
|
||||
vt_copy_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
|
||||
vt_copy_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
|
||||
viperlib.snprintf(vt_bb_buf3, 64, "vt.skip.%d", vtc3)
|
||||
vt_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
|
||||
vt_skip_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, trans._cur_func, vt_bb_buf3)
|
||||
if vt_copy_bb is None or vt_skip_bb is None: return 0
|
||||
mlirlite.build_cond_br(builder, cmp_vt, vt_copy_bb, vt_skip_bb)
|
||||
# copy block: create internal copy global (zeroinit) + memcpy + repoint object at it.
|
||||
|
||||
@@ -354,14 +354,14 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
|
||||
|
||||
# 2. Create the LLVM StructType
|
||||
# Build the ParamNode chain
|
||||
first_node: rawptr[mlirlite.ParamNode] = None
|
||||
prev_node: rawptr[mlirlite.ParamNode] = None
|
||||
first_node: mlirlite.ParamNode* = None
|
||||
prev_node: mlirlite.ParamNode* = None
|
||||
total_field_count: int = field_count
|
||||
|
||||
# With a vtable, add an i8* vtable pointer as the first field
|
||||
if has_vtable == 1:
|
||||
i8_ptr_ty: mlirlite.LLVMType* = mlirlite.Ptr(pool, mlirlite.Int8(pool))
|
||||
vtable_node: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
vtable_node: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if vtable_node is None:
|
||||
VLogger.error(f"failed to alloc vtable node for {class_name}", "CLASS")
|
||||
return 0
|
||||
@@ -377,7 +377,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
|
||||
fty: mlirlite.LLVMType* = (mlirlite.LLVMType*)(fty_addr)
|
||||
|
||||
# Create the ParamNode
|
||||
pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
pnode: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if pnode is None: continue
|
||||
string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__())
|
||||
pnode.Ty = fty
|
||||
@@ -419,7 +419,7 @@ novirtual class ClassGenDef(ClassGenBase.ClassGenBase):
|
||||
# field body into the same object before module_add_named_type to avoid re-registration.
|
||||
if fill_fwd != 0 and existing is not None and existing.Ty is not None:
|
||||
_fwd_name: str = mlirlite.get_struct_name(existing.Ty)
|
||||
_fwd_fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty)
|
||||
_fwd_fields: mlirlite.ParamNode* = mlirlite.get_struct_fields(struct_ty)
|
||||
_fwd_fc: int = mlirlite.get_struct_fcount(struct_ty)
|
||||
*existing.Ty = mlirlite.LLVMType.Struct(_fwd_fields, _fwd_fc, _fwd_name)
|
||||
struct_ty = existing.Ty
|
||||
|
||||
@@ -180,7 +180,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
lst: ast.List* = ast.List*(node)
|
||||
return self._enum_elts_visible_names(lst.elts)
|
||||
if k == ast.ASTKind.Starred:
|
||||
st: rawptr[ast.Starred] = rawptr[ast.Starred](node)
|
||||
st: ast.Starred* = ast.Starred*(node)
|
||||
return self._enum_target_visible_names(st.value)
|
||||
return 0
|
||||
def _enum_body_visible_names(self, children: list[ast.AST*]*) -> int:
|
||||
@@ -199,7 +199,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
|
||||
n += self._enum_target_visible_names(aa.target)
|
||||
elif sk == ast.ASTKind.Expr:
|
||||
ex: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
ex: ast.Expr* = ast.Expr*(stmt)
|
||||
n += self._enum_target_visible_names(ex.value)
|
||||
return n
|
||||
def _enum_first_unregistered_node(self, children: list[ast.AST*]*) -> ast.AST*:
|
||||
@@ -210,7 +210,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
if stmt is None: continue
|
||||
sk: int = stmt.kind()
|
||||
if sk == ast.ASTKind.Expr:
|
||||
ex: rawptr[ast.Expr] = rawptr[ast.Expr](stmt)
|
||||
ex: ast.Expr* = ast.Expr*(stmt)
|
||||
if self._enum_target_visible_names(ex.value) > 0: return stmt
|
||||
elif sk == ast.ASTKind.AnnAssign:
|
||||
aa: ast.AnnAssign* = ast.AnnAssign*(stmt)
|
||||
@@ -357,7 +357,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
base_ty = mty
|
||||
|
||||
# Register the enum
|
||||
entry: rawptr[GenTypes.EnumEntry] = self.Gen.StmtGenDecl.register_enum(pool, class_name, base_ty)
|
||||
entry: GenTypes.EnumEntry* = self.Gen.StmtGenDecl.register_enum(pool, class_name, base_ty)
|
||||
if entry is None:
|
||||
VLogger.error("failed to register {class_name}", "ENUM")
|
||||
return 0
|
||||
@@ -394,7 +394,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
is_packed: int = self.Gen.StructGen.struct_type_is_packed(ty)
|
||||
total: int = 0
|
||||
max_align: int = 1
|
||||
cur: rawptr[mlirlite.ParamNode] = fields
|
||||
cur: mlirlite.ParamNode* = fields
|
||||
i: int = 0
|
||||
while cur is not None and i < fcount:
|
||||
if cur.Ty is not None:
|
||||
@@ -437,7 +437,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
if self.Gen.StructGen.struct_type_is_packed(ty) != 0: return 1
|
||||
# A struct's alignment is the largest field alignment
|
||||
max_align: int = 1
|
||||
cur: rawptr[mlirlite.ParamNode] = fields
|
||||
cur: mlirlite.ParamNode* = fields
|
||||
i: int = 0
|
||||
while cur is not None and i < fcount:
|
||||
if cur.Ty is not None:
|
||||
@@ -530,7 +530,7 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
array_ty: mlirlite.LLVMType* = mlirlite.Array(pool, i8_ty, max_size)
|
||||
|
||||
# Build the ParamNode list (single field: byte array)
|
||||
pnode: rawptr[mlirlite.ParamNode] = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
pnode: mlirlite.ParamNode* = pool.alloc(mlirlite.ParamNode.__sizeof__())
|
||||
if pnode is None: return 0
|
||||
string.memset(pnode, 0, mlirlite.ParamNode.__sizeof__())
|
||||
pnode.Ty = array_ty
|
||||
@@ -790,8 +790,21 @@ novirtual class ClassGenEnum(ClassGenBase.ClassGenBase):
|
||||
# Register the named struct into the module
|
||||
mlirlite.module_add_named_type(trans.Module, pool, renum_ty)
|
||||
|
||||
# Register into HandlesStruct
|
||||
entry: GenTypes.StructEntry* = self.Gen.StructGen.register_struct(pool, class_name, renum_ty, trans.ModuleSha1)
|
||||
# Register into HandlesStruct.
|
||||
# A forward-declared placeholder for THIS class may have been created *during the variant walk*
|
||||
# above: a variant field like `Pointee: LLVMType*` is `BinOp(LLVMType | t.CPtr)` (parser's
|
||||
# _make_ptr_type expands the C-style suffix into a union, NOT into `rawptr[...]`), so resolving it
|
||||
# resolves the class name and calls ensure_forward_class. register_struct de-duplicates by Ty
|
||||
# pointer, so it would add a SECOND same-named entry and get_struct_type/find_struct (first match
|
||||
# wins) would keep returning the opaque placeholder -> __sizeof__() == 0 at the first use
|
||||
# ("registered but size 0, field chain unfilled"). Fill the placeholder in place instead, which is
|
||||
# exactly what ensure_forward_class documents ("the definition side fills the same Ty in place").
|
||||
entry: GenTypes.StructEntry* = self.Gen.StructGen.find_struct_by_module(class_name, trans.ModuleSha1)
|
||||
if entry is not None and entry.IsForwardDecl != 0:
|
||||
entry.Ty = renum_ty
|
||||
entry.IsForwardDecl = 0
|
||||
else:
|
||||
entry = self.Gen.StructGen.register_struct(pool, class_name, renum_ty, trans.ModuleSha1)
|
||||
if entry is None:
|
||||
VLogger.error(f"failed to register {class_name}", "RENUM")
|
||||
return 0
|
||||
|
||||
@@ -599,7 +599,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
if sig_only != 0: return 0
|
||||
|
||||
# Create the entry block.
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None: return 0
|
||||
|
||||
# Create the method's own builder.
|
||||
@@ -633,9 +633,9 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
tls_m_buf: str = pool.alloc(64)
|
||||
if tls_m_buf is not None:
|
||||
viperlib.snprintf(tls_m_buf, 64, "tls.skip.%d", lc_m)
|
||||
tls_m_skip: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_m_buf)
|
||||
tls_m_skip: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, tls_m_buf)
|
||||
viperlib.snprintf(tls_m_buf, 64, "tls.cont.%d", lc_m)
|
||||
tls_m_cont: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_m_buf)
|
||||
tls_m_cont: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, tls_m_buf)
|
||||
if tls_m_skip is not None and tls_m_cont is not None:
|
||||
mlirlite.build_cond_br(func_builder, tls_m_ld, tls_m_skip, tls_m_cont)
|
||||
mlirlite.position_at_end(func_builder, tls_m_skip)
|
||||
@@ -897,7 +897,7 @@ novirtual class ClassGenVTable(ClassGenBase.ClassGenBase):
|
||||
rc_ut: int = self.Gen.CallGenLeafKit.update_global_func_spec(full_name, func)
|
||||
|
||||
# Create the entry block + builder.
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None: return 0
|
||||
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
|
||||
if func_builder is None: return 0
|
||||
|
||||
@@ -297,7 +297,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
enum_nm: ast.Name* = ast.Name*(at.value)
|
||||
if enum_nm.id is not None:
|
||||
if self.Gen.StmtGenDecl.is_enum_class(enum_nm.id) == 1:
|
||||
member: rawptr[GenTypes.EnumMember] = self.Gen.StmtGenDecl.lookup_enum_member(enum_nm.id, at.attr)
|
||||
member: GenTypes.EnumMember* = self.Gen.StmtGenDecl.lookup_enum_member(enum_nm.id, at.attr)
|
||||
if member is not None:
|
||||
base_ty: mlirlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(enum_nm.id)
|
||||
if base_ty is not None:
|
||||
@@ -316,7 +316,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
inner_at_e: ast.Attribute* = ast.Attribute*(at.value)
|
||||
if inner_at_e.attr is not None:
|
||||
if self.Gen.StmtGenDecl.is_enum_class(inner_at_e.attr) == 1:
|
||||
member_e: rawptr[GenTypes.EnumMember] = self.Gen.StmtGenDecl.lookup_enum_member( inner_at_e.attr, at.attr)
|
||||
member_e: GenTypes.EnumMember* = self.Gen.StmtGenDecl.lookup_enum_member( inner_at_e.attr, at.attr)
|
||||
if member_e is not None:
|
||||
base_ty_e: mlirlite.LLVMType* = self.Gen.StmtGenDecl.get_enum_base_type(inner_at_e.attr)
|
||||
if base_ty_e is not None:
|
||||
@@ -325,7 +325,7 @@ novirtual class ExprGenAttr(ExprGenBase.ExprGenBase):
|
||||
return mlirlite.ConstInt(pool, base_ty_e, member_e.Value, name_buf_e)
|
||||
return mlirlite.const_int32(pool, member_e.Value)
|
||||
# fast-fail: nested enum member not found
|
||||
dbg_ee: rawptr[GenTypes.EnumEntry] = self.Gen.StmtGenDecl.find_enum(inner_at_e.attr)
|
||||
dbg_ee: GenTypes.EnumEntry* = self.Gen.StmtGenDecl.find_enum(inner_at_e.attr)
|
||||
dbg_mc: int = -1
|
||||
if dbg_ee is not None: dbg_mc = dbg_ee.MemberCount
|
||||
VLogger.error(f"嵌套枚举成员未找到: {inner_at_e.attr}.{at.attr} (enum_members={dbg_mc})", "ATTR")
|
||||
|
||||
@@ -74,7 +74,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
if buf is None: return None
|
||||
viperlib.snprintf(buf, path_len, "%s/%s", base_dir, rel_used)
|
||||
# existence check: if missing under SourceDir and IncludesDir differs, retry IncludesDir
|
||||
pf_chk: rawptr[fileio.File] = fileio.File(buf, fileio.MODE.R)
|
||||
pf_chk: fileio.File* = fileio.File(buf, fileio.MODE.R)
|
||||
if pf_chk.closed:
|
||||
pf_chk.close()
|
||||
if Config.IncludesDir is not None and base_dir != Config.IncludesDir:
|
||||
@@ -84,7 +84,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
buf = stdlib.malloc(path_len2)
|
||||
if buf is None: return None
|
||||
viperlib.snprintf(buf, path_len2, "%s/%s", Config.IncludesDir, rel_used)
|
||||
pf_chk2: rawptr[fileio.File] = fileio.File(buf, fileio.MODE.R)
|
||||
pf_chk2: fileio.File* = fileio.File(buf, fileio.MODE.R)
|
||||
if pf_chk2.closed:
|
||||
pf_chk2.close()
|
||||
stdlib.free(buf)
|
||||
@@ -208,7 +208,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
|
||||
if pyi_buf is None:
|
||||
stdlib.free(pyi_path)
|
||||
return -1
|
||||
pf: rawptr[fileio.File] = fileio.File(pyi_path, fileio.MODE.R)
|
||||
pf: fileio.File* = fileio.File(pyi_path, fileio.MODE.R)
|
||||
need_py_fallback: int = 0
|
||||
bytes_read: LONG = 0
|
||||
if pf.closed:
|
||||
|
||||
@@ -33,7 +33,7 @@ novirtual class ExprGenCls(ExprGenBase.ExprGenBase):
|
||||
if body is None or len(body) == 0: return None
|
||||
first: ast.AST* = body.get(0)
|
||||
if first is None or first.kind() != ast.ASTKind.Expr: return None
|
||||
ex: rawptr[ast.Expr] = rawptr[ast.Expr](first)
|
||||
ex: ast.Expr* = ast.Expr*(first)
|
||||
if ex is None or ex.value is None or ex.value.kind() != ast.ASTKind.Constant: return None
|
||||
cn: ast.Constant* = ast.Constant*(ex.value)
|
||||
if cn is None or cn.const_kind != ast.CONST_STR: return None
|
||||
|
||||
@@ -23,7 +23,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
|
||||
def translate_joined_str(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Lower an f-string to snprintf into a per-site i8* stack buffer."""
|
||||
if node is None or builder is None or trans is None: return None
|
||||
js: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](node)
|
||||
js: ast.JoinedStr* = ast.JoinedStr*(node)
|
||||
if js is None or js.values is None: return None
|
||||
|
||||
# Compile-time format string buffer (pool-allocated)
|
||||
@@ -47,7 +47,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
|
||||
self._fstr_append_literal(fmt_buf, pcn.str_val)
|
||||
continue
|
||||
if part.kind() != ast.ASTKind.FormattedValue: continue
|
||||
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](part)
|
||||
fv: ast.FormattedValue* = ast.FormattedValue*(part)
|
||||
if fv.value is None: continue
|
||||
val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, fv.value, None, 0, trans)
|
||||
if val is None:
|
||||
@@ -80,7 +80,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
|
||||
def translate_formatted_value(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a bare FormattedValue without any literal parts."""
|
||||
if node is None or builder is None or trans is None: return None
|
||||
fv: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](node)
|
||||
fv: ast.FormattedValue* = ast.FormattedValue*(node)
|
||||
if fv is None or fv.value is None: return None
|
||||
fmt_buf: str = pool.alloc(FSTR_BUF_SIZE)
|
||||
if fmt_buf is None: return None
|
||||
@@ -186,7 +186,7 @@ novirtual class ExprGenFstr(ExprGenBase.ExprGenBase):
|
||||
spec[0] = '\0'
|
||||
sk: int = spec_node.kind()
|
||||
if sk == ast.ASTKind.JoinedStr:
|
||||
jss: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](spec_node)
|
||||
jss: ast.JoinedStr* = ast.JoinedStr*(spec_node)
|
||||
if jss.values is None: return None
|
||||
vn: sizet = len(jss.values)
|
||||
for vi in range(vn):
|
||||
|
||||
@@ -61,7 +61,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
elif k == ast.ASTKind.Await:
|
||||
# Coroutine await (TPV-M1): inline-translate when the await target is an async call.
|
||||
# Returns the child coroutine's i32 ret; top-level await is handled by AsyncGen.
|
||||
aw: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw: ast.Await* = ast.Await*(node)
|
||||
if aw is not None and aw.value is not None and aw.value.kind() == ast.ASTKind.Call:
|
||||
aw_cl: ast.Call* = ast.Call*(aw.value)
|
||||
if aw_cl.func is not None and aw_cl.func.kind() == ast.ASTKind.Name:
|
||||
@@ -72,7 +72,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
|
||||
elif k == ast.ASTKind.Starred:
|
||||
# *x in a value context: the parser tags '*' as Starred, but Viper has no unpacking.
|
||||
# Treat it as C unary deref (*ptr -> load pointee) by building a Deref UnaryOp.
|
||||
st: rawptr[ast.Starred] = rawptr[ast.Starred](node)
|
||||
st: ast.Starred* = ast.Starred*(node)
|
||||
if st is None or st.value is None: return None
|
||||
deref_node: ast.AST* = ast.UnaryOp(pool, ast.OpKind.Deref, st.value)
|
||||
if deref_node is None: return None
|
||||
|
||||
@@ -488,7 +488,7 @@ novirtual class ExprGenName(ExprGenBase.ExprGenBase):
|
||||
# Slice form a[start:end] (e.g. path[n:]): return an i8* base pointer plus the start offset.
|
||||
# Slices must not be treated as single-index subscripts, or the argument is dropped entirely.
|
||||
if sub.slice is not None and sub.slice.kind() == ast.ASTKind.Slice:
|
||||
slc: rawptr[ast.Slice] = rawptr[ast.Slice](sub.slice)
|
||||
slc: ast.Slice* = ast.Slice*(sub.slice)
|
||||
base_v: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, sub.value, None, 0, trans)
|
||||
if base_v is None: return None
|
||||
if slc.lower is None: return base_v
|
||||
|
||||
@@ -22,7 +22,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
def translate_ifexp(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a ternary (body if test else orelse) into a phi Value."""
|
||||
if node is None or builder is None or trans is None: return None
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
if ie is None: return None
|
||||
|
||||
func: mlirlite.Function* = trans._cur_func
|
||||
@@ -40,11 +40,11 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
name_buf: str = pool.alloc(32)
|
||||
if name_buf is None: return None
|
||||
viperlib.snprintf(name_buf, 32, "ifexp.then.%d", cnt)
|
||||
then_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
then_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "ifexp.else.%d", cnt)
|
||||
else_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
else_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "ifexp.merge.%d", cnt)
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
if then_bb is None or else_bb is None or merge_bb is None: return None
|
||||
|
||||
@@ -54,7 +54,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
# 4. then branch
|
||||
mlirlite.position_at_end(builder, then_bb)
|
||||
body_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.body, None, 0, trans)
|
||||
then_blk_for_phi: rawptr[mlirlite.BasicBlock] = trans._cur_builder.CurBlock
|
||||
then_blk_for_phi: mlirlite.BasicBlock* = trans._cur_builder.CurBlock
|
||||
if body_val is None:
|
||||
# fail-fast: ternary then-branch translation failed; abort compilation (expose the upstream root cause)
|
||||
self.Gen.TypeGenErr.fatal_error(ie.body, "三元表达式分支翻译失败", "TypeError")
|
||||
@@ -66,7 +66,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
if self.is_ptr_type(body_val.Ty) != 0: orelse_target_ty = body_val.Ty
|
||||
mlirlite.position_at_end(builder, else_bb)
|
||||
orelse_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, ie.orelse, None, 0, trans, orelse_target_ty)
|
||||
else_blk_for_phi: rawptr[mlirlite.BasicBlock] = trans._cur_builder.CurBlock
|
||||
else_blk_for_phi: mlirlite.BasicBlock* = trans._cur_builder.CurBlock
|
||||
if orelse_val is None:
|
||||
# fail-fast: ternary else-branch translation failed; abort compilation (expose the upstream root cause)
|
||||
self.Gen.TypeGenErr.fatal_error(ie.orelse, "三元表达式分支翻译失败", "TypeError")
|
||||
@@ -290,7 +290,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
return 0
|
||||
def translate_compare(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a comparison expression and return an i1 result."""
|
||||
cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cmp: ast.Compare* = ast.Compare*(node)
|
||||
if cmp is None: return None
|
||||
|
||||
ops_list: list[int]* = (list[int]*)(cmp.ops)
|
||||
@@ -672,7 +672,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
# and: a false short-circuits to merge (returns a's i1); or: a true short-circuits; the last value is evaluated then branches to merge; merge phis all i1 edges.
|
||||
def translate_boolop(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, funcs_ptr: t.CPtr = None, func_count: int = 0, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate boolean and/or with short-circuit evaluation, returning i1."""
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bo is None: return None
|
||||
|
||||
op: int = bo.op
|
||||
@@ -692,7 +692,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
name_buf: str = pool.alloc(32)
|
||||
if name_buf is None: return None
|
||||
viperlib.snprintf(name_buf, 32, "bool.merge.%d", cnt)
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# phi incoming list head/tail
|
||||
phi_head: mlirlite.PhiIncoming* = None
|
||||
@@ -712,14 +712,14 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
|
||||
cnt = builder.Counter
|
||||
builder.Counter = cnt + 1
|
||||
viperlib.snprintf(name_buf, 32, "bool.next.%d", cnt)
|
||||
next_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
next_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# and: false -> merge, true -> next; or: true -> merge, false -> next
|
||||
if op == ast.OpKind.And: mlirlite.build_cond_br(builder, val_i1, next_bb, merge_bb)
|
||||
else: mlirlite.build_cond_br(builder, val_i1, merge_bb, next_bb)
|
||||
|
||||
# Add the phi incoming edge: (val_i1, the BB holding cond_br)
|
||||
cur_bb: rawptr[mlirlite.BasicBlock] = builder.CurBlock
|
||||
cur_bb: mlirlite.BasicBlock* = builder.CurBlock
|
||||
inc: mlirlite.PhiIncoming* = mlirlite.new_phi_incoming(pool, val_i1, cur_bb)
|
||||
if phi_head is None:
|
||||
phi_head = inc
|
||||
|
||||
@@ -220,7 +220,7 @@ novirtual class FuncGenBase(CallGenBase.CallGenBase):
|
||||
stmt_f: ast.AST* = body_f.get(bi_f)
|
||||
if stmt_f is None: continue
|
||||
if stmt_f.kind() != ast.ASTKind.Raise: continue
|
||||
rn_f: rawptr[ast.Raise] = rawptr[ast.Raise](stmt_f)
|
||||
rn_f: ast.Raise* = ast.Raise*(stmt_f)
|
||||
if rn_f is None or rn_f.exc is None: continue
|
||||
ek_f: int = rn_f.exc.kind()
|
||||
is_stop_f: int = 0
|
||||
|
||||
@@ -512,7 +512,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
self.Gen.CallGenLeafKit.update_global_func_spec(fd.name, func)
|
||||
|
||||
# Create the entry block
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None: return 0
|
||||
|
||||
# Create the function-specific builder
|
||||
@@ -549,9 +549,9 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
tls_bb_buf: str = pool.alloc(64)
|
||||
if tls_bb_buf is not None:
|
||||
viperlib.snprintf(tls_bb_buf, 64, "tls.skip.%d", lc_t)
|
||||
tls_skip_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_bb_buf)
|
||||
tls_skip_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, tls_bb_buf)
|
||||
viperlib.snprintf(tls_bb_buf, 64, "tls.cont.%d", lc_t)
|
||||
tls_cont_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, tls_bb_buf)
|
||||
tls_cont_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, tls_bb_buf)
|
||||
if tls_skip_bb is not None and tls_cont_bb is not None:
|
||||
mlirlite.build_cond_br(func_builder, tls_flag_ld, tls_skip_bb, tls_cont_bb)
|
||||
# skip block: return a default value matching the return type
|
||||
@@ -698,8 +698,8 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
old_ret_annot: ast.AST* = trans.CurFuncRetAnnot
|
||||
# break/continue targets and the match-case flag must be cleared for the new function scope (see assignments below),
|
||||
# otherwise break/continue in a nested function inherits the outer (even cross-function) br targets.
|
||||
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break_bb: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue_bb: mlirlite.BasicBlock* = trans._continue_bb
|
||||
old_insw: int = trans._in_switch_case
|
||||
|
||||
trans._cur_func = func
|
||||
@@ -885,10 +885,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
mlirlite.add_param(pool, wrapper, (mlirlite.LLVMType*)(param_tys[pi]), pname_w)
|
||||
|
||||
# ---- Create blocks ----
|
||||
entry_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "entry")
|
||||
loop_h_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.header")
|
||||
loop_b_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "loop.body")
|
||||
post_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "post")
|
||||
entry_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "entry")
|
||||
loop_h_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "loop.header")
|
||||
loop_b_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "loop.body")
|
||||
post_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "post")
|
||||
if entry_bb is None or loop_h_bb is None or loop_b_bb is None or post_bb is None: return None
|
||||
|
||||
# Recursion guard flag (outermost): @__decor_rec_{wrapper} = global i8 0
|
||||
@@ -915,10 +915,10 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
|
||||
|
||||
# ---- entry: recursion guard check (outermost) ----
|
||||
mlirlite.position_at_end(wb, entry_bb)
|
||||
loop_pred_bb: rawptr[mlirlite.BasicBlock] = entry_bb
|
||||
loop_pred_bb: mlirlite.BasicBlock* = entry_bb
|
||||
if rec_flag_ref is not None:
|
||||
rec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "recursive_call")
|
||||
dec_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, wrapper, "decorated_entry")
|
||||
rec_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "recursive_call")
|
||||
dec_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, wrapper, "decorated_entry")
|
||||
if rec_bb is None or dec_bb is None: return None
|
||||
rec_val: mlirlite.Value* = mlirlite.build_load(wb, i8_ty, rec_flag_ref)
|
||||
rec_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i8_ty, 0, "0")
|
||||
|
||||
@@ -90,7 +90,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
param_count += 1
|
||||
|
||||
# 3. Create the entry block and builder
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None: return 0
|
||||
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
|
||||
if func_builder is None: return 0
|
||||
@@ -160,8 +160,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
old_env_count: int = trans._closure_env_count
|
||||
# break/continue targets and match-case flag must be cleared for the new scope (see
|
||||
# assignments below); otherwise a nested break/continue inherits the outer target.
|
||||
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break_bb: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue_bb: mlirlite.BasicBlock* = trans._continue_bb
|
||||
old_insw: int = trans._in_switch_case
|
||||
# Separate nonlocal buffer: sharing [0] would overwrite the parent's set (ClosureTest2
|
||||
# Test 7: level2's b clobbers level1's a). Restored after translation.
|
||||
@@ -414,13 +414,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
if aan.value is not None: self._closure_scan_captures(trans, aan.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.AugAssign:
|
||||
aun: rawptr[ast.AugAssign] = rawptr[ast.AugAssign](node)
|
||||
aun: ast.AugAssign* = ast.AugAssign*(node)
|
||||
# The target is also read (reads the old value), so it participates in capture
|
||||
if aun.target is not None: self._closure_scan_captures(trans, aun.target)
|
||||
if aun.value is not None: self._closure_scan_captures(trans, aun.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.If:
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](node)
|
||||
ifn: ast.If* = ast.If*(node)
|
||||
if ifn.test is not None: self._closure_scan_captures(trans, ifn.test)
|
||||
if ifn.children is not None:
|
||||
bn_if: sizet = len(ifn.children)
|
||||
@@ -441,7 +441,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_fe in range(bn_fe): self._closure_scan_captures(trans, for_n.orelse.get(bi_fe))
|
||||
return 1
|
||||
if k == ast.ASTKind.While:
|
||||
wh_n: rawptr[ast.While] = rawptr[ast.While](node)
|
||||
wh_n: ast.While* = ast.While*(node)
|
||||
if wh_n.test is not None: self._closure_scan_captures(trans, wh_n.test)
|
||||
if wh_n.children is not None:
|
||||
bn_w: sizet = len(wh_n.children)
|
||||
@@ -451,11 +451,11 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_we in range(bn_we): self._closure_scan_captures(trans, wh_n.orelse.get(bi_we))
|
||||
return 1
|
||||
if k == ast.ASTKind.Return:
|
||||
rt_n: rawptr[ast.Return] = rawptr[ast.Return](node)
|
||||
rt_n: ast.Return* = ast.Return*(node)
|
||||
if rt_n.value is not None: self._closure_scan_captures(trans, rt_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.Expr:
|
||||
ex_n: rawptr[ast.Expr] = rawptr[ast.Expr](node)
|
||||
ex_n: ast.Expr* = ast.Expr*(node)
|
||||
if ex_n.value is not None: self._closure_scan_captures(trans, ex_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.With:
|
||||
@@ -465,19 +465,19 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_wi in range(bn_wi):
|
||||
wi_n: ast.AST* = wth.items.get(bi_wi)
|
||||
if wi_n is not None and wi_n.kind() == ast.ASTKind.WithItem:
|
||||
wi_c: rawptr[ast.WithItem] = rawptr[ast.WithItem](wi_n)
|
||||
wi_c: ast.WithItem* = ast.WithItem*(wi_n)
|
||||
if wi_c.context_expr is not None: self._closure_scan_captures(trans, wi_c.context_expr)
|
||||
if wth.children is not None:
|
||||
bn_wb: sizet = len(wth.children)
|
||||
for bi_wb in range(bn_wb): self._closure_scan_captures(trans, wth.children.get(bi_wb))
|
||||
return 1
|
||||
if k == ast.ASTKind.Raise:
|
||||
rs_n: rawptr[ast.Raise] = rawptr[ast.Raise](node)
|
||||
rs_n: ast.Raise* = ast.Raise*(node)
|
||||
if rs_n.exc is not None: self._closure_scan_captures(trans, rs_n.exc)
|
||||
if rs_n.cause is not None: self._closure_scan_captures(trans, rs_n.cause)
|
||||
return 1
|
||||
if k == ast.ASTKind.Assert:
|
||||
as_n: rawptr[ast.Assert] = rawptr[ast.Assert](node)
|
||||
as_n: ast.Assert* = ast.Assert*(node)
|
||||
if as_n.test is not None: self._closure_scan_captures(trans, as_n.test)
|
||||
if as_n.msg is not None: self._closure_scan_captures(trans, as_n.msg)
|
||||
return 1
|
||||
@@ -510,7 +510,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_mc in range(bn_mc):
|
||||
mc_n: ast.AST* = mt_n.cases.get(bi_mc)
|
||||
if mc_n is not None and mc_n.kind() == ast.ASTKind.MatchCase:
|
||||
mc_c: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_n)
|
||||
mc_c: ast.MatchCase* = ast.MatchCase*(mc_n)
|
||||
if mc_c.guard is not None: self._closure_scan_captures(trans, mc_c.guard)
|
||||
if mc_c.children is not None:
|
||||
bn_mcb: sizet = len(mc_c.children)
|
||||
@@ -527,13 +527,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
if uop.operand is not None: self._closure_scan_captures(trans, uop.operand)
|
||||
return 1
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bop2: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bop2: ast.BoolOp* = ast.BoolOp*(node)
|
||||
if bop2.values is not None:
|
||||
bn_bo: sizet = len(bop2.values)
|
||||
for bi_bo in range(bn_bo): self._closure_scan_captures(trans, bop2.values.get(bi_bo))
|
||||
return 1
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cmp: ast.Compare* = ast.Compare*(node)
|
||||
if cmp.left is not None: self._closure_scan_captures(trans, cmp.left)
|
||||
if cmp.comparators is not None:
|
||||
bn_cmp: sizet = len(cmp.comparators)
|
||||
@@ -550,7 +550,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_ck in range(bn_ck):
|
||||
kw_n: ast.AST* = cal.keywords.get(bi_ck)
|
||||
if kw_n is not None and kw_n.kind() == ast.ASTKind.Keyword:
|
||||
kw_c: rawptr[ast.Keyword] = rawptr[ast.Keyword](kw_n)
|
||||
kw_c: ast.Keyword* = ast.Keyword*(kw_n)
|
||||
if kw_c.value is not None: self._closure_scan_captures(trans, kw_c.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.Subscript:
|
||||
@@ -563,13 +563,13 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
if at_n.value is not None: self._closure_scan_captures(trans, at_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
if ie.test is not None: self._closure_scan_captures(trans, ie.test)
|
||||
if ie.body is not None: self._closure_scan_captures(trans, ie.body)
|
||||
if ie.orelse is not None: self._closure_scan_captures(trans, ie.orelse)
|
||||
return 1
|
||||
if k == ast.ASTKind.Dict:
|
||||
dc: rawptr[ast.Dict] = rawptr[ast.Dict](node)
|
||||
dc: ast.Dict* = ast.Dict*(node)
|
||||
if dc.keys is not None:
|
||||
bn_dk: sizet = len(dc.keys)
|
||||
for bi_dk in range(bn_dk): self._closure_scan_captures(trans, dc.keys.get(bi_dk))
|
||||
@@ -578,7 +578,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_dv in range(bn_dv): self._closure_scan_captures(trans, dc.values.get(bi_dv))
|
||||
return 1
|
||||
if k == ast.ASTKind.Set:
|
||||
st_n: rawptr[ast.Set] = rawptr[ast.Set](node)
|
||||
st_n: ast.Set* = ast.Set*(node)
|
||||
if st_n.elts is not None:
|
||||
bn_set: sizet = len(st_n.elts)
|
||||
for bi_set in range(bn_set): self._closure_scan_captures(trans, st_n.elts.get(bi_set))
|
||||
@@ -596,40 +596,40 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_tp in range(bn_tp): self._closure_scan_captures(trans, tp_n.elts.get(bi_tp))
|
||||
return 1
|
||||
if k == ast.ASTKind.Starred:
|
||||
sr_n: rawptr[ast.Starred] = rawptr[ast.Starred](node)
|
||||
sr_n: ast.Starred* = ast.Starred*(node)
|
||||
if sr_n.value is not None: self._closure_scan_captures(trans, sr_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.NamedExpr:
|
||||
ne_n: rawptr[ast.NamedExpr] = rawptr[ast.NamedExpr](node)
|
||||
ne_n: ast.NamedExpr* = ast.NamedExpr*(node)
|
||||
if ne_n.value is not None: self._closure_scan_captures(trans, ne_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.Slice:
|
||||
sl_n: rawptr[ast.Slice] = rawptr[ast.Slice](node)
|
||||
sl_n: ast.Slice* = ast.Slice*(node)
|
||||
if sl_n.lower is not None: self._closure_scan_captures(trans, sl_n.lower)
|
||||
if sl_n.upper is not None: self._closure_scan_captures(trans, sl_n.upper)
|
||||
if sl_n.step is not None: self._closure_scan_captures(trans, sl_n.step)
|
||||
return 1
|
||||
if k == ast.ASTKind.JoinedStr:
|
||||
js_n: rawptr[ast.JoinedStr] = rawptr[ast.JoinedStr](node)
|
||||
js_n: ast.JoinedStr* = ast.JoinedStr*(node)
|
||||
if js_n.values is not None:
|
||||
bn_js: sizet = len(js_n.values)
|
||||
for bi_js in range(bn_js): self._closure_scan_captures(trans, js_n.values.get(bi_js))
|
||||
return 1
|
||||
if k == ast.ASTKind.FormattedValue:
|
||||
fv_n: rawptr[ast.FormattedValue] = rawptr[ast.FormattedValue](node)
|
||||
fv_n: ast.FormattedValue* = ast.FormattedValue*(node)
|
||||
if fv_n.value is not None: self._closure_scan_captures(trans, fv_n.value)
|
||||
if fv_n.format_spec is not None: self._closure_scan_captures(trans, fv_n.format_spec)
|
||||
return 1
|
||||
if k == ast.ASTKind.Await:
|
||||
aw_n: rawptr[ast.Await] = rawptr[ast.Await](node)
|
||||
aw_n: ast.Await* = ast.Await*(node)
|
||||
if aw_n.value is not None: self._closure_scan_captures(trans, aw_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.Yield:
|
||||
yd_n: rawptr[ast.Yield] = rawptr[ast.Yield](node)
|
||||
yd_n: ast.Yield* = ast.Yield*(node)
|
||||
if yd_n.value is not None: self._closure_scan_captures(trans, yd_n.value)
|
||||
return 1
|
||||
if k == ast.ASTKind.YieldFrom:
|
||||
yf_n: rawptr[ast.YieldFrom] = rawptr[ast.YieldFrom](node)
|
||||
yf_n: ast.YieldFrom* = ast.YieldFrom*(node)
|
||||
if yf_n.value is not None: self._closure_scan_captures(trans, yf_n.value)
|
||||
return 1
|
||||
is_comp: int = 0
|
||||
@@ -637,21 +637,21 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
elif k == ast.ASTKind.SetComp: is_comp = 1
|
||||
elif k == ast.ASTKind.GeneratorExp: is_comp = 1
|
||||
if is_comp != 0:
|
||||
lc_n: rawptr[ast.ListComp] = rawptr[ast.ListComp](node)
|
||||
lc_n: ast.ListComp* = ast.ListComp*(node)
|
||||
if lc_n.elt is not None: self._closure_scan_captures(trans, lc_n.elt)
|
||||
if lc_n.generators is not None:
|
||||
bn_gen: sizet = len(lc_n.generators)
|
||||
for bi_gen in range(bn_gen):
|
||||
cp_n: ast.AST* = lc_n.generators.get(bi_gen)
|
||||
if cp_n is not None and cp_n.kind() == ast.ASTKind.Comprehension:
|
||||
cp_c: rawptr[ast.Comprehension] = rawptr[ast.Comprehension](cp_n)
|
||||
cp_c: ast.Comprehension* = ast.Comprehension*(cp_n)
|
||||
if cp_c.iter is not None: self._closure_scan_captures(trans, cp_c.iter)
|
||||
if cp_c.ifs is not None:
|
||||
bn_cpi: sizet = len(cp_c.ifs)
|
||||
for bi_cpi in range(bn_cpi): self._closure_scan_captures(trans, cp_c.ifs.get(bi_cpi))
|
||||
return 1
|
||||
if k == ast.ASTKind.DictComp:
|
||||
dcn: rawptr[ast.DictComp] = rawptr[ast.DictComp](node)
|
||||
dcn: ast.DictComp* = ast.DictComp*(node)
|
||||
if dcn.key is not None: self._closure_scan_captures(trans, dcn.key)
|
||||
if dcn.value is not None: self._closure_scan_captures(trans, dcn.value)
|
||||
if dcn.generators is not None:
|
||||
@@ -659,7 +659,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
for bi_dgen in range(bn_dgen):
|
||||
cp_dn: ast.AST* = dcn.generators.get(bi_dgen)
|
||||
if cp_dn is not None and cp_dn.kind() == ast.ASTKind.Comprehension:
|
||||
cp_dc: rawptr[ast.Comprehension] = rawptr[ast.Comprehension](cp_dn)
|
||||
cp_dc: ast.Comprehension* = ast.Comprehension*(cp_dn)
|
||||
if cp_dc.iter is not None: self._closure_scan_captures(trans, cp_dc.iter)
|
||||
if cp_dc.ifs is not None:
|
||||
bn_dcpi: sizet = len(cp_dc.ifs)
|
||||
@@ -743,7 +743,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
k: int = st.kind()
|
||||
if k == ast.ASTKind.FunctionDef: count = self._collect_chain_nonlocals(trans, st, names, count)
|
||||
elif k == ast.ASTKind.Nonlocal:
|
||||
nl_node: rawptr[ast.Nonlocal] = rawptr[ast.Nonlocal](st)
|
||||
nl_node: ast.Nonlocal* = ast.Nonlocal*(st)
|
||||
if nl_node is not None and nl_node.names is not None:
|
||||
nl_list: list[ast.AST*]* = nl_node.names
|
||||
nn: sizet = len(nl_list)
|
||||
@@ -829,7 +829,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
def translate_lambda(self, builder: mlirlite.IRBuilder*, pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, node: ast.AST*, trans: HT.Translator* = None) -> mlirlite.Value*:
|
||||
"""Translate a lambda expression and return the closure pointer (i8*)"""
|
||||
if node is None or trans is None or builder is None: return None
|
||||
lam: rawptr[ast.Lambda] = rawptr[ast.Lambda](node)
|
||||
lam: ast.Lambda* = ast.Lambda*(node)
|
||||
if lam is None: return None
|
||||
|
||||
i32_ty: mlirlite.LLVMType* = mlirlite.Int32(pool)
|
||||
@@ -910,7 +910,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
mlirlite.add_param(pool, func, p_ty2, pname_l)
|
||||
|
||||
# 5. Entry block + builder
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, "entry")
|
||||
if entry_blk is None: return None
|
||||
func_builder: mlirlite.IRBuilder* = mlirlite.new_builder(pool, func)
|
||||
if func_builder is None: return None
|
||||
@@ -938,8 +938,8 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
old_env_count: int = trans._closure_env_count
|
||||
# break/continue targets and match-case flag must be cleared for the new scope (see
|
||||
# assignments below); otherwise a lambda break/continue inherits the outer target.
|
||||
old_break_bb: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue_bb: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break_bb: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue_bb: mlirlite.BasicBlock* = trans._continue_bb
|
||||
old_insw: int = trans._in_switch_case
|
||||
trans._cur_func = func
|
||||
trans._cur_builder = func_builder
|
||||
@@ -1129,7 +1129,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
uop: ast.UnaryOp* = ast.UnaryOp*(node)
|
||||
return self._lambda_scan_body(trans, uop.operand, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count)
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bop2: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bop2: ast.BoolOp* = ast.BoolOp*(node)
|
||||
cc2: int = cap_count
|
||||
if bop2.values is not None:
|
||||
vs: list[ast.AST*]* = bop2.values
|
||||
@@ -1138,7 +1138,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
cc2 = self._lambda_scan_body(trans, vs.get(vi), param_names, param_count, cap_names, cap_allocas, cap_tys, cc2)
|
||||
return cc2
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cmp: ast.Compare* = ast.Compare*(node)
|
||||
cc3: int = self._lambda_scan_body(trans, cmp.left, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count)
|
||||
if cmp.comparators is not None:
|
||||
cl: list[ast.AST*]* = cmp.comparators
|
||||
@@ -1158,7 +1158,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
kws: list[ast.AST*]* = cal.keywords
|
||||
kn: sizet = len(kws)
|
||||
for ki in range(kn):
|
||||
kw: rawptr[ast.Keyword] = rawptr[ast.Keyword](kws.get(ki))
|
||||
kw: ast.Keyword* = ast.Keyword*(kws.get(ki))
|
||||
if kw is not None and kw.value is not None:
|
||||
cc4 = self._lambda_scan_body(trans, kw.value, param_names, param_count, cap_names, cap_allocas, cap_tys, cc4)
|
||||
return cc4
|
||||
@@ -1172,7 +1172,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
at: ast.Attribute* = ast.Attribute*(node)
|
||||
return self._lambda_scan_body(trans, at.value, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count)
|
||||
if k == ast.ASTKind.IfExp:
|
||||
ie: rawptr[ast.IfExp] = rawptr[ast.IfExp](node)
|
||||
ie: ast.IfExp* = ast.IfExp*(node)
|
||||
cc6: int = self._lambda_scan_body(trans, ie.test, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count)
|
||||
cc6 = self._lambda_scan_body(trans, ie.body, param_names, param_count, cap_names, cap_allocas, cap_tys, cc6)
|
||||
return self._lambda_scan_body(trans, ie.orelse, param_names, param_count, cap_names, cap_allocas, cap_tys, cc6)
|
||||
@@ -1186,6 +1186,6 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
|
||||
cc7 = self._lambda_scan_body(trans, es.get(ei), param_names, param_count, cap_names, cap_allocas, cap_tys, cc7)
|
||||
return cc7
|
||||
if k == ast.ASTKind.Lambda:
|
||||
lam2: rawptr[ast.Lambda] = rawptr[ast.Lambda](node)
|
||||
lam2: ast.Lambda* = ast.Lambda*(node)
|
||||
return self._lambda_scan_body(trans, lam2.body, param_names, param_count, cap_names, cap_allocas, cap_tys, cap_count)
|
||||
return cap_count
|
||||
@@ -479,7 +479,7 @@ def translate_children(trans: HT.Translator*, tree: ast.AST*) -> int:
|
||||
|
||||
|
||||
# ---------------- init_symbol_table (delegates to VarGenMixin.init_symbol_table) ----------------
|
||||
def init_symbol_table(pool: memhub.MemBuddy*) -> rawptr[GenTypes.SymbolTable]:
|
||||
def init_symbol_table(pool: memhub.MemBuddy*) -> GenTypes.SymbolTable*:
|
||||
"""Delegate to gen.init_symbol_table"""
|
||||
if _g_gen is not None: return _g_gen.VarGen.init_symbol_table(pool)
|
||||
return None
|
||||
|
||||
@@ -279,20 +279,20 @@ novirtual class ReplFuncEntry:
|
||||
novirtual class ReplCtx:
|
||||
"""REPL mode context (host-owned, translator-read-only)"""
|
||||
Marker: int # REPL_CTX_MARKER (guards against a non-ReplCtx object)
|
||||
Table: rawptr[ReplVarEntry] # Session table array (PermPool, capacity Cap)
|
||||
Table: ReplVarEntry* # Session table array (PermPool, capacity Cap)
|
||||
Count: int # Registered entry count (= allocated slots)
|
||||
Cap: int # Capacity (REPL_VAR_CAP)
|
||||
CtxParam: str # Fragment function ctx param name (PermPool copy)
|
||||
SlotSize: int # Slot stride (REPL_SLOT_SIZE)
|
||||
# Shadow entry (host-built, PermPool): only classifies bare-expression results; it
|
||||
# occupies no session slot and is not counted; Name is fixed to "<expr>".
|
||||
Scratch: rawptr[ReplVarEntry]
|
||||
Scratch: ReplVarEntry*
|
||||
# Permanent pool provided by the host: cross-fragment data (session names, struct
|
||||
# names) must be deep-copied here, since a fragment's trans.Pool is reset each line.
|
||||
Perm: memhub.MemBuddy*
|
||||
# Session function table (M3; host-writes, Gen-reads): capacity FuncCap, FuncCount
|
||||
# registered. Entries are appended only after a fragment DLL loads and GetProcAddress hits.
|
||||
FuncTable: rawptr[ReplFuncEntry]
|
||||
FuncTable: ReplFuncEntry*
|
||||
FuncCount: int
|
||||
FuncCap: int # Capacity (REPL_FUNC_CAP)
|
||||
|
||||
|
||||
@@ -60,380 +60,380 @@ novirtual class Generator:
|
||||
"""Generator holding pointers to all GenMixin sub-objects (bidirectional composition)."""
|
||||
|
||||
# ---- sub-object pointers (46, permanent pool) ----
|
||||
BaseGen: rawptr[BaseGenMixin.BaseGenMixin]
|
||||
TypeGenBase: rawptr[TypeGenBase.TypeGenBase]
|
||||
TypeGen: rawptr[TypeGenMixin.TypeGenMixin]
|
||||
TypeGenCDef: rawptr[TypeGenCDef.TypeGenCDef]
|
||||
TypeGenCType: rawptr[TypeGenCType.TypeGenCType]
|
||||
TypeGenResolve: rawptr[TypeGenResolve.TypeGenResolve]
|
||||
TypeGenErr: rawptr[TypeGenErr.TypeGenErr]
|
||||
StructGen: rawptr[StructGenMixin.StructGenMixin]
|
||||
ExprGenBase: rawptr[ExprGenBase.ExprGenBase]
|
||||
ExprGen: rawptr[ExprGenMixin.ExprGenMixin]
|
||||
ExprGenConst: rawptr[ExprGenConst.ExprGenConst]
|
||||
ExprGenFstr: rawptr[ExprGenFstr.ExprGenFstr]
|
||||
ExprGenOps: rawptr[ExprGenOps.ExprGenOps]
|
||||
ExprGenCdef: rawptr[ExprGenCdef.ExprGenCdef]
|
||||
ExprGenName: rawptr[ExprGenName.ExprGenName]
|
||||
ExprGenAttr: rawptr[ExprGenAttr.ExprGenAttr]
|
||||
ExprGenCls: rawptr[ExprGenCls.ExprGenCls]
|
||||
CallGenBase: rawptr[CallGenBase.CallGenBase]
|
||||
CallGenCBuiltin: rawptr[CallGenCBuiltin.CallGenCBuiltin]
|
||||
CallGenLeafKit: rawptr[CallGenLeafKit.CallGenLeafKit]
|
||||
CallGenCtor: rawptr[CallGenCtor.CallGenCtor]
|
||||
CallGenCall: rawptr[CallGenCall.CallGenCall]
|
||||
CallGen: rawptr[CallGenMixin.CallGenMixin]
|
||||
CallGenDispatch: rawptr[CallGenDispatch.CallGenDispatch]
|
||||
CallGenLib: rawptr[CallGenLib.CallGenLib]
|
||||
CallGenVt: rawptr[CallGenVt.CallGenVt]
|
||||
CallGenVa: rawptr[CallGenVa.CallGenVa]
|
||||
CallGenProp: rawptr[CallGenProp.CallGenProp]
|
||||
CallGenFd: rawptr[CallGenFd.CallGenFd]
|
||||
FuncGenBase: rawptr[FuncGenBase.FuncGenBase]
|
||||
FuncGenDef: rawptr[FuncGenDef.FuncGenDef]
|
||||
FuncGen: rawptr[FuncGenMixin.FuncGenMixin]
|
||||
ClassGenBase: rawptr[ClassGenBase.ClassGenBase]
|
||||
ClassGen: rawptr[ClassGenMixin.ClassGenMixin]
|
||||
ClassGenEnum: rawptr[ClassGenEnum.ClassGenEnum]
|
||||
ClassGenGeneric: rawptr[ClassGenGeneric.ClassGenGeneric]
|
||||
ClassGenVTable: rawptr[ClassGenVTable.ClassGenVTable]
|
||||
ClassGenDef: rawptr[ClassGenDef.ClassGenDef]
|
||||
ImportsGen: rawptr[ImportsGenMixin.ImportsGenMixin]
|
||||
StmtGenCif: rawptr[StmtGenCifMixin.StmtGenCifMixin]
|
||||
StmtGenDecl: rawptr[StmtGenDeclMixin.StmtGenDeclMixin]
|
||||
StmtGen: rawptr[StmtGenMixin.StmtGenMixin]
|
||||
MatchGen: rawptr[MatchGenMixin.MatchGenMixin]
|
||||
AssignGen: rawptr[AssignGenMixin.AssignGenMixin]
|
||||
AsyncGen: rawptr[AsyncGenMixin.AsyncGenMixin]
|
||||
VarGen: rawptr[VarGenMixin.VarGenMixin]
|
||||
TranslatorGen: rawptr[TranslatorGenMixin.TranslatorGenMixin]
|
||||
BaseGen: BaseGenMixin.BaseGenMixin*
|
||||
TypeGenBase: TypeGenBase.TypeGenBase*
|
||||
TypeGen: TypeGenMixin.TypeGenMixin*
|
||||
TypeGenCDef: TypeGenCDef.TypeGenCDef*
|
||||
TypeGenCType: TypeGenCType.TypeGenCType*
|
||||
TypeGenResolve: TypeGenResolve.TypeGenResolve*
|
||||
TypeGenErr: TypeGenErr.TypeGenErr*
|
||||
StructGen: StructGenMixin.StructGenMixin*
|
||||
ExprGenBase: ExprGenBase.ExprGenBase*
|
||||
ExprGen: ExprGenMixin.ExprGenMixin*
|
||||
ExprGenConst: ExprGenConst.ExprGenConst*
|
||||
ExprGenFstr: ExprGenFstr.ExprGenFstr*
|
||||
ExprGenOps: ExprGenOps.ExprGenOps*
|
||||
ExprGenCdef: ExprGenCdef.ExprGenCdef*
|
||||
ExprGenName: ExprGenName.ExprGenName*
|
||||
ExprGenAttr: ExprGenAttr.ExprGenAttr*
|
||||
ExprGenCls: ExprGenCls.ExprGenCls*
|
||||
CallGenBase: CallGenBase.CallGenBase*
|
||||
CallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin*
|
||||
CallGenLeafKit: CallGenLeafKit.CallGenLeafKit*
|
||||
CallGenCtor: CallGenCtor.CallGenCtor*
|
||||
CallGenCall: CallGenCall.CallGenCall*
|
||||
CallGen: CallGenMixin.CallGenMixin*
|
||||
CallGenDispatch: CallGenDispatch.CallGenDispatch*
|
||||
CallGenLib: CallGenLib.CallGenLib*
|
||||
CallGenVt: CallGenVt.CallGenVt*
|
||||
CallGenVa: CallGenVa.CallGenVa*
|
||||
CallGenProp: CallGenProp.CallGenProp*
|
||||
CallGenFd: CallGenFd.CallGenFd*
|
||||
FuncGenBase: FuncGenBase.FuncGenBase*
|
||||
FuncGenDef: FuncGenDef.FuncGenDef*
|
||||
FuncGen: FuncGenMixin.FuncGenMixin*
|
||||
ClassGenBase: ClassGenBase.ClassGenBase*
|
||||
ClassGen: ClassGenMixin.ClassGenMixin*
|
||||
ClassGenEnum: ClassGenEnum.ClassGenEnum*
|
||||
ClassGenGeneric: ClassGenGeneric.ClassGenGeneric*
|
||||
ClassGenVTable: ClassGenVTable.ClassGenVTable*
|
||||
ClassGenDef: ClassGenDef.ClassGenDef*
|
||||
ImportsGen: ImportsGenMixin.ImportsGenMixin*
|
||||
StmtGenCif: StmtGenCifMixin.StmtGenCifMixin*
|
||||
StmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin*
|
||||
StmtGen: StmtGenMixin.StmtGenMixin*
|
||||
MatchGen: MatchGenMixin.MatchGenMixin*
|
||||
AssignGen: AssignGenMixin.AssignGenMixin*
|
||||
AsyncGen: AsyncGenMixin.AsyncGenMixin*
|
||||
VarGen: VarGenMixin.VarGenMixin*
|
||||
TranslatorGen: TranslatorGenMixin.TranslatorGenMixin*
|
||||
|
||||
def __init__(self, pool: memhub.MemBuddy*):
|
||||
if self is None: return
|
||||
# ---- alloc 46 sub-objects + back-pointers (permanent pool, fail-fast) ----
|
||||
SubBaseGen: rawptr[BaseGenMixin.BaseGenMixin] = CompilerFactory.factory.PermPool.alloc(BaseGenMixin.BaseGenMixin.__sizeof__())
|
||||
SubBaseGen: BaseGenMixin.BaseGenMixin* = CompilerFactory.factory.PermPool.alloc(BaseGenMixin.BaseGenMixin.__sizeof__())
|
||||
if SubBaseGen is None:
|
||||
stdio.printf("FAIL: BaseGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubBaseGen, 0, BaseGenMixin.BaseGenMixin.__sizeof__())
|
||||
SubBaseGen.Gen = self
|
||||
self.BaseGen = SubBaseGen
|
||||
SubTypeGenBase: rawptr[TypeGenBase.TypeGenBase] = CompilerFactory.factory.PermPool.alloc(TypeGenBase.TypeGenBase.__sizeof__())
|
||||
SubTypeGenBase: TypeGenBase.TypeGenBase* = CompilerFactory.factory.PermPool.alloc(TypeGenBase.TypeGenBase.__sizeof__())
|
||||
if SubTypeGenBase is None:
|
||||
stdio.printf("FAIL: TypeGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenBase, 0, TypeGenBase.TypeGenBase.__sizeof__())
|
||||
SubTypeGenBase.Gen = self
|
||||
self.TypeGenBase = SubTypeGenBase
|
||||
SubTypeGen: rawptr[TypeGenMixin.TypeGenMixin] = CompilerFactory.factory.PermPool.alloc(TypeGenMixin.TypeGenMixin.__sizeof__())
|
||||
SubTypeGen: TypeGenMixin.TypeGenMixin* = CompilerFactory.factory.PermPool.alloc(TypeGenMixin.TypeGenMixin.__sizeof__())
|
||||
if SubTypeGen is None:
|
||||
stdio.printf("FAIL: TypeGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGen, 0, TypeGenMixin.TypeGenMixin.__sizeof__())
|
||||
SubTypeGen.Gen = self
|
||||
self.TypeGen = SubTypeGen
|
||||
SubTypeGenCDef: rawptr[TypeGenCDef.TypeGenCDef] = CompilerFactory.factory.PermPool.alloc(TypeGenCDef.TypeGenCDef.__sizeof__())
|
||||
SubTypeGenCDef: TypeGenCDef.TypeGenCDef* = CompilerFactory.factory.PermPool.alloc(TypeGenCDef.TypeGenCDef.__sizeof__())
|
||||
if SubTypeGenCDef is None:
|
||||
stdio.printf("FAIL: TypeGenCDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenCDef, 0, TypeGenCDef.TypeGenCDef.__sizeof__())
|
||||
SubTypeGenCDef.Gen = self
|
||||
self.TypeGenCDef = SubTypeGenCDef
|
||||
SubTypeGenCType: rawptr[TypeGenCType.TypeGenCType] = CompilerFactory.factory.PermPool.alloc(TypeGenCType.TypeGenCType.__sizeof__())
|
||||
SubTypeGenCType: TypeGenCType.TypeGenCType* = CompilerFactory.factory.PermPool.alloc(TypeGenCType.TypeGenCType.__sizeof__())
|
||||
if SubTypeGenCType is None:
|
||||
stdio.printf("FAIL: TypeGenCType alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenCType, 0, TypeGenCType.TypeGenCType.__sizeof__())
|
||||
SubTypeGenCType.Gen = self
|
||||
self.TypeGenCType = SubTypeGenCType
|
||||
SubTypeGenResolve: rawptr[TypeGenResolve.TypeGenResolve] = CompilerFactory.factory.PermPool.alloc(TypeGenResolve.TypeGenResolve.__sizeof__())
|
||||
SubTypeGenResolve: TypeGenResolve.TypeGenResolve* = CompilerFactory.factory.PermPool.alloc(TypeGenResolve.TypeGenResolve.__sizeof__())
|
||||
if SubTypeGenResolve is None:
|
||||
stdio.printf("FAIL: TypeGenResolve alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenResolve, 0, TypeGenResolve.TypeGenResolve.__sizeof__())
|
||||
SubTypeGenResolve.Gen = self
|
||||
self.TypeGenResolve = SubTypeGenResolve
|
||||
SubTypeGenErr: rawptr[TypeGenErr.TypeGenErr] = CompilerFactory.factory.PermPool.alloc(TypeGenErr.TypeGenErr.__sizeof__())
|
||||
SubTypeGenErr: TypeGenErr.TypeGenErr* = CompilerFactory.factory.PermPool.alloc(TypeGenErr.TypeGenErr.__sizeof__())
|
||||
if SubTypeGenErr is None:
|
||||
stdio.printf("FAIL: TypeGenErr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTypeGenErr, 0, TypeGenErr.TypeGenErr.__sizeof__())
|
||||
SubTypeGenErr.Gen = self
|
||||
self.TypeGenErr = SubTypeGenErr
|
||||
SubStructGen: rawptr[StructGenMixin.StructGenMixin] = CompilerFactory.factory.PermPool.alloc(StructGenMixin.StructGenMixin.__sizeof__())
|
||||
SubStructGen: StructGenMixin.StructGenMixin* = CompilerFactory.factory.PermPool.alloc(StructGenMixin.StructGenMixin.__sizeof__())
|
||||
if SubStructGen is None:
|
||||
stdio.printf("FAIL: StructGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStructGen, 0, StructGenMixin.StructGenMixin.__sizeof__())
|
||||
SubStructGen.Gen = self
|
||||
self.StructGen = SubStructGen
|
||||
SubExprGenBase: rawptr[ExprGenBase.ExprGenBase] = CompilerFactory.factory.PermPool.alloc(ExprGenBase.ExprGenBase.__sizeof__())
|
||||
SubExprGenBase: ExprGenBase.ExprGenBase* = CompilerFactory.factory.PermPool.alloc(ExprGenBase.ExprGenBase.__sizeof__())
|
||||
if SubExprGenBase is None:
|
||||
stdio.printf("FAIL: ExprGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenBase, 0, ExprGenBase.ExprGenBase.__sizeof__())
|
||||
SubExprGenBase.Gen = self
|
||||
self.ExprGenBase = SubExprGenBase
|
||||
SubExprGen: rawptr[ExprGenMixin.ExprGenMixin] = CompilerFactory.factory.PermPool.alloc(ExprGenMixin.ExprGenMixin.__sizeof__())
|
||||
SubExprGen: ExprGenMixin.ExprGenMixin* = CompilerFactory.factory.PermPool.alloc(ExprGenMixin.ExprGenMixin.__sizeof__())
|
||||
if SubExprGen is None:
|
||||
stdio.printf("FAIL: ExprGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGen, 0, ExprGenMixin.ExprGenMixin.__sizeof__())
|
||||
SubExprGen.Gen = self
|
||||
self.ExprGen = SubExprGen
|
||||
SubExprGenConst: rawptr[ExprGenConst.ExprGenConst] = CompilerFactory.factory.PermPool.alloc(ExprGenConst.ExprGenConst.__sizeof__())
|
||||
SubExprGenConst: ExprGenConst.ExprGenConst* = CompilerFactory.factory.PermPool.alloc(ExprGenConst.ExprGenConst.__sizeof__())
|
||||
if SubExprGenConst is None:
|
||||
stdio.printf("FAIL: ExprGenConst alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenConst, 0, ExprGenConst.ExprGenConst.__sizeof__())
|
||||
SubExprGenConst.Gen = self
|
||||
self.ExprGenConst = SubExprGenConst
|
||||
SubExprGenFstr: rawptr[ExprGenFstr.ExprGenFstr] = CompilerFactory.factory.PermPool.alloc(ExprGenFstr.ExprGenFstr.__sizeof__())
|
||||
SubExprGenFstr: ExprGenFstr.ExprGenFstr* = CompilerFactory.factory.PermPool.alloc(ExprGenFstr.ExprGenFstr.__sizeof__())
|
||||
if SubExprGenFstr is None:
|
||||
stdio.printf("FAIL: ExprGenFstr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenFstr, 0, ExprGenFstr.ExprGenFstr.__sizeof__())
|
||||
SubExprGenFstr.Gen = self
|
||||
self.ExprGenFstr = SubExprGenFstr
|
||||
SubExprGenOps: rawptr[ExprGenOps.ExprGenOps] = CompilerFactory.factory.PermPool.alloc(ExprGenOps.ExprGenOps.__sizeof__())
|
||||
SubExprGenOps: ExprGenOps.ExprGenOps* = CompilerFactory.factory.PermPool.alloc(ExprGenOps.ExprGenOps.__sizeof__())
|
||||
if SubExprGenOps is None:
|
||||
stdio.printf("FAIL: ExprGenOps alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenOps, 0, ExprGenOps.ExprGenOps.__sizeof__())
|
||||
SubExprGenOps.Gen = self
|
||||
self.ExprGenOps = SubExprGenOps
|
||||
SubExprGenCdef: rawptr[ExprGenCdef.ExprGenCdef] = CompilerFactory.factory.PermPool.alloc(ExprGenCdef.ExprGenCdef.__sizeof__())
|
||||
SubExprGenCdef: ExprGenCdef.ExprGenCdef* = CompilerFactory.factory.PermPool.alloc(ExprGenCdef.ExprGenCdef.__sizeof__())
|
||||
if SubExprGenCdef is None:
|
||||
stdio.printf("FAIL: ExprGenCdef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenCdef, 0, ExprGenCdef.ExprGenCdef.__sizeof__())
|
||||
SubExprGenCdef.Gen = self
|
||||
self.ExprGenCdef = SubExprGenCdef
|
||||
SubExprGenName: rawptr[ExprGenName.ExprGenName] = CompilerFactory.factory.PermPool.alloc(ExprGenName.ExprGenName.__sizeof__())
|
||||
SubExprGenName: ExprGenName.ExprGenName* = CompilerFactory.factory.PermPool.alloc(ExprGenName.ExprGenName.__sizeof__())
|
||||
if SubExprGenName is None:
|
||||
stdio.printf("FAIL: ExprGenName alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenName, 0, ExprGenName.ExprGenName.__sizeof__())
|
||||
SubExprGenName.Gen = self
|
||||
self.ExprGenName = SubExprGenName
|
||||
SubExprGenAttr: rawptr[ExprGenAttr.ExprGenAttr] = CompilerFactory.factory.PermPool.alloc(ExprGenAttr.ExprGenAttr.__sizeof__())
|
||||
SubExprGenAttr: ExprGenAttr.ExprGenAttr* = CompilerFactory.factory.PermPool.alloc(ExprGenAttr.ExprGenAttr.__sizeof__())
|
||||
if SubExprGenAttr is None:
|
||||
stdio.printf("FAIL: ExprGenAttr alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenAttr, 0, ExprGenAttr.ExprGenAttr.__sizeof__())
|
||||
SubExprGenAttr.Gen = self
|
||||
self.ExprGenAttr = SubExprGenAttr
|
||||
SubExprGenCls: rawptr[ExprGenCls.ExprGenCls] = CompilerFactory.factory.PermPool.alloc(ExprGenCls.ExprGenCls.__sizeof__())
|
||||
SubExprGenCls: ExprGenCls.ExprGenCls* = CompilerFactory.factory.PermPool.alloc(ExprGenCls.ExprGenCls.__sizeof__())
|
||||
if SubExprGenCls is None:
|
||||
stdio.printf("FAIL: ExprGenCls alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubExprGenCls, 0, ExprGenCls.ExprGenCls.__sizeof__())
|
||||
SubExprGenCls.Gen = self
|
||||
self.ExprGenCls = SubExprGenCls
|
||||
SubCallGenBase: rawptr[CallGenBase.CallGenBase] = CompilerFactory.factory.PermPool.alloc(CallGenBase.CallGenBase.__sizeof__())
|
||||
SubCallGenBase: CallGenBase.CallGenBase* = CompilerFactory.factory.PermPool.alloc(CallGenBase.CallGenBase.__sizeof__())
|
||||
if SubCallGenBase is None:
|
||||
stdio.printf("FAIL: CallGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenBase, 0, CallGenBase.CallGenBase.__sizeof__())
|
||||
SubCallGenBase.Gen = self
|
||||
self.CallGenBase = SubCallGenBase
|
||||
SubCallGenCBuiltin: rawptr[CallGenCBuiltin.CallGenCBuiltin] = CompilerFactory.factory.PermPool.alloc(CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
|
||||
SubCallGenCBuiltin: CallGenCBuiltin.CallGenCBuiltin* = CompilerFactory.factory.PermPool.alloc(CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
|
||||
if SubCallGenCBuiltin is None:
|
||||
stdio.printf("FAIL: CallGenCBuiltin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCBuiltin, 0, CallGenCBuiltin.CallGenCBuiltin.__sizeof__())
|
||||
SubCallGenCBuiltin.Gen = self
|
||||
self.CallGenCBuiltin = SubCallGenCBuiltin
|
||||
SubCallGenLeafKit: rawptr[CallGenLeafKit.CallGenLeafKit] = CompilerFactory.factory.PermPool.alloc(CallGenLeafKit.CallGenLeafKit.__sizeof__())
|
||||
SubCallGenLeafKit: CallGenLeafKit.CallGenLeafKit* = CompilerFactory.factory.PermPool.alloc(CallGenLeafKit.CallGenLeafKit.__sizeof__())
|
||||
if SubCallGenLeafKit is None:
|
||||
stdio.printf("FAIL: CallGenLeafKit alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenLeafKit, 0, CallGenLeafKit.CallGenLeafKit.__sizeof__())
|
||||
SubCallGenLeafKit.Gen = self
|
||||
self.CallGenLeafKit = SubCallGenLeafKit
|
||||
SubCallGenCtor: rawptr[CallGenCtor.CallGenCtor] = CompilerFactory.factory.PermPool.alloc(CallGenCtor.CallGenCtor.__sizeof__())
|
||||
SubCallGenCtor: CallGenCtor.CallGenCtor* = CompilerFactory.factory.PermPool.alloc(CallGenCtor.CallGenCtor.__sizeof__())
|
||||
if SubCallGenCtor is None:
|
||||
stdio.printf("FAIL: CallGenCtor alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCtor, 0, CallGenCtor.CallGenCtor.__sizeof__())
|
||||
SubCallGenCtor.Gen = self
|
||||
self.CallGenCtor = SubCallGenCtor
|
||||
SubCallGenCall: rawptr[CallGenCall.CallGenCall] = CompilerFactory.factory.PermPool.alloc(CallGenCall.CallGenCall.__sizeof__())
|
||||
SubCallGenCall: CallGenCall.CallGenCall* = CompilerFactory.factory.PermPool.alloc(CallGenCall.CallGenCall.__sizeof__())
|
||||
if SubCallGenCall is None:
|
||||
stdio.printf("FAIL: CallGenCall alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenCall, 0, CallGenCall.CallGenCall.__sizeof__())
|
||||
SubCallGenCall.Gen = self
|
||||
self.CallGenCall = SubCallGenCall
|
||||
SubCallGen: rawptr[CallGenMixin.CallGenMixin] = CompilerFactory.factory.PermPool.alloc(CallGenMixin.CallGenMixin.__sizeof__())
|
||||
SubCallGen: CallGenMixin.CallGenMixin* = CompilerFactory.factory.PermPool.alloc(CallGenMixin.CallGenMixin.__sizeof__())
|
||||
if SubCallGen is None:
|
||||
stdio.printf("FAIL: CallGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGen, 0, CallGenMixin.CallGenMixin.__sizeof__())
|
||||
SubCallGen.Gen = self
|
||||
self.CallGen = SubCallGen
|
||||
SubCallGenDispatch: rawptr[CallGenDispatch.CallGenDispatch] = CompilerFactory.factory.PermPool.alloc(CallGenDispatch.CallGenDispatch.__sizeof__())
|
||||
SubCallGenDispatch: CallGenDispatch.CallGenDispatch* = CompilerFactory.factory.PermPool.alloc(CallGenDispatch.CallGenDispatch.__sizeof__())
|
||||
if SubCallGenDispatch is None:
|
||||
stdio.printf("FAIL: CallGenDispatch alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenDispatch, 0, CallGenDispatch.CallGenDispatch.__sizeof__())
|
||||
SubCallGenDispatch.Gen = self
|
||||
self.CallGenDispatch = SubCallGenDispatch
|
||||
SubCallGenLib: rawptr[CallGenLib.CallGenLib] = CompilerFactory.factory.PermPool.alloc(CallGenLib.CallGenLib.__sizeof__())
|
||||
SubCallGenLib: CallGenLib.CallGenLib* = CompilerFactory.factory.PermPool.alloc(CallGenLib.CallGenLib.__sizeof__())
|
||||
if SubCallGenLib is None:
|
||||
stdio.printf("FAIL: CallGenLib alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenLib, 0, CallGenLib.CallGenLib.__sizeof__())
|
||||
SubCallGenLib.Gen = self
|
||||
self.CallGenLib = SubCallGenLib
|
||||
SubCallGenVt: rawptr[CallGenVt.CallGenVt] = CompilerFactory.factory.PermPool.alloc(CallGenVt.CallGenVt.__sizeof__())
|
||||
SubCallGenVt: CallGenVt.CallGenVt* = CompilerFactory.factory.PermPool.alloc(CallGenVt.CallGenVt.__sizeof__())
|
||||
if SubCallGenVt is None:
|
||||
stdio.printf("FAIL: CallGenVt alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenVt, 0, CallGenVt.CallGenVt.__sizeof__())
|
||||
SubCallGenVt.Gen = self
|
||||
self.CallGenVt = SubCallGenVt
|
||||
SubCallGenVa: rawptr[CallGenVa.CallGenVa] = CompilerFactory.factory.PermPool.alloc(CallGenVa.CallGenVa.__sizeof__())
|
||||
SubCallGenVa: CallGenVa.CallGenVa* = CompilerFactory.factory.PermPool.alloc(CallGenVa.CallGenVa.__sizeof__())
|
||||
if SubCallGenVa is None:
|
||||
stdio.printf("FAIL: CallGenVa alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenVa, 0, CallGenVa.CallGenVa.__sizeof__())
|
||||
SubCallGenVa.Gen = self
|
||||
self.CallGenVa = SubCallGenVa
|
||||
SubCallGenProp: rawptr[CallGenProp.CallGenProp] = CompilerFactory.factory.PermPool.alloc(CallGenProp.CallGenProp.__sizeof__())
|
||||
SubCallGenProp: CallGenProp.CallGenProp* = CompilerFactory.factory.PermPool.alloc(CallGenProp.CallGenProp.__sizeof__())
|
||||
if SubCallGenProp is None:
|
||||
stdio.printf("FAIL: CallGenProp alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenProp, 0, CallGenProp.CallGenProp.__sizeof__())
|
||||
SubCallGenProp.Gen = self
|
||||
self.CallGenProp = SubCallGenProp
|
||||
SubCallGenFd: rawptr[CallGenFd.CallGenFd] = CompilerFactory.factory.PermPool.alloc(CallGenFd.CallGenFd.__sizeof__())
|
||||
SubCallGenFd: CallGenFd.CallGenFd* = CompilerFactory.factory.PermPool.alloc(CallGenFd.CallGenFd.__sizeof__())
|
||||
if SubCallGenFd is None:
|
||||
stdio.printf("FAIL: CallGenFd alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubCallGenFd, 0, CallGenFd.CallGenFd.__sizeof__())
|
||||
SubCallGenFd.Gen = self
|
||||
self.CallGenFd = SubCallGenFd
|
||||
SubFuncGenBase: rawptr[FuncGenBase.FuncGenBase] = CompilerFactory.factory.PermPool.alloc(FuncGenBase.FuncGenBase.__sizeof__())
|
||||
SubFuncGenBase: FuncGenBase.FuncGenBase* = CompilerFactory.factory.PermPool.alloc(FuncGenBase.FuncGenBase.__sizeof__())
|
||||
if SubFuncGenBase is None:
|
||||
stdio.printf("FAIL: FuncGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGenBase, 0, FuncGenBase.FuncGenBase.__sizeof__())
|
||||
SubFuncGenBase.Gen = self
|
||||
self.FuncGenBase = SubFuncGenBase
|
||||
SubFuncGenDef: rawptr[FuncGenDef.FuncGenDef] = CompilerFactory.factory.PermPool.alloc(FuncGenDef.FuncGenDef.__sizeof__())
|
||||
SubFuncGenDef: FuncGenDef.FuncGenDef* = CompilerFactory.factory.PermPool.alloc(FuncGenDef.FuncGenDef.__sizeof__())
|
||||
if SubFuncGenDef is None:
|
||||
stdio.printf("FAIL: FuncGenDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGenDef, 0, FuncGenDef.FuncGenDef.__sizeof__())
|
||||
SubFuncGenDef.Gen = self
|
||||
self.FuncGenDef = SubFuncGenDef
|
||||
SubFuncGen: rawptr[FuncGenMixin.FuncGenMixin] = CompilerFactory.factory.PermPool.alloc(FuncGenMixin.FuncGenMixin.__sizeof__())
|
||||
SubFuncGen: FuncGenMixin.FuncGenMixin* = CompilerFactory.factory.PermPool.alloc(FuncGenMixin.FuncGenMixin.__sizeof__())
|
||||
if SubFuncGen is None:
|
||||
stdio.printf("FAIL: FuncGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubFuncGen, 0, FuncGenMixin.FuncGenMixin.__sizeof__())
|
||||
SubFuncGen.Gen = self
|
||||
self.FuncGen = SubFuncGen
|
||||
SubClassGenBase: rawptr[ClassGenBase.ClassGenBase] = CompilerFactory.factory.PermPool.alloc(ClassGenBase.ClassGenBase.__sizeof__())
|
||||
SubClassGenBase: ClassGenBase.ClassGenBase* = CompilerFactory.factory.PermPool.alloc(ClassGenBase.ClassGenBase.__sizeof__())
|
||||
if SubClassGenBase is None:
|
||||
stdio.printf("FAIL: ClassGenBase alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenBase, 0, ClassGenBase.ClassGenBase.__sizeof__())
|
||||
SubClassGenBase.Gen = self
|
||||
self.ClassGenBase = SubClassGenBase
|
||||
SubClassGen: rawptr[ClassGenMixin.ClassGenMixin] = CompilerFactory.factory.PermPool.alloc(ClassGenMixin.ClassGenMixin.__sizeof__())
|
||||
SubClassGen: ClassGenMixin.ClassGenMixin* = CompilerFactory.factory.PermPool.alloc(ClassGenMixin.ClassGenMixin.__sizeof__())
|
||||
if SubClassGen is None:
|
||||
stdio.printf("FAIL: ClassGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGen, 0, ClassGenMixin.ClassGenMixin.__sizeof__())
|
||||
SubClassGen.Gen = self
|
||||
self.ClassGen = SubClassGen
|
||||
SubClassGenEnum: rawptr[ClassGenEnum.ClassGenEnum] = CompilerFactory.factory.PermPool.alloc(ClassGenEnum.ClassGenEnum.__sizeof__())
|
||||
SubClassGenEnum: ClassGenEnum.ClassGenEnum* = CompilerFactory.factory.PermPool.alloc(ClassGenEnum.ClassGenEnum.__sizeof__())
|
||||
if SubClassGenEnum is None:
|
||||
stdio.printf("FAIL: ClassGenEnum alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenEnum, 0, ClassGenEnum.ClassGenEnum.__sizeof__())
|
||||
SubClassGenEnum.Gen = self
|
||||
self.ClassGenEnum = SubClassGenEnum
|
||||
SubClassGenGeneric: rawptr[ClassGenGeneric.ClassGenGeneric] = CompilerFactory.factory.PermPool.alloc(ClassGenGeneric.ClassGenGeneric.__sizeof__())
|
||||
SubClassGenGeneric: ClassGenGeneric.ClassGenGeneric* = CompilerFactory.factory.PermPool.alloc(ClassGenGeneric.ClassGenGeneric.__sizeof__())
|
||||
if SubClassGenGeneric is None:
|
||||
stdio.printf("FAIL: ClassGenGeneric alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenGeneric, 0, ClassGenGeneric.ClassGenGeneric.__sizeof__())
|
||||
SubClassGenGeneric.Gen = self
|
||||
self.ClassGenGeneric = SubClassGenGeneric
|
||||
SubClassGenVTable: rawptr[ClassGenVTable.ClassGenVTable] = CompilerFactory.factory.PermPool.alloc(ClassGenVTable.ClassGenVTable.__sizeof__())
|
||||
SubClassGenVTable: ClassGenVTable.ClassGenVTable* = CompilerFactory.factory.PermPool.alloc(ClassGenVTable.ClassGenVTable.__sizeof__())
|
||||
if SubClassGenVTable is None:
|
||||
stdio.printf("FAIL: ClassGenVTable alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenVTable, 0, ClassGenVTable.ClassGenVTable.__sizeof__())
|
||||
SubClassGenVTable.Gen = self
|
||||
self.ClassGenVTable = SubClassGenVTable
|
||||
SubClassGenDef: rawptr[ClassGenDef.ClassGenDef] = CompilerFactory.factory.PermPool.alloc(ClassGenDef.ClassGenDef.__sizeof__())
|
||||
SubClassGenDef: ClassGenDef.ClassGenDef* = CompilerFactory.factory.PermPool.alloc(ClassGenDef.ClassGenDef.__sizeof__())
|
||||
if SubClassGenDef is None:
|
||||
stdio.printf("FAIL: ClassGenDef alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubClassGenDef, 0, ClassGenDef.ClassGenDef.__sizeof__())
|
||||
SubClassGenDef.Gen = self
|
||||
self.ClassGenDef = SubClassGenDef
|
||||
SubImportsGen: rawptr[ImportsGenMixin.ImportsGenMixin] = CompilerFactory.factory.PermPool.alloc(ImportsGenMixin.ImportsGenMixin.__sizeof__())
|
||||
SubImportsGen: ImportsGenMixin.ImportsGenMixin* = CompilerFactory.factory.PermPool.alloc(ImportsGenMixin.ImportsGenMixin.__sizeof__())
|
||||
if SubImportsGen is None:
|
||||
stdio.printf("FAIL: ImportsGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubImportsGen, 0, ImportsGenMixin.ImportsGenMixin.__sizeof__())
|
||||
SubImportsGen.Gen = self
|
||||
self.ImportsGen = SubImportsGen
|
||||
SubStmtGenCif: rawptr[StmtGenCifMixin.StmtGenCifMixin] = CompilerFactory.factory.PermPool.alloc(StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
|
||||
SubStmtGenCif: StmtGenCifMixin.StmtGenCifMixin* = CompilerFactory.factory.PermPool.alloc(StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
|
||||
if SubStmtGenCif is None:
|
||||
stdio.printf("FAIL: StmtGenCifMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGenCif, 0, StmtGenCifMixin.StmtGenCifMixin.__sizeof__())
|
||||
SubStmtGenCif.Gen = self
|
||||
self.StmtGenCif = SubStmtGenCif
|
||||
SubStmtGenDecl: rawptr[StmtGenDeclMixin.StmtGenDeclMixin] = CompilerFactory.factory.PermPool.alloc(StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
|
||||
SubStmtGenDecl: StmtGenDeclMixin.StmtGenDeclMixin* = CompilerFactory.factory.PermPool.alloc(StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
|
||||
if SubStmtGenDecl is None:
|
||||
stdio.printf("FAIL: StmtGenDeclMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGenDecl, 0, StmtGenDeclMixin.StmtGenDeclMixin.__sizeof__())
|
||||
SubStmtGenDecl.Gen = self
|
||||
self.StmtGenDecl = SubStmtGenDecl
|
||||
SubStmtGen: rawptr[StmtGenMixin.StmtGenMixin] = CompilerFactory.factory.PermPool.alloc(StmtGenMixin.StmtGenMixin.__sizeof__())
|
||||
SubStmtGen: StmtGenMixin.StmtGenMixin* = CompilerFactory.factory.PermPool.alloc(StmtGenMixin.StmtGenMixin.__sizeof__())
|
||||
if SubStmtGen is None:
|
||||
stdio.printf("FAIL: StmtGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubStmtGen, 0, StmtGenMixin.StmtGenMixin.__sizeof__())
|
||||
SubStmtGen.Gen = self
|
||||
self.StmtGen = SubStmtGen
|
||||
SubMatchGen: rawptr[MatchGenMixin.MatchGenMixin] = CompilerFactory.factory.PermPool.alloc(MatchGenMixin.MatchGenMixin.__sizeof__())
|
||||
SubMatchGen: MatchGenMixin.MatchGenMixin* = CompilerFactory.factory.PermPool.alloc(MatchGenMixin.MatchGenMixin.__sizeof__())
|
||||
if SubMatchGen is None:
|
||||
stdio.printf("FAIL: MatchGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubMatchGen, 0, MatchGenMixin.MatchGenMixin.__sizeof__())
|
||||
SubMatchGen.Gen = self
|
||||
self.MatchGen = SubMatchGen
|
||||
SubAssignGen: rawptr[AssignGenMixin.AssignGenMixin] = CompilerFactory.factory.PermPool.alloc(AssignGenMixin.AssignGenMixin.__sizeof__())
|
||||
SubAssignGen: AssignGenMixin.AssignGenMixin* = CompilerFactory.factory.PermPool.alloc(AssignGenMixin.AssignGenMixin.__sizeof__())
|
||||
if SubAssignGen is None:
|
||||
stdio.printf("FAIL: AssignGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubAssignGen, 0, AssignGenMixin.AssignGenMixin.__sizeof__())
|
||||
SubAssignGen.Gen = self
|
||||
self.AssignGen = SubAssignGen
|
||||
SubVarGen: rawptr[VarGenMixin.VarGenMixin] = CompilerFactory.factory.PermPool.alloc(VarGenMixin.VarGenMixin.__sizeof__())
|
||||
SubVarGen: VarGenMixin.VarGenMixin* = CompilerFactory.factory.PermPool.alloc(VarGenMixin.VarGenMixin.__sizeof__())
|
||||
if SubVarGen is None:
|
||||
stdio.printf("FAIL: VarGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubVarGen, 0, VarGenMixin.VarGenMixin.__sizeof__())
|
||||
SubVarGen.Gen = self
|
||||
self.VarGen = SubVarGen
|
||||
SubTranslatorGen: rawptr[TranslatorGenMixin.TranslatorGenMixin] = CompilerFactory.factory.PermPool.alloc(TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
SubTranslatorGen: TranslatorGenMixin.TranslatorGenMixin* = CompilerFactory.factory.PermPool.alloc(TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
if SubTranslatorGen is None:
|
||||
stdio.printf("FAIL: TranslatorGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
string.memset(SubTranslatorGen, 0, TranslatorGenMixin.TranslatorGenMixin.__sizeof__())
|
||||
SubTranslatorGen.Gen = self
|
||||
self.TranslatorGen = SubTranslatorGen
|
||||
SubAsyncGen: rawptr[AsyncGenMixin.AsyncGenMixin] = CompilerFactory.factory.PermPool.alloc(AsyncGenMixin.AsyncGenMixin.__sizeof__())
|
||||
SubAsyncGen: AsyncGenMixin.AsyncGenMixin* = CompilerFactory.factory.PermPool.alloc(AsyncGenMixin.AsyncGenMixin.__sizeof__())
|
||||
if SubAsyncGen is None:
|
||||
stdio.printf("FAIL: AsyncGenMixin alloc failed\n")
|
||||
stdlib.exit(1)
|
||||
|
||||
@@ -479,7 +479,7 @@ novirtual class ImportsGenMixin:
|
||||
stdio.printf(' File "%s", line %d\n', file_name, lineno)
|
||||
# Show the source line's content (read line lineno for quick location)
|
||||
if lineno > 0 and file_name is not None:
|
||||
f_err: rawptr[fileio.File] = fileio.File(file_name, fileio.MODE.R)
|
||||
f_err: fileio.File* = fileio.File(file_name, fileio.MODE.R)
|
||||
if not f_err.closed:
|
||||
line_buf_err: bytes = stdlib.malloc(512)
|
||||
if line_buf_err is not None:
|
||||
@@ -525,7 +525,7 @@ novirtual class ImportsGenMixin:
|
||||
path_buf[sep_pos] = '\0'
|
||||
string.strcat(path_buf, mod_name)
|
||||
string.strcat(path_buf, ".vp")
|
||||
fex: rawptr[fileio.File] = fileio.File(path_buf, fileio.MODE.R)
|
||||
fex: fileio.File* = fileio.File(path_buf, fileio.MODE.R)
|
||||
if not fex.closed:
|
||||
fex.close()
|
||||
stdlib.free(path_buf)
|
||||
|
||||
@@ -79,17 +79,17 @@ novirtual class MatchGenMixin:
|
||||
while dci < ccn:
|
||||
dcase: ast.AST* = cases_chk.get(dci)
|
||||
if dcase is not None and dcase.kind() == ast.ASTKind.MatchCase:
|
||||
dpat: ast.AST* = rawptr[ast.MatchCase](dcase).pattern
|
||||
dpat: ast.AST* = ast.MatchCase*(dcase).pattern
|
||||
if dpat is not None:
|
||||
if dpat.kind() == ast.ASTKind.MatchAs and rawptr[ast.MatchAs](dpat).pattern is None:
|
||||
if dpat.kind() == ast.ASTKind.MatchAs and ast.MatchAs*(dpat).pattern is None:
|
||||
# Count only guardless wildcard arms; guarded `case _ if ...` arms may repeat and are not counted as default.
|
||||
if rawptr[ast.MatchCase](dcase).guard is None: default_cnt = default_cnt + 1
|
||||
if ast.MatchCase*(dcase).guard is None: default_cnt = default_cnt + 1
|
||||
elif m_node.is_switch == 0:
|
||||
dcj: int = dci + 1
|
||||
while dcj < ccn:
|
||||
dcase2: ast.AST* = cases_chk.get(dcj)
|
||||
if dcase2 is not None and dcase2.kind() == ast.ASTKind.MatchCase:
|
||||
dpat2: ast.AST* = rawptr[ast.MatchCase](dcase2).pattern
|
||||
dpat2: ast.AST* = ast.MatchCase*(dcase2).pattern
|
||||
if self._case_label_same(dpat, dpat2) != 0:
|
||||
self.Gen.TypeGenErr.fatal_error(dcase2, f"match 出现重名 case:第 {dci} 与第 {dcj} 个 case 的标签相同(match 不允许重复 case 标签)", "SyntaxError")
|
||||
dcj = dcj + 1
|
||||
@@ -133,7 +133,7 @@ novirtual class MatchGenMixin:
|
||||
while ci < cn and is_renum == 0:
|
||||
case_node: ast.AST* = cases_list.get(ci)
|
||||
if case_node is not None and case_node.kind() == ast.ASTKind.MatchCase:
|
||||
mc: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(case_node)
|
||||
mc: ast.MatchCase* = (ast.MatchCase*)(case_node)
|
||||
pat: ast.AST* = mc.pattern
|
||||
if pat is not None and pat.kind() == ast.ASTKind.MatchClass:
|
||||
rnm: str = self._extract_renum_name_from_cls(pat)
|
||||
@@ -151,7 +151,7 @@ novirtual class MatchGenMixin:
|
||||
# LLVMType.Ptr -> 'LLVMType'; mlirlite.LLVMType.Ptr -> 'LLVMType'; a bare Name('Ptr') is resolved by scanning all REnum classes.
|
||||
def _extract_renum_name_from_cls(self, pattern: ast.AST*) -> str:
|
||||
if pattern is None: return None
|
||||
mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pattern)
|
||||
mc: ast.MatchClass* = ast.MatchClass*(pattern)
|
||||
cls_node: ast.AST* = mc.cls
|
||||
if cls_node is None: return None
|
||||
# Attribute form.
|
||||
@@ -173,7 +173,7 @@ novirtual class MatchGenMixin:
|
||||
# _extract_variant_name_from_cls - extract the variant name from MatchClass.cls.
|
||||
def _extract_variant_name_from_cls(self, pattern: ast.AST*) -> str:
|
||||
if pattern is None: return None
|
||||
mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pattern)
|
||||
mc: ast.MatchClass* = ast.MatchClass*(pattern)
|
||||
cls_node: ast.AST* = mc.cls
|
||||
if cls_node is None: return None
|
||||
if cls_node.kind() == ast.ASTKind.Attribute:
|
||||
@@ -228,8 +228,8 @@ novirtual class MatchGenMixin:
|
||||
ka: int = a.kind()
|
||||
if ka != b.kind(): return 0
|
||||
if ka == ast.ASTKind.MatchValue:
|
||||
av: ast.AST* = rawptr[ast.MatchValue](a).value
|
||||
bv: ast.AST* = rawptr[ast.MatchValue](b).value
|
||||
av: ast.AST* = ast.MatchValue*(a).value
|
||||
bv: ast.AST* = ast.MatchValue*(b).value
|
||||
return self._value_label_same(av, bv)
|
||||
if ka == ast.ASTKind.MatchSingleton:
|
||||
return 1 # MatchSingleton can only be None
|
||||
@@ -240,8 +240,8 @@ novirtual class MatchGenMixin:
|
||||
if string.strcmp(an, bn) == 0: return 1
|
||||
return 0
|
||||
if ka == ast.ASTKind.MatchOr:
|
||||
ap: list[ast.AST*]* = rawptr[ast.MatchOr](a).patterns
|
||||
bp: list[ast.AST*]* = rawptr[ast.MatchOr](b).patterns
|
||||
ap: list[ast.AST*]* = ast.MatchOr*(a).patterns
|
||||
bp: list[ast.AST*]* = ast.MatchOr*(b).patterns
|
||||
if ap is None or bp is None or len(ap) != len(bp): return 0
|
||||
oi: int = 0
|
||||
while oi < len(ap):
|
||||
@@ -279,7 +279,7 @@ novirtual class MatchGenMixin:
|
||||
while rn_i < rn_n:
|
||||
rn_case: ast.AST* = rn_cases.get(rn_i)
|
||||
if rn_case is not None and rn_case.kind() == ast.ASTKind.MatchCase:
|
||||
if rawptr[ast.MatchCase](rn_case).guard is not None:
|
||||
if ast.MatchCase*(rn_case).guard is not None:
|
||||
self.Gen.TypeGenErr.fatal_error(rn_case, "REnum match 暂不支持 guard 守卫(该臂会被 switch(tag) 静默忽略);请改为普通 match 或去掉 guard", "NotImplementedError")
|
||||
rn_i = rn_i + 1
|
||||
|
||||
@@ -333,9 +333,9 @@ novirtual class MatchGenMixin:
|
||||
# fail-fast: label buffer allocation failed.
|
||||
self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError")
|
||||
viperlib.snprintf(name_buf, 32, "match.default.%d", cnt)
|
||||
default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 3. Prepare collection arrays (CSizeT arrays holding pointers).
|
||||
cases_list: list[ast.AST*]* = node.cases
|
||||
@@ -361,8 +361,8 @@ novirtual class MatchGenMixin:
|
||||
default_case_node: ast.AST* = None
|
||||
|
||||
# SwitchCase linked list.
|
||||
sw_head: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_tail: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_head: mlirlite.SwitchCase* = None
|
||||
sw_tail: mlirlite.SwitchCase* = None
|
||||
sw_count: int = 0
|
||||
|
||||
# Count of arms that must submit a case value (non-default MatchClass always has a variant tag, MatchValue a constant); a mismatch with sw_count means a case was silently dropped, so fail-fast before build_switch.
|
||||
@@ -390,7 +390,7 @@ novirtual class MatchGenMixin:
|
||||
if case_node.kind() != ast.ASTKind.MatchCase:
|
||||
i = i + 1
|
||||
continue
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](case_node)
|
||||
mc: ast.MatchCase* = ast.MatchCase*(case_node)
|
||||
pat: ast.AST* = mc.pattern
|
||||
|
||||
is_def: int = 0
|
||||
@@ -412,29 +412,29 @@ novirtual class MatchGenMixin:
|
||||
if tag_buf is not None: viperlib.snprintf(tag_buf, 32, "%d", tag)
|
||||
cv = mlirlite.ConstInt(pool, tag_ty, tag, tag_buf if tag_buf is not None else "0")
|
||||
elif pk == ast.ASTKind.MatchAs:
|
||||
ma: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat)
|
||||
ma: ast.MatchAs* = ast.MatchAs*(pat)
|
||||
if ma.pattern is None:
|
||||
is_def = 1
|
||||
has_default = 1
|
||||
default_case_node = case_node
|
||||
elif pk == ast.ASTKind.MatchValue:
|
||||
mv: rawptr[ast.MatchValue] = rawptr[ast.MatchValue](pat)
|
||||
mv: ast.MatchValue* = ast.MatchValue*(pat)
|
||||
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
|
||||
elif pk == ast.ASTKind.MatchOr:
|
||||
# MatchOr: multiple values share one BB (use the first value as the case).
|
||||
mo: rawptr[ast.MatchOr] = rawptr[ast.MatchOr](pat)
|
||||
mo: ast.MatchOr* = ast.MatchOr*(pat)
|
||||
pats: list[ast.AST*]* = mo.patterns
|
||||
if pats is not None and len(pats) > 0:
|
||||
first_pat: ast.AST* = pats.get(0)
|
||||
if first_pat is not None and first_pat.kind() == ast.ASTKind.MatchValue:
|
||||
mv2: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(first_pat)
|
||||
mv2: ast.MatchValue* = (ast.MatchValue*)(first_pat)
|
||||
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv2.value, trans._funcs, trans._func_count, trans)
|
||||
|
||||
# Create the case BB.
|
||||
if is_def == 0:
|
||||
if collected >= MAX_MATCH_CASES: break
|
||||
viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i)
|
||||
bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
else: bb = default_bb
|
||||
|
||||
# Detect NoBreak.
|
||||
@@ -457,7 +457,7 @@ novirtual class MatchGenMixin:
|
||||
|
||||
# Build the SwitchCase list (non-default cases that have a value).
|
||||
if is_def == 0 and cv is not None:
|
||||
sc: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, cv, bb)
|
||||
sc: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, cv, bb)
|
||||
if sc is not None:
|
||||
if sw_head is None:
|
||||
sw_head = sc
|
||||
@@ -501,7 +501,7 @@ novirtual class MatchGenMixin:
|
||||
i = 0
|
||||
while i < collected:
|
||||
# pass2 uses the mc cached by pass1 (avoids re-index mismatch).
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_arr[i])
|
||||
mc: ast.MatchCase* = ast.MatchCase*(mc_arr[i])
|
||||
if mc is None:
|
||||
i = i + 1
|
||||
continue
|
||||
@@ -509,7 +509,7 @@ novirtual class MatchGenMixin:
|
||||
|
||||
# Fetch the BB.
|
||||
bb_addr: sizet = bb_arr[i]
|
||||
case_bb: rawptr[mlirlite.BasicBlock] = (rawptr[mlirlite.BasicBlock])(bb_addr)
|
||||
case_bb: mlirlite.BasicBlock* = (mlirlite.BasicBlock*)(bb_addr)
|
||||
is_def: int = def_arr[i]
|
||||
nb: int = nb_arr[i]
|
||||
|
||||
@@ -522,7 +522,7 @@ novirtual class MatchGenMixin:
|
||||
mlirlite.position_at_end(builder, case_bb)
|
||||
|
||||
# break inside a case exits the match (C switch semantics): save the outer loop's break target, override with end_bb, restore on exit.
|
||||
rmb_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
rmb_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
rmb_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = node.is_switch
|
||||
@@ -568,7 +568,7 @@ novirtual class MatchGenMixin:
|
||||
rmb_ft_nj: int = i + 1
|
||||
while rmb_ft_nj < collected and def_arr[rmb_ft_nj] != 0: rmb_ft_nj = rmb_ft_nj + 1
|
||||
if rmb_ft_nj < collected:
|
||||
rmb_ft_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](bb_arr[rmb_ft_nj])
|
||||
rmb_ft_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(bb_arr[rmb_ft_nj])
|
||||
mlirlite.build_br(builder, rmb_ft_bb)
|
||||
elif has_default != 0: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -587,9 +587,9 @@ novirtual class MatchGenMixin:
|
||||
rm_merge_reach = 1
|
||||
else:
|
||||
# Explicit default: translate the `case _` arm recorded by pass1 directly (no def_arr reverse lookup into cases_list, whose indices misalign when arms are skipped).
|
||||
dmc_d: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](default_case_node)
|
||||
dmc_d: ast.MatchCase* = ast.MatchCase*(default_case_node)
|
||||
# The default arm also follows match-case semantics: break exits the match.
|
||||
rmd_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
rmd_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
rmd_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = 1
|
||||
@@ -622,7 +622,7 @@ novirtual class MatchGenMixin:
|
||||
# Binds the pointee in `case LLVMType.Ptr(pointee)` to the subject's payload field.
|
||||
def _bind_variant_fields(self, pat: ast.AST*, renum_name: str, renum_entry: GenTypes.StructEntry*, renum_ty: mlirlite.LLVMType*, subject_ptr: mlirlite.Value*, trans: HT.Translator*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*):
|
||||
if pat is None or renum_entry is None or renum_ty is None: return
|
||||
mc: rawptr[ast.MatchClass] = rawptr[ast.MatchClass](pat)
|
||||
mc: ast.MatchClass* = ast.MatchClass*(pat)
|
||||
pats: list[ast.AST*]* = mc.patterns
|
||||
if pats is None: return
|
||||
# bitcast subject_ptr to renum_ptr_ty (ensures GEP type match).
|
||||
@@ -633,7 +633,7 @@ novirtual class MatchGenMixin:
|
||||
for j in range(pn):
|
||||
sub_pat: ast.AST* = pats.get(j)
|
||||
if sub_pat is not None and sub_pat.kind() == ast.ASTKind.MatchAs:
|
||||
ma: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](sub_pat)
|
||||
ma: ast.MatchAs* = ast.MatchAs*(sub_pat)
|
||||
bind_name: str = ma.name
|
||||
if bind_name is not None:
|
||||
# Bind by position: the j-th MatchClass argument -> payload index j+1 (TPC HandlesMatch.py:305-306; no case-sensitive field-name matching).
|
||||
@@ -730,9 +730,9 @@ novirtual class MatchGenMixin:
|
||||
name_buf: str = pool.alloc(32)
|
||||
if name_buf is None: return 0
|
||||
viperlib.snprintf(name_buf, 32, "match.seq.default.%d", cnt)
|
||||
default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.seq.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 3. Pass 1: collect case info (check/body BBs, default flag, nobreak, guard).
|
||||
cases_list: list[ast.AST*]* = node.cases
|
||||
@@ -760,13 +760,13 @@ novirtual class MatchGenMixin:
|
||||
if case_node is None or case_node.kind() != ast.ASTKind.MatchCase:
|
||||
i = i + 1
|
||||
continue
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](case_node)
|
||||
mc: ast.MatchCase* = ast.MatchCase*(case_node)
|
||||
pat: ast.AST* = mc.pattern
|
||||
is_def: int = 0
|
||||
if pat is not None:
|
||||
pk: int = pat.kind()
|
||||
if pk == ast.ASTKind.MatchAs:
|
||||
ma0: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat)
|
||||
ma0: ast.MatchAs* = ast.MatchAs*(pat)
|
||||
if ma0.pattern is None:
|
||||
# A top-level `case _ if <cond>`: this sequence path treats `_` as default (always true) and would silently ignore the guard; fail-fast before any IR is produced.
|
||||
if mc.guard is not None:
|
||||
@@ -783,9 +783,9 @@ novirtual class MatchGenMixin:
|
||||
else:
|
||||
if collected >= MAX_MATCH_CASES: break
|
||||
viperlib.snprintf(name_buf, 32, "match.seq.check.%d.%d", cnt, i)
|
||||
cbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cbb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.seq.body.%d.%d", cnt, i)
|
||||
bbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
bbb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
check_arr[collected] = sizet(cbb)
|
||||
body_arr[collected] = sizet(bbb)
|
||||
if first_check < 0: first_check = collected
|
||||
@@ -799,7 +799,7 @@ novirtual class MatchGenMixin:
|
||||
|
||||
# 4. Entry -> first check (or default/end).
|
||||
if first_check >= 0:
|
||||
head_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[first_check])
|
||||
head_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(check_arr[first_check])
|
||||
mlirlite.build_br(builder, head_bb)
|
||||
elif has_default == 1: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -810,15 +810,15 @@ novirtual class MatchGenMixin:
|
||||
if def_arr[ci] == 1:
|
||||
ci = ci + 1
|
||||
continue
|
||||
cbb2: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[ci])
|
||||
bbb2: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[ci])
|
||||
cbb2: mlirlite.BasicBlock* = mlirlite.BasicBlock*(check_arr[ci])
|
||||
bbb2: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[ci])
|
||||
mlirlite.position_at_end(builder, cbb2)
|
||||
|
||||
# Compute the match condition (element comparisons && guard).
|
||||
cond: mlirlite.Value* = None
|
||||
cnode: ast.AST* = cases_list.get(ci)
|
||||
mc2: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](cnode)
|
||||
ms: rawptr[ast.MatchSequence] = (rawptr[ast.MatchSequence])(mc2.pattern)
|
||||
mc2: ast.MatchCase* = ast.MatchCase*(cnode)
|
||||
ms: ast.MatchSequence* = (ast.MatchSequence*)(mc2.pattern)
|
||||
pats: list[ast.AST*]* = None
|
||||
if ms is not None: pats = ms.patterns
|
||||
pcount: sizet = 0
|
||||
@@ -834,7 +834,7 @@ novirtual class MatchGenMixin:
|
||||
if pat1 is None: continue
|
||||
pk1: int = pat1.kind()
|
||||
if pk1 == ast.ASTKind.MatchValue:
|
||||
mv: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(pat1)
|
||||
mv: ast.MatchValue* = (ast.MatchValue*)(pat1)
|
||||
pv: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
|
||||
if pv is None: self.Gen.TypeGenErr.fatal_error(pat1, f"序列模式元素 {pi} 翻译失败", "TypeError")
|
||||
sv1: mlirlite.Value* = mlirlite.Value*(subj_vals[pi])
|
||||
@@ -843,7 +843,7 @@ novirtual class MatchGenMixin:
|
||||
if cond is None: cond = c1
|
||||
else: cond = mlirlite.build_and(builder, cond, c1)
|
||||
elif pk1 == ast.ASTKind.MatchAs:
|
||||
ma2: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat1)
|
||||
ma2: ast.MatchAs* = ast.MatchAs*(pat1)
|
||||
if ma2.pattern is None:
|
||||
continue # `_` wildcard: always true
|
||||
if ma2.name is not None:
|
||||
@@ -868,10 +868,10 @@ novirtual class MatchGenMixin:
|
||||
if cond is None: cond = mlirlite.const_int(pool, 1, 1)
|
||||
|
||||
# Next check (or default/end).
|
||||
nxt: rawptr[mlirlite.BasicBlock] = None
|
||||
nxt: mlirlite.BasicBlock* = None
|
||||
nj: int = ci + 1
|
||||
while nj < collected and def_arr[nj] == 1: nj = nj + 1
|
||||
if nj < collected: nxt = rawptr[mlirlite.BasicBlock](check_arr[nj])
|
||||
if nj < collected: nxt = mlirlite.BasicBlock*(check_arr[nj])
|
||||
elif has_default == 1: nxt = default_bb
|
||||
else: nxt = end_bb
|
||||
mlirlite.build_cond_br(builder, cond, bbb2, nxt)
|
||||
@@ -883,12 +883,12 @@ novirtual class MatchGenMixin:
|
||||
if def_arr[ci] == 1:
|
||||
ci = ci + 1
|
||||
continue
|
||||
bbb3: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[ci])
|
||||
bbb3: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[ci])
|
||||
mlirlite.position_at_end(builder, bbb3)
|
||||
cnode2: ast.AST* = cases_list.get(ci)
|
||||
mc3: rawptr[ast.MatchCase] = (rawptr[ast.MatchCase])(cnode2)
|
||||
mc3: ast.MatchCase* = (ast.MatchCase*)(cnode2)
|
||||
# break inside a case exits the match (C switch semantics): save/override _break_bb.
|
||||
sqb_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
sqb_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
sqb_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = 1
|
||||
@@ -912,7 +912,7 @@ novirtual class MatchGenMixin:
|
||||
nj2: int = ci + 1
|
||||
while nj2 < collected and def_arr[nj2] == 1: nj2 = nj2 + 1
|
||||
if nj2 < collected:
|
||||
nbb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[nj2])
|
||||
nbb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[nj2])
|
||||
mlirlite.build_br(builder, nbb)
|
||||
elif has_default == 1: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -925,9 +925,9 @@ novirtual class MatchGenMixin:
|
||||
dbody: list[ast.AST*]* = None
|
||||
if has_default == 1 and default_case_node is not None:
|
||||
# Translate the `case _` arm recorded by pass1 directly (no def_arr reverse lookup into cases_list, whose collected indices misalign with the original ones when arms are skipped).
|
||||
dmc_d: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](default_case_node)
|
||||
dmc_d: ast.MatchCase* = ast.MatchCase*(default_case_node)
|
||||
# The default arm also follows match-case semantics: break exits the match.
|
||||
sqd_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
sqd_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
sqd_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = 1
|
||||
@@ -991,7 +991,7 @@ novirtual class MatchGenMixin:
|
||||
while cg_i < cg_n:
|
||||
cg_case: ast.AST* = cases_g.get(cg_i)
|
||||
if cg_case is not None and cg_case.kind() == ast.ASTKind.MatchCase:
|
||||
if rawptr[ast.MatchCase](cg_case).guard is not None: has_guard = 1
|
||||
if ast.MatchCase*(cg_case).guard is not None: has_guard = 1
|
||||
cg_i = cg_i + 1
|
||||
if has_guard != 0: return self._handle_guarded_simple_match(trans, node, subj_val)
|
||||
|
||||
@@ -1003,9 +1003,9 @@ novirtual class MatchGenMixin:
|
||||
# fail-fast: label buffer allocation failed.
|
||||
self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError")
|
||||
viperlib.snprintf(name_buf, 32, "match.default.%d", cnt)
|
||||
default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 3. Collect case info.
|
||||
cases_list: list[ast.AST*]* = node.cases
|
||||
@@ -1028,8 +1028,8 @@ novirtual class MatchGenMixin:
|
||||
has_default: int = 0
|
||||
# MatchCase node of the exhaustive `case _` arm: recorded in pass1 and used directly in step 7, instead of a def_arr reverse lookup (whose collected -> cases_list indices misalign when arms are skipped, idling default_bb and misjudging merge reachability).
|
||||
default_case_node: ast.AST* = None
|
||||
sw_head: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_tail: rawptr[mlirlite.SwitchCase] = None
|
||||
sw_head: mlirlite.SwitchCase* = None
|
||||
sw_tail: mlirlite.SwitchCase* = None
|
||||
sw_count: int = 0
|
||||
|
||||
# 4. Pass 1: collect + create BBs + build the list.
|
||||
@@ -1042,7 +1042,7 @@ novirtual class MatchGenMixin:
|
||||
if case_node.kind() != ast.ASTKind.MatchCase:
|
||||
i = i + 1
|
||||
continue
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](case_node)
|
||||
mc: ast.MatchCase* = ast.MatchCase*(case_node)
|
||||
pat: ast.AST* = mc.pattern
|
||||
|
||||
is_def: int = 0
|
||||
@@ -1053,14 +1053,14 @@ novirtual class MatchGenMixin:
|
||||
if pat is not None:
|
||||
pk: int = pat.kind()
|
||||
if pk == ast.ASTKind.MatchValue:
|
||||
mv: rawptr[ast.MatchValue] = rawptr[ast.MatchValue](pat)
|
||||
mv: ast.MatchValue* = ast.MatchValue*(pat)
|
||||
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
|
||||
elif pk == ast.ASTKind.MatchSingleton:
|
||||
ms: rawptr[ast.MatchSingleton] = (rawptr[ast.MatchSingleton])(pat)
|
||||
ms: ast.MatchSingleton* = (ast.MatchSingleton*)(pat)
|
||||
# None -> 0
|
||||
cv = mlirlite.const_int32(pool, 0)
|
||||
elif pk == ast.ASTKind.MatchAs:
|
||||
ma: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat)
|
||||
ma: ast.MatchAs* = ast.MatchAs*(pat)
|
||||
if ma.pattern is None:
|
||||
is_def = 1
|
||||
has_default = 1
|
||||
@@ -1078,7 +1078,7 @@ novirtual class MatchGenMixin:
|
||||
if is_def == 0:
|
||||
if collected >= MAX_MATCH_CASES: break
|
||||
viperlib.snprintf(name_buf, 32, "match.case.%d.%d", cnt, i)
|
||||
bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
else: bb = default_bb
|
||||
|
||||
body_list: list[ast.AST*]* = mc.children
|
||||
@@ -1098,7 +1098,7 @@ novirtual class MatchGenMixin:
|
||||
mo_addr: sizet = mo_arr[cur_slot]
|
||||
if mo_addr != 0:
|
||||
# MatchOr arm: emit one case value per alternative, all pointing to the same bb (equivalent to C `case 1: case 2:` sharing a body); non-MatchValue/MatchSingleton alternatives fail-fast.
|
||||
mo2: rawptr[ast.MatchOr] = (rawptr[ast.MatchOr])(mo_addr)
|
||||
mo2: ast.MatchOr* = (ast.MatchOr*)(mo_addr)
|
||||
pats2: list[ast.AST*]* = mo2.patterns
|
||||
if pats2 is None or len(pats2) == 0: self.Gen.TypeGenErr.fatal_error(pat, "switch OR 模式无备选子模式", "TypeError")
|
||||
pats2_n: sizet = len(pats2)
|
||||
@@ -1108,14 +1108,14 @@ novirtual class MatchGenMixin:
|
||||
if alt_pat is not None:
|
||||
alt_cv: mlirlite.Value* = None
|
||||
if alt_pat.kind() == ast.ASTKind.MatchValue:
|
||||
alt_mv: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(alt_pat)
|
||||
alt_mv: ast.MatchValue* = (ast.MatchValue*)(alt_pat)
|
||||
alt_cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, alt_mv.value, trans._funcs, trans._func_count, trans)
|
||||
elif alt_pat.kind() == ast.ASTKind.MatchSingleton:
|
||||
# None -> 0 (same as the single-value/guard paths).
|
||||
alt_cv = mlirlite.const_int32(pool, 0)
|
||||
else: self.Gen.TypeGenErr.fatal_error(alt_pat, "switch OR 模式备选不是值模式", "TypeError")
|
||||
if alt_cv is not None:
|
||||
sc2: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, alt_cv, bb)
|
||||
sc2: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, alt_cv, bb)
|
||||
if sc2 is not None:
|
||||
if sw_head is None:
|
||||
sw_head = sc2
|
||||
@@ -1126,7 +1126,7 @@ novirtual class MatchGenMixin:
|
||||
sw_count = sw_count + 1
|
||||
pats2_i = pats2_i + 1
|
||||
elif cv is not None:
|
||||
sc: rawptr[mlirlite.SwitchCase] = mlirlite.new_switch_case(pool, cv, bb)
|
||||
sc: mlirlite.SwitchCase* = mlirlite.new_switch_case(pool, cv, bb)
|
||||
if sc is not None:
|
||||
if sw_head is None:
|
||||
sw_head = sc
|
||||
@@ -1148,10 +1148,10 @@ novirtual class MatchGenMixin:
|
||||
if case_node is None:
|
||||
i = i + 1
|
||||
continue
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](case_node)
|
||||
mc: ast.MatchCase* = ast.MatchCase*(case_node)
|
||||
|
||||
bb_addr: sizet = bb_arr[i]
|
||||
case_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](bb_addr)
|
||||
case_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(bb_addr)
|
||||
is_def: int = def_arr[i]
|
||||
nb: int = nb_arr[i]
|
||||
|
||||
@@ -1163,7 +1163,7 @@ novirtual class MatchGenMixin:
|
||||
mlirlite.position_at_end(builder, case_bb)
|
||||
|
||||
# break inside a case exits the match (C switch semantics): save/override _break_bb.
|
||||
smb_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
smb_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
smb_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = 1
|
||||
@@ -1191,7 +1191,7 @@ novirtual class MatchGenMixin:
|
||||
sm_ft_nj: int = i + 1
|
||||
while sm_ft_nj < collected and def_arr[sm_ft_nj] != 0: sm_ft_nj = sm_ft_nj + 1
|
||||
if sm_ft_nj < collected:
|
||||
sm_ft_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](bb_arr[sm_ft_nj])
|
||||
sm_ft_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(bb_arr[sm_ft_nj])
|
||||
mlirlite.build_br(builder, sm_ft_bb)
|
||||
elif has_default != 0: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -1210,9 +1210,9 @@ novirtual class MatchGenMixin:
|
||||
sm_merge_reach = 1
|
||||
else:
|
||||
# Translate the `case _` arm recorded by pass1 directly (no def_arr reverse lookup into cases_list, whose collected indices misalign with the original ones when arms are skipped).
|
||||
dmc_d: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](default_case_node)
|
||||
dmc_d: ast.MatchCase* = ast.MatchCase*(default_case_node)
|
||||
# The default arm also follows match-case semantics: break exits the match.
|
||||
smd_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
smd_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
smd_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = node.is_switch
|
||||
@@ -1256,9 +1256,9 @@ novirtual class MatchGenMixin:
|
||||
name_buf: str = pool.alloc(32)
|
||||
if name_buf is None: self.Gen.TypeGenErr.fatal_error(node, "标签缓冲区分配失败", "TypeError")
|
||||
viperlib.snprintf(name_buf, 32, "match.guard.default.%d", cnt)
|
||||
default_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
default_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.guard.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# 2. Collect case info (check/body BBs, default flag, nobreak, mc, cv).
|
||||
cases_list: list[ast.AST*]* = node.cases
|
||||
@@ -1289,7 +1289,7 @@ novirtual class MatchGenMixin:
|
||||
if case_node is None or case_node.kind() != ast.ASTKind.MatchCase:
|
||||
i = i + 1
|
||||
continue
|
||||
mc: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](case_node)
|
||||
mc: ast.MatchCase* = ast.MatchCase*(case_node)
|
||||
pat: ast.AST* = mc.pattern
|
||||
gnode0: ast.AST* = mc.guard
|
||||
is_def: int = 0
|
||||
@@ -1299,13 +1299,13 @@ novirtual class MatchGenMixin:
|
||||
if pat is not None:
|
||||
pk: int = pat.kind()
|
||||
if pk == ast.ASTKind.MatchValue:
|
||||
mv: rawptr[ast.MatchValue] = rawptr[ast.MatchValue](pat)
|
||||
mv: ast.MatchValue* = ast.MatchValue*(pat)
|
||||
cv = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, mv.value, trans._funcs, trans._func_count, trans)
|
||||
elif pk == ast.ASTKind.MatchSingleton:
|
||||
# None -> 0
|
||||
cv = mlirlite.const_int32(pool, 0)
|
||||
elif pk == ast.ASTKind.MatchAs:
|
||||
ma: rawptr[ast.MatchAs] = rawptr[ast.MatchAs](pat)
|
||||
ma: ast.MatchAs* = ast.MatchAs*(pat)
|
||||
if ma.pattern is None and gnode0 is None:
|
||||
# The single guardless wildcard arm -> default.
|
||||
is_def = 1
|
||||
@@ -1323,9 +1323,9 @@ novirtual class MatchGenMixin:
|
||||
body_arr[collected] = sizet(default_bb)
|
||||
else:
|
||||
viperlib.snprintf(name_buf, 32, "match.guard.check.%d.%d", cnt, i)
|
||||
cbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cbb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "match.guard.body.%d.%d", cnt, i)
|
||||
bbb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
bbb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
check_arr[collected] = sizet(cbb)
|
||||
body_arr[collected] = sizet(bbb)
|
||||
if first_check < 0: first_check = collected
|
||||
@@ -1341,7 +1341,7 @@ novirtual class MatchGenMixin:
|
||||
|
||||
# 3. Entry -> first check (or default/end).
|
||||
if first_check >= 0:
|
||||
head_bb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[first_check])
|
||||
head_bb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(check_arr[first_check])
|
||||
mlirlite.build_br(builder, head_bb)
|
||||
elif has_default == 1: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -1352,17 +1352,17 @@ novirtual class MatchGenMixin:
|
||||
if def_arr[ci] == 1:
|
||||
ci = ci + 1
|
||||
continue
|
||||
cbb2: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](check_arr[ci])
|
||||
bbb2: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[ci])
|
||||
cbb2: mlirlite.BasicBlock* = mlirlite.BasicBlock*(check_arr[ci])
|
||||
bbb2: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[ci])
|
||||
mlirlite.position_at_end(builder, cbb2)
|
||||
mc2: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_arr[ci])
|
||||
mc2: ast.MatchCase* = ast.MatchCase*(mc_arr[ci])
|
||||
# Value condition: subj_val == case value (a wildcard arm has no case value, so cond stays None = always true).
|
||||
cond: mlirlite.Value* = None
|
||||
or_addr: sizet = or_arr[ci]
|
||||
cv_addr: sizet = cv_arr[ci]
|
||||
if or_addr != 0:
|
||||
# MatchOr arm: cond = (subj_val == cv_0) OR (subj_val == cv_1) OR ...; each alternative is compared then ORed (non-MatchValue/MatchSingleton alternatives cannot produce a value -> fail-fast).
|
||||
mo4: rawptr[ast.MatchOr] = (rawptr[ast.MatchOr])(or_addr)
|
||||
mo4: ast.MatchOr* = (ast.MatchOr*)(or_addr)
|
||||
pats4: list[ast.AST*]* = mo4.patterns
|
||||
if pats4 is None or len(pats4) == 0: self.Gen.TypeGenErr.fatal_error(node, "guard OR 模式无备选子模式", "TypeError")
|
||||
pats4_n: sizet = len(pats4)
|
||||
@@ -1372,7 +1372,7 @@ novirtual class MatchGenMixin:
|
||||
if alt_pat2 is not None:
|
||||
alt_cv2: mlirlite.Value* = None
|
||||
if alt_pat2.kind() == ast.ASTKind.MatchValue:
|
||||
alt_mv2: rawptr[ast.MatchValue] = (rawptr[ast.MatchValue])(alt_pat2)
|
||||
alt_mv2: ast.MatchValue* = (ast.MatchValue*)(alt_pat2)
|
||||
alt_cv2 = self.Gen.ExprGen.translate_value(builder, pool, trans.Module, alt_mv2.value, trans._funcs, trans._func_count, trans)
|
||||
elif alt_pat2.kind() == ast.ASTKind.MatchSingleton:
|
||||
# None -> 0 (same as the single-value path).
|
||||
@@ -1405,10 +1405,10 @@ novirtual class MatchGenMixin:
|
||||
else: cond = mlirlite.build_and(builder, cond, g1)
|
||||
if cond is None: cond = mlirlite.const_int(pool, 1, 1)
|
||||
# Next check (skipping default) -> else default/end.
|
||||
nxt: rawptr[mlirlite.BasicBlock] = None
|
||||
nxt: mlirlite.BasicBlock* = None
|
||||
nj: int = ci + 1
|
||||
while nj < collected and def_arr[nj] == 1: nj = nj + 1
|
||||
if nj < collected: nxt = rawptr[mlirlite.BasicBlock](check_arr[nj])
|
||||
if nj < collected: nxt = mlirlite.BasicBlock*(check_arr[nj])
|
||||
elif has_default == 1: nxt = default_bb
|
||||
else: nxt = end_bb
|
||||
mlirlite.build_cond_br(builder, cond, bbb2, nxt)
|
||||
@@ -1420,11 +1420,11 @@ novirtual class MatchGenMixin:
|
||||
if def_arr[ci] == 1:
|
||||
ci = ci + 1
|
||||
continue
|
||||
bbb3: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[ci])
|
||||
bbb3: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[ci])
|
||||
mlirlite.position_at_end(builder, bbb3)
|
||||
mc3: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_arr[ci])
|
||||
mc3: ast.MatchCase* = ast.MatchCase*(mc_arr[ci])
|
||||
# break inside a case exits the match (C switch semantics): save/override _break_bb.
|
||||
gmb_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
gmb_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
gmb_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = 1
|
||||
@@ -1448,7 +1448,7 @@ novirtual class MatchGenMixin:
|
||||
nj2: int = ci + 1
|
||||
while nj2 < collected and def_arr[nj2] == 1: nj2 = nj2 + 1
|
||||
if nj2 < collected:
|
||||
nbb: rawptr[mlirlite.BasicBlock] = rawptr[mlirlite.BasicBlock](body_arr[nj2])
|
||||
nbb: mlirlite.BasicBlock* = mlirlite.BasicBlock*(body_arr[nj2])
|
||||
mlirlite.build_br(builder, nbb)
|
||||
elif has_default == 1: mlirlite.build_br(builder, default_bb)
|
||||
else: mlirlite.build_br(builder, end_bb)
|
||||
@@ -1465,9 +1465,9 @@ novirtual class MatchGenMixin:
|
||||
trans._ctrl_merge_reachable = 1
|
||||
gm_merge_reach = 1
|
||||
else:
|
||||
dmc_d: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](default_case_node)
|
||||
dmc_d: ast.MatchCase* = ast.MatchCase*(default_case_node)
|
||||
# The default arm also follows match-case semantics: break exits the match.
|
||||
gmd_old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
gmd_old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
trans._break_bb = end_bb
|
||||
gmd_old_inmc: int = trans._in_switch_case
|
||||
trans._in_switch_case = node.is_switch
|
||||
|
||||
@@ -32,7 +32,7 @@ novirtual class StmtGenCifMixin:
|
||||
CifEvalOk: sizet
|
||||
|
||||
# --- enum registry (was HandlesEnum._enum_table/_enum_count) ---
|
||||
EnumTable: rawptr[GenTypes.EnumEntry]
|
||||
EnumTable: GenTypes.EnumEntry*
|
||||
EnumCount: int
|
||||
|
||||
# --- OOM stmt-level diag count (translate_stmt rate-limits printed used) ---
|
||||
@@ -180,7 +180,7 @@ novirtual class StmtGenCifMixin:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.BoolOp:
|
||||
bo: rawptr[ast.BoolOp] = rawptr[ast.BoolOp](node)
|
||||
bo: ast.BoolOp* = ast.BoolOp*(node)
|
||||
vals: list[ast.AST*]* = bo.values
|
||||
if vals is None:
|
||||
self.CifEvalOk = 0
|
||||
@@ -201,7 +201,7 @@ novirtual class StmtGenCifMixin:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
if k == ast.ASTKind.Compare:
|
||||
cmp: rawptr[ast.Compare] = rawptr[ast.Compare](node)
|
||||
cmp: ast.Compare* = ast.Compare*(node)
|
||||
lv: int = self._cif_eval_node(pool, trans, cmp.left)
|
||||
if self.CifEvalOk == 0: return 0
|
||||
ops_list: list[int]* = (list[int]*)(cmp.ops)
|
||||
@@ -263,7 +263,7 @@ novirtual class StmtGenCifMixin:
|
||||
self.CifEvalOk = 0
|
||||
return 0
|
||||
|
||||
def _eval_ctraits_isptr(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int:
|
||||
def _eval_ctraits_isptr(self, symtab: GenTypes.SymbolTable*, name: str) -> int:
|
||||
"""Evaluate ctraits.isptr(name): 1 if pointer, 0 if not, -1 if undeterminable."""
|
||||
if name is None or symtab is None: return -1
|
||||
v: mlirlite.Value* = self.Gen.VarGen.lookup_var(symtab, name)
|
||||
@@ -354,7 +354,7 @@ novirtual class StmtGenCifMixin:
|
||||
# a bare return emits the return-type default zero (void→ret void, ptr→null, float→0.0).
|
||||
def translate_return(self, trans: HT.Translator*, node: ast.AST*) -> int:
|
||||
"""Translate a Return statement."""
|
||||
rt: rawptr[ast.Return] = rawptr[ast.Return](node)
|
||||
rt: ast.Return* = ast.Return*(node)
|
||||
if rt is None: return 0
|
||||
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
@@ -550,7 +550,7 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
if builder is None or func is None: return 0
|
||||
|
||||
if_node: rawptr[ast.If] = rawptr[ast.If](node)
|
||||
if_node: ast.If* = ast.If*(node)
|
||||
|
||||
# 0. compile-time macro condition: if c.CIf/CIfdef/CIfndef - if evaluable, compile only
|
||||
# the taken branch (elif recurses); if not, fall back to runtime translation.
|
||||
@@ -596,10 +596,10 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "if.then.%d", cnt)
|
||||
then_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
then_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "if.end.%d", cnt)
|
||||
merge_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
merge_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# check for an else branch
|
||||
has_else: int = 0
|
||||
@@ -607,7 +607,7 @@ novirtual class StmtGenCifMixin:
|
||||
if orelse_list is not None:
|
||||
if len(orelse_list) > 0: has_else = 1
|
||||
|
||||
else_bb: rawptr[mlirlite.BasicBlock] = None
|
||||
else_bb: mlirlite.BasicBlock* = None
|
||||
if has_else == 1:
|
||||
viperlib.snprintf(name_buf, 32, "if.else.%d", cnt)
|
||||
else_bb = mlirlite.create_block(pool, func, name_buf)
|
||||
@@ -673,14 +673,14 @@ novirtual class StmtGenCifMixin:
|
||||
if len(orelse_list) > 0: return 1
|
||||
return 0
|
||||
|
||||
def _MakeLoopElseBlock(self, pool: memhub.MemBuddy*, func: mlirlite.Function*, name_buf: str, kind: str, cnt: int, has_else: int) -> rawptr[mlirlite.BasicBlock]:
|
||||
def _MakeLoopElseBlock(self, pool: memhub.MemBuddy*, func: mlirlite.Function*, name_buf: str, kind: str, cnt: int, has_else: int) -> mlirlite.BasicBlock*:
|
||||
"""Create the loop-else block named kind.else.cnt when has_else is set, else None."""
|
||||
if has_else == 0: return None
|
||||
if func is None: return None
|
||||
viperlib.snprintf(name_buf, 32, "%s.else.%d", kind, cnt)
|
||||
return mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
def _EmitLoopElse(self, trans: HT.Translator*, orelse_list: list[ast.AST*]*, else_bb: rawptr[mlirlite.BasicBlock], end_bb: rawptr[mlirlite.BasicBlock]) -> int:
|
||||
def _EmitLoopElse(self, trans: HT.Translator*, orelse_list: list[ast.AST*]*, else_bb: mlirlite.BasicBlock*, end_bb: mlirlite.BasicBlock*) -> int:
|
||||
"""Emit the loop-else block into else_bb, translating orelse and branching to end_bb."""
|
||||
if else_bb is None: return 0
|
||||
builder: mlirlite.IRBuilder* = trans._cur_builder
|
||||
@@ -710,7 +710,7 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
if builder is None or func is None: return 0
|
||||
|
||||
while_node: rawptr[ast.While] = rawptr[ast.While](node)
|
||||
while_node: ast.While* = ast.While*(node)
|
||||
|
||||
# 1. create blocks cond/body/end (trans._label_counter labels, not shared with SSA)
|
||||
cnt: int = trans._label_counter
|
||||
@@ -718,17 +718,17 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "while.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "while.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "while.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: the natural-exit (condition false) edge targets else_bb (else end_bb)
|
||||
has_else_while: int = self._LoopElseCount(while_node.orelse)
|
||||
else_bb_while: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "while", cnt, has_else_while)
|
||||
else_bb_while: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "while", cnt, has_else_while)
|
||||
|
||||
# 2. branch to the cond block
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
@@ -748,8 +748,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.position_at_end(builder, body_bb)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = cond_bb
|
||||
|
||||
@@ -1065,20 +1065,20 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "for.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "for.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: the exhausted-iterator (i out of range) edge targets else_bb (else end_bb)
|
||||
has_else_for: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_for: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "for", cnt, has_else_for)
|
||||
else_bb_for: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "for", cnt, has_else_for)
|
||||
|
||||
# 7. branch to the cond block
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
@@ -1112,8 +1112,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.position_at_end(builder, body_bb)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -1336,20 +1336,20 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "seq.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "seq.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "seq.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "seq.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: the exhausted edge (any source out of range/terminator) targets else_bb (else end_bb)
|
||||
has_else_seq: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_seq: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "seq", cnt, has_else_seq)
|
||||
else_bb_seq: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "seq", cnt, has_else_seq)
|
||||
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
|
||||
@@ -1424,8 +1424,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_store(builder, v2c, t2_alloca)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -1508,20 +1508,20 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "ptr.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "ptr.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: the terminating-element (empty deref) edge targets else_bb (else end_bb)
|
||||
has_else_ptr: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_ptr: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "ptr", cnt, has_else_ptr)
|
||||
else_bb_ptr: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "ptr", cnt, has_else_ptr)
|
||||
|
||||
# branch to cond
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
@@ -1549,8 +1549,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_store(builder, cur_elem, var_alloca)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -1624,23 +1624,23 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "arr.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "arr.elem.%d", cnt)
|
||||
elem_check_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
elem_check_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "arr.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "arr.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "arr.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: out-of-range or terminator (natural end) edge targets else_bb (else end_bb)
|
||||
has_else_arr: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_arr: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "arr", cnt, has_else_arr)
|
||||
else_bb_arr: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "arr", cnt, has_else_arr)
|
||||
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
|
||||
@@ -1678,8 +1678,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.position_at_end(builder, body_bb)
|
||||
mlirlite.build_store(builder, cur_elem, var_alloca)
|
||||
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -1798,20 +1798,20 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "lst.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "lst.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "lst.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "lst.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: exhausted (idx out of range) edge targets else_bb (else end_bb)
|
||||
has_else_lst: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_lst: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "lst", cnt, has_else_lst)
|
||||
else_bb_lst: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "lst", cnt, has_else_lst)
|
||||
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
|
||||
@@ -1833,8 +1833,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_store(builder, cur_elem, var_alloca)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -1896,20 +1896,20 @@ novirtual class StmtGenCifMixin:
|
||||
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dict.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "dict.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "dict.incr.%d", cnt)
|
||||
incr_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
incr_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
viperlib.snprintf(name_buf, 32, "dict.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
|
||||
# loop else: exhausted (idx out of range) edge targets else_bb (else end_bb)
|
||||
has_else_dict: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_dict: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "dict", cnt, has_else_dict)
|
||||
else_bb_dict: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "dict", cnt, has_else_dict)
|
||||
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
|
||||
@@ -1930,8 +1930,8 @@ novirtual class StmtGenCifMixin:
|
||||
mlirlite.build_store(builder, cur_key, var_alloca)
|
||||
|
||||
# save the old loop context and set break/continue targets
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = incr_bb
|
||||
|
||||
@@ -2024,18 +2024,18 @@ novirtual class StmtGenCifMixin:
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "oop.cond.%d", cnt)
|
||||
cond_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
cond_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "oop.body.%d", cnt)
|
||||
body_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
body_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "oop.step.%d", cnt)
|
||||
step_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
step_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
viperlib.snprintf(name_buf, 32, "oop.end.%d", cnt)
|
||||
end_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
end_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
if cond_bb is None or body_bb is None or step_bb is None or end_bb is None: return 0
|
||||
|
||||
# loop else: __next__ returning stop (exhausted) edge targets else_bb (else end_bb)
|
||||
has_else_oop: int = self._LoopElseCount(for_node.orelse)
|
||||
else_bb_oop: rawptr[mlirlite.BasicBlock] = self._MakeLoopElseBlock(pool, func, name_buf, "oop", cnt, has_else_oop)
|
||||
else_bb_oop: mlirlite.BasicBlock* = self._MakeLoopElseBlock(pool, func, name_buf, "oop", cnt, has_else_oop)
|
||||
|
||||
mlirlite.build_br(builder, cond_bb)
|
||||
|
||||
@@ -2065,8 +2065,8 @@ novirtual class StmtGenCifMixin:
|
||||
# 7. body block: store element → translate loop body → br step
|
||||
mlirlite.position_at_end(builder, body_bb)
|
||||
if var_alloca is not None: mlirlite.build_store(builder, next_val, var_alloca)
|
||||
old_break: rawptr[mlirlite.BasicBlock] = trans._break_bb
|
||||
old_continue: rawptr[mlirlite.BasicBlock] = trans._continue_bb
|
||||
old_break: mlirlite.BasicBlock* = trans._break_bb
|
||||
old_continue: mlirlite.BasicBlock* = trans._continue_bb
|
||||
trans._break_bb = end_bb
|
||||
trans._continue_bb = step_bb
|
||||
body: list[ast.AST*]* = for_node.children
|
||||
|
||||
@@ -32,7 +32,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
|
||||
def translate_global(self, trans: HT.Translator*, node: ast.AST*) -> int:
|
||||
"""Translate a global statement and record the global variable names"""
|
||||
gn: rawptr[ast.Global] = rawptr[ast.Global](node)
|
||||
gn: ast.Global* = ast.Global*(node)
|
||||
if gn is None: return 0
|
||||
names: list[ast.AST*]* = gn.names
|
||||
if names is None: return 0
|
||||
@@ -46,7 +46,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
|
||||
def translate_nonlocal(self, trans: HT.Translator*, node: ast.AST*) -> int:
|
||||
"""Translate a nonlocal statement and record names with their types"""
|
||||
nl: rawptr[ast.Nonlocal] = rawptr[ast.Nonlocal](node)
|
||||
nl: ast.Nonlocal* = ast.Nonlocal*(node)
|
||||
if nl is None: return 0
|
||||
names: list[ast.AST*]* = nl.names
|
||||
if names is None: return 0
|
||||
@@ -74,7 +74,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
|
||||
def translate_expr_stmt(self, trans: HT.Translator*, node: ast.AST*) -> int:
|
||||
"""Translate an expression statement (e.g. a printf call)"""
|
||||
ex: rawptr[ast.Expr] = rawptr[ast.Expr](node)
|
||||
ex: ast.Expr* = ast.Expr*(node)
|
||||
if ex is None: return 0
|
||||
call_node: ast.AST* = ex.value
|
||||
if call_node is None: return 0
|
||||
@@ -101,7 +101,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
# Generic call (result discarded). M3: a bare-name call to a session function also
|
||||
# writes the result to ctx (classified by the session table's return token).
|
||||
if trans is not None and trans.ReplCtx is not None and func_node.kind() == ast.ASTKind.Name and self.Gen.VarGen.repl_in_frag_scope(trans.SymTab) != 0:
|
||||
sfn_ent: rawptr[GenTypes.ReplFuncEntry] = self.Gen.VarGen.repl_find_func_entry(trans.ReplCtx, func_name)
|
||||
sfn_ent: GenTypes.ReplFuncEntry* = self.Gen.VarGen.repl_find_func_entry(trans.ReplCtx, func_name)
|
||||
if sfn_ent is not None and sfn_ent.RetTag != GenTypes.REPL_TY_VOID:
|
||||
sfn_v: mlirlite.Value* = self.Gen.CallGen.translate_call(trans.Pool, trans._cur_builder, trans.Module, call_node, trans._funcs, trans._func_count, trans)
|
||||
if sfn_v is not None:
|
||||
@@ -118,7 +118,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
k: int = node.kind()
|
||||
if k == ast.ASTKind.AnnAssign: return self.Gen.AssignGen.translate_annassign_prescan(trans, node)
|
||||
if k == ast.ASTKind.If:
|
||||
ifn: rawptr[ast.If] = rawptr[ast.If](node)
|
||||
ifn: ast.If* = ast.If*(node)
|
||||
if ifn.children is not None:
|
||||
bn_pre_i: sizet = len(ifn.children)
|
||||
for bi_pre_i in range(bn_pre_i): self.pre_scan_allocas(trans, ifn.children.get(bi_pre_i))
|
||||
@@ -136,7 +136,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
for bi_pre_fe in range(bn_pre_fe): self.pre_scan_allocas(trans, for_n.orelse.get(bi_pre_fe))
|
||||
return 0
|
||||
if k == ast.ASTKind.While:
|
||||
wh_n: rawptr[ast.While] = rawptr[ast.While](node)
|
||||
wh_n: ast.While* = ast.While*(node)
|
||||
if wh_n.children is not None:
|
||||
bn_pre_w: sizet = len(wh_n.children)
|
||||
for bi_pre_w in range(bn_pre_w): self.pre_scan_allocas(trans, wh_n.children.get(bi_pre_w))
|
||||
@@ -178,7 +178,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
for bi_pre_mc in range(bn_pre_mc):
|
||||
mc_pre: ast.AST* = mt_n.cases.get(bi_pre_mc)
|
||||
if mc_pre is not None and mc_pre.kind() == ast.ASTKind.MatchCase:
|
||||
mcc_pre: rawptr[ast.MatchCase] = rawptr[ast.MatchCase](mc_pre)
|
||||
mcc_pre: ast.MatchCase* = ast.MatchCase*(mc_pre)
|
||||
if mcc_pre.children is not None:
|
||||
bn_pre_mcb: sizet = len(mcc_pre.children)
|
||||
for bi_pre_mcb in range(bn_pre_mcb): self.pre_scan_allocas(trans, mcc_pre.children.get(bi_pre_mcb))
|
||||
@@ -212,7 +212,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
dead_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
mlirlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
@@ -242,7 +242,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
trans._label_counter = cnt + 1
|
||||
name_buf: str = pool.alloc(32)
|
||||
viperlib.snprintf(name_buf, 32, "dead.%d", cnt)
|
||||
dead_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, name_buf)
|
||||
dead_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, name_buf)
|
||||
mlirlite.position_at_end(builder, dead_bb)
|
||||
return 0
|
||||
|
||||
@@ -356,33 +356,33 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
self.EnumCount = 0
|
||||
return 1
|
||||
|
||||
def _get_enum_entry(self, i: int) -> rawptr[GenTypes.EnumEntry]:
|
||||
def _get_enum_entry(self, i: int) -> GenTypes.EnumEntry*:
|
||||
"""Get the i-th enum entry"""
|
||||
if self.EnumTable is None or i < 0 or i >= ENUM_MAX: return None
|
||||
entry_size: sizet = GenTypes.EnumEntry.__sizeof__()
|
||||
addr: uint64 = uint64(self.EnumTable) + i * entry_size
|
||||
return rawptr[GenTypes.EnumEntry](addr)
|
||||
return GenTypes.EnumEntry*(addr)
|
||||
|
||||
def _get_enum_member(self, enum_entry: rawptr[GenTypes.EnumEntry], i: int) -> rawptr[GenTypes.EnumMember]:
|
||||
def _get_enum_member(self, enum_entry: GenTypes.EnumEntry*, i: int) -> GenTypes.EnumMember*:
|
||||
"""Get the i-th enum member entry"""
|
||||
if enum_entry is None or i < 0 or i >= ENUM_MEMBER_MAX: return None
|
||||
member_size: sizet = GenTypes.EnumMember.__sizeof__()
|
||||
addr: uint64 = uint64(enum_entry.Members) + i * member_size
|
||||
return rawptr[GenTypes.EnumMember](addr)
|
||||
return GenTypes.EnumMember*(addr)
|
||||
|
||||
def register_enum(self, pool: memhub.MemBuddy*, name: str, base_ty: mlirlite.LLVMType*) -> rawptr[GenTypes.EnumEntry]:
|
||||
def register_enum(self, pool: memhub.MemBuddy*, name: str, base_ty: mlirlite.LLVMType*) -> GenTypes.EnumEntry*:
|
||||
"""Register an enum type and return its EnumEntry pointer"""
|
||||
if self.init_enum_table(pool) == 0: return None
|
||||
|
||||
# Check whether it is already registered
|
||||
existing: rawptr[GenTypes.EnumEntry] = self.find_enum(name)
|
||||
existing: GenTypes.EnumEntry* = self.find_enum(name)
|
||||
if existing is not None: return existing
|
||||
|
||||
if self.EnumCount >= ENUM_MAX:
|
||||
VLogger.error(f"table full, cannot register {name}", "ENUM")
|
||||
return None
|
||||
|
||||
entry: rawptr[GenTypes.EnumEntry] = self._get_enum_entry(self.EnumCount)
|
||||
entry: GenTypes.EnumEntry* = self._get_enum_entry(self.EnumCount)
|
||||
if entry is None: return None
|
||||
|
||||
# Allocate the member array (permanent pool: survives mark/reset like EnumTable)
|
||||
@@ -410,14 +410,14 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
self.EnumCount += 1
|
||||
return entry
|
||||
|
||||
def add_enum_member(self, pool: memhub.MemBuddy*, enum_entry: rawptr[GenTypes.EnumEntry], member_name: str, member_val: int64, member_ty: mlirlite.LLVMType*) -> int:
|
||||
def add_enum_member(self, pool: memhub.MemBuddy*, enum_entry: GenTypes.EnumEntry*, member_name: str, member_val: int64, member_ty: mlirlite.LLVMType*) -> int:
|
||||
"""Add a member to an enum; returns the member index or -1 on failure"""
|
||||
if enum_entry is None or member_name is None or member_ty is None: return -1
|
||||
|
||||
# Dedup: skip an existing member with the same name (cross-module enum merging, e.g.
|
||||
# w32.fileio and fat32_types both define FRESULT).
|
||||
for ei_d in range(enum_entry.MemberCount):
|
||||
ex_d: rawptr[GenTypes.EnumMember] = self._get_enum_member(enum_entry, ei_d)
|
||||
ex_d: GenTypes.EnumMember* = self._get_enum_member(enum_entry, ei_d)
|
||||
if ex_d is not None and ex_d.Name is not None:
|
||||
if string.strcmp(ex_d.Name, member_name) == 0: return ei_d
|
||||
|
||||
@@ -426,7 +426,7 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
return -1
|
||||
|
||||
idx: int = enum_entry.MemberCount
|
||||
me: rawptr[GenTypes.EnumMember] = self._get_enum_member(enum_entry, idx)
|
||||
me: GenTypes.EnumMember* = self._get_enum_member(enum_entry, idx)
|
||||
if me is None: return -1
|
||||
|
||||
# Copy the member name (permanent-pool deep copy: the member table survives mark/reset)
|
||||
@@ -442,22 +442,22 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
enum_entry.MemberCount = idx + 1
|
||||
return idx
|
||||
|
||||
def find_enum(self, name: str) -> rawptr[GenTypes.EnumEntry]:
|
||||
def find_enum(self, name: str) -> GenTypes.EnumEntry*:
|
||||
"""Look up an enum by class name; returns EnumEntry or None"""
|
||||
if name is None or self.EnumTable is None: return None
|
||||
for i in range(self.EnumCount):
|
||||
entry: rawptr[GenTypes.EnumEntry] = self._get_enum_entry(i)
|
||||
entry: GenTypes.EnumEntry* = self._get_enum_entry(i)
|
||||
if entry is not None and entry.Name is not None:
|
||||
if string.strcmp(entry.Name, name) == 0: return entry
|
||||
return None
|
||||
|
||||
def lookup_enum_member(self, enum_name: str, member_name: str) -> rawptr[GenTypes.EnumMember]:
|
||||
def lookup_enum_member(self, enum_name: str, member_name: str) -> GenTypes.EnumMember*:
|
||||
"""Look up a member by enum class name and member name; returns EnumMember or None"""
|
||||
if enum_name is None or member_name is None: return None
|
||||
entry: rawptr[GenTypes.EnumEntry] = self.find_enum(enum_name)
|
||||
entry: GenTypes.EnumEntry* = self.find_enum(enum_name)
|
||||
if entry is None: return None
|
||||
for mi in range(entry.MemberCount):
|
||||
me: rawptr[GenTypes.EnumMember] = self._get_enum_member(entry, mi)
|
||||
me: GenTypes.EnumMember* = self._get_enum_member(entry, mi)
|
||||
if me is not None and me.Name is not None:
|
||||
if string.strcmp(me.Name, member_name) == 0: return me
|
||||
return None
|
||||
@@ -470,6 +470,6 @@ novirtual class StmtGenDeclMixin(StmtGenCifMixin.StmtGenCifMixin):
|
||||
|
||||
def get_enum_base_type(self, enum_name: str) -> mlirlite.LLVMType*:
|
||||
"""Get the base type for an enum class name"""
|
||||
entry: rawptr[GenTypes.EnumEntry] = self.find_enum(enum_name)
|
||||
entry: GenTypes.EnumEntry* = self.find_enum(enum_name)
|
||||
if entry is not None: return entry.BaseTy
|
||||
return None
|
||||
@@ -77,7 +77,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
def translate_delete(self, trans: HT.Translator*, node: ast.AST*) -> int:
|
||||
"""Translate a del statement; returns 0"""
|
||||
if trans is None or node is None: return 0
|
||||
dnode: rawptr[ast.Delete] = rawptr[ast.Delete](node)
|
||||
dnode: ast.Delete* = ast.Delete*(node)
|
||||
if dnode is None or dnode.targets is None: return 0
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
mod: mlirlite.LLVMModule* = trans.Module
|
||||
@@ -168,15 +168,15 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
bb_buf_t: str = pool.alloc(64)
|
||||
if bb_buf_t is None: return 0
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.dispatch.%d", lc_t)
|
||||
dispatch_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
dispatch_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.after.%d", lc_t)
|
||||
after_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
after_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.unhandled.%d", lc_t)
|
||||
unhandled_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
unhandled_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.body.%d", lc_t)
|
||||
try_bb: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
try_bb: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
if dispatch_bb is None or after_bb is None or unhandled_bb is None or try_bb is None: return 0
|
||||
else_bb: rawptr[mlirlite.BasicBlock] = None
|
||||
else_bb: mlirlite.BasicBlock* = None
|
||||
if tr.orelse is not None and len(tr.orelse) > 0:
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.else.%d", lc_t)
|
||||
else_bb = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
@@ -184,19 +184,19 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
if tr.handlers is not None: n_handlers_t = len(tr.handlers)
|
||||
# NOTE: list[ptr](pool, N)'s second arg is elem_size, not capacity; pointer
|
||||
# elements must pass 8, else append strides wrongly and reads garbage.
|
||||
except_bbs: list[rawptr[mlirlite.BasicBlock]]* = list[rawptr[mlirlite.BasicBlock]](pool, 8)
|
||||
match_bbs: list[rawptr[mlirlite.BasicBlock]]* = list[rawptr[mlirlite.BasicBlock]](pool, 8)
|
||||
except_bbs: list[mlirlite.BasicBlock*]* = list[mlirlite.BasicBlock*](pool, 8)
|
||||
match_bbs: list[mlirlite.BasicBlock*]* = list[mlirlite.BasicBlock*](pool, 8)
|
||||
if except_bbs is None or match_bbs is None: return 0
|
||||
for i_t in range(n_handlers_t):
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.except.%d.%d", lc_t, i_t)
|
||||
eb_t: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
eb_t: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
viperlib.snprintf(bb_buf_t, 64, "try.match.%d.%d", lc_t, i_t)
|
||||
mb_t: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
mb_t: mlirlite.BasicBlock* = mlirlite.create_block(pool, func, bb_buf_t)
|
||||
except_bbs.append(eb_t)
|
||||
match_bbs.append(mb_t)
|
||||
|
||||
# ---- 3. save outer try context, set this try context ----
|
||||
old_dispatch_t: rawptr[mlirlite.BasicBlock] = trans._eh_dispatch_bb
|
||||
old_dispatch_t: mlirlite.BasicBlock* = trans._eh_dispatch_bb
|
||||
old_code_t: mlirlite.Value* = trans._eh_code_ptr
|
||||
old_msg_t: mlirlite.Value* = trans._eh_msg_ptr
|
||||
trans._eh_dispatch_bb = dispatch_bb
|
||||
@@ -224,10 +224,10 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
mlirlite.build_br(builder, unhandled_bb)
|
||||
else:
|
||||
eh_code_val: mlirlite.Value* = mlirlite.build_load(builder, i32_ty_t, exception_code)
|
||||
next_check_t: rawptr[mlirlite.BasicBlock] = None
|
||||
next_check_t: mlirlite.BasicBlock* = None
|
||||
for i_t in range(n_handlers_t):
|
||||
hdr_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
|
||||
match_bb_t: rawptr[mlirlite.BasicBlock] = match_bbs.get(i_t)
|
||||
match_bb_t: mlirlite.BasicBlock* = match_bbs.get(i_t)
|
||||
if i_t > 0 and next_check_t is not None:
|
||||
mlirlite.position_at_end(builder, next_check_t)
|
||||
eh_code_val = mlirlite.build_load(builder, i32_ty_t, exception_code)
|
||||
@@ -277,7 +277,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
if h_alloca_t is not None:
|
||||
h_msg_t: mlirlite.Value* = mlirlite.build_load(builder, i8_ptr_ty_t, eh_message)
|
||||
if h_msg_t is not None: mlirlite.build_store(builder, h_msg_t, h_alloca_t)
|
||||
except_bb_t: rawptr[mlirlite.BasicBlock] = except_bbs.get(i_t)
|
||||
except_bb_t: mlirlite.BasicBlock* = except_bbs.get(i_t)
|
||||
mlirlite.build_br(builder, except_bb_t)
|
||||
|
||||
# ---- 6. UnhandledBB: no except matched -> propagate or swallow ----
|
||||
@@ -295,7 +295,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
# ---- 7. except bodies ----
|
||||
for i_t in range(n_handlers_t):
|
||||
hdr2_t: ast.ExceptHandler* = ast.ExceptHandler*(tr.handlers.get(i_t))
|
||||
except_bb2_t: rawptr[mlirlite.BasicBlock] = except_bbs.get(i_t)
|
||||
except_bb2_t: mlirlite.BasicBlock* = except_bbs.get(i_t)
|
||||
mlirlite.position_at_end(builder, except_bb2_t)
|
||||
if hdr2_t is not None and hdr2_t.children is not None:
|
||||
hn2_t: sizet = len(hdr2_t.children)
|
||||
@@ -328,7 +328,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
builder: mlirlite.IRBuilder* = trans._cur_builder
|
||||
mod: mlirlite.LLVMModule* = trans.Module
|
||||
if pool is None or builder is None or mod is None: return 0
|
||||
rn: rawptr[ast.Raise] = rawptr[ast.Raise](node)
|
||||
rn: ast.Raise* = ast.Raise*(node)
|
||||
if rn is None or rn.exc is None:
|
||||
# bare raise (no exc): v1 has no active exception; just return default
|
||||
self._eh_ret_default(trans, pool, builder)
|
||||
@@ -448,7 +448,7 @@ novirtual class StmtGenMixin(StmtGenDeclMixin.StmtGenDeclMixin):
|
||||
item_node: ast.AST* = items.get(i)
|
||||
if item_node is None: continue
|
||||
if item_node.kind() != ast.ASTKind.WithItem: continue
|
||||
item: rawptr[ast.WithItem] = rawptr[ast.WithItem](item_node)
|
||||
item: ast.WithItem* = ast.WithItem*(item_node)
|
||||
if item is None or item.context_expr is None: continue
|
||||
# translate context_expr (object construction, e.g. MemPool(arena, 4096))
|
||||
ctx_val: mlirlite.Value* = self.Gen.ExprGen.translate_value(builder, pool, mod, item.context_expr, trans._funcs, trans._func_count, trans)
|
||||
|
||||
@@ -889,7 +889,7 @@ novirtual class StructGenMixin:
|
||||
if entry.FieldCount != fcount:
|
||||
self.Gen.TypeGenErr.fatal_error(None, f"结构体 '{entry.Name}' 的字段表条数({entry.FieldCount})与 LLVM 槽位数({fcount})不一致:" f"字段条目与结构体布局由两条路径产生,错位会让字段访问按错误下标算 GEP" f"(实证:ast.Name.id 落到 ctx 槽 ⇒ 指针被读成整数 1 ⇒ strlen(0x1) 崩溃)。", "TypeError")
|
||||
return 0
|
||||
node: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(struct_ty)
|
||||
node: mlirlite.ParamNode* = mlirlite.get_struct_fields(struct_ty)
|
||||
i: int = 0
|
||||
while i < entry.FieldCount and node is not None:
|
||||
fe: GenTypes.FieldEntry* = self._get_field_entry(entry, i)
|
||||
@@ -1531,7 +1531,7 @@ novirtual class StructGenMixin:
|
||||
case mlirlite.LLVMType.Struct(fields, fcount, sname):
|
||||
# Walk the field list.
|
||||
if fields is not None:
|
||||
fld: rawptr[mlirlite.ParamNode] = fields
|
||||
fld: mlirlite.ParamNode* = fields
|
||||
cnt_ef: int = 0
|
||||
while fld is not None:
|
||||
# Step guard: a cyclic field list (memory corruption) would loop forever (G3 LinkedNode.prepend hang candidate); over the limit, report and abort immediately.
|
||||
|
||||
@@ -71,7 +71,7 @@ novirtual class Translator:
|
||||
_coro_state_ptr: mlirlite.Value*
|
||||
_coro_done_ptr: mlirlite.Value*
|
||||
_coro_ret_ptr: mlirlite.Value*
|
||||
_coro_exit_bb: rawptr[mlirlite.BasicBlock]
|
||||
_coro_exit_bb: mlirlite.BasicBlock*
|
||||
_coro_await_slot: mlirlite.Value*
|
||||
_coro_frame: mlirlite.Value*
|
||||
_coro_next_state: int
|
||||
@@ -83,8 +83,8 @@ novirtual class Translator:
|
||||
_coro_await_count: int # Total await count (= resume blocks = switch cases)
|
||||
_coro_local_base: int # Local slot start index (= 3 + nparams)
|
||||
_coro_extra_base: int # Extra slot (__await_N) start index
|
||||
_coro_break_bb: rawptr[mlirlite.BasicBlock] # While break target (M2 single level)
|
||||
_coro_continue_bb: rawptr[mlirlite.BasicBlock] # While continue target
|
||||
_coro_break_bb: mlirlite.BasicBlock* # While break target (M2 single level)
|
||||
_coro_continue_bb: mlirlite.BasicBlock* # While continue target
|
||||
_coro_state_bbs: sizet* # Pre-built state block array (locates await resume blocks)
|
||||
# M3-M7 coroutine extensions
|
||||
_coro_exc_ptr: mlirlite.Value* # Frame exc slot (i32, M4)
|
||||
@@ -130,8 +130,8 @@ novirtual class Translator:
|
||||
|
||||
# Loop control-flow targets (break/continue). A break inside a match case exits the match:
|
||||
# MatchGenMixin temporarily overrides _break_bb with the match end_bb while in a case body.
|
||||
_break_bb: rawptr[mlirlite.BasicBlock]
|
||||
_continue_bb: rawptr[mlirlite.BasicBlock]
|
||||
_break_bb: mlirlite.BasicBlock*
|
||||
_continue_bb: mlirlite.BasicBlock*
|
||||
|
||||
# Whether we are inside a switch case body (1=yes). `fallthrough` is legal only there;
|
||||
# match case bodies and non-switch code fail-fast. Set from node.is_switch by MatchGenMixin.
|
||||
@@ -177,7 +177,7 @@ novirtual class Translator:
|
||||
|
||||
# try-except state: dispatch block plus exception code/message allocas of the innermost try.
|
||||
# Set by translate_try; written by translate_raise and call-site EH checks. None outside try.
|
||||
_eh_dispatch_bb: rawptr[mlirlite.BasicBlock]
|
||||
_eh_dispatch_bb: mlirlite.BasicBlock*
|
||||
_eh_code_ptr: mlirlite.Value*
|
||||
_eh_msg_ptr: mlirlite.Value*
|
||||
# Current function's __eh_msg_out__ (i8**) / __eh_code_out__ (i32*) output parameters,
|
||||
@@ -218,11 +218,11 @@ novirtual class Translator:
|
||||
_pre_allow_dep_inject: int
|
||||
|
||||
# Nested-scope symbol table
|
||||
SymTab: rawptr[GenTypes.SymbolTable]
|
||||
SymTab: GenTypes.SymbolTable*
|
||||
|
||||
# REPL mode context (M2 session variables): None means non-REPL (normal path unchanged).
|
||||
# Only Repl.vp sets it; Gen-side session-slot interception checks `trans.ReplCtx is not None`.
|
||||
ReplCtx: rawptr[GenTypes.ReplCtx]
|
||||
ReplCtx: GenTypes.ReplCtx*
|
||||
|
||||
def __init__(self):
|
||||
self.Module = None
|
||||
@@ -845,7 +845,7 @@ def _tb_find_install_function(mod: mlirlite.LLVMModule*) -> mlirlite.Function*:
|
||||
|
||||
# InjectTracebackInstallCtor - inject the startup Install() ctor into the module.
|
||||
# NOTE: emitted with default (external) linkage since FunctionPrint has no linkage field; no clash.
|
||||
def InjectTracebackInstallCtor(tr: rawptr[Translator]) -> int:
|
||||
def InjectTracebackInstallCtor(tr: Translator*) -> int:
|
||||
if tr is None or tr.Module is None: return 0
|
||||
if tr._declare_only != 0: return 0
|
||||
pool: memhub.MemBuddy* = tr.Pool
|
||||
|
||||
@@ -195,7 +195,7 @@ novirtual class TranslatorGenMixin:
|
||||
elif ek_n == ast.ASTKind.Set:
|
||||
# Brace literals (e.g. font tables {0x00, ...}): Set.elts is
|
||||
# isomorphic to List, so wrap it in a temp List and recurse.
|
||||
se_n: rawptr[ast.Set] = rawptr[ast.Set](en_n)
|
||||
se_n: ast.Set* = ast.Set*(en_n)
|
||||
if se_n is not None and se_n.elts is not None: sub_n = self._build_array_initializer_text(pool, elem_ty, ast.List(pool, se_n.elts, ast.ASTCtx.Load))
|
||||
if sub_n is None:
|
||||
# Missing/unevaluable element: zero-initialize the whole sub-array
|
||||
@@ -876,7 +876,7 @@ novirtual class TranslatorGenMixin:
|
||||
VLogger.error("CreateFunction main returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
entry_blk: rawptr[mlirlite.BasicBlock] = mlirlite.create_block(pool, main_func, "entry")
|
||||
entry_blk: mlirlite.BasicBlock* = mlirlite.create_block(pool, main_func, "entry")
|
||||
if entry_blk is None:
|
||||
VLogger.error("CreateBlock returned NULL", "TR")
|
||||
return 0
|
||||
|
||||
@@ -26,7 +26,7 @@ novirtual class TypeGenBase:
|
||||
|
||||
# --- Python-Traceback-like call stack (was _g_trace_frames/_g_trace_count) ---
|
||||
Gen: Generator.Generator*
|
||||
TraceFrames: rawptr[GenTypes.TraceFrame] # malloc array (TypeGenMixin.TRACE_MAX slots)
|
||||
TraceFrames: GenTypes.TraceFrame* # malloc array (TypeGenMixin.TRACE_MAX slots)
|
||||
TraceCount: int
|
||||
|
||||
# --- Global generic specialization context (was _g_generic_tp_names/_g_generic_type_args) ---
|
||||
@@ -168,17 +168,17 @@ novirtual class TypeGenBase:
|
||||
if self.TraceFrames is None: return 0
|
||||
string.memset(self.TraceFrames, 0, entry_size * TypeGenMixin.TRACE_MAX)
|
||||
return 1
|
||||
def _get_trace_frame(self, i: int) -> rawptr[GenTypes.TraceFrame]:
|
||||
def _get_trace_frame(self, i: int) -> GenTypes.TraceFrame*:
|
||||
"""Return the i-th TraceFrame slot."""
|
||||
if self.TraceFrames is None or i < 0 or i >= TypeGenMixin.TRACE_MAX: return None
|
||||
entry_size: sizet = GenTypes.TraceFrame.__sizeof__()
|
||||
addr: uint64 = uint64(self.TraceFrames) + i * entry_size
|
||||
return rawptr[GenTypes.TraceFrame](addr)
|
||||
return GenTypes.TraceFrame*(addr)
|
||||
def push_trace(self, file_name: str, lineno: int, col_start: int = 0, col_end: int = 0) -> None:
|
||||
"""Push a translation context frame."""
|
||||
if self._ensure_trace_init() == 0: return
|
||||
if self.TraceCount >= TypeGenMixin.TRACE_MAX: return
|
||||
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(self.TraceCount)
|
||||
frame: GenTypes.TraceFrame* = self._get_trace_frame(self.TraceCount)
|
||||
if frame is None: return
|
||||
frame.file_name = file_name
|
||||
frame.lineno = lineno
|
||||
@@ -189,7 +189,7 @@ novirtual class TypeGenBase:
|
||||
"""Pop the top trace frame."""
|
||||
if self.TraceCount <= 0: return
|
||||
self.TraceCount -= 1
|
||||
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(self.TraceCount)
|
||||
frame: GenTypes.TraceFrame* = self._get_trace_frame(self.TraceCount)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
@@ -198,7 +198,7 @@ novirtual class TypeGenBase:
|
||||
def clear_trace(self) -> None:
|
||||
"""Clear the trace stack (called before translating each file)."""
|
||||
for i in range(self.TraceCount):
|
||||
frame: rawptr[GenTypes.TraceFrame] = self._get_trace_frame(i)
|
||||
frame: GenTypes.TraceFrame* = self._get_trace_frame(i)
|
||||
if frame is not None:
|
||||
frame.file_name = None
|
||||
frame.lineno = 0
|
||||
|
||||
@@ -28,7 +28,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
def _read_source_line(self, file_path: str, lineno: int) -> str:
|
||||
"""Read line lineno from the source file"""
|
||||
if file_path is None or lineno <= 0: return None
|
||||
f: rawptr[fileio.File] = fileio.File(file_path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(file_path, fileio.MODE.R)
|
||||
if f.closed: return None
|
||||
# Allocate by actual file size: a fixed 256KB buffer truncated large files so late line
|
||||
# numbers were unreadable. The 64MB cap guards against reading abnormally huge files.
|
||||
@@ -96,7 +96,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
stdio.printf("Traceback (most recent call last, compile-time error):\n")
|
||||
# Print the call stack frames (bottom to top)
|
||||
for i in range(self.Gen.TypeGenBase.TraceCount):
|
||||
frame: rawptr[GenTypes.TraceFrame] = self.Gen.TypeGenBase._get_trace_frame(i)
|
||||
frame: GenTypes.TraceFrame* = self.Gen.TypeGenBase._get_trace_frame(i)
|
||||
if frame is not None and frame.file_name is not None:
|
||||
if frame.lineno > 0:
|
||||
stdio.printf(' File "%s", line %d\n', frame.file_name, frame.lineno)
|
||||
@@ -115,7 +115,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
if lineno <= 0 and self.Gen.TypeGenBase.TraceCount > 0:
|
||||
ti_b: int = self.Gen.TypeGenBase.TraceCount - 1
|
||||
while ti_b >= 0:
|
||||
tfb: rawptr[GenTypes.TraceFrame] = self.Gen.TypeGenBase._get_trace_frame(ti_b)
|
||||
tfb: GenTypes.TraceFrame* = self.Gen.TypeGenBase._get_trace_frame(ti_b)
|
||||
if tfb is not None and tfb.file_name is not None and tfb.lineno > 0:
|
||||
file_name = tfb.file_name
|
||||
lineno = tfb.lineno
|
||||
@@ -278,7 +278,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
for bi in range(bn):
|
||||
stmt: ast.AST* = body.get(bi)
|
||||
if stmt is not None and stmt.kind() == ast.ASTKind.Return:
|
||||
rt: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rt: ast.Return* = ast.Return*(stmt)
|
||||
if rt.value is not None:
|
||||
expr_ty: mlirlite.LLVMType* = self.infer_expr_type(pool, rt.value, param_types)
|
||||
if expr_ty is not None:
|
||||
@@ -295,7 +295,7 @@ novirtual class TypeGenErr(TypeGenBase.TypeGenBase):
|
||||
if stmt is None: continue
|
||||
k: int = stmt.kind()
|
||||
if k == ast.ASTKind.Return:
|
||||
rt: rawptr[ast.Return] = rawptr[ast.Return](stmt)
|
||||
rt: ast.Return* = ast.Return*(stmt)
|
||||
if rt.value is not None:
|
||||
# return None (CONST_NONE) does not count as returning a non-None value
|
||||
if rt.value.kind() == ast.ASTKind.Constant:
|
||||
|
||||
@@ -731,7 +731,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if base_buf_m is not None: stdlib.free(base_buf_m)
|
||||
if inner_buf_m is not None: stdlib.free(inner_buf_m)
|
||||
# Prefer ast.parse_expression (single-expression entry returning an Expression wrapper)
|
||||
expr_node: rawptr[ast.Expression] = ast.parse_expression(type_str, pool)
|
||||
expr_node: ast.Expression* = ast.parse_expression(type_str, pool)
|
||||
if expr_node is not None:
|
||||
expr_body: ast.AST* = expr_node.body
|
||||
if expr_body is not None: return expr_body
|
||||
@@ -743,7 +743,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if ch_s is not None and len(ch_s) > 0:
|
||||
st0: ast.AST* = ch_s.get(0)
|
||||
if st0 is not None and st0.kind() == ast.ASTKind.Expr:
|
||||
ex0: rawptr[ast.Expr] = rawptr[ast.Expr](st0)
|
||||
ex0: ast.Expr* = ast.Expr*(st0)
|
||||
if ex0.value is not None: return ex0.value
|
||||
return None
|
||||
|
||||
@@ -1012,7 +1012,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if b_buf is None:
|
||||
stdlib.free(b_path)
|
||||
return None
|
||||
bf: rawptr[fileio.File] = fileio.File(b_path, fileio.MODE.R)
|
||||
bf: fileio.File* = fileio.File(b_path, fileio.MODE.R)
|
||||
stdlib.free(b_path)
|
||||
if bf.closed:
|
||||
stdlib.free(b_buf)
|
||||
@@ -1184,7 +1184,7 @@ novirtual class TypeGenResolve(TypeGenBase.TypeGenBase):
|
||||
if m_buf is None:
|
||||
stdlib.free(m_path)
|
||||
return None
|
||||
mf: rawptr[fileio.File] = fileio.File(m_path, fileio.MODE.R)
|
||||
mf: fileio.File* = fileio.File(m_path, fileio.MODE.R)
|
||||
stdlib.free(m_path)
|
||||
if mf.closed:
|
||||
stdlib.free(m_buf)
|
||||
|
||||
@@ -67,10 +67,10 @@ novirtual class VarGenMixin:
|
||||
|
||||
# lookup_var_entry - walk from the current scope upward, returning the VarEntry
|
||||
# ============================================================
|
||||
def lookup_var_entry(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> GenTypes.VarEntry*:
|
||||
def lookup_var_entry(self, symtab: GenTypes.SymbolTable*, name: str) -> GenTypes.VarEntry*:
|
||||
"""Walk up from the current scope to find a variable, return the VarEntry or None"""
|
||||
if symtab is None or name is None: return None
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
while scope is not None:
|
||||
result: GenTypes.VarEntry* = self.find_var_entry(scope.Vars, scope.VarCount, name)
|
||||
if result is not None: return result
|
||||
@@ -79,7 +79,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# set_var_annot_class_name - set a variable's original type-annotation class name.
|
||||
# Stores it in Spec.SourceName so method dispatch can recover the struct type when alloca is Ptr(i8).
|
||||
def set_var_annot_class_name(self, symtab: rawptr[GenTypes.SymbolTable], name: str, class_name: str) -> int:
|
||||
def set_var_annot_class_name(self, symtab: GenTypes.SymbolTable*, name: str, class_name: str) -> int:
|
||||
"""Set a variable's original type-annotation class name into Spec.SourceName, return 0=success / 1=failure"""
|
||||
if symtab is None or name is None: return 1
|
||||
entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name)
|
||||
@@ -106,7 +106,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# set_var_ptr_element - mark a variable with "pointer element" semantics.
|
||||
# bytes*/str*/T*/64-bit scalar|CPtr degrade to i8*, but indexing must use 8-byte slot strides (ElemBits=64).
|
||||
def set_var_ptr_element(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int:
|
||||
def set_var_ptr_element(self, symtab: GenTypes.SymbolTable*, name: str) -> int:
|
||||
"""Mark a variable as ptr-element (Spec.ElemBits=64), return 0=success / 1=failure"""
|
||||
if symtab is None or name is None: return 1
|
||||
entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name)
|
||||
@@ -132,7 +132,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# set_var_volatile - mark a variable volatile (annotation union contains t.CVolatile).
|
||||
# Every load/store of it carries LLVM volatile, preventing hoisting/removal of busy-wait loads.
|
||||
def set_var_volatile(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int:
|
||||
def set_var_volatile(self, symtab: GenTypes.SymbolTable*, name: str) -> int:
|
||||
"""Mark a variable as volatile (VarEntry.IsVolatile=1), return 0=success / 1=failure"""
|
||||
if symtab is None or name is None: return 1
|
||||
entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name)
|
||||
@@ -148,7 +148,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# set_var_pointee_volatile - mark the pointed-to object volatile (rawptr[t.CVolatile | T]).
|
||||
# Dereferences (p[i] / p.field / c.Deref(p)) then use LLVM volatile load/store on the pointee.
|
||||
def set_var_pointee_volatile(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int:
|
||||
def set_var_pointee_volatile(self, symtab: GenTypes.SymbolTable*, name: str) -> int:
|
||||
"""Mark the variable's pointee volatile (VarEntry.PointeeVolatile=1), return 0=success / 1=failure"""
|
||||
if symtab is None or name is None: return 1
|
||||
entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name)
|
||||
@@ -164,7 +164,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# set_var_const - mark a variable as a const object (annotation has t.CConst and the type is not a pointer).
|
||||
# Assignment / augmented assignment / element assignment to it are then rejected (same rule as TPC).
|
||||
def set_var_const(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> int:
|
||||
def set_var_const(self, symtab: GenTypes.SymbolTable*, name: str) -> int:
|
||||
"""Mark a variable as a const object (VarEntry.IsConst=1), return 0=success / 1=failure"""
|
||||
if symtab is None or name is None: return 1
|
||||
entry: GenTypes.VarEntry* = self.lookup_var_entry(symtab, name)
|
||||
@@ -233,9 +233,9 @@ novirtual class VarGenMixin:
|
||||
|
||||
# _create_scope - create a new scope node (internal helper)
|
||||
# ============================================================
|
||||
def _create_scope(self, pool: memhub.MemBuddy*, parent: rawptr[GenTypes.Scope], kind: int) -> rawptr[GenTypes.Scope]:
|
||||
def _create_scope(self, pool: memhub.MemBuddy*, parent: GenTypes.Scope*, kind: int) -> GenTypes.Scope*:
|
||||
"""Create and initialize a scope node"""
|
||||
scope: rawptr[GenTypes.Scope] = pool.alloc(GenTypes.Scope.__sizeof__())
|
||||
scope: GenTypes.Scope* = pool.alloc(GenTypes.Scope.__sizeof__())
|
||||
if scope is None: return None
|
||||
string.memset(scope, 0, GenTypes.Scope.__sizeof__())
|
||||
scope.Parent = parent
|
||||
@@ -247,16 +247,16 @@ novirtual class VarGenMixin:
|
||||
|
||||
# init_symbol_table - create the symbol table (with the module-level root scope)
|
||||
# ============================================================
|
||||
def init_symbol_table(self, pool: memhub.MemBuddy*) -> rawptr[GenTypes.SymbolTable]:
|
||||
def init_symbol_table(self, pool: memhub.MemBuddy*) -> GenTypes.SymbolTable*:
|
||||
"""Create and initialize the symbol table with a module-level root scope"""
|
||||
if pool is None: return None
|
||||
symtab: rawptr[GenTypes.SymbolTable] = pool.alloc(GenTypes.SymbolTable.__sizeof__())
|
||||
symtab: GenTypes.SymbolTable* = pool.alloc(GenTypes.SymbolTable.__sizeof__())
|
||||
if symtab is None: return None
|
||||
string.memset(symtab, 0, GenTypes.SymbolTable.__sizeof__())
|
||||
symtab.Pool = pool
|
||||
|
||||
# Create the root scope (module level)
|
||||
root: rawptr[GenTypes.Scope] = self._create_scope(pool, None, SCOPE_MODULE)
|
||||
root: GenTypes.Scope* = self._create_scope(pool, None, SCOPE_MODULE)
|
||||
if root is None: return None
|
||||
|
||||
symtab.Root = root
|
||||
@@ -265,27 +265,27 @@ novirtual class VarGenMixin:
|
||||
|
||||
# enter_scope - enter a new scope
|
||||
# ============================================================
|
||||
def enter_scope(self, symtab: rawptr[GenTypes.SymbolTable], kind: int) -> rawptr[GenTypes.Scope]:
|
||||
def enter_scope(self, symtab: GenTypes.SymbolTable*, kind: int) -> GenTypes.Scope*:
|
||||
"""Enter a new scope and return it"""
|
||||
if symtab is None: return None
|
||||
pool: memhub.MemBuddy* = symtab.Pool
|
||||
scope: rawptr[GenTypes.Scope] = self._create_scope(pool, symtab.Current, kind)
|
||||
scope: GenTypes.Scope* = self._create_scope(pool, symtab.Current, kind)
|
||||
if scope is None: return None
|
||||
symtab.Current = scope
|
||||
return scope
|
||||
|
||||
# exit_scope - exit the current scope
|
||||
# ============================================================
|
||||
def exit_scope(self, symtab: rawptr[GenTypes.SymbolTable]):
|
||||
def exit_scope(self, symtab: GenTypes.SymbolTable*):
|
||||
"""Exit the current scope and restore its parent"""
|
||||
if symtab is not None and symtab.Current is not None: symtab.Current = symtab.Current.Parent
|
||||
|
||||
# define_var - define a variable in the current scope
|
||||
# ============================================================
|
||||
def define_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str, alloca: mlirlite.Value*) -> int:
|
||||
def define_var(self, symtab: GenTypes.SymbolTable*, name: str, alloca: mlirlite.Value*) -> int:
|
||||
"""Define a variable in the current scope, return 0 on success"""
|
||||
if symtab is None or name is None or alloca is None: return 1
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
if scope is None: return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0: scope.VarCount = scope.VarCount + 1
|
||||
@@ -293,10 +293,10 @@ novirtual class VarGenMixin:
|
||||
|
||||
# define_module_var - define a variable in the module scope
|
||||
# ============================================================
|
||||
def define_module_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str, alloca: mlirlite.Value*) -> int:
|
||||
def define_module_var(self, symtab: GenTypes.SymbolTable*, name: str, alloca: mlirlite.Value*) -> int:
|
||||
"""Define a variable in the module scope, return 0 on success"""
|
||||
if symtab is None or name is None or alloca is None: return 1
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Root
|
||||
scope: GenTypes.Scope* = symtab.Root
|
||||
if scope is None: return 1
|
||||
ret: int = self.add_var(scope.Vars, scope.VarCount, name, alloca)
|
||||
if ret == 0: scope.VarCount = scope.VarCount + 1
|
||||
@@ -304,10 +304,10 @@ novirtual class VarGenMixin:
|
||||
|
||||
# lookup_var - walk from the current scope upward looking for a variable
|
||||
# ============================================================
|
||||
def lookup_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*:
|
||||
def lookup_var(self, symtab: GenTypes.SymbolTable*, name: str) -> mlirlite.Value*:
|
||||
"""Walk up from the current scope to find a variable, return its alloca or None"""
|
||||
if symtab is None or name is None: return None
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
while scope is not None:
|
||||
result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
|
||||
if result is not None: return result
|
||||
@@ -316,25 +316,25 @@ novirtual class VarGenMixin:
|
||||
|
||||
# lookup_current - look up a variable only in the current scope
|
||||
# ============================================================
|
||||
def lookup_current(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*:
|
||||
def lookup_current(self, symtab: GenTypes.SymbolTable*, name: str) -> mlirlite.Value*:
|
||||
"""Look up a variable in the current scope only"""
|
||||
if symtab is None or name is None: return None
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
if scope is None: return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# lookup_module_var - look up a variable in the module scope
|
||||
# ============================================================
|
||||
def lookup_module_var(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*:
|
||||
def lookup_module_var(self, symtab: GenTypes.SymbolTable*, name: str) -> mlirlite.Value*:
|
||||
"""Look up a variable in the module scope"""
|
||||
if symtab is None or name is None: return None
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Root
|
||||
scope: GenTypes.Scope* = symtab.Root
|
||||
if scope is None: return None
|
||||
return self.find_var(scope.Vars, scope.VarCount, name)
|
||||
|
||||
# is_module_scope - whether the current scope is module level.
|
||||
# Module-level AnnAssign modifies a module variable; inside a function (without global) it creates a local.
|
||||
def is_module_scope(self, symtab: rawptr[GenTypes.SymbolTable]) -> int:
|
||||
def is_module_scope(self, symtab: GenTypes.SymbolTable*) -> int:
|
||||
"""Whether the current scope is module level (Current == Root), 1=module / 0=function scope"""
|
||||
if symtab is None: return 0
|
||||
if symtab.Root is None or symtab.Current is None: return 0
|
||||
@@ -343,10 +343,10 @@ novirtual class VarGenMixin:
|
||||
return 0
|
||||
|
||||
# _lookup_through_match_scope - look up a variable, walking through match-case scopes
|
||||
def _lookup_through_match_scope(self, symtab: rawptr[GenTypes.SymbolTable], name: str) -> mlirlite.Value*:
|
||||
def _lookup_through_match_scope(self, symtab: GenTypes.SymbolTable*, name: str) -> mlirlite.Value*:
|
||||
"""Walk up from the current scope through SCOPE_MATCH scopes only to find a variable alloca"""
|
||||
if symtab is None or name is None: return None
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
while scope is not None:
|
||||
result: mlirlite.Value* = self.find_var(scope.Vars, scope.VarCount, name)
|
||||
if result is not None: return result
|
||||
@@ -358,7 +358,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# get_or_create_sym - find or create a variable (in the current scope)
|
||||
# ============================================================
|
||||
def get_or_create_sym(self, symtab: rawptr[GenTypes.SymbolTable], pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, name: str, ty: mlirlite.LLVMType*) -> mlirlite.Value*:
|
||||
def get_or_create_sym(self, symtab: GenTypes.SymbolTable*, pool: memhub.MemBuddy*, builder: mlirlite.IRBuilder*, name: str, ty: mlirlite.LLVMType*) -> mlirlite.Value*:
|
||||
"""Find or create a variable alloca in the current scope"""
|
||||
existing: mlirlite.Value* = self.lookup_current(symtab, name)
|
||||
if existing is not None: return existing
|
||||
@@ -372,7 +372,7 @@ novirtual class VarGenMixin:
|
||||
|
||||
# REPL mode (M2) - session variable slot read/write; entered only when trans.ReplCtx != None (slots hold the value at ctx + x.Offset).
|
||||
# ---- repl_find_entry - look up a session table entry by name ----
|
||||
def repl_find_entry(self, ctx: rawptr[GenTypes.ReplCtx], name: str) -> rawptr[GenTypes.ReplVarEntry]:
|
||||
def repl_find_entry(self, ctx: GenTypes.ReplCtx*, name: str) -> GenTypes.ReplVarEntry*:
|
||||
"""Look up an entry by name in the session table; None if ctx is invalid or unregistered"""
|
||||
if ctx is None or name is None: return None
|
||||
# Magic check: avoid treating a non-ReplCtx pointer as a context (better not to intercept than to over-intercept)
|
||||
@@ -381,15 +381,15 @@ novirtual class VarGenMixin:
|
||||
entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__()
|
||||
for i in range(ctx.Count):
|
||||
entry_addr: uint64 = uint64(ctx.Table) + i * entry_size
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](entry_addr)
|
||||
entry: GenTypes.ReplVarEntry* = GenTypes.ReplVarEntry*(entry_addr)
|
||||
if entry.Name is not None and string.strcmp(entry.Name, name) == 0: return entry
|
||||
return None
|
||||
|
||||
# ---- repl_in_frag_scope - whether the nearest function scope is the fragment function itself ----
|
||||
def repl_in_frag_scope(self, symtab: rawptr[GenTypes.SymbolTable]) -> int:
|
||||
def repl_in_frag_scope(self, symtab: GenTypes.SymbolTable*) -> int:
|
||||
"""1=the nearest function scope is the fragment body itself (its parent is the module root); 0=otherwise."""
|
||||
if symtab is None or symtab.Current is None or symtab.Root is None: return 0
|
||||
scope: rawptr[GenTypes.Scope] = symtab.Current
|
||||
scope: GenTypes.Scope* = symtab.Current
|
||||
while scope is not None:
|
||||
if scope.Kind == SCOPE_FUNCTION:
|
||||
if scope.Parent is not None and uint64(scope.Parent) == uint64(symtab.Root): return 1
|
||||
@@ -398,10 +398,10 @@ novirtual class VarGenMixin:
|
||||
return 0
|
||||
|
||||
# ---- repl_ctx_ptr - load the fragment function's ctx parameter value (i8*) ----
|
||||
def repl_ctx_ptr(self, trans: HT.Translator*, ctx: rawptr[GenTypes.ReplCtx], node: ast.AST*) -> mlirlite.Value*:
|
||||
def repl_ctx_ptr(self, trans: HT.Translator*, ctx: GenTypes.ReplCtx*, node: ast.AST*) -> mlirlite.Value*:
|
||||
"""Load the snippet function's ctx parameter (alloca built by FuncGenDef); fail fast on error"""
|
||||
if trans is None or ctx is None or ctx.CtxParam is None: return None
|
||||
symtab: rawptr[GenTypes.SymbolTable] = trans.SymTab
|
||||
symtab: GenTypes.SymbolTable* = trans.SymTab
|
||||
param_alloca: mlirlite.Value* = self.lookup_var(symtab, ctx.CtxParam)
|
||||
if param_alloca is None or param_alloca.Ty is None or param_alloca.Ty.Pointee == 0:
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 片段函数缺少 ctx 形参 '{ctx.CtxParam}'(包裹模板与 M2 调用约定不一致)", "InternalCompilerError")
|
||||
@@ -422,7 +422,7 @@ novirtual class VarGenMixin:
|
||||
return 1
|
||||
|
||||
# ---- repl_find_func_entry - look up a session function table entry by name (M3) ----
|
||||
def repl_find_func_entry(self, ctx: rawptr[GenTypes.ReplCtx], name: str) -> rawptr[GenTypes.ReplFuncEntry]:
|
||||
def repl_find_func_entry(self, ctx: GenTypes.ReplCtx*, name: str) -> GenTypes.ReplFuncEntry*:
|
||||
"""Look up by name in the session function table; None if ctx is invalid or unregistered (read-only)"""
|
||||
if ctx is None or name is None: return None
|
||||
if ctx.Marker != GenTypes.REPL_CTX_MARKER: return None
|
||||
@@ -430,7 +430,7 @@ novirtual class VarGenMixin:
|
||||
entry_size: sizet = GenTypes.ReplFuncEntry.__sizeof__()
|
||||
for i in range(ctx.FuncCount):
|
||||
entry_addr: uint64 = uint64(ctx.FuncTable) + i * entry_size
|
||||
entry: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](entry_addr)
|
||||
entry: GenTypes.ReplFuncEntry* = GenTypes.ReplFuncEntry*(entry_addr)
|
||||
if entry.Name is not None and string.strcmp(entry.Name, name) == 0: return entry
|
||||
return None
|
||||
|
||||
@@ -456,8 +456,8 @@ novirtual class VarGenMixin:
|
||||
"""Session function call: return the call result on hit (void returns None but hit is set)"""
|
||||
if trans is None or trans.ReplCtx is None or pool is None or builder is None: return None
|
||||
if func_name is None or hit is None: return None
|
||||
ctx: rawptr[GenTypes.ReplCtx] = trans.ReplCtx
|
||||
entry: rawptr[GenTypes.ReplFuncEntry] = self.repl_find_func_entry(ctx, func_name)
|
||||
ctx: GenTypes.ReplCtx* = trans.ReplCtx
|
||||
entry: GenTypes.ReplFuncEntry* = self.repl_find_func_entry(ctx, func_name)
|
||||
if entry is None: return None
|
||||
# Same rule as M2's read path: the fragment entry function or a promoted session function may call
|
||||
# other session functions; nested closures (no ctx param) are rejected, letting the existing path report.
|
||||
@@ -581,7 +581,7 @@ novirtual class VarGenMixin:
|
||||
return None
|
||||
|
||||
# ---- repl_llvm_ty - entry -> LLVM value type (structs re-resolved by name) ----
|
||||
def repl_llvm_ty(self, pool: memhub.MemBuddy*, entry: rawptr[GenTypes.ReplVarEntry]) -> mlirlite.LLVMType*:
|
||||
def repl_llvm_ty(self, pool: memhub.MemBuddy*, entry: GenTypes.ReplVarEntry*) -> mlirlite.LLVMType*:
|
||||
"""Infer the entry's LLVM value type; None when untyped or a struct type cannot be re-resolved in this fragment."""
|
||||
if entry is None or pool is None: return None
|
||||
if entry.Kind == GenTypes.REPL_KIND_UNTYPED: return None
|
||||
@@ -602,7 +602,7 @@ novirtual class VarGenMixin:
|
||||
return None
|
||||
|
||||
# ---- repl_slot_ty - the value type stored in the slot ----
|
||||
def repl_slot_ty(self, pool: memhub.MemBuddy*, entry: rawptr[GenTypes.ReplVarEntry]) -> mlirlite.LLVMType*:
|
||||
def repl_slot_ty(self, pool: memhub.MemBuddy*, entry: GenTypes.ReplVarEntry*) -> mlirlite.LLVMType*:
|
||||
"""The value type stored in the slot equals the entry's value type (scalars/pointers/structs inline); None if it overflows the slot."""
|
||||
if entry is None or pool is None: return None
|
||||
vt: mlirlite.LLVMType* = self.repl_llvm_ty(pool, entry)
|
||||
@@ -636,9 +636,9 @@ novirtual class VarGenMixin:
|
||||
case _:
|
||||
pass
|
||||
if elem_ty is not None: return self.repl_type_align(elem_ty, depth + 1)
|
||||
fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty)
|
||||
fields: mlirlite.ParamNode* = mlirlite.get_struct_fields(ty)
|
||||
if fields is None: return 0
|
||||
cur: rawptr[mlirlite.ParamNode] = fields
|
||||
cur: mlirlite.ParamNode* = fields
|
||||
best: int = 1
|
||||
while cur is not None:
|
||||
fty: mlirlite.LLVMType* = mlirlite.paramnode_get_ty(cur)
|
||||
@@ -668,11 +668,11 @@ novirtual class VarGenMixin:
|
||||
es: int = self.repl_type_size(elem_ty, depth + 1)
|
||||
if es <= 0 or cnt <= 0: return 0
|
||||
return es * cnt
|
||||
fields: rawptr[mlirlite.ParamNode] = mlirlite.get_struct_fields(ty)
|
||||
fields: mlirlite.ParamNode* = mlirlite.get_struct_fields(ty)
|
||||
if fields is None: return 0
|
||||
align_struct: int = self.repl_type_align(ty, depth + 1)
|
||||
if align_struct <= 0: return 0
|
||||
cur: rawptr[mlirlite.ParamNode] = fields
|
||||
cur: mlirlite.ParamNode* = fields
|
||||
off: int = 0
|
||||
counted: int = 0
|
||||
while cur is not None:
|
||||
@@ -691,7 +691,7 @@ novirtual class VarGenMixin:
|
||||
return off
|
||||
|
||||
# ---- repl_seal - first-time typing (if already typed, verify the type tag matches) ----
|
||||
def repl_seal(self, trans: HT.Translator*, entry: rawptr[GenTypes.ReplVarEntry], val_ty: mlirlite.LLVMType*, node: ast.AST*) -> int:
|
||||
def repl_seal(self, trans: HT.Translator*, entry: GenTypes.ReplVarEntry*, val_ty: mlirlite.LLVMType*, node: ast.AST*) -> int:
|
||||
"""Type the entry by val_ty; return 0=success (idempotent hits included) / 1=unsupported or conflicting (fail-fast already raised)."""
|
||||
if trans is None or entry is None or val_ty is None: return 1
|
||||
perm: memhub.MemBuddy* = self.repl_perm_pool(trans)
|
||||
@@ -796,12 +796,12 @@ novirtual class VarGenMixin:
|
||||
|
||||
# ---- repl_ensure_entry - allocate a slot when an untyped session variable name is first seen ----
|
||||
# Allocation happens during fragment translation on a local-table miss; a full table fails fast (no silent drop).
|
||||
def repl_ensure_entry(self, trans: HT.Translator*, name: str, node: ast.AST*) -> rawptr[GenTypes.ReplVarEntry]:
|
||||
def repl_ensure_entry(self, trans: HT.Translator*, name: str, node: ast.AST*) -> GenTypes.ReplVarEntry*:
|
||||
"""Get an entry by name, allocating and registering a slot if absent; None on failure (fail-fast already raised)."""
|
||||
if trans is None or name is None: return None
|
||||
ctx: rawptr[GenTypes.ReplCtx] = trans.ReplCtx
|
||||
ctx: GenTypes.ReplCtx* = trans.ReplCtx
|
||||
if ctx is None or ctx.Marker != GenTypes.REPL_CTX_MARKER: return None
|
||||
hit: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(ctx, name)
|
||||
hit: GenTypes.ReplVarEntry* = self.repl_find_entry(ctx, name)
|
||||
if hit is not None: return hit
|
||||
if ctx.Table is None or ctx.Cap <= 0:
|
||||
self.Gen.TypeGenErr.fatal_error(node, "REPL: 会话变量表未初始化(宿主未建 ctx)", "InternalCompilerError")
|
||||
@@ -818,7 +818,7 @@ novirtual class VarGenMixin:
|
||||
self.Gen.TypeGenErr.fatal_error(node, f"REPL: 会话变量 '{name}' 的名字深拷贝失败", "InternalCompilerError")
|
||||
return None
|
||||
entry_size: sizet = GenTypes.ReplVarEntry.__sizeof__()
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = rawptr[GenTypes.ReplVarEntry](uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size))
|
||||
entry: GenTypes.ReplVarEntry* = GenTypes.ReplVarEntry*(uint64(ctx.Table) + uint64(ctx.Count) * uint64(entry_size))
|
||||
if entry is None: return None
|
||||
entry.Name = name_copy
|
||||
entry.TyName = None
|
||||
@@ -914,7 +914,7 @@ novirtual class VarGenMixin:
|
||||
def repl_try_read(self, trans: HT.Translator*, name: str, node: ast.AST*) -> mlirlite.Value*:
|
||||
"""REPL session variable read: return the slot value on a hit (a box address for structs), else None."""
|
||||
if trans is None or trans.ReplCtx is None or name is None: return None
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name)
|
||||
entry: GenTypes.ReplVarEntry* = self.repl_find_entry(trans.ReplCtx, name)
|
||||
if entry is None: return None
|
||||
if self.repl_in_frag_scope(trans.SymTab) == 0: return None
|
||||
if entry.Kind == GenTypes.REPL_KIND_UNTYPED:
|
||||
@@ -937,7 +937,7 @@ novirtual class VarGenMixin:
|
||||
def repl_try_addr(self, trans: HT.Translator*, name: str, node: ast.AST*) -> mlirlite.Value*:
|
||||
"""Session variable address-of: return the slot address (Ptr(value type)); None when unregistered, untyped, or outside the fragment body."""
|
||||
if trans is None or trans.ReplCtx is None or name is None: return None
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name)
|
||||
entry: GenTypes.ReplVarEntry* = self.repl_find_entry(trans.ReplCtx, name)
|
||||
if entry is None: return None
|
||||
if self.repl_in_frag_scope(trans.SymTab) == 0: return None
|
||||
if entry.Kind == GenTypes.REPL_KIND_UNTYPED:
|
||||
@@ -958,7 +958,7 @@ novirtual class VarGenMixin:
|
||||
return slot
|
||||
|
||||
# ---- repl_store_slot - write a typed value into the slot (and into the result area) ----
|
||||
def repl_store_slot(self, trans: HT.Translator*, entry: rawptr[GenTypes.ReplVarEntry], ctx_val: mlirlite.Value*, rhs_val: mlirlite.Value*, node: ast.AST*) -> int:
|
||||
def repl_store_slot(self, trans: HT.Translator*, entry: GenTypes.ReplVarEntry*, ctx_val: mlirlite.Value*, rhs_val: mlirlite.Value*, node: ast.AST*) -> int:
|
||||
"""Coerce to the slot type, store into the slot, then write the result area; 0=success (fail-fast already raised on failure)."""
|
||||
if trans is None or entry is None or ctx_val is None or rhs_val is None: return 1
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
@@ -990,7 +990,7 @@ novirtual class VarGenMixin:
|
||||
def repl_try_assign(self, trans: HT.Translator*, name: str, rhs_val: mlirlite.Value*, rhs_node: ast.AST*, node: ast.AST*) -> int:
|
||||
"""REPL session variable assignment: return 1 on a hit (registered and inside the fragment entry function), else 0."""
|
||||
if trans is None or trans.ReplCtx is None or name is None or rhs_val is None: return 0
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name)
|
||||
entry: GenTypes.ReplVarEntry* = self.repl_find_entry(trans.ReplCtx, name)
|
||||
if entry is None: return 0
|
||||
if self.repl_in_frag_entry_scope(trans) == 0: return 0
|
||||
if rhs_val.Ty is None:
|
||||
@@ -1006,7 +1006,7 @@ novirtual class VarGenMixin:
|
||||
def repl_try_annassign(self, trans: HT.Translator*, name: str, annot_node: ast.AST*, value_node: ast.AST*, node: ast.AST*) -> int:
|
||||
"""REPL session variable annotated path (x: int = 1 / x: int, typing only): resolve the annotation, then type the entry and use it as the RHS target type."""
|
||||
if trans is None or trans.ReplCtx is None or name is None: return 0
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name)
|
||||
entry: GenTypes.ReplVarEntry* = self.repl_find_entry(trans.ReplCtx, name)
|
||||
if entry is None: return 0
|
||||
if self.repl_in_frag_entry_scope(trans) == 0: return 0
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
@@ -1044,7 +1044,7 @@ novirtual class VarGenMixin:
|
||||
def repl_try_augassign(self, trans: HT.Translator*, name: str, op: int, rhs_node: ast.AST*, node: ast.AST*) -> int:
|
||||
"""REPL session variable x += v: read slot, apply the binary op, write the slot and result area (return 1 on a hit)."""
|
||||
if trans is None or trans.ReplCtx is None or name is None: return 0
|
||||
entry: rawptr[GenTypes.ReplVarEntry] = self.repl_find_entry(trans.ReplCtx, name)
|
||||
entry: GenTypes.ReplVarEntry* = self.repl_find_entry(trans.ReplCtx, name)
|
||||
if entry is None: return 0
|
||||
if self.repl_in_frag_entry_scope(trans) == 0: return 0
|
||||
pool: memhub.MemBuddy* = trans.Pool
|
||||
@@ -1078,7 +1078,7 @@ novirtual class VarGenMixin:
|
||||
ctx_val: mlirlite.Value* = self.repl_ctx_ptr(trans, trans.ReplCtx, value_node)
|
||||
if ctx_val is None: return 1
|
||||
# Type classification uses the host's scratch entry (occupies no session slot, not in the table); reset to untyped each time
|
||||
sh: rawptr[GenTypes.ReplVarEntry] = trans.ReplCtx.Scratch
|
||||
sh: GenTypes.ReplVarEntry* = trans.ReplCtx.Scratch
|
||||
if sh is None:
|
||||
self.Gen.TypeGenErr.fatal_error(value_node, "REPL: 会话缺少影子条目(宿主未初始化)", "InternalCompilerError")
|
||||
return 1
|
||||
|
||||
@@ -134,7 +134,7 @@ def compute_file_sha1(pool: memhub.MemBuddy*, file_path: str) -> str:
|
||||
buf[write_pos] = 0
|
||||
|
||||
# compute SHA1
|
||||
ctx: rawptr[hashlib.sha1] = hashlib.sha1()
|
||||
ctx: hashlib.sha1* = hashlib.sha1()
|
||||
if ctx is None:
|
||||
stdlib.free(buf)
|
||||
return None
|
||||
@@ -168,7 +168,7 @@ def scan_directory_recursive(pool: memhub.MemBuddy*, root_dir: str, rel_prefix:
|
||||
|
||||
# find_data buffer +16 slack: TPV's WIN32_FIND_DATAA.__sizeof__() undercounts Windows writes
|
||||
fd_size_s: sizet = win32file.WIN32_FIND_DATAA.__sizeof__()
|
||||
find_data: rawptr[win32file.WIN32_FIND_DATAA] = stdlib.malloc(fd_size_s + 16)
|
||||
find_data: win32file.WIN32_FIND_DATAA* = stdlib.malloc(fd_size_s + 16)
|
||||
if find_data is None: return 1
|
||||
string.memset(find_data, 0, fd_size_s + 16)
|
||||
|
||||
|
||||
+32
-32
@@ -232,11 +232,11 @@ ReplNeedleBuf: bytes = None
|
||||
# ctx session buffer (shared by host and fragment; byte view, passed as the fragment's first arg).
|
||||
ReplCtxBuf: bytes = None
|
||||
# Session context object (read by Gen: tables/caps/param name/perm pool/scratch entry).
|
||||
ReplCtxObj: rawptr[GenTypes.ReplCtx] = None
|
||||
ReplCtxObj: GenTypes.ReplCtx* = None
|
||||
# Session variable table (PermPool, ReplCtxObj.Table).
|
||||
ReplVarTable: rawptr[GenTypes.ReplVarEntry] = None
|
||||
ReplVarTable: GenTypes.ReplVarEntry* = None
|
||||
# Scratch entry (PermPool): classifies bare-expression results only; no session slot or table entry.
|
||||
ReplScratch: rawptr[GenTypes.ReplVarEntry] = None
|
||||
ReplScratch: GenTypes.ReplVarEntry* = None
|
||||
# Recovery-point jmp_buf (PermPool, lives for the session): run _setjmp's into it and
|
||||
# VLogger.repl_abort longjmps back from any pipeline depth; re-registered per fragment.
|
||||
ReplJmpBuf: rawptr = None
|
||||
@@ -271,7 +271,7 @@ ReplLiftNameCount: int = 0
|
||||
ReplSigTags: bytes = None
|
||||
ReplSigBits: bytes = None
|
||||
# Signature result struct (PermPool, reused; named to avoid the ReplSigOut class).
|
||||
ReplSigResult: rawptr[ReplSigOut] = None
|
||||
ReplSigResult: ReplSigOut* = None
|
||||
# Session function table watermark (ReplCtxObj.FuncCount) at fragment start; restored on
|
||||
# failure to drop half-registered entries (same idea as ReplSavedVarCount, see ⓪).
|
||||
ReplSavedFuncCount: int = 0
|
||||
@@ -445,21 +445,21 @@ def _block_append(line: str, n: int) -> int:
|
||||
|
||||
|
||||
# ctx header view (int64 interpretation): host reads/writes magic/kind/result_a...
|
||||
def _ctx_head() -> rawptr[GenTypes.ReplResult]:
|
||||
def _ctx_head() -> GenTypes.ReplResult*:
|
||||
"""ctx header view; None when the session is not initialized."""
|
||||
if ReplCtxBuf is None: return None
|
||||
return rawptr[GenTypes.ReplResult](ReplCtxBuf)
|
||||
return GenTypes.ReplResult*(ReplCtxBuf)
|
||||
|
||||
|
||||
# ctx header view (double interpretation of result_a): for echoing float results.
|
||||
def _ctx_float_head() -> rawptr[ReplFloatView]:
|
||||
def _ctx_float_head() -> ReplFloatView*:
|
||||
"""Float view of the ctx header; None when the session is not initialized."""
|
||||
if ReplCtxBuf is None: return None
|
||||
return rawptr[ReplFloatView](ReplCtxBuf)
|
||||
return ReplFloatView*(ReplCtxBuf)
|
||||
|
||||
|
||||
# Result echo: read the ctx result area by result_kind and print it.
|
||||
def _repl_echo_result(frag_name: str, res: rawptr[GenTypes.ReplResult]) -> int:
|
||||
def _repl_echo_result(frag_name: str, res: GenTypes.ReplResult*) -> int:
|
||||
"""Echo this fragment's result by result_kind; 0=handled (including "no result")."""
|
||||
if frag_name is None or res is None: return 1
|
||||
k: int = res.Kind
|
||||
@@ -470,7 +470,7 @@ def _repl_echo_result(frag_name: str, res: rawptr[GenTypes.ReplResult]) -> int:
|
||||
stdio.printf("%s => %lld\n", frag_name, res.A)
|
||||
return 0
|
||||
if k == GenTypes.REPL_RES_FLOAT:
|
||||
fv: rawptr[ReplFloatView] = _ctx_float_head()
|
||||
fv: ReplFloatView* = _ctx_float_head()
|
||||
if fv is None: return 1
|
||||
stdio.printf("%s => %f\n", frag_name, fv.F)
|
||||
return 0
|
||||
@@ -649,7 +649,7 @@ def _repl_cmd_append_implibs(cmd: bytes, cap: int, pos: int) -> int:
|
||||
|
||||
# ---- includes class registration (once per session; per-module isolation, warnings only) ----
|
||||
|
||||
def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.ScanResult], vpi_dir: str) -> int:
|
||||
def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult*, vpi_dir: str) -> int:
|
||||
"""Inject each includes module's .vpi into a temp module so its classes enter the session StructTable; 0=done."""
|
||||
global ReplIncClsMods, ReplIncClsFail, ReplIncClsMissing
|
||||
if mb is None or sr is None or vpi_dir is None or sr.Entries is None: return 1
|
||||
@@ -669,7 +669,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Sca
|
||||
GenApi.SetTempDir(vpi_dir)
|
||||
GenApi.set_current_file_type(vpi_dir)
|
||||
tmp_mod: mlirlite.LLVMModule* = mlirlite.new_module(_perm_pool, _REPL_INC_MOD_NAME)
|
||||
tr_inc: rawptr[HandlesTranslator.Translator] = _perm_pool.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
tr_inc: HandlesTranslator.Translator* = _perm_pool.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
if tmp_mod is None or tr_inc is None: return 1
|
||||
tr_inc.__before_init__()
|
||||
tr_inc.__init__()
|
||||
@@ -702,7 +702,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Sca
|
||||
stdio.printf("includes 类注册: 结构体表已达 %d 条(上限附近)," "停止注册;未注册的类在会话里不可用(import 其模块" "仍可按需注册)\n", GenApi.get_struct_count())
|
||||
stdio.fflush(None)
|
||||
return 0
|
||||
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(sr.Entries) + uint64(i) * uint64(es))
|
||||
ent: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(uint64(sr.Entries) + uint64(i) * uint64(es))
|
||||
if ent is None or ent.Sha1 is None:
|
||||
st[i] = sizet(1)
|
||||
ReplIncClsFail += 1
|
||||
@@ -848,7 +848,7 @@ def ReplInitSession() -> int:
|
||||
ReplScratch.Bits = 0
|
||||
# 5') Session function table (M3; PermPool, host writes, Gen reads only) - entry array zeroed.
|
||||
func_entry_size: sizet = GenTypes.ReplFuncEntry.__sizeof__()
|
||||
ReplFuncTable: rawptr[GenTypes.ReplFuncEntry] = _perm_pool.alloc(func_entry_size * GenTypes.REPL_FUNC_CAP)
|
||||
ReplFuncTable: GenTypes.ReplFuncEntry* = _perm_pool.alloc(func_entry_size * GenTypes.REPL_FUNC_CAP)
|
||||
if ReplFuncTable is None: return 1
|
||||
string.memset(ReplFuncTable, 0, func_entry_size * GenTypes.REPL_FUNC_CAP)
|
||||
# 6) Session context object (the Gen-side switch: trans.ReplCtx).
|
||||
@@ -872,7 +872,7 @@ def ReplInitSession() -> int:
|
||||
ReplCtxObj.FuncCap = GenTypes.REPL_FUNC_CAP
|
||||
ReplSavedFuncCount = 0
|
||||
# 7) ctx fixed header: magic/version written once by the host (fragments read-only, no validation).
|
||||
head: rawptr[GenTypes.ReplResult] = _ctx_head()
|
||||
head: GenTypes.ReplResult* = _ctx_head()
|
||||
if head is None: return 1
|
||||
head.Magic = GenTypes.REPL_CTX_MAGIC
|
||||
head.Version = GenTypes.REPL_CTX_VERSION
|
||||
@@ -911,7 +911,7 @@ def ReplInitSession() -> int:
|
||||
|
||||
# ============================================================
|
||||
# includes session init: scan dir -> register "module -> SHA1" -> pre-generate .vpi stubs.
|
||||
def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.ScanResult], vpi_dir: str) -> int:
|
||||
def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult*, vpi_dir: str) -> int:
|
||||
"""Pre-generate .vpi stubs for the includes scan; returns the count of new stubs (-1=bad args)."""
|
||||
global ReplIncVpiNew, ReplIncVpiReuse, ReplIncVpiFail
|
||||
if mb is None or sr is None or vpi_dir is None: return -1
|
||||
@@ -920,7 +920,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Scan
|
||||
dl: sizet = string.strlen(vpi_dir)
|
||||
n: int
|
||||
for n in range(sr.Count):
|
||||
ent: rawptr[IncludesScanner.FileEntry] = rawptr[IncludesScanner.FileEntry](uint64(sr.Entries) + uint64(n) * es)
|
||||
ent: IncludesScanner.FileEntry* = IncludesScanner.FileEntry*(uint64(sr.Entries) + uint64(n) * es)
|
||||
if ent is None or ent.Sha1 is None or ent.Path is None:
|
||||
ReplIncVpiFail += 1
|
||||
continue
|
||||
@@ -931,7 +931,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Scan
|
||||
mb.reset_to(fm)
|
||||
continue
|
||||
# Existing stub -> reuse.
|
||||
vf: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.R)
|
||||
vf: fileio.File* = fileio.File(vpi_path, fileio.MODE.R)
|
||||
if not vf.closed:
|
||||
vf.close()
|
||||
stdlib.free(vpi_path)
|
||||
@@ -939,7 +939,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Scan
|
||||
mb.reset_to(fm)
|
||||
continue
|
||||
# Read source file (1MB cap matching Phase1/BuildPipeline SRC_BUF_SIZE).
|
||||
f: rawptr[fileio.File] = fileio.File(ent.Path, fileio.MODE.R)
|
||||
f: fileio.File* = fileio.File(ent.Path, fileio.MODE.R)
|
||||
if f.closed:
|
||||
stdlib.free(vpi_path)
|
||||
ReplIncVpiFail += 1
|
||||
@@ -990,7 +990,7 @@ def _repl_gen_includes_vpi(mb: memhub.MemBuddy*, sr: rawptr[IncludesScanner.Scan
|
||||
# Pass the absolute ent.Path as rel_path: vpi fatal_error reads source lines via it.
|
||||
pos: sizet = StubConverter._GeneratePyiFromAst(mb, tree, ent.Path, pyi_buf, _REPL_VPI_BUF_CAP)
|
||||
if pos > 0:
|
||||
pf: rawptr[fileio.File] = fileio.File(vpi_path, fileio.MODE.W)
|
||||
pf: fileio.File* = fileio.File(vpi_path, fileio.MODE.W)
|
||||
if not pf.closed:
|
||||
pf.write(pyi_buf, pos)
|
||||
pf.close()
|
||||
@@ -1020,7 +1020,7 @@ def ReplInitIncludes(mb: memhub.MemBuddy*) -> int:
|
||||
return 1
|
||||
# 1) Scan includes (no reachability: REPL has no SourceDir/deps graph, so scan all).
|
||||
t0: uint64 = win32base.GetTickCount64()
|
||||
sr: rawptr[IncludesScanner.ScanResult] = IncludesScanner.scan_includes(mb, inc_dirs)
|
||||
sr: IncludesScanner.ScanResult* = IncludesScanner.scan_includes(mb, inc_dirs)
|
||||
if sr is None:
|
||||
stdio.printf("REPL: includes 扫描失败(目录: %s);" "import includes 模块会报未注册 SHA1\n", inc_dirs)
|
||||
return 1
|
||||
@@ -1345,13 +1345,13 @@ def _repl_build_frag_src_multi(name: str, body: bytes) -> int:
|
||||
# M3 session function table: host owns it (writes table + ctx slots); Gen reads only.
|
||||
|
||||
# Find a session function table entry by name (host side; same as Gen's repl_find_func_entry).
|
||||
def _repl_func_entry_find(name: str) -> rawptr[GenTypes.ReplFuncEntry]:
|
||||
def _repl_func_entry_find(name: str) -> GenTypes.ReplFuncEntry*:
|
||||
"""1=entry found; None=not registered or table not built."""
|
||||
if ReplCtxObj is None or ReplCtxObj.FuncTable is None or name is None: return None
|
||||
es: sizet = GenTypes.ReplFuncEntry.__sizeof__()
|
||||
i: int
|
||||
for i in range(ReplCtxObj.FuncCount):
|
||||
e: rawptr[GenTypes.ReplFuncEntry] = rawptr[GenTypes.ReplFuncEntry](uint64(ReplCtxObj.FuncTable) + uint64(i) * uint64(es))
|
||||
e: GenTypes.ReplFuncEntry* = GenTypes.ReplFuncEntry*(uint64(ReplCtxObj.FuncTable) + uint64(i) * uint64(es))
|
||||
if e.Name is not None and string.strcmp(e.Name, name) == 0: return e
|
||||
return None
|
||||
|
||||
@@ -1417,7 +1417,7 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int:
|
||||
if rc != 0:
|
||||
stdio.printf("M3: 会话函数 '%s' 的签名解析失败(rc=%d)\n", nm, rc)
|
||||
return 1
|
||||
old: rawptr[GenTypes.ReplFuncEntry] = _repl_func_entry_find(nm)
|
||||
old: GenTypes.ReplFuncEntry* = _repl_func_entry_find(nm)
|
||||
if old is None:
|
||||
new_cnt += 1
|
||||
continue
|
||||
@@ -1440,7 +1440,7 @@ def _repl_precheck_session_funcs(mod: mlirlite.LLVMModule*) -> int:
|
||||
|
||||
|
||||
# Render an existing entry's signature (for redefinition-conflict diagnostics; into ReplSigText2).
|
||||
def _repl_entry_sig_text(e: rawptr[GenTypes.ReplFuncEntry]) -> str:
|
||||
def _repl_entry_sig_text(e: GenTypes.ReplFuncEntry*) -> str:
|
||||
if e is None or ReplSigText2 is None: return "(?)"
|
||||
pos: int = _repl_cat_str(ReplSigText2, _REPL_SIG_TEXT_CAP, 0, "(")
|
||||
for i in range(e.ParamCount):
|
||||
@@ -1469,7 +1469,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli
|
||||
if addr is None:
|
||||
stdio.printf("M3: 会话函数 '%s' 未出现在片段 DLL 的导出表" "(GetProcAddress 返回空;本片段不执行)\n", nm)
|
||||
return 1
|
||||
ent: rawptr[GenTypes.ReplFuncEntry] = _repl_func_entry_find(nm)
|
||||
ent: GenTypes.ReplFuncEntry* = _repl_func_entry_find(nm)
|
||||
if ent is None:
|
||||
# New entry (signature already validated; re-parse to recover the scratch tokens).
|
||||
rc: int = _repl_model_func_sig(mod, nm, ReplSigResult)
|
||||
@@ -1478,7 +1478,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli
|
||||
return 1
|
||||
j: int = ReplCtxObj.FuncCount
|
||||
es: sizet = GenTypes.ReplFuncEntry.__sizeof__()
|
||||
ent = rawptr[GenTypes.ReplFuncEntry](uint64(ReplCtxObj.FuncTable) + uint64(j) * uint64(es))
|
||||
ent = GenTypes.ReplFuncEntry*(uint64(ReplCtxObj.FuncTable) + uint64(j) * uint64(es))
|
||||
nm_c: str = _repl_perm_dup(nm)
|
||||
nm_s: str = _repl_perm_dup(nm)
|
||||
tags_b: bytes = _perm_pool.alloc(GenTypes.REPL_FUNC_PARAM_MAX)
|
||||
@@ -1504,7 +1504,7 @@ def _repl_register_session_funcs(h_lib: win32base.HANDLE, frag_no: int, mod: mli
|
||||
# Redefinition (same signature): only swap address and fragment number; slot offset unchanged.
|
||||
ent.FragNo = frag_no
|
||||
# Write the ctx slot (low 8 bytes = address, high 8 bytes reserved 0).
|
||||
sv: rawptr[ReplFuncSlotView] = rawptr[ReplFuncSlotView](uint64(ReplCtxBuf) + uint64(ent.SlotOff))
|
||||
sv: ReplFuncSlotView* = ReplFuncSlotView*(uint64(ReplCtxBuf) + uint64(ent.SlotOff))
|
||||
sv.Addr = addr
|
||||
sv.Reserved = None
|
||||
stdio.printf("会话函数 %s: 导出符号 %s → ctx 槽 +%d(定义片段 %d,签名 %s)\n", nm, nm, ent.SlotOff, frag_no, _repl_entry_sig_text(ent))
|
||||
@@ -1570,7 +1570,7 @@ def _repl_ty_name(ty: mlirlite.LLVMType*) -> str:
|
||||
|
||||
# Take a session function signature from the translation model (not by parsing IR define lines).
|
||||
# Codes: 0=ok; 1=not found; 2=unsupported type; 3=EH params; 4=first param not ctx; 5=too many params.
|
||||
def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, out: rawptr[ReplSigOut]) -> int:
|
||||
def _repl_model_func_sig(mod: mlirlite.LLVMModule*, name: str, out: ReplSigOut*) -> int:
|
||||
if name is None or out is None or mod is None: return 1
|
||||
out.RetTag = GenTypes.REPL_TY_VOID
|
||||
out.RetBits = 0
|
||||
@@ -1735,7 +1735,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int:
|
||||
|
||||
# 4) Write the wrapped source to disk (used only for error echo: fatal_error reads this file).
|
||||
viperlib.snprintf(ReplSrcPath, _REPL_PATH_CAP, "%s/%s.vp", ReplTmpDir, ReplNameBuf)
|
||||
sf: rawptr[fileio.File] = fileio.File(ReplSrcPath, fileio.MODE.W)
|
||||
sf: fileio.File* = fileio.File(ReplSrcPath, fileio.MODE.W)
|
||||
if not sf.closed:
|
||||
sf.write(ReplSrcBuf, string.strlen(ReplSrcBuf))
|
||||
sf.close()
|
||||
@@ -1779,7 +1779,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int:
|
||||
|
||||
# 7) Translate to full module IR. ModuleSha1 = session sha1 (types are "<sha1>.<Type>");
|
||||
# ReplCtx enables REPL mode and is cleared after translation.
|
||||
tr: rawptr[HandlesTranslator.Translator] = mb.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
tr: HandlesTranslator.Translator* = mb.alloc(HandlesTranslator.Translator.__sizeof__())
|
||||
if tr is None:
|
||||
stdio.printf("片段 %s: Translator 分配失败\n", ReplNameBuf)
|
||||
return 1
|
||||
@@ -1906,7 +1906,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int:
|
||||
|
||||
# 13) Reset the result area (kind=none) and refresh var_count/last_frag; call indirectly (the
|
||||
# module stays resident, so no FreeLibrary).
|
||||
head: rawptr[GenTypes.ReplResult] = _ctx_head()
|
||||
head: GenTypes.ReplResult* = _ctx_head()
|
||||
if head is None: return 1
|
||||
head.Kind = GenTypes.REPL_RES_NONE
|
||||
head.VarCount = ReplCtxObj.Count
|
||||
|
||||
+1
-1
@@ -111,7 +111,7 @@ def main() -> int:
|
||||
lib._mbuddy = mb
|
||||
|
||||
# P2: create the project-level Generator singleton (reused across Phase1/Phase2/BuildPipeline;
|
||||
gen: rawptr[GenGenerator.Generator] = mb.alloc(GenGenerator.Generator.__sizeof__())
|
||||
gen: GenGenerator.Generator* = mb.alloc(GenGenerator.Generator.__sizeof__())
|
||||
if gen is None:
|
||||
stdio.printf("FAIL: Generator alloc failed\n")
|
||||
return 1
|
||||
|
||||
Reference in new issue
Block a user