基本稳定

This commit is contained in:
TermiNexus committed 2026-08-05 20:11:38 +08:00
1 parent 0a10b20dde
commit a39b5da0f8
27 files changed
+392 -962

No files matched your search

+1 -1
View File
@@ -17,7 +17,7 @@ from .base import (
_init_ast, _copy_str, _set_pos, _inherit_pos, _set_parent_list,
_binop_from_op, _augop_from_op, _cmpop_from_op,
_emit, _emit_str, _emit_int, _dump_list,
dump,
dump, _op_name,
)
# 语句节点
from .stmts import (
+8
View File
@@ -553,6 +553,14 @@ def _read_string(lx: Lexer | t.CPtr):
conv_buf[wpos] = '\t'
elif next_ch == 'r':
conv_buf[wpos] = '\r'
elif next_ch == 'f':
conv_buf[wpos] = '\f'
elif next_ch == 'v':
conv_buf[wpos] = '\v'
elif next_ch == 'a':
conv_buf[wpos] = '\a'
elif next_ch == 'b':
conv_buf[wpos] = '\b'
elif next_ch == '\\':
conv_buf[wpos] = '\\'
elif next_ch == '\'':
+1 -1
View File
@@ -154,7 +154,7 @@ def a2b_hex(hexstr: str, length: t.CInt) -> str:
out[oi] = '\0'
return out
def unhexlify(data: str, length: t.CInt):
def unhexlify(data: str, length: t.CInt) -> bytes:
return a2b_hex(data, length)
def b2a_base64(data: str, length: t.CInt) -> str:
+4 -4
View File
@@ -504,10 +504,10 @@ def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, "global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
TypePrint(ty_buf, 512, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
# 初始化值
@@ -541,10 +541,10 @@ def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
_append_cstr(buf, size, " = external global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
ty_buf: t.CChar | t.CPtr = pool.alloc(512)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
TypePrint(ty_buf, 512, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
+179 -8
View File
@@ -4,6 +4,7 @@ import viperlib
import string
import memhub
import stdio
import stdlib
from linkedlist import GSListNode
@@ -383,8 +384,23 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
pool 用于递归打印子类型时分配临时缓冲区。
"""
_TypePrintDepth(buf, size, ty, pool, 0)
# 递归深度上限:悬空/自引用的 LLVMType 树(1b reset 后内存被复用)会导致
# Ptr(pointee)/Struct(fields)/Func(params) 无限递归,每次递归分配临时缓冲
# 造成 OOM(单文件暴涨 900MB 根因)。超过 100 层即停止打印。
TYPEPRINT_MAX_DEPTH: t.CDefine = 100
def _TypePrintDepth(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt):
"""带递归深度上限的 TypePrint 内部实现"""
if ty is None or buf is None or size == 0:
return
if depth >= TYPEPRINT_MAX_DEPTH:
viperlib.snprintf(buf, size, "...")
return
buf[0] = '\0'
match ty:
case LLVMType.Int(bits):
@@ -400,7 +416,10 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
match pointee:
case LLVMType.Struct(sfields, sfcount, sname):
if sname is not None:
viperlib.snprintf(buf, size, "%%\"%s\"*", sname)
# 悬空防护:sname 可能指向被 reset 回收/部分复用的 pool 内存,
# 用受限打印避免读越界崩溃;完整名在 vtable 生成后由
# TypeStr 兜底(stdlib 深拷贝,跨 reset 存活)
viperlib.snprintf(buf, size, "%%\"%.40s\"*", sname)
return
case LLVMType.Void():
# Ptr(Void) → i8*(LLVM IR void* 非法)
@@ -419,7 +438,7 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
string.strcpy(buf, "i8*")
return
# 通用路径: 递归打印 pointee 后追加 '*'
TypePrint(buf, size, pointee, pool)
_TypePrintDepth(buf, size, pointee, pool, depth + 1)
pos: t.CSizeT = string.strlen(buf)
if pos + 1 < size:
buf[pos] = '*'
@@ -431,7 +450,7 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
# 嵌套指针/数组更易超过 128,使用 512 字节避免截断
tmp: t.CChar | t.CPtr = pool.alloc(512)
if tmp is not None:
TypePrint(tmp, 512, elem_ty, pool)
_TypePrintDepth(tmp, 512, elem_ty, pool, depth + 1)
_strappend(buf, size, tmp)
_strappend(buf, size, "]")
case LLVMType.Struct(fields, fcount, name):
@@ -440,20 +459,26 @@ def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
viperlib.snprintf(buf, size, "%%\"%s\"", name)
else:
# 匿名结构体: {ty1, ty2, ...}
_print_struct_body(buf, size, fields, pool)
_print_struct_body(buf, size, fields, pool, depth)
case LLVMType.Func(ret, params, count):
# ret (ty1, ty2, ...)
TypePrint(buf, size, ret, pool)
_TypePrintDepth(buf, size, ret, pool, depth + 1)
_strappend(buf, size, " (")
cur2: ParamNode | t.CPtr = params
first2: t.CInt = 1
_pc2: t.CInt = 0
# 函数参数类型可能为 SHA1 限定命名结构体指针,512 字节避免截断
tmp3: t.CChar | t.CPtr = pool.alloc(512)
while cur2 is not None:
# 悬空保护:参数链若被 reset 回收后内容复用,可能成环无限循环
_pc2 += 1
if _pc2 > 200:
_strappend(buf, size, "...)")
break
if first2 == 0:
_strappend(buf, size, ", ")
if tmp3 is not None:
TypePrint(tmp3, 512, cur2.Ty, pool)
_TypePrintDepth(tmp3, 512, cur2.Ty, pool, depth + 1)
_strappend(buf, size, tmp3)
cur2 = cur2.Next
first2 = 0
@@ -502,7 +527,8 @@ def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr)
# 供 TypePrint(匿名结构体)和 PrintStructDefinition(命名结构体定义行)复用
# ============================================================
def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
depth: t.CInt = 0):
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)
直接在 buf 当前末尾写入字段类型,避免 pool.alloc 返回与 buf 重叠的内存
@@ -515,13 +541,18 @@ def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
first: t.CInt = 1
fidx: t.CInt = 0
while cur is not None:
# 悬空保护:ParamNode 链若被 reset 回收后内容复用,Next 指针可能成环或
# 指向垃圾,无限循环。最多打印 200 个字段即停止,防止 OOM。
if fidx >= 200:
_strappend(buf, size, "...}")
return
if first == 0:
_strappend(buf, size, ", ")
# 直接在 buf 当前末尾位置写入字段类型
# TypePrint 首字节置 '\0' 是无害的(pos 处本来就是 '\0')
pos: t.CSizeT = string.strlen(buf)
if pos + 2 < size:
TypePrint(buf + pos, size - pos, cur.Ty, pool)
_TypePrintDepth(buf + pos, size - pos, cur.Ty, pool, depth + 1)
cur = cur.Next
first = 0
fidx += 1
@@ -574,4 +605,144 @@ def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
return None
def get_struct_fields(ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
"""获取结构体的字段链表(供跨模块重建 Struct 类型用)"""
if ty is None:
return None
match ty:
case LLVMType.Struct(fields, fcount, name):
return fields
case _:
return None
def get_struct_fcount(ty: LLVMType | t.CPtr) -> t.CInt:
"""获取结构体的字段数量(供跨模块重建 Struct 类型用)"""
if ty is None:
return 0
match ty:
case LLVMType.Struct(fields, fcount, name):
return fcount
case _:
return 0
# ============================================================
# DeepCopyType - 深拷贝 LLVMType 到 stdlib 区(跨文件 reset 存活)
#
# 背景: 1b 阶段(mark1 之后)新注册的结构体(泛型特化类等),其
# struct_ty 是 pool 分配的 LLVMType,所在文件翻译完 reset_to(mark1)
# 后指针悬空。_struct_table 中的 entry.Ty 指向它,后续文件遍历
# _struct_table(find_struct_by_type/lookup_field 等)时解引用悬空
# 指针导致崩溃(0xC0000005)。
#
# 本函数递归拷贝整棵 LLVMType 树到 stdlib(含 ParamNode 字段链和
# 字符串名),保证 entry.Ty 跨文件永久存活。
#
# 注意: 自引用类型(如 Value 含 Ptr(Value) 字段)会导致无限递归,
# 用深度上限防护(超过即返回浅拷贝副本,后续不再递归)。
# ============================================================
DEEPCOPY_MAX_DEPTH: t.CDefine = 64
def DeepCopyType(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
"""深拷贝 LLVMType 到 stdlib 区(深度限制防自引用递归),失败返回 None"""
return _DeepCopyDepth(pool, ty, 0)
def _DeepCopyDepth(pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr, depth: t.CInt) -> LLVMType | t.CPtr:
"""带深度上限的深拷贝实现"""
if ty is None:
return None
new_ty: LLVMType | t.CPtr = (LLVMType | t.CPtr)(stdlib.malloc(LLVMType.__sizeof__()))
if new_ty is None:
return None
string.memset(new_ty, 0, LLVMType.__sizeof__())
if depth >= DEEPCOPY_MAX_DEPTH:
# 深度超限:浅拷贝 tag 后停止递归(复制当前变体但不深拷子类型)
match ty:
case LLVMType.Int(bits):
c.DerefAs(new_ty, LLVMType.Int(bits))
case LLVMType.Float(bits):
c.DerefAs(new_ty, LLVMType.Float(bits))
case LLVMType.Void():
c.DerefAs(new_ty, LLVMType.Void())
case LLVMType.Label():
c.DerefAs(new_ty, LLVMType.Label())
case LLVMType.Metadata():
c.DerefAs(new_ty, LLVMType.Metadata())
case _:
c.DerefAs(new_ty, LLVMType.Void())
return new_ty
match ty:
case LLVMType.Int(bits):
c.DerefAs(new_ty, LLVMType.Int(bits))
case LLVMType.Float(bits):
c.DerefAs(new_ty, LLVMType.Float(bits))
case LLVMType.Void():
c.DerefAs(new_ty, LLVMType.Void())
case LLVMType.Label():
c.DerefAs(new_ty, LLVMType.Label())
case LLVMType.Metadata():
c.DerefAs(new_ty, LLVMType.Metadata())
case LLVMType.Ptr(pointee):
c.DerefAs(new_ty, LLVMType.Ptr(_DeepCopyDepth(pool, pointee, depth + 1)))
case LLVMType.Array(elem_ty, count):
c.DerefAs(new_ty, LLVMType.Array(_DeepCopyDepth(pool, elem_ty, depth + 1), count))
case LLVMType.Func(ret, params, pcount):
c.DerefAs(new_ty, LLVMType.Func(
_DeepCopyDepth(pool, ret, depth + 1),
_DeepCopyParamChain(pool, params, depth + 1), pcount))
case LLVMType.Struct(fields, fcount, name):
c.DerefAs(new_ty, LLVMType.Struct(
_DeepCopyParamChain(pool, fields, depth + 1),
fcount, _DeepCopyStr(pool, name)))
case _:
stdlib.free(new_ty)
return None
return new_ty
def _DeepCopyParamChain(pool: memhub.MemBuddy | t.CPtr,
head: ParamNode | t.CPtr, depth: t.CInt) -> ParamNode | t.CPtr:
"""深拷贝 ParamNode 链表到 stdlib"""
if head is None:
return None
first: ParamNode | t.CPtr = None
prev: ParamNode | t.CPtr = None
cur: ParamNode | t.CPtr = head
guard: t.CInt = 0
while cur is not None:
guard += 1
if guard > 512:
break
node: ParamNode | t.CPtr = (ParamNode | t.CPtr)(stdlib.malloc(PNODE_SIZE))
if node is None:
break
string.memset(node, 0, PNODE_SIZE)
node.Ty = _DeepCopyDepth(pool, paramnode_get_ty(cur), depth + 1)
node.Next = None
if first is None:
first = node
if prev is not None:
prev.Next = node
prev = node
cur = paramnode_get_next(cur)
return first
def _DeepCopyStr(pool: memhub.MemBuddy | t.CPtr, s: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
"""深拷贝字符串到 stdlib"""
if s is None:
return None
slen: t.CSizeT = string.strlen(s)
copy: t.CChar | t.CPtr = stdlib.malloc(slen + 1)
if copy is None:
return None
string.strcpy(copy, s)
return copy
+116 -6
View File
@@ -4,7 +4,7 @@ import string
import atom
import viperio
import stdio
import sys
import stdlib
# ============================================================
# memhub - Unified memory management library
@@ -26,7 +26,6 @@ MEMBUDDY_MIN_BLOCK: t.CDefine = 32
MEMBUDDY_MAX_ORDERS: t.CDefine = 32
MEMBUDDY_HEADER_SIZE: t.CDefine = 8
def _align_up(val: t.CSizeT, align: t.CSizeT) -> t.CSizeT:
if align == 0: return val
return (val + align - 1) & ~(align - 1)
@@ -134,7 +133,13 @@ class MemPool(MemManager):
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
if size == 0: return None
aligned: t.CSizeT = _align_up(size, MEMHUB_ALIGN)
if self.offset + aligned > self.size: return None
if self.offset + aligned > self.size:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败\n", size)
stdio.printf("[OOM] MemPool: total=%zu used=%zu (bump allocator, 无释放)\n",
self.size, self.offset)
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
stdlib.exit(1)
ptr: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(self.base) + self.offset, t.CPtr)
self.offset += aligned
if self.offset > self.high_water:
@@ -211,8 +216,18 @@ class MemSlab(MemManager):
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
# Slab mode: allocate one block only if requested size <= block_size
if self.free_list is None: return None
if size > self.block_size: return None
if self.free_list is None:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败(free_list 已空)\n", size)
stdio.printf("[OOM] MemSlab: block_size=%zu block_count=%zu used=%zu\n",
self.block_size, self.block_count, self.used_count)
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
stdlib.exit(1)
if size > self.block_size:
stdio.printf("\n[OOM] 内存不足 (Out of Memory)\n")
stdio.printf("[OOM] 尝试分配: %zu 字节,失败(超过 block_size=%zu)\n", size, self.block_size)
stdio.printf("[OOM] 说明: 请求大小超过 MemSlab 块大小,应改用 MemBuddy/MemPool。\n")
stdlib.exit(1)
block: t.CVoid | t.CPtr = self.free_list
self.free_list = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
self.used_count += 1
@@ -254,6 +269,11 @@ class MemSlab(MemManager):
# MemBuddy - Buddy system allocator
# Free list head array stored at arena start; subsequent memory managed in power-of-two sized blocks
# Thread-safe (spinlock enabled), supports block coalescing
#
# Checkpoint 支持(供编译器等长任务回收阶段性分配):
# mark() → 返回当前分配水位(不分配内存)
# reset_to(m) → 释放水位 m 之后分配的所有块(回收到 free list)
# 记录栈从 usable 顶部预留 _CHK_RESERVE 字节,不参与 buddy 分配。
# ============================================================
class MemBuddy(MemManager):
# Override parent __provides__: MemBuddy provides both __mbuddy__ and __memmgr__.
@@ -265,6 +285,10 @@ class MemBuddy(MemManager):
lock_val: t.CVolatile | t.CInt # Spinlock
usable: t.CVoid | t.CPtr # Start of usable memory region (skips free_lists)
usable_size: t.CSizeT # Size of usable memory (power of two)
chk_stack: t.CUInt64T | t.CPtr # Checkpoint 分配记录栈(存 block 地址)
chk_cap: t.CSizeT # 记录栈容量(条目数)
chk_depth: t.CSizeT # 当前记录深度
chk_base: t.CVoid | t.CPtr # 记录栈起始地址(由 stdlib.malloc 分配,独立于 buddy 区)
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
self.base = base
@@ -274,6 +298,10 @@ class MemBuddy(MemManager):
self.lock_val = 0
self.usable = None
self.usable_size = 0
self.chk_stack = None
self.chk_cap = 0
self.chk_depth = 0
self.chk_base = None
self.lock_val = 0
fl_bytes: t.CSizeT = (MEMBUDDY_MAX_ORDERS + 1) * 8
@@ -291,6 +319,12 @@ class MemBuddy(MemManager):
return
remaining: t.CSizeT = size - fl_bytes
# 注意:不能在 __init__ 里预留 checkpoint 记录栈!
# buddy 区必须从 fl_bytes 后开始、大小必须是 2 的幂。
# 若预留 512KB,remaining = 2^30 - 512KB 不是 2 的幂,
# _largest_pow2_le 会取到 2^29 = 512MB,1GB 池直接砍半。
# 记录栈改为 mark() 时从 buddy 池懒分配(见 mark())。
usable: t.CSizeT = _largest_pow2_le(remaining)
if usable < MEMBUDDY_MIN_BLOCK:
@@ -312,6 +346,60 @@ class MemBuddy(MemManager):
# Entire usable memory region as a max_order free block
self._fl_push(self.max_order, self.usable)
# === Checkpoint support ===
def mark(self) -> t.CSizeT:
"""返回当前分配水位(checkpoint)
记录栈用 stdlib.malloc 分配(64K 条目 × 8B = 512KB,独立于 buddy 区),
首次调用时懒分配。这样不占用 buddy 池、不会把 1GB 池砍半、
reset_to 也不会误释放栈自身。
"""
if self.chk_stack is None:
# 记录栈用 stdlib.malloc 分配(独立于 buddy 区,避免占用 buddy 池、
# 避免 reset_to 误释放栈自身,也避免栈内存与 buddy 块重叠)。
cap: t.CSizeT = 64 * 1024
base: t.CVoid | t.CPtr = t.CVoid(stdlib.malloc(cap * 8), t.CPtr)
if base is None:
return 0
self.chk_base = base
self.chk_stack = (t.CUInt64T | t.CPtr)(t.CVoid(base, t.CPtr))
self.chk_cap = cap
self.chk_depth = 0
return self.chk_depth
def reset_to(self, mark: t.CSizeT):
"""释放水位 mark 之后分配的所有块,回收到 free list
栈中每个 block:若 header 仍标记为已分配(奇数),_coalesce 归还;
若已被单独 free(header==0),跳过避免重复归还。
"""
if self.chk_stack is None:
return
if mark >= self.chk_depth:
return
self._lock()
while self.chk_depth > mark:
self.chk_depth -= 1
block: t.CVoid | t.CPtr = t.CVoid(self.chk_stack[self.chk_depth], t.CPtr)
if block is None:
continue
stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
stored_val: t.CUInt64T = t.CUInt64T(stored)
if (stored_val & 1) == 0:
continue # 已被单独 free,跳过
order: t.CInt = t.CInt(stored_val >> 1)
if order < 0 or order > self.max_order:
continue
self._coalesce(block, order)
self._unlock()
def reset_all(self):
"""回收全部已分配块(等价 reset_to(0))"""
if self.chk_stack is None:
return
self.reset_to(0)
# === Free list operations ===
def _fl_push(self, order: t.CInt, block: t.CVoid | t.CPtr):
@@ -405,6 +493,24 @@ class MemBuddy(MemManager):
order: t.CInt = t.CInt(stored_val >> 1)
if order < 0: return 0
if order > self.max_order: return 0
# 记录栈一致性校验:分配时(alloc)每个 block 地址都会压入 chk_stack。
# reset_to(mark) 会把 [mark, chk_depth) 的块弹栈并归还 free list,
# 之后这些地址会被重新分配。若一个 header 恰好是合法奇数(假阳性),
# 但地址不在当前 chk_stack[0..chk_depth) 存活区间内,说明已被回收,
# 不能当作有效指针(否则 _format_func_type_str/TypePrint 会沿垃圾链
# 无限分配导致 OOM)。
# 注意:chk_stack 容量满(64K)后 alloc 不再记录新块(chk_depth==chk_cap),
# 此时无法区分,跳过校验(退化到仅 header 校验,避免误判正常 free)。
if self.chk_stack is not None and self.chk_depth < self.chk_cap:
alive: t.CInt = 0
ci: t.CSizeT = 0
while ci < self.chk_depth:
if self.chk_stack[ci] == t.CUInt64T(block):
alive = 1
break
ci += 1
if alive == 0:
return 0
return 1
# === Spinlock ===
@@ -430,6 +536,10 @@ class MemBuddy(MemManager):
if block is not None:
c.DerefAs(block, t.CVoid(t.CUInt64T((order << 1) | 1), t.CPtr))
result = t.CVoid(t.CUInt64T(block) + MEMBUDDY_HEADER_SIZE, t.CPtr)
# 记录到 checkpoint 栈(供 reset_to 回收)
if self.chk_stack is not None and self.chk_depth < self.chk_cap:
self.chk_stack[self.chk_depth] = t.CUInt64T(block)
self.chk_depth += 1
if result is None:
# Allocation failure: print memory usage statistics and exit with OOM
fb: t.CSizeT = self.free_bytes()
@@ -439,7 +549,7 @@ class MemBuddy(MemManager):
stdio.printf("[OOM] 内存池: total=%zu used=%zu free=%zu free_blocks=%zu\n",
self.usable_size, ub, fb, self.free_count())
stdio.printf("[OOM] 说明: 内存池已耗尽。可能原因: (1) 池大小不足,需增大 POOL_SIZE; (2) 存在内存泄漏。\n")
sys.exit(1)
stdlib.exit(1)
self._unlock()
return result
+21 -20
View File
@@ -7,106 +7,107 @@ import os._win32
import os._posix
# os 包入口
# 根据 platmacro.IS_WINDOWS 分派到 _win32 或 _posix 后端
# os.path 为跨平台纯字符串操作,直接可用
# os package entry point
# Dispatches to _win32 or _posix backend based on platmacro.IS_WINDOWS
# os.path is for cross-platform pure string operations, can be used directly
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
# Module-level global MBuddy pointer (initialized by the user in main)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# File/Directory Attribute Query
# =============================================================================
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
"""Check if the file/directory exists"""
if platmacro.IS_WINDOWS:
return os._win32.exists(path)
return os._posix.exists(path)
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
"""Check if the path is a directory"""
if platmacro.IS_WINDOWS:
return os._win32.isdir(path)
return os._posix.isdir(path)
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
"""Check if the path is a regular file"""
if platmacro.IS_WINDOWS:
return os._win32.isfile(path)
return os._posix.isfile(path)
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
"""Returns the file size (in bytes). Returns -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.getsize(path)
return os._posix.getsize(path)
# =============================================================================
# 工作目录
# Working Directory
# =============================================================================
def getcwd() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
"""Return the current working directory (memory allocated via _mbuddy)"""
if platmacro.IS_WINDOWS:
return os._win32.getcwd()
return os._posix.getcwd_impl()
def chdir(path: str) -> int:
"""切换当前工作目录。成功返回 0,失败返回 -1。"""
"""Switch the current working directory. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.chdir(path)
return os._posix.chdir_impl(path)
# =============================================================================
# 文件/目录操作
# File/Directory Operations
# =============================================================================
def mkdir(path: str) -> int:
"""创建目录。成功返回 0,失败返回 -1。"""
"""Create a directory. Returns 0 on success, -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.mkdir(path)
return os._posix.mkdir_impl(path)
def remove(path: str) -> int:
"""删除文件。成功返回 0,失败返回 -1。"""
"""Delete the file. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.remove(path)
return os._posix.remove(path)
def rmdir(path: str) -> int:
"""删除空目录。成功返回 0,失败返回 -1。"""
"""Delete empty directories. Returns 0 if successful, -1 if it fails."""
if platmacro.IS_WINDOWS:
return os._win32.rmdir(path)
return os._posix.rmdir_impl(path)
def rename(old_path: str, new_path: str) -> int:
"""重命名/移动文件或目录。成功返回 0,失败返回 -1。"""
"""Rename/move a file or directory. Returns 0 on success, -1 on failure."""
if platmacro.IS_WINDOWS:
return os._win32.rename(old_path, new_path)
return os._posix.rename_impl(old_path, new_path)
def chmod(path: str, mode: int) -> int:
"""修改文件权限。成功返回 0,失败返回 -1。
Windows 上只处理只读位(S_IWUSR);POSIX 上使用完整权限位。"""
"""Modify file permissions. Returns 0 on success, -1 on failure.
On Windows, only the read-only bit (S_IWUSR) is handled;
On POSIX, full permission bits are used."""
if platmacro.IS_WINDOWS:
return os._win32.chmod(path, mode)
return os._posix.chmod_impl(path, mode)
# =============================================================================
# 目录列举
# Table of Contents Listing
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
+1 -1
View File
@@ -193,7 +193,7 @@ def _rmtree_posix(path: str) -> int:
path_len: t.CSizeT = len(path)
result: int = 0
entry: posix.Dirent = posix.readdir(dirp)
entry: posix.Dirent | t.CPtr = posix.readdir(dirp)
while entry != None:
name: str = entry.d_name
# Skip . and ..
+2 -1
View File
@@ -6,4 +6,5 @@ def malloc(size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def calloc(nmemb: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def realloc(p: t.CVoid | t.CPtr, size: t.CSizeT) -> t.CVoid | t.CPtr | t.State: pass
def free(p: t.CVoid | t.CPtr) -> t.State: pass
def system(cmd: t.CConst | t.CChar | t.CPtr) -> INT | t.State: pass
def system(cmd: t.CConst | t.CChar | t.CPtr) -> INT | t.State: pass
def exit(status: int) -> t.State: pass
+1 -1
View File
@@ -385,5 +385,5 @@ class FileW:
def open(filename: str, mode: ULONG, share: ULONG = SHARE_READ) -> File | t.CPtr:
return File(filename, mode, share)
def openw(filename: LPCWSTR, mode: ULONG, share: ULONG = SHARE_READ) -> FileW | t.CPtr:
def openw(filename: w32.win32base.LPCWSTR, mode: ULONG, share: ULONG = SHARE_READ) -> FileW | t.CPtr:
return FileW(filename, mode, share)
+2
View File
@@ -1,3 +1,5 @@
# from string import memset, memcpy
# from stdio import malloc, free, calloc, realloc
from stdint import *
import zlib.zdeflate as zdeflate
import zlib.zinflate as zinflate
-1
View File
@@ -1,5 +1,4 @@
from stdint import *
import stddef
import string
import stdlib
import memhub