chore: 改名同步 TransPyV -> ViperC(源码/配置内的纯替换)

This commit is contained in:
TermiNexus committed 2026-10-12 15:06:28 +08:00
1 parent d0c7b9c77c
commit 3384941cd1
12 files changed
+37 -37

No files matched your search

+4 -4
View File
@@ -34,7 +34,7 @@ import lib.Stub.StubMerger.StubMergerCollect as StubMergerCollect
_mbuddy: memhub.MemBuddy*
# ASan mode (--asan): instrument .ll via opt -passes=asan; the ASan runtime is
# declared explicitly in project.vpj's linker.static_libs / dynamic_libs (TPV injects nothing).
# declared explicitly in project.vpj's linker.static_libs / dynamic_libs (VPC injects nothing).
_asan_mode: bool = 0
# Traceback mode (--traceback): force-build includes/traceback.vp, inject the startup
@@ -364,7 +364,7 @@ def compile_ll_to_obj(ir_path: str, output_dir: str, module_name: str, cc_cmd: s
if obj_path is None: return 1
# ASan mode: run opt -passes=asan before llc. -asan-globals=false disables global
# instrumentation: TPV addresses globals directly and ASan redzones would shift them.
# instrumentation: VPC addresses globals directly and ASan redzones would shift them.
compile_input: str = ir_path
# ---- MLIR lowering (fixed, no switch): mlir-opt (validate) -> mlir-translate ----
@@ -552,7 +552,7 @@ def _phase2_write_cmd(cmd: str) -> None:
if _phase2_bat_init == 0:
_phase2_bat_init = 1
hdr1: str = "@echo off\r\n"
hdr2: str = "rem TransPyV --phase2command generated commands\r\n"
hdr2: str = "rem ViperC --phase2command generated commands\r\n"
f.write(hdr1, string.strlen(hdr1))
f.write(hdr2, string.strlen(hdr2))
f.write(cmd, string.strlen(cmd))
@@ -968,7 +968,7 @@ def link_objs_to_exe(obj_paths: str, obj_paths_len: sizet, linker_cmd: str, link
if includes_binary_dir is not None: extra_len = collect_obj_files(includes_binary_dir, extra_objs, EXTRA_BUF_SIZE)
# Command: clang++ obj_paths extra_objs -o linker_output linker_flags. The ASan runtime
# comes from project.vpj, not TPV. Host export: import lib is <linker_output>.dll.a.
# comes from project.vpj, not VPC. Host export: import lib is <linker_output>.dll.a.
if linker_output is not None:
implib_len2: sizet = string.strlen(linker_output) + 8
implib_path2: str = _mbuddy.alloc(implib_len2)
+3 -3
View File
@@ -3113,7 +3113,7 @@ def _inject_method_declare(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*, m_
if pseg_ty is not None:
match pseg_ty:
case mlirlite.LLVMType.Struct(_, _, _):
# Bare struct param: methods are always internal TPV symbols (mangled
# Bare struct param: methods are always internal VPC symbols (mangled
# {sha1}.{Class}.{method}, no C ABI define), so is_c_abi=0 -> Ptr(struct).
param_ty = _AggregateParamTy(mod, pool, pseg_ty, 0)
case mlirlite.LLVMType.Array(aelem_ty, _):
@@ -3811,7 +3811,7 @@ def _repl_stub_collect_module(pool: memhub.MemBuddy*, mod: mlirlite.LLVMModule*,
ReplStubNoStub += 1
if ReplStubWarnLeft > 0:
ReplStubWarnLeft -= 1
stdio.printf("includes class layout: module %s has no .meta stub (data missing) -- this module " "classes with parent/vtable will each be explicitly refused as data missing (layout metadata cannot be read => no " "field count to compare, not a field count mismatch). First run batch processing once in the same project to generate stubs, " "then reuse them with `--project .\\project.vpj --repl` (in the TransPyV directory)\n", src_sha1)
stdio.printf("includes class layout: module %s has no .meta stub (data missing) -- this module " "classes with parent/vtable will each be explicitly refused as data missing (layout metadata cannot be read => no " "field count to compare, not a field count mismatch). First run batch processing once in the same project to generate stubs, " "then reuse them with `--project .\\project.vpj --repl` (in the ViperC directory)\n", src_sha1)
cnt: int = 0
i: sizet
for i in range(int(n)):
@@ -3867,7 +3867,7 @@ def ReplStubLayoutFinish() -> int:
if ReplStubRefused > 0 or ReplStubNoStub > 0:
stdio.printf(" Note: field access on refused classes reports class not registered/attribute access failed " "(it does not silently access at a wrong offset); method calls are unaffected.\n")
if ReplStubRefusedNoStub > 0:
stdio.printf(" Of these, the %d classes with data missing simply failed to read the module layout metadata (the session temp directory %s " "is missing these {sha1}.meta): only batch processing writes meta to disk (the REPL branch runs before Phase1 " "and returns, so --repl itself does not generate stubs). Fix: run batch processing once in the same project " "(TransPyV directory: .\\tpv_build\\output\\TransPyV.exe --project " ".\\project.vpj; add --rebuild-includes when includes changed), then " "reuse its temp directory with --project .\\project.vpj --repl\n", ReplStubRefusedNoStub, ReplStubTempDir)
stdio.printf(" Of these, the %d classes with data missing simply failed to read the module layout metadata (the session temp directory %s " "is missing these {sha1}.meta): only batch processing writes meta to disk (the REPL branch runs before Phase1 " "and returns, so --repl itself does not generate stubs). Fix: run batch processing once in the same project " "(ViperC directory: .\\tpv_build\\output\\viperc.exe --project " ".\\project.vpj; add --rebuild-includes when includes changed), then " "reuse its temp directory with --project .\\project.vpj --repl\n", ReplStubRefusedNoStub, ReplStubTempDir)
if ReplStubRefusedNoClass + ReplStubRefusedOpaque > 0:
stdio.printf(" Of these, the %d classes with criterion refused: data exists but is untrusted (the stub has no field count for this class, " "or it is declared opaque); per M4.2 none are allowed through -- please confirm whether this class should have been registered as a struct " "in the first place: if it should be registered as a struct but is not found in the stub => the stub is stale/incomplete (rebuild includes " "stubs)\n", ReplStubRefusedNoClass + ReplStubRefusedOpaque)
return ReplStubOk
+9 -9
View File
@@ -163,7 +163,7 @@ novirtual class AssignGenMixin:
「左侧只会看到截断了的数据」:超宽的值先按 bits 取低位(如 WORD(0x80000000) → 0),
不是直接把原值搬过来、也不是只对"刚好越界一点"的值做重解释。
实现用左移后算术右移,而不是 `value & 0xFFFFFFFF` 这类大掩码字面量:
掩码字面量(如 4294967295)超出 int32 范围,其加宽方向在 TPC/TPV 上可能判成 sext,
掩码字面量(如 4294967295)超出 int32 范围,其加宽方向在 TPC/VPC 上可能判成 sext,
会得到 0xFFFFFFFFFFFFFFFF 而不是 0xFFFFFFFF,导致截断失效。
"""
if bits == 8: return (value << 56) >> 56
@@ -203,7 +203,7 @@ novirtual class AssignGenMixin:
if value <= 2147483647: return 32
# 2^31..2^32-1:无符号 32 位位型即可容纳 → 32 位。
# 用 (value >> 32) == 0 判断,**不要**写成 uint64(uint32(value)) == value:uint32(...) 之后的
# 加宽方向(zext/sext)由 should_zext_widen 按节点无符号性决定,TPC 与 TPV 自举的判定可能不一致;
# 加宽方向(zext/sext)由 should_zext_widen 按节点无符号性决定,TPC 与 VPC 自举的判定可能不一致;
# 一旦判成 sext,uint64(0x80000000) 会变成 0xFFFFFFFF80000000 ≠ value → 误判 64 位 →
# `GENERIC_READ | GENERIC_WRITE` 被放大到 i64 → 赋给 32 位目标报隐式窄化。
if (value >> 32) == 0: return 32
@@ -280,9 +280,9 @@ novirtual class AssignGenMixin:
v: int64 = 0
if self._static_int_of(count_node, &v) == 0: return
if v < 0:
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] shift count is negative ({v}): shifting by a negative amount is undefined. " "Fix: use a non-negative count.", "ValueError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] shift count is negative ({v}): shifting by a negative amount is undefined. " "Fix: use a non-negative count.", "ValueError")
if uint64(v) >= uint64(lhs_bits):
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] shift count out of range: the count {v} is >= the left operand width {lhs_bits} bits; " f"the result would be 0 or undefined (not a value the compiler may guess). " f"Fix: use a count < {lhs_bits}, or widen the left operand.", "ValueError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] shift count out of range: the count {v} is >= the left operand width {lhs_bits} bits; " f"the result would be 0 or undefined (not a value the compiler may guess). " f"Fix: use a count < {lhs_bits}, or widen the left operand.", "ValueError")
def _is_cdefine_marker_node(self, node: ast.AST*) -> int:
"""Return 1 if the node is a t.CDefine marker node."""
@@ -494,7 +494,7 @@ novirtual class AssignGenMixin:
bits: int = self._define_annot_bits(pool, annot)
wmin: int = self.define_min_width(value)
if self._int_text_exceeds_64(text) != 0:
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant value not storable: the initial value {text} of constant '{name}' exceeds 64 bits " f"(the widest integer type in this language is 64 bits; the storable range under both signed and unsigned interpretations is " f"-9223372036854775808..18446744073709551615; no wider integer type exists => widening is required). " f"Silent truncation/downgrade is forbidden; compilation aborted. Available integer types: int8/uint8, " f"int16/uint16, int32/uint32, int64/uint64 " f"(or int8/uint8/.../uint64, char, sizet). " f"Fix: move the value into the 64-bit range, or introduce a larger integer type for this number (widen).", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] define constant value not storable: the initial value {text} of constant '{name}' exceeds 64 bits " f"(the widest integer type in this language is 64 bits; the storable range under both signed and unsigned interpretations is " f"-9223372036854775808..18446744073709551615; no wider integer type exists => widening is required). " f"Silent truncation/downgrade is forbidden; compilation aborted. Available integer types: int8/uint8, " f"int16/uint16, int32/uint32, int64/uint64 " f"(or int8/uint8/.../uint64, char, sizet). " f"Fix: move the value into the 64-bit range, or introduce a larger integer type for this number (widen).", "TypeError")
return
if bits == 0: return
# Explicit truncation exemption: the RHS narrowed itself to rhs_bits (a cast such as WORD(...)),
@@ -512,7 +512,7 @@ novirtual class AssignGenMixin:
hi = 65535
elif bits == 64: return
if value < lo or value > hi:
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant value not storable: the initial value {value} of constant '{name}' is not storable. " f"Minimal storable width W_min: {wmin} bits; declared type width {bits} bits, " f"storable range of this declaration: {lo}..{hi}. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the explicit type to a wider type (such as int32 / int64 / uint64), " f"or correct the literal.", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] define constant value not storable: the initial value {value} of constant '{name}' is not storable. " f"Minimal storable width W_min: {wmin} bits; declared type width {bits} bits, " f"storable range of this declaration: {lo}..{hi}. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the explicit type to a wider type (such as int32 / int64 / uint64), " f"or correct the literal.", "TypeError")
def require_cdefine_use_width(self, pool: memhub.MemBuddy*, trans: HT.Translator*, target_annot: ast.AST*, value_node: ast.AST*) -> None:
"""Fail fast when a define constant is wider than its use-site type.
@@ -534,7 +534,7 @@ novirtual class AssignGenMixin:
dw: int = self.Gen.TypeGenCDef.lookup_cdefine_bits(rn.id)
if dw == 0: dw = self.define_min_width(cdef_val)
if bits >= dw: return
self.Gen.TypeGenErr.fatal_error(value_node, f"[TPV] define constant use-site width insufficient: constant '{rn.id}' is {dw} bits wide " f"(declared width; actual value {cdef_val}), but the use site (variable declaration annotation) provides only {bits} bits. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the variable declaration annotation to at least {dw} bits (such as int{dw}T / CUInt{dw}T), " f"or narrow the constant at its define with an explicit cast.", "TypeError")
self.Gen.TypeGenErr.fatal_error(value_node, f"[VPC] define constant use-site width insufficient: constant '{rn.id}' is {dw} bits wide " f"(declared width; actual value {cdef_val}), but the use site (variable declaration annotation) provides only {bits} bits. " f"Silent truncation/downgrade is forbidden; compilation aborted. " f"Fix: widen the variable declaration annotation to at least {dw} bits (such as int{dw}T / CUInt{dw}T), " f"or narrow the constant at its define with an explicit cast.", "TypeError")
# _register_cdefine_from_value - register a CDefine constant (float or int)
def _register_cdefine_from_value(self, pool: memhub.MemBuddy*, name: str, val_node: ast.AST*, annot: ast.AST* = None) -> None:
@@ -1459,13 +1459,13 @@ novirtual class AssignGenMixin:
cn_aa: ast.Constant* = ast.Constant*(y_node_aa)
if cn_aa.const_kind == ast.CONST_INT: y_bits_eff = self.define_min_width(cn_aa.int_val)
if y_bits_eff > lhs_bits:
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] augmented assignment operand too wide: the right-hand side needs {y_bits_eff} bits, " f"but the target provides only {lhs_bits} bits; an implicit narrowing is forbidden. " f"Fix: narrow the right-hand side explicitly (e.g. uint{lhs_bits}(...) / int{lhs_bits}(...)) before the operation.", "CastError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] augmented assignment operand too wide: the right-hand side needs {y_bits_eff} bits, " f"but the target provides only {lhs_bits} bits; an implicit narrowing is forbidden. " f"Fix: narrow the right-hand side explicitly (e.g. uint{lhs_bits}(...) / int{lhs_bits}(...)) before the operation.", "CastError")
x_uns_aa: int = 0
if lhs_node is not None: x_uns_aa = self.Gen.ExprGenOps._node_type_unsigned(pool, lhs_node, trans)
y_sgn_aa: int = 0
if y_node_aa is not None: y_sgn_aa = self.Gen.ExprGenOps._node_type_signed(pool, y_node_aa, trans)
if x_uns_aa != 0 and y_sgn_aa != 0:
self.Gen.TypeGenErr.fatal_error(node, "[TPV] augmented assignment operand signedness conflict: the right-hand side is explicitly signed " "while the target is unsigned; sign extension would turn negative values into huge unsigned values. " "Fix: use an unsigned right-hand side (e.g. uint32(...)), or make the target signed.", "CastError")
self.Gen.TypeGenErr.fatal_error(node, "[VPC] augmented assignment operand signedness conflict: the right-hand side is explicitly signed " "while the target is unsigned; sign extension would turn negative values into huge unsigned values. " "Fix: use an unsigned right-hand side (e.g. uint32(...)), or make the target signed.", "CastError")
# Integer op: type promotion
if lhs_bits > rhs_bits and rhs_bits > 0: rhs = self.Gen.ExprGenBase.coerce_to_type(builder, rhs, lhs.Ty, node, trans)
+3 -3
View File
@@ -15,10 +15,10 @@ import lib.core.Gen.Call.CallGenBase as CallGenBase
# ============================================================
# AsyncGenMixin - TPV-M1 coroutine translation (async def / await / coro.coro_run)
# AsyncGenMixin - VPC-M1 coroutine translation (async def / await / coro.coro_run)
define SCOPE_FUNCTION = 1
novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
"""Coroutine translation mixin (TPV-M1 state machine)"""
"""Coroutine translation mixin (VPC-M1 state machine)"""
# Entry: async function definition. Called by FuncGenDef.translate_function_def after
# detecting fd.flags & FLAG_IS_ASYNC; early-returns so it never enters the normal path.
@@ -609,7 +609,7 @@ novirtual class AsyncGenMixin(CallGenBase.CallGenBase):
if self.Gen.CallGenBase.find_func_in_module(mod, mangled) is not None: return 0
func: mlirlite.Function* = mlirlite.create_function(pool, mod, mangled, frame_ptr_ty)
if func is None: return 0
# params (i32, frame slot 5+i). TPV has no Python "%" formatting ("%" is modulo),
# params (i32, frame slot 5+i). VPC has no Python "%" formatting ("%" is modulo),
# so names are built with snprintf ("%%arg" -> "%arg", matching resume's "%frame").
pi: int = 0
argn_buf: str = pool.alloc(16)
+2 -2
View File
@@ -847,7 +847,7 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
「左侧只会看到截断了的数据」:超宽的值先按 bits 取低位(WORD(0x80000000) → 0),
而不是只对"刚好越界一点"的值做重解释。
实现用左移后算术右移,而不是 `value & 0xFFFFFFFF` 这类大掩码字面量:
掩码字面量(如 4294967295)超出 int32 范围,其加宽方向在 TPC/TPV 上可能判成 sext,
掩码字面量(如 4294967295)超出 int32 范围,其加宽方向在 TPC/VPC 上可能判成 sext,
会得到 0xFFFFFFFFFFFFFFFF 而不是 0xFFFFFFFF,导致截断失效。
"""
if bits == 8: return (value << 56) >> 56
@@ -877,6 +877,6 @@ novirtual class ExprGenCdef(ExprGenBase.ExprGenBase):
# this language's str is i8* with no `str + str`: `+` degrades to pointer add.
# Build strings with f-string interpolation / string.strcat / viperlib.snprintf.
ctx = f"({use_ctx})"
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] define constant use site width insufficient: constant '{name}' actual value {value} " f"needs at least {wmin} bits (minimum representable width W_min), " f"but the use site{ctx} provides only {bits} bits " f"(the acceptable range for this bit width under both signed/unsigned interpretation: {lo}..{hi}). " f"silent truncation/downgrade is forbidden, compilation aborted. " f"fix: widen the type of the use site{ctx} to at least {wmin} bits " f"(e.g. int{wmin}T / CUInt{wmin}T or wider types), or use a smaller constant value.", "TypeError")
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] define constant use site width insufficient: constant '{name}' actual value {value} " f"needs at least {wmin} bits (minimum representable width W_min), " f"but the use site{ctx} provides only {bits} bits " f"(the acceptable range for this bit width under both signed/unsigned interpretation: {lo}..{hi}). " f"silent truncation/downgrade is forbidden, compilation aborted. " f"fix: widen the type of the use site{ctx} to at least {wmin} bits " f"(e.g. int{wmin}T / CUInt{wmin}T or wider types), or use a smaller constant value.", "TypeError")
return None
return mlirlite.const_int(pool, bits, self._cdefine_bits_value(value, bits))
+1 -1
View File
@@ -61,7 +61,7 @@ novirtual class ExprGenMixin(ExprGenBase.ExprGenBase):
elif k == ast.ASTKind.JoinedStr: return self.Gen.ExprGenFstr.translate_joined_str(builder, pool, mod, node, trans)
elif k == ast.ASTKind.FormattedValue: return self.Gen.ExprGenFstr.translate_formatted_value(builder, pool, mod, node, trans)
elif k == ast.ASTKind.Await:
# Coroutine await (TPV-M1): inline-translate when the await target is an async call.
# Coroutine await (VPC-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: ast.Await* = ast.Await*(node)
if aw is not None and aw.value is not None and aw.value.kind() == ast.ASTKind.Call:
+1 -1
View File
@@ -1096,7 +1096,7 @@ novirtual class ExprGenOps(ExprGenBase.ExprGenBase):
if string.strcmp(rty_buf, "i8*") == 0: rty_lbl = "str(i8*)"
col_s: int = 0
if node is not None: col_s = node.col_offset + 1
self.Gen.TypeGenErr.fatal_error(node, f"[TPV] illegal double-pointer arithmetic type: op = '{op_lbl}'{aug_note}, " f"left operand type = {lty_lbl}, right operand type = {rty_lbl}. " f"in this language str is i8*, with no `+` concatenation semantics (`str + str` and pointer +/- pointer " f"both degrade to raw pointer add/sub => illegal IR: opt reports " f"invalid operand type for instruction). " f"silent degradation is forbidden, compilation aborted. " f"fix: build strings with f-string interpolation, string.strcat, or viperlib.snprintf.", "TypeError", col_s, col_s)
self.Gen.TypeGenErr.fatal_error(node, f"[VPC] illegal double-pointer arithmetic type: op = '{op_lbl}'{aug_note}, " f"left operand type = {lty_lbl}, right operand type = {rty_lbl}. " f"in this language str is i8*, with no `+` concatenation semantics (`str + str` and pointer +/- pointer " f"both degrade to raw pointer add/sub => illegal IR: opt reports " f"invalid operand type for instruction). " f"silent degradation is forbidden, compilation aborted. " f"fix: build strings with f-string interpolation, string.strcat, or viperlib.snprintf.", "TypeError", col_s, col_s)
return 1
# binop_needs_int_promotion - whether this op takes C-style integer promotion (to >= 32 bits)
def binop_needs_int_promotion(self, op: int) -> int:
+3 -3
View File
@@ -262,7 +262,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
self.Gen.ClassGenGeneric._register_generic_func_template(trans.Pool, fd, trans.ModuleSha1)
return 0
# async def (TPV-M1 coroutine): FLAG_IS_ASYNC=1 (parser stores async def as FunctionDef with flags & 1)
# async def (VPC-M1 coroutine): FLAG_IS_ASYNC=1 (parser stores async def as FunctionDef with flags & 1)
# -> AsyncGenMixin state machine (create_<name>/resume_<name>); early-return so the plain path cannot suspend/resume.
if fd.flags is not None and (fd.flags & 1) != 0: return self.Gen.AsyncGen.translate_async_function(trans, node)
@@ -368,7 +368,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
# Skip t-module storage markers (@t.CExport/@t.CExtern/@t.State/@t.TLS/@t.CStatic/@t.CInline/@t.CVTable/
# @t.NoVTable/@t.Object/@t.CEnum/@t.CUnion/@t.REnum/@t.CDefine). Attribute-form @t.xxx is not handled here.
# 另跳过**编译期生命期标注**(P2:规范形式 @life(willFree(...)) 与兼容叠加形式 @willFree(...)):
# 它们是纯标注、没有运行时装饰器函数。漏在这里会让 TPV 生成 __decor_wrap_<name> wrapper,
# 它们是纯标注、没有运行时装饰器函数。漏在这里会让 VPC 生成 __decor_wrap_<name> wrapper,
# 去调用并不存在的 @life/@willFree,并把被装饰的 extern def(如 stdlib.free)变成 internal 声明
# (现场:llc 报 "invalid linkage for function declaration")。
if string.strcmp(dname, "CExport") == 0 or string.strcmp(dname, "CExtern") == 0 or string.strcmp(dname, "State") == 0 or string.strcmp(dname, "TLS") == 0 or string.strcmp(dname, "CStatic") == 0 or string.strcmp(dname, "CInline") == 0 or string.strcmp(dname, "CVTable") == 0 or string.strcmp(dname, "NoVTable") == 0 or string.strcmp(dname, "Object") == 0 or string.strcmp(dname, "CEnum") == 0 or string.strcmp(dname, "CUnion") == 0 or string.strcmp(dname, "REnum") == 0 or string.strcmp(dname, "CDefine") == 0 or string.strcmp(dname, "life") == 0 or string.strcmp(dname, "willFree") == 0:
@@ -1103,7 +1103,7 @@ novirtual class FuncGenDef(CallGenBase.CallGenBase):
if null_ret is not None: mlirlite.value_set_next(null_ret, null_dec)
n_calls: mlirlite.Value* = mlirlite.build_call(wb, handler_name, ctx_ptr, 6, i32_ty, 0)
# 7. Counter alloca (TPV uses an alloca counter instead of phi)
# 7. Counter alloca (VPC uses an alloca counter instead of phi)
cnt_alloca: mlirlite.Value* = mlirlite.build_alloca(wb, i32_ty)
cnt_zero: mlirlite.Value* = mlirlite.ConstInt(pool, i32_ty, 0, "0")
if cnt_alloca is not None and cnt_zero is not None: mlirlite.build_store(wb, cnt_zero, cnt_alloca)
+1 -1
View File
@@ -999,7 +999,7 @@ novirtual class FuncGenMixin(CallGenBase.CallGenBase):
# 9. Captured variables: load values from env heap slots into local allocas
for ci in range(int(cap_count)):
# Take the capture name via str pointer offset (like param_names + pi*32). Do not use
# (str)(cap_addr): TPV compiles that to itoa, corrupting define_var keys.
# (str)(cap_addr): VPC compiles that to itoa, corrupting define_var keys.
cap_slot: str = cap_names + ci * 64
if cap_slot[0] == '\0': continue
ty_addr3: uint64 = uint64(cap_tys) + ci * 8
+1 -1
View File
@@ -133,7 +133,7 @@ novirtual class TranslatorGenMixin:
"""Build LLVM IR array initializer text from an AST List node; None on failure."""
if var_ty is None or list_node is None: return None
# Re-cast so the TPV compiler recognizes ast.List, avoiding type inference degrading
# Re-cast so the VPC compiler recognizes ast.List, avoiding type inference degrading
# to t.CPtr when init_list_node's initial value is None.
ln: ast.List* = ast.List*(list_node)
if ln is None: return None
+1 -1
View File
@@ -44,7 +44,7 @@ define SCOPE_BLOCK = 2
# 保存的旧值还原)——否则内层函数会在 0 号槽覆写外层登记项,且内层出口会把外层的对象一起 free 掉。
# · 表的存储必须**跨文件存活**:trans.Pool 是每文件池,Phase2 每翻完一个文件就 reset_to(mark2)
# (见 Phase2/__init__.vp)。若表落在这个池里,第二个文件起表体已是被回收的内存,后续
# 写入就是往活跃数据上砸(现场:TransPyV.exe 编译任何工程 access-violation on 0x0,
# 写入就是往活跃数据上砸(现场:viperc.exe 编译任何工程 access-violation on 0x0,
# 崩点每次都不同)。故与 _g_freed_slots 同口径,用 stdlib.malloc。
# 登记表容量(P5:128 → 256)。超限时 **fail-fast**(不再静默退化为"不登记 = 不释放"的泄漏)。
define _SLIFE_MAX = 256
+8 -8
View File
@@ -198,7 +198,7 @@ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int:
return 1
else: string.strcpy(c2, "(GetModuleFileNameA failed)")
# Not found in either place: emit diagnostics (needs --project + both searched paths).
viperlib.snprintf(Diag, DiagCap, " Searched(1): %s\n" " Searched(2): %s\n" " --project needed: without repl.vpj the REPL cannot get the project config; " "specify it with --project <path/to/repl.vpj>\n" " Template location: TransPyV/repl.vpj in the repo; copy it next to TransPyV.exe" "or into the current working directory to be found automatically\n", c1, c2)
viperlib.snprintf(Diag, DiagCap, " Searched(1): %s\n" " Searched(2): %s\n" " --project needed: without repl.vpj the REPL cannot get the project config; " "specify it with --project <path/to/repl.vpj>\n" " Template location: ViperC/repl.vpj in the repo; copy it next to viperc.exe" "or into the current working directory to be found automatically\n", c1, c2)
stdlib.free(c1)
stdlib.free(c2)
return 0
@@ -209,7 +209,7 @@ def ReplFindProject(Out: bytes, Cap: int, Diag: bytes, DiagCap: int) -> int:
ReplFragFn: callable[[rawptr], int] = None
# Fragment sequence number: module-level and monotonic, so names/files are never reused.
ReplFragNo: int = 1
# Session temp dir %TEMP%\TransPyV_repl\<pid> (keeps user projects clean; pid isolates sessions).
# Session temp dir %TEMP%\ViperC_repl\<pid> (keeps user projects clean; pid isolates sessions).
ReplTmpDir: bytes = None
# Fragment symbol name __repl_frag_<n>.
ReplNameBuf: bytes = None
@@ -767,7 +767,7 @@ def ReplInitIncludesClasses(mb: memhub.MemBuddy*, sr: IncludesScanner.ScanResult
# ============================================================
# Session init: create %TEMP%\TransPyV_repl\<pid>\ and allocate permanent buffers + ctx.
# Session init: create %TEMP%\ViperC_repl\<pid>\ and allocate permanent buffers + ctx.
def ReplInitSession() -> int:
"""Create the temp dir plus PermPool resident buffers and ctx session memory; 0=success."""
global ReplTmpDir, ReplNameBuf, ReplSrcBuf, ReplSrcPath, ReplIrBuf, ReplNeedleBuf
@@ -788,10 +788,10 @@ def ReplInitSession() -> int:
tmp_len: ULONG = win32file.GetTempPathA(_REPL_TMP_CAP, tmp_buf)
if tmp_len == 0: return 1
if int(tmp_len) >= _REPL_TMP_CAP: return 1
# 2) Session dir <TEMP>TransPyV_repl/<pid> (pid isolates sessions; paths use '/').
# 2) Session dir <TEMP>ViperC_repl/<pid> (pid isolates sessions; paths use '/').
ReplTmpDir = _perm_pool.alloc(_REPL_PATH_CAP)
if ReplTmpDir is None: return 1
viperlib.snprintf(ReplTmpDir, _REPL_PATH_CAP, "%sTransPyV_repl/%u", tmp_buf, win32process.GetCurrentProcessId())
viperlib.snprintf(ReplTmpDir, _REPL_PATH_CAP, "%sViperC_repl/%u", tmp_buf, win32process.GetCurrentProcessId())
if BuildPipeline.ensure_dir(ReplTmpDir) != 0: return 1
# 3) Permanent buffers (live for the session, not re-allocated per fragment).
ReplNameBuf = _perm_pool.alloc(_REPL_NAME_CAP)
@@ -1872,7 +1872,7 @@ def ReplExecFragment(mb: memhub.MemBuddy*, src: str) -> int:
if link_rc != 0:
stdio.printf("fragment %s: failed to generate .dll (exit=%d)\n command: %s\n", ReplNameBuf, link_rc, cmd)
if ReplHostImplib is None:
stdio.printf(" Hint: host import lib (<exe name>.dll.a) not found -- " "cross-module symbols (of the form <16-hex>.<func name>) cannot be resolved; " "build the host with TransPyV/project.vpj (including -Wl,--export-all-symbols), " "and keep <exe name>.dll.a in the same dir as the exe\n")
stdio.printf(" Hint: host import lib (<exe name>.dll.a) not found -- " "cross-module symbols (of the form <16-hex>.<func name>) cannot be resolved; " "build the host with ViperC/project.vpj (including -Wl,--export-all-symbols), " "and keep <exe name>.dll.a in the same dir as the exe\n")
else:
stdio.printf(" Hint: if the output contains undefined symbol of the form <16-hex>.<name>, " "that symbol is not defined/exported by the host (the corresponding includes module was not linked when building the host); " "if the function is `export def` in source (CExport, bare-name definition) yet still carries a prefix, " "the include stub .vpi is probably missing (see the includes scan line at session start)\n")
return 1
@@ -1979,7 +1979,7 @@ def run(mb: memhub.MemBuddy*) -> int:
if lg is not None: lg.set_jit_flag(False)
return 1
stdio.printf("TransPyV REPL (M2/M3/M4) - session variables + session functions (cross-fragment) + ctx result echo;\n")
stdio.printf("ViperC REPL (M2/M3/M4) - session variables + session functions (cross-fragment) + ctx result echo;\n")
stdio.printf(" Supports expressions (1+2), definitions (x = 1 / x: int = 5), references (x + 1),\n")
stdio.printf(" augmented assignment (x += 2), address-of (p = &x), etc.; blank lines are skipped, Ctrl+Z or EOF exits\n")
stdio.printf(" Multi-line block: a trailing ':' enters continuation (prompt ...), a blank line ends it and runs the block once\n")
@@ -2022,7 +2022,7 @@ def run(mb: memhub.MemBuddy*) -> int:
if ReplFindHostImplib() != 0:
stdio.printf("Host symbol import lib: %s (fragments can call includes functions/globals across modules)\n", ReplHostImplib)
else:
stdio.printf("Host symbol import lib: <exe name>.dll.a not found; fragment calls to includes module-level " "functions will report undefined symbol at link time (the session does not terminate). Build the host with " "TransPyV/project.vpj (which declares -Wl,--export-all-symbols), " "and keep the exe and .dll.a in the same dir\n")
stdio.printf("Host symbol import lib: <exe name>.dll.a not found; fragment calls to includes module-level " "functions will report undefined symbol at link time (the session does not terminate). Build the host with " "ViperC/project.vpj (which declares -Wl,--export-all-symbols), " "and keep the exe and .dll.a in the same dir\n")
stdio.fflush(None)
# === Read loop: single-line fragments + block continuation ===