snapshot before regression test

This commit is contained in:
t committed 2026-07-18 19:25:40 +08:00
commit 796222a300
2295 files changed
+206453

No files matched your search

+425
View File
@@ -0,0 +1,425 @@
# GCC/Clang 内建函数声明
# 所有函数均为仅声明(t.State 等价于 CExtern | CExport),由编译器/运行时提供实现
import t
# ============================================================
# 随机数生成 (RDRAND / RDSEED)
# ============================================================
def __builtin_ia32_rdrand16_step(p: t.CUInt16T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_rdrand32_step(p: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_rdrand64_step(p: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_rdseed16_step(p: t.CUInt16T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_rdseed32_step(p: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_rdseed64_step(p: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass
# ============================================================
# 时间戳计数器 (RDTSC / RDTSCP)
# ============================================================
def __builtin_ia32_rdtsc() -> t.CUInt64T | t.State: pass
def __builtin_ia32_rdtscp(p: t.CUInt32T | t.CPtr) -> t.CUInt64T | t.State: pass
def __builtin_ia32_rdpmc(counter: t.CUInt32T) -> t.CUInt64T | t.State: pass
# ============================================================
# CPUID
# ============================================================
def __builtin_ia32_cpuid(level: t.CUInt32T, a: t.CUInt32T | t.CPtr, b: t.CUInt32T | t.CPtr, c: t.CUInt32T | t.CPtr, d: t.CUInt32T | t.CPtr) -> t.CUInt32T | t.State: pass
def __builtin_ia32_cpuid_count(level: t.CUInt32T, count: t.CUInt32T, a: t.CUInt32T | t.CPtr, b: t.CUInt32T | t.CPtr, c: t.CUInt32T | t.CPtr, d: t.CUInt32T | t.CPtr) -> t.CUInt32T | t.State: pass
# ============================================================
# 内存屏障 (Fence)
# ============================================================
def __builtin_ia32_lfence() -> t.State: pass
def __builtin_ia32_mfence() -> t.State: pass
def __builtin_ia32_sfence() -> t.State: pass
def __builtin_ia32_pause() -> t.State: pass
# ============================================================
# 位操作 (POPCNT / BSF / BSR / TZCNT / LZCNT / BEXTR / PDEP / PEXT / ANDN)
# ============================================================
def __builtin_ia32_popcntsi(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_ia32_popcntdi(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_ia32_popcntqi(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_ia32_bsfsi(src: t.CUInt32T, dst: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_bsrsi(src: t.CUInt32T, dst: t.CUInt32T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_bsfqi(src: t.CUInt64T, dst: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_bsrqi(src: t.CUInt64T, dst: t.CUInt64T | t.CPtr) -> t.CInt | t.State: pass
def __builtin_ia32_tzcntsi(x: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_tzcntdi(x: t.CUInt64T) -> t.CUInt64T | t.State: pass
def __builtin_ia32_lzcntsi(x: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_lzcntdi(x: t.CUInt64T) -> t.CUInt64T | t.State: pass
def __builtin_ia32_bextrsi(src: t.CUInt32T, start: t.CUInt32T, len: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_bextrdi(src: t.CUInt64T, start: t.CUInt32T, len: t.CUInt32T) -> t.CUInt64T | t.State: pass
def __builtin_ia32_pdep_si(src: t.CUInt32T, mask: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_pext_si(src: t.CUInt32T, mask: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_pdep_di(src: t.CUInt64T, mask: t.CUInt64T) -> t.CUInt64T | t.State: pass
def __builtin_ia32_pext_di(src: t.CUInt64T, mask: t.CUInt64T) -> t.CUInt64T | t.State: pass
def __builtin_ia32_andn_si(a: t.CUInt32T, b: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_andn_di(a: t.CUInt64T, b: t.CUInt64T) -> t.CUInt64T | t.State: pass
# ============================================================
# 字节序交换 (BSWAP)
# ============================================================
def __builtin_bswap16(x: t.CUInt16T) -> t.CUInt16T | t.State: pass
def __builtin_bswap32(x: t.CUInt32T) -> t.CUInt32T | t.State: pass
def __builtin_bswap64(x: t.CUInt64T) -> t.CUInt64T | t.State: pass
# ============================================================
# 缓存操作 (Cache)
# ============================================================
def __builtin_ia32_clflush(p: t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_clflushopt(p: t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_clwb(p: t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_clzero() -> t.State: pass
# ============================================================
# 预取 (Prefetch)
# ============================================================
def __builtin_prefetch(addr: t.CConst | t.CPtr, rw: t.CInt = 0, locality: t.CInt = 3) -> t.State: pass
def __builtin_ia32_prefetch0(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_prefetch1(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_prefetch2(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass
def __builtin_ia32_prefetchnta(p: t.CChar | t.CConst | t.CPtr) -> t.State: pass
# ============================================================
# 非临时存储 (Non-Temporal Store)
# ============================================================
def __builtin_ia32_movnti(p: t.CUInt32T | t.CPtr, val: t.CUInt32T) -> t.State: pass
def __builtin_ia32_movnti64(p: t.CUInt64T | t.CPtr, val: t.CUInt64T) -> t.State: pass
def __builtin_ia32_movntdq(p: t.CPtr, val: t.CPtr) -> t.State: pass
def __builtin_ia32_movntps(p: t.CFloat | t.CPtr, val: t.CFloat) -> t.State: pass
def __builtin_ia32_movntpd(p: t.CDouble | t.CPtr, val: t.CDouble) -> t.State: pass
# ============================================================
# I/O 端口操作 (Port I/O)
# ============================================================
def __builtin_ia32_inb(port: t.CUInt16T) -> t.CUInt8T | t.State: pass
def __builtin_ia32_inw(port: t.CUInt16T) -> t.CUInt16T | t.State: pass
def __builtin_ia32_inl(port: t.CUInt16T) -> t.CUInt32T | t.State: pass
def __builtin_ia32_outb(val: t.CUInt8T, port: t.CUInt16T) -> t.State: pass
def __builtin_ia32_outw(val: t.CUInt16T, port: t.CUInt16T) -> t.State: pass
def __builtin_ia32_outl(val: t.CUInt32T, port: t.CUInt16T) -> t.State: pass
# ============================================================
# 模型特定寄存器 (MSR)
# ============================================================
def __builtin_ia32_rdmsr(msr: t.CUInt32T, val: t.CUInt64T | t.CPtr) -> t.State: pass
def __builtin_ia32_wrmsr(msr: t.CUInt32T, val: t.CUInt64T) -> t.State: pass
# ============================================================
# 系统指令 (System)
# ============================================================
def __builtin_ia32_hlt() -> t.State: pass
def __builtin_ia32_invd() -> t.State: pass
def __builtin_ia32_wbinvd() -> t.State: pass
def __builtin_ia32_invlpg(p: t.CPtr) -> t.State: pass
def __builtin_ia32_clts() -> t.State: pass
def __builtin_ia32_cli() -> t.State: pass
def __builtin_ia32_sti() -> t.State: pass
def __builtin_ia32_int3() -> t.State: pass
def __builtin_ia32_int(n: t.CUInt8T) -> t.State: pass
def __builtin_ia32_ud2() -> t.State: pass
# ============================================================
# 描述符表 (GDT / IDT / LDT / TR)
# ============================================================
def __builtin_ia32_lgdt(p: t.CPtr) -> t.State: pass
def __builtin_ia32_sgdt(p: t.CPtr) -> t.State: pass
def __builtin_ia32_lidt(p: t.CPtr) -> t.State: pass
def __builtin_ia32_sidt(p: t.CPtr) -> t.State: pass
def __builtin_ia32_lldt(sel: t.CUInt32T) -> t.State: pass
def __builtin_ia32_sldt(p: t.CPtr) -> t.State: pass
def __builtin_ia32_ltr(sel: t.CUInt32T) -> t.State: pass
def __builtin_ia32_str(p: t.CPtr) -> t.State: pass
# ============================================================
# 控制寄存器 (CR / MSW)
# ============================================================
def __builtin_ia32_lmsw(val: t.CUInt32T) -> t.State: pass
def __builtin_ia32_smsw(p: t.CPtr) -> t.State: pass
# ============================================================
# 监控等待 (MONITOR / MWAIT)
# ============================================================
def __builtin_ia32_monitor(p: t.CPtr, extensions: t.CUInt32T, hints: t.CUInt32T) -> t.State: pass
def __builtin_ia32_mwait(extensions: t.CUInt32T, hints: t.CUInt32T) -> t.State: pass
# ============================================================
# XSAVE 状态操作
# ============================================================
def __builtin_ia32_xsave(p: t.CPtr, mask: t.CUInt64T) -> t.State: pass
def __builtin_ia32_xrstor(p: t.CConst | t.CPtr, mask: t.CUInt64T) -> t.State: pass
def __builtin_ia32_xsaveopt(p: t.CPtr, mask: t.CUInt64T) -> t.State: pass
def __builtin_ia32_xsavec(p: t.CPtr, mask: t.CUInt64T) -> t.State: pass
def __builtin_ia32_xrstors(p: t.CConst | t.CPtr, mask: t.CUInt64T) -> t.State: pass
def __builtin_ia32_xsaves(p: t.CPtr, mask: t.CUInt64T) -> t.State: pass
# ============================================================
# 通用内建函数 (Generic Builtins)
# ============================================================
def __builtin_expect(exp: t.CLong, c: t.CLong) -> t.CLong | t.State: pass
def __builtin_unreachable() -> t.State: pass
def __builtin_trap() -> t.State: pass
def __builtin_abort() -> t.State: pass
def __builtin_assume_aligned(addr: t.CConst | t.CPtr, align: t.CSizeT, *args) -> t.CPtr | t.State: pass
def __builtin_constant_p(expr: t.CVoid) -> t.CInt | t.State: pass
def __builtin_types_compatible_p(t1: t.CVoid, t2: t.CVoid) -> t.CInt | t.State: pass
def __builtin_choose_expr(const_exp: t.CUInt32T, exp1: t.CVoid, exp2: t.CVoid) -> t.CPtr | t.State: pass
def __builtin_offsetof(typ: t.CVoid, member: t.CVoid) -> t.CSizeT | t.State: pass
def __builtin_function_start(func: t.CPtr) -> t.CPtr | t.State: pass
# ============================================================
# 可变参数 (VaList)
# ============================================================
def __builtin_va_start(va: t.CPtr, *args) -> t.State: pass
def __builtin_va_end(va: t.CPtr) -> t.State: pass
def __builtin_va_arg(va: t.CPtr, typ: t.CVoid) -> t.State: pass
def __builtin_va_copy(dst: t.CPtr, src: t.CConst | t.CPtr) -> t.State: pass
# ============================================================
# 栈与调用信息 (Stack / Frame)
# ============================================================
def __builtin_return_address(level: t.CUInt32T) -> t.CPtr | t.State: pass
def __builtin_frame_address(level: t.CUInt32T) -> t.CPtr | t.State: pass
def __builtin_alloca(size: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin_alloca_with_align(size: t.CSizeT, alignment: t.CSizeT) -> t.CPtr | t.State: pass
# ============================================================
# 内存操作 (Memory)
# ============================================================
def __builtin_memcpy(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin_memset(s: t.CPtr, c: t.CInt, n: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin_memmove(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin_memcmp(s1: t.CConst | t.CPtr, s2: t.CConst | t.CPtr, n: t.CSizeT) -> t.CInt | t.State: pass
def __builtin_mempcpy(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin_memchr(s: t.CConst | t.CPtr, c: t.CInt, n: t.CSizeT) -> t.CPtr | t.State: pass
# ============================================================
# 字符串操作 (String)
# ============================================================
def __builtin_strcpy(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strncpy(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strcat(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strncat(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strlen(s: t.CChar | t.CConst | t.CPtr) -> t.CSizeT | t.State: pass
def __builtin_strcmp(s1: t.CChar | t.CConst | t.CPtr, s2: t.CChar | t.CConst | t.CPtr) -> t.CInt | t.State: pass
def __builtin_strncmp(s1: t.CChar | t.CConst | t.CPtr, s2: t.CChar | t.CConst | t.CPtr, n: t.CSizeT) -> t.CInt | t.State: pass
def __builtin_strchr(s: t.CChar | t.CConst | t.CPtr, c: t.CInt) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strrchr(s: t.CChar | t.CConst | t.CPtr, c: t.CInt) -> t.CChar | t.CPtr | t.State: pass
def __builtin_strstr(haystack: t.CChar | t.CConst | t.CPtr, needle: t.CChar | t.CConst | t.CPtr) -> t.CChar | t.CPtr | t.State: pass
# ============================================================
# 数学内建函数 (Math)
# ============================================================
def __builtin_sqrt(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_sqrtf(x: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_sqrtl(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_pow(x: t.CDouble, y: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_powf(x: t.CFloat, y: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_sin(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_sinf(x: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_cos(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_cosf(x: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_tan(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_tanf(x: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_atan(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_atan2(y: t.CDouble, x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_exp(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_log(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_log2(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_log10(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_fabs(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_fabsf(x: t.CFloat) -> t.CFloat | t.State: pass
def __builtin_abs(x: t.CInt) -> t.CInt | t.State: pass
def __builtin_labs(x: t.CLong) -> t.CLong | t.State: pass
def __builtin_llabs(x: t.CInt64T) -> t.CInt64T | t.State: pass
def __builtin_fma(x: t.CDouble, y: t.CDouble, z: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_fmod(x: t.CDouble, y: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_floor(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_ceil(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_trunc(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_round(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_nearbyint(x: t.CDouble) -> t.CDouble | t.State: pass
def __builtin_rint(x: t.CDouble) -> t.CDouble | t.State: pass
# ============================================================
# 位计数内建函数 (Bit Counting)
# ============================================================
def __builtin_ffs(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_clz(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_ctz(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_popcount(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_parity(x: t.CUInt32T) -> t.CInt | t.State: pass
def __builtin_ffsl(x: t.CULong) -> t.CInt | t.State: pass
def __builtin_clzl(x: t.CULong) -> t.CInt | t.State: pass
def __builtin_ctzl(x: t.CULong) -> t.CInt | t.State: pass
def __builtin_popcountl(x: t.CULong) -> t.CInt | t.State: pass
def __builtin_parityl(x: t.CULong) -> t.CInt | t.State: pass
def __builtin_ffsll(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_clzll(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_ctzll(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_popcountll(x: t.CUInt64T) -> t.CInt | t.State: pass
def __builtin_parityll(x: t.CUInt64T) -> t.CInt | t.State: pass
# ============================================================
# 对象大小检查 (Object size check)
# ============================================================
def __builtin_object_size(ptr: t.CConst | t.CPtr, typ: t.CInt) -> t.CSizeT | t.State: pass
def __builtin_dynamic_object_size(ptr: t.CConst | t.CPtr, typ: t.CInt) -> t.CSizeT | t.State: pass
def __builtin___memcpy_chk(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin___memmove_chk(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin___memset_chk(s: t.CPtr, c: t.CInt, n: t.CSizeT, objsize: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin___mempcpy_chk(dst: t.CPtr, src: t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CPtr | t.State: pass
def __builtin___strcpy_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin___strncpy_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin___strcat_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin___strncat_chk(dst: t.CChar | t.CPtr, src: t.CChar | t.CConst | t.CPtr, n: t.CSizeT, objsize: t.CSizeT) -> t.CChar | t.CPtr | t.State: pass
def __builtin___snprintf_chk(s: t.CChar | t.CPtr, maxlen: t.CSizeT, flag: t.CInt, slen: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.State: pass
def __builtin___sprintf_chk(s: t.CChar | t.CPtr, flag: t.CInt, slen: t.CSizeT, fmt: t.CChar | t.CConst | t.CPtr, *args) -> t.CInt | t.State: pass
# ============================================================
# 浮点分类 (FP Classification)
# ============================================================
def __builtin_isnan(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isinf(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isinf_sign(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isfinite(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isnormal(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_signbit(x: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isgreater(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isgreaterequal(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isless(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
def __builtin_islessequal(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
def __builtin_islessgreater(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
def __builtin_isunordered(x: t.CDouble, y: t.CDouble) -> t.CInt | t.State: pass
# ============================================================
# 特殊值 (Special Values)
# ============================================================
def __builtin_nan(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass
def __builtin_nanf(s: t.CChar | t.CConst | t.CPtr) -> t.CFloat | t.State: pass
def __builtin_nanl(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass
def __builtin_nans(s: t.CChar | t.CConst | t.CPtr) -> t.CDouble | t.State: pass
def __builtin_nansf(s: t.CChar | t.CConst | t.CPtr) -> t.CFloat | t.State: pass
def __builtin_inf() -> t.CDouble | t.State: pass
def __builtin_inff() -> t.CFloat | t.State: pass
def __builtin_infl() -> t.CDouble | t.State: pass
def __builtin_huge_val() -> t.CDouble | t.State: pass
def __builtin_huge_valf() -> t.CFloat | t.State: pass
def __builtin_huge_vall() -> t.CDouble | t.State: pass
def __builtin_inf_sign() -> t.CInt | t.State: pass
# ============================================================
# 类型转换与溢出检查 (Overflow)
# ============================================================
def __builtin_add_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_sub_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_mul_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_sadd_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_ssub_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_smul_overflow(a: t.CInt64T, b: t.CInt64T, res: t.CInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_uadd_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_usub_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
def __builtin_umul_overflow(a: t.CUInt64T, b: t.CUInt64T, res: t.CUInt64T | t.CPtr) -> t.CBool | t.State: pass
# ============================================================
# MMX / SSE 状态
# ============================================================
def __builtin_ia32_emms() -> t.State: pass
def __builtin_ia32_femms() -> t.State: pass
# ============================================================
# 排队指令 (ENQCMD)
# ============================================================
def __builtin_ia32_enqcmd(dst: t.CPtr, src: t.CConst | t.CPtr) -> t.CBool | t.State: pass
def __builtin_ia32_enqcmds(dst: t.CPtr, src: t.CConst | t.CPtr) -> t.CBool | t.State: pass
# ============================================================
# 用户级等待 (UMWAIT / UMONITOR / TPAUSE)
# ============================================================
def __builtin_ia32_umonitor(p: t.CPtr) -> t.State: pass
def __builtin_ia32_umwait(extensions: t.CUInt32T, counter: t.CUInt64T) -> t.CUInt8T | t.State: pass
def __builtin_ia32_tpause(extensions: t.CUInt32T, counter: t.CUInt64T) -> t.CUInt8T | t.State: pass
# ============================================================
# 访问控制 (CLAC / STAC)
# ============================================================
def __builtin_ia32_clac() -> t.State: pass
def __builtin_ia32_stac() -> t.State: pass
# ============================================================
# TLB 无效化 (INVLPG 变体)
# ============================================================
def __builtin_ia32_invlpgb(aux: t.CUInt64T, pcid: t.CUInt64T) -> t.State: pass
def __builtin_ia32_tlbsync() -> t.State: pass
+271
View File
@@ -0,0 +1,271 @@
import t, c
import memhub
import string
import json
from stdint import *
# Variant 类型标签 (与 _variant.py 保持一致)
VARIANT_NONE: t.CDefine = 0 # 无类型/空值
VARIANT_INT: t.CDefine = 1 # int (i64)
VARIANT_FLOAT: t.CDefine = 2 # float (f32)
VARIANT_DOUBLE: t.CDefine = 3 # double (f64)
VARIANT_STR: t.CDefine = 4 # str (i8*)
VARIANT_DICT: t.CDefine = 5 # dict*
VARIANT_LIST: t.CDefine = 6 # list*
VARIANT_BOOL: t.CDefine = 7 # bool (i1/i32)
VARIANT_PTR: t.CDefine = 8 # 自定义指针类型
# Variant 结构体大小: vtype(i32, 4 bytes) + padding(4 bytes) + ptr(i8*, 8 bytes) = 16 bytes
_VARIANT_SIZE: t.CDefine = 16
class dict:
"""堆上动态字典容器,基于 mbuddy 分配器。
键类型固定为 str (i8*),值使用 Variant 存储 (类型标签 + 无类型指针)。
支持嵌套 dict/list 和 JSON 序列化。
用法:
mb: memhub.MemBuddy = memhub.MemBuddy(arena, arena_size)
d: dict = dict(mb)
d.set_int("x", 42)
p: t.CPtr = d["x"]
v: int = c.Deref(p)
# 嵌套 dict
inner: dict = dict(mb)
inner.set_int("a", 1)
d.set_dict("sub", inner)
sub: dict = c.Deref(d["sub"])
av: int = c.Deref(sub["a"])
"""
__keys__: t.CPtr
__values__: t.CPtr
__count__: t.CSizeT = 0
__capacity__: t.CSizeT = 8
__mbuddy__: memhub.MemBuddy | t.CPtr
__iter_index__: t.CSizeT = 0
def __new__(self, mb: memhub.MemBuddy | t.CPtr) -> t.CPtr:
# 堆分配 dict 对象
return mb.alloc(dict.__sizeof__())
def __init__(self, mb: memhub.MemBuddy | t.CPtr):
self.__mbuddy__ = mb
self.__keys__ = mb.alloc(self.__capacity__ * 8)
self.__values__ = mb.alloc(self.__capacity__ * _VARIANT_SIZE)
def __len__(self) -> t.CSizeT:
return self.__count__
def _find(self, key: str) -> t.CSizeT:
"""查找 key 的索引,找不到返回 __count__"""
for i in range(self.__count__):
key_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__keys__) + i * 8)
if key_ptr[0] == key: return i
return self.__count__
def __getitem__(self, key: str) -> t.CPtr:
"""返回值的无类型指针。用户用 c.Deref 解引用获取实际值。
例: p: t.CPtr = d["x"]; v: int = c.Deref(p)"""
idx: t.CSizeT = self._find(key)
if idx >= self.__count__: return None
# Variant.ptr 在 Variant 结构体偏移 8 处
val_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8)
return val_ptr[0]
def __setitem__(self, key: str, val: t.CNeedPtr):
"""存储值为 VARIANT_PTR。val 自动取地址 (t.CNeedPtr)。
注意: val 指向的值生命周期由调用者管理。
如需持久存储,请使用 set_int / set_str 等类型化方法。"""
self._set_variant_raw(key, VARIANT_PTR, val)
def _set_variant_raw(self, key: str, vtype: t.CInt, ptr: t.CPtr):
"""内部方法: 存储 Variant (vtype + ptr)。不自动取地址。"""
idx: t.CSizeT = self._find(key)
if idx < self.__count__:
# 更新已有键
vtype_ptr: t.CInt | t.CPtr = t.CPtr(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE)
vtype_ptr[0] = vtype
val_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8)
val_ptr[0] = ptr
return
if self.__count__ >= self.__capacity__:
new_cap: t.CSizeT = self.__capacity__ * 2
new_keys: t.CPtr = self.__mbuddy__.alloc(new_cap * 8)
new_values: t.CPtr = self.__mbuddy__.alloc(new_cap * _VARIANT_SIZE)
if new_keys is None or new_values is None: return
string.memcpy(new_keys, self.__keys__, self.__count__ * 8)
string.memcpy(new_values, self.__values__, self.__count__ * _VARIANT_SIZE)
self.__keys__ = new_keys
self.__values__ = new_values
self.__capacity__ = new_cap
key_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__keys__) + self.__count__ * 8)
key_ptr[0] = key
vtype_ptr: t.CInt | t.CPtr = t.CPtr(t.CUInt64T(self.__values__) + self.__count__ * _VARIANT_SIZE)
vtype_ptr[0] = vtype
val_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__values__) + self.__count__ * _VARIANT_SIZE + 8)
val_ptr[0] = ptr
self.__count__ += 1
# ============================================================
# 类型化 setter — 在 __mbuddy__ 中分配持久存储
# ============================================================
def set_int(self, key: str, val: int):
"""存储 int 值 (VARIANT_INT)。值复制到 __mbuddy__ 持久存储。"""
storage: t.CPtr = self.__mbuddy__.alloc(8)
int_ptr: int | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
int_ptr[0] = val
self._set_variant_raw(key, VARIANT_INT, storage)
def set_str(self, key: str, val: str):
"""存储 str 值 (VARIANT_STR)。直接存储字符串指针。"""
self._set_variant_raw(key, VARIANT_STR, val)
def set_float(self, key: str, val: float):
"""存储 float 值 (VARIANT_FLOAT)。值复制到 __mbuddy__ 持久存储。"""
storage: t.CPtr = self.__mbuddy__.alloc(8)
float_ptr: float | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
float_ptr[0] = val
self._set_variant_raw(key, VARIANT_FLOAT, storage)
def set_double(self, key: str, val: t.CDouble):
"""存储 double 值 (VARIANT_DOUBLE)。值复制到 __mbuddy__ 持久存储。"""
storage: t.CPtr = self.__mbuddy__.alloc(8)
dbl_ptr: t.CDouble | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
dbl_ptr[0] = val
self._set_variant_raw(key, VARIANT_DOUBLE, storage)
def set_dict(self, key: str, val: dict | t.CPtr):
"""存储嵌套 dict 指针 (VARIANT_DICT)。"""
self._set_variant_raw(key, VARIANT_DICT, val)
def set_list(self, key: str, val: t.CPtr):
"""存储嵌套 list 指针 (VARIANT_LIST)。"""
self._set_variant_raw(key, VARIANT_LIST, val)
def set_bool(self, key: str, val: t.CInt):
"""存储 bool 值 (VARIANT_BOOL)。值复制到 __mbuddy__ 持久存储。"""
storage: t.CPtr = self.__mbuddy__.alloc(8)
bool_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
bool_ptr[0] = val
self._set_variant_raw(key, VARIANT_BOOL, storage)
# ============================================================
# 查询方法
# ============================================================
def get_vtype(self, key: str) -> t.CInt:
"""返回 key 对应值的 Variant 类型标签。"""
idx: t.CSizeT = self._find(key)
if idx >= self.__count__:
return VARIANT_NONE
vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE, t.CPtr)
return vtype_ptr[0]
def get(self, key: str, default: t.CPtr) -> t.CPtr:
"""返回值指针,不存在则返回 default。"""
idx: t.CSizeT = self._find(key)
if idx >= self.__count__:
return default
val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + idx * _VARIANT_SIZE + 8, t.CPtr)
return val_ptr[0]
def contains(self, key: str) -> t.CInt:
"""检查 key 是否存在。"""
idx: t.CSizeT = self._find(key)
if idx < self.__count__:
return 1
return 0
def __iter__(self) -> dict | t.CPtr:
self.__iter_index__ = 0
return self
def __next__(self) -> str:
if self.__iter_index__ >= self.__count__:
raise StopIteration
idx: t.CSizeT = self.__iter_index__
self.__iter_index__ = idx + 1
key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + idx * 8, t.CPtr)
return key_ptr[0]
# ============================================================
# JSON 处理:利用 includes/json 库实现序列化/反序列化
# ============================================================
def to_json(self, pool: memhub.MemManager | t.CPtr) -> json.JsonValue | t.CPtr:
"""将 dict 转换为 JsonValue 对象 (JSON_OBJECT)。
根据 Variant 类型标签自动选择合适的 JSON 值类型。"""
obj: json.JsonValue | t.CPtr = json.object(pool)
i: t.CSizeT = 0
while i < self.__count__:
key_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__keys__) + i * 8, t.CPtr)
vtype_ptr: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + i * _VARIANT_SIZE, t.CPtr)
val_ptr: str | t.CPtr = t.CVoid(t.CUInt64T(self.__values__) + i * _VARIANT_SIZE + 8, t.CPtr)
vt: t.CInt = vtype_ptr[0]
vp: t.CPtr = val_ptr[0]
jv: json.JsonValue | t.CPtr = json.null(pool)
if jv != None:
if vt == VARIANT_INT:
jv.vtype = 2 # JSON_INT
ip: int | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr)
jv.int_val = ip[0]
elif vt == VARIANT_STR:
jv.vtype = 4 # JSON_STRING
jv.str_val = vp
elif vt == VARIANT_BOOL:
jv.vtype = 1 # JSON_BOOL
bp: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr)
jv.bool_val = bp[0]
elif vt == VARIANT_FLOAT:
jv.vtype = 3 # JSON_FLOAT
fp: float | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr)
jv.float_val = fp[0]
elif vt == VARIANT_PTR:
# 默认: 将 PTR 作为整数处理
jv.vtype = 2 # JSON_INT
ip: int | t.CPtr = t.CVoid(t.CUInt64T(vp), t.CPtr)
jv.int_val = ip[0]
json.object_set(pool, obj, key_ptr[0], jv)
i += 1
return obj
def from_json(self, pool: memhub.MemManager | t.CPtr, root: json.JsonValue | t.CPtr):
"""从 JsonValue 对象填充 dict。
根据 JSON 值类型自动提取并存储为对应 Variant 类型。"""
if root == None:
return
if root.vtype != 6: # JSON_OBJECT
return
cur: json.JsonValue | t.CPtr = root.child
while cur != None:
if cur.key != None:
if cur.vtype == 2: # JSON_INT
storage: t.CPtr = self.__mbuddy__.alloc(8)
ip: int | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
ip[0] = cur.int_val
self._set_variant_raw(cur.key, VARIANT_INT, storage)
elif cur.vtype == 4: # JSON_STRING
self._set_variant_raw(cur.key, VARIANT_STR, cur.str_val)
elif cur.vtype == 1: # JSON_BOOL
storage: t.CPtr = self.__mbuddy__.alloc(8)
bp: t.CInt | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
bp[0] = cur.bool_val
self._set_variant_raw(cur.key, VARIANT_BOOL, storage)
elif cur.vtype == 3: # JSON_FLOAT
storage: t.CPtr = self.__mbuddy__.alloc(8)
fp: float | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
fp[0] = cur.float_val
self._set_variant_raw(cur.key, VARIANT_FLOAT, storage)
cur = cur.next
def dumps(self, pool: memhub.MemManager | t.CPtr) -> str:
"""将 dict 序列化为 JSON 字符串。"""
obj: json.JsonValue | t.CPtr = self.to_json(pool)
return json.write(pool, obj, False)
def loads(self, pool: memhub.MemManager | t.CPtr, json_str: str):
"""从 JSON 字符串解析并填充 dict。"""
root: json.JsonValue | t.CPtr = json.parse(pool, json_str)
self.from_json(pool, root)
+319
View File
@@ -0,0 +1,319 @@
import t
import memhub
import string
class _Type:
def type_id(self) -> int:
return 99
class _str:
# 编译期元数据:声明此类希望从 with 上下文获取 __mbuddy__ 字段(非必要,找不到不报错)
__requires__: list[str] = ['__mbuddy__']
__data__: str
__mbuddy__: memhub.MemBuddy | t.CPtr
def upper(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
for i, ch in enumerate(src):
if ch >= 97:
if ch <= 122:
buf[i] = ch - 32
else:
buf[i] = ch
else:
buf[i] = ch
buf[length] = 0
return str(buf)
def lower(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
for i, ch in enumerate(src):
if ch >= 65:
if ch <= 90:
buf[i] = ch + 32
else:
buf[i] = ch
else:
buf[i] = ch
buf[length] = 0
return str(buf)
def capitalize(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
first: bool = True
for i, ch in enumerate(src):
if first:
first = False
if ch >= 97:
if ch <= 122:
buf[i] = ch - 32
else:
buf[i] = ch
else:
buf[i] = ch
else:
if ch >= 65:
if ch <= 90:
buf[i] = ch + 32
else:
buf[i] = ch
else:
buf[i] = ch
buf[length] = 0
return str(buf)
def swapcase(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
for i, ch in enumerate(src):
if ch >= 97:
if ch <= 122:
buf[i] = ch - 32
else:
buf[i] = ch
else:
if ch >= 65:
if ch <= 90:
buf[i] = ch + 32
else:
buf[i] = ch
else:
buf[i] = ch
buf[length] = 0
return str(buf)
def title(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
prev_alpha: bool = False
for i, ch in enumerate(src):
cur_alpha: bool = False
if ch >= 65:
if ch <= 90:
cur_alpha = True
else:
if ch >= 97:
if ch <= 122:
cur_alpha = True
if cur_alpha:
if prev_alpha:
if ch >= 65:
if ch <= 90:
buf[i] = ch + 32
else:
buf[i] = ch
else:
buf[i] = ch
else:
if ch >= 97:
if ch <= 122:
buf[i] = ch - 32
else:
buf[i] = ch
else:
buf[i] = ch
else:
buf[i] = ch
prev_alpha = cur_alpha
buf[length] = 0
return str(buf)
def casefold(self) -> str:
src: str = self.__data__
length: t.CSizeT = len(src)
buf: bytes = self.__mbuddy__.alloc(length + 1)
if buf == None: return self.__data__
for i, ch in enumerate(src):
if ch >= 65:
if ch <= 90:
buf[i] = ch + 32
else:
buf[i] = ch
else:
buf[i] = ch
buf[length] = 0
return str(buf)
def isupper(self) -> bool:
src: str = self.__data__
has_alpha: bool = False
for ch in src:
if ch >= 65:
if ch <= 90:
has_alpha = True
else:
if ch >= 97:
if ch <= 122:
return False
return has_alpha
def islower(self) -> bool:
src: str = self.__data__
has_alpha: bool = False
for ch in src:
if ch >= 97:
if ch <= 122:
has_alpha = True
if ch >= 65:
if ch <= 90:
return False
return has_alpha
def isalpha(self) -> bool:
src: str = self.__data__
has_char: bool = False
for ch in src:
has_char = True
cur_alpha: bool = False
if ch >= 65:
if ch <= 90:
cur_alpha = True
else:
if ch >= 97:
if ch <= 122:
cur_alpha = True
if not cur_alpha:
return False
return has_char
def isdigit(self) -> bool:
src: str = self.__data__
has_char: bool = False
for ch in src:
has_char = True
if ch >= 48:
if ch > 57:
return False
else:
return False
return has_char
def isalnum(self) -> bool:
src: str = self.__data__
has_char: bool = False
for ch in src:
has_char = True
ok: bool = False
if ch >= 48:
if ch <= 57:
ok = True
if not ok:
if ch >= 65:
if ch <= 90:
ok = True
else:
if ch >= 97:
if ch <= 122:
ok = True
if not ok:
return False
return has_char
def isspace(self) -> bool:
src: str = self.__data__
has_char: bool = False
for ch in src:
has_char = True
is_space: bool = False
if ch == 32 or ch == 9 or ch == 10 or ch == 13 or ch == 11 or ch == 12:
is_space = True
if not is_space:
return False
return has_char
def isascii(self) -> bool:
src: str = self.__data__
has_char: bool = False
for ch in src:
has_char = True
if ch > 127: return False
return has_char
def istitle(self) -> bool:
src: str = self.__data__
has_char: bool = False
prev_alpha: bool = False
for ch in src:
has_char = True
cur_alpha: bool = False
if ch >= 65:
if ch <= 90:
cur_alpha = True
else:
if ch >= 97:
if ch <= 122:
cur_alpha = True
if cur_alpha:
if not prev_alpha:
if ch >= 97:
if ch <= 122:
return False
else:
if ch >= 65:
if ch <= 90:
return False
prev_alpha = cur_alpha
return has_char
def split(self, delimiter: str) -> list[str]:
result = list[str](self.__mbuddy__)
src: str = self.__data__
length: t.CSizeT = len(src)
delim_len: t.CSizeT = string.strlen(delimiter)
start: t.CSizeT = 0
i: t.CSizeT = 0
cur: str = src
sub_len: t.CSizeT = 0
sub: bytes = None
src_off: bytes = None
term: bytes = None
if delim_len == 0:
sub_len = length
sub = self.__mbuddy__.alloc(sub_len + 1)
if sub != None:
src_off = bytes(t.CUInt64T(src) + start)
string.memcpy(sub, src_off, sub_len)
term = sub
term[sub_len] = 0
result.append(str(sub))
return result
while i + delim_len <= length:
if string.strncmp(cur, delimiter, delim_len) == 0:
sub_len = i - start
sub = self.__mbuddy__.alloc(sub_len + 1)
if sub != None:
src_off = bytes(t.CUInt64T(src) + start)
string.memcpy(sub, src_off, sub_len)
term = sub
term[sub_len] = 0
result.append(str(sub))
start = i + delim_len
cur += delim_len
i += delim_len
else:
cur += 1
i += 1
sub_len = length - start
sub = self.__mbuddy__.alloc(sub_len + 1)
if sub != None:
src_off = bytes(t.CUInt64T(src) + start)
string.memcpy(sub, src_off, sub_len)
term = sub
term[sub_len] = 0
result.append(str(sub))
return result
+90
View File
@@ -0,0 +1,90 @@
import t, c
import memhub
import string
from stdint import *
class list[T]:
"""堆上动态列表容器,基于 memhub.MemManager 多态分配器。
用法:
pool: memhub.MemManager = memhub.MemBuddy(arena, arena_size)
nums: list[int] = list[int](pool)
nums.append(42)
x: int = nums.get(0)
对于指针类型(如 AST | t.CPtr),传 elem_size=8 避免对象切片:
lst: list[AST | t.CPtr] = list[AST | t.CPtr](pool, 8)
"""
__data__: t.CVoid | t.CPtr
__count__: t.CSizeT
__capacity__: t.CSizeT
__pool__: memhub.MemManager | t.CPtr
__elem_size__: t.CSizeT
__iter_index__: t.CSizeT
def __new__(self, pool: memhub.MemManager | t.CPtr, elem_size: t.CSizeT = 0):
# 堆分配 list[T] 对象 (6 字段 × 8 = 48 字节,无 vtable)
return pool.alloc(48)
def __init__(self, pool: memhub.MemManager | t.CPtr, elem_size: t.CSizeT = 0):
self.__pool__ = pool
self.__count__ = 0
self.__capacity__ = 8
if elem_size == 0:
self.__elem_size__ = T.__sizeof__()
else:
self.__elem_size__ = elem_size
self.__data__ = pool.alloc(self.__capacity__ * self.__elem_size__)
self.__iter_index__ = 0
def __len__(self) -> t.CSizeT:
return self.__count__
def append(self, item: T):
if self.__count__ >= self.__capacity__:
new_cap: t.CSizeT = self.__capacity__ * 2
new_data: t.CPtr = self.__pool__.alloc(new_cap * self.__elem_size__)
if new_data == None: return
string.memcpy(new_data, self.__data__, self.__count__ * self.__elem_size__)
self.__data__ = new_data
self.__capacity__ = new_cap
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__)
elem_ptr[0] = item
self.__count__ += 1
def get(self, index: t.CSizeT) -> T:
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__)
return elem_ptr[0]
def __getitem__(self, index: t.CSizeT) -> T:
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__)
return elem_ptr[0]
def set(self, index: t.CSizeT, value: T):
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__)
elem_ptr[0] = value
def __setitem__(self, index: t.CSizeT, value: T):
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + index * self.__elem_size__)
elem_ptr[0] = value
def pop(self) -> T:
self.__count__ -= 1
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + self.__count__ * self.__elem_size__)
return elem_ptr[0]
def clear(self):
self.__count__ = 0
def __iter__(self) -> list[T] | t.CPtr:
self.__iter_index__ = 0
return self
def __next__(self) -> T:
if self.__iter_index__ >= self.__count__:
raise StopIteration
idx: t.CSizeT = self.__iter_index__
self.__iter_index__ = idx + 1
elem_ptr: T | t.CPtr = t.CPtr(t.CUInt64T(self.__data__) + idx * self.__elem_size__)
return elem_ptr[0]
+64
View File
@@ -0,0 +1,64 @@
import t, c
from stdint import *
# Variant 类型标签 (固定枚举 + 自定义 PTR)
VARIANT_NONE: t.CDefine = 0 # 无类型/空值
VARIANT_INT: t.CDefine = 1 # int (i64)
VARIANT_FLOAT: t.CDefine = 2 # float (f32)
VARIANT_DOUBLE: t.CDefine = 3 # double (f64)
VARIANT_STR: t.CDefine = 4 # str (i8*)
VARIANT_DICT: t.CDefine = 5 # dict*
VARIANT_LIST: t.CDefine = 6 # list*
VARIANT_BOOL: t.CDefine = 7 # bool (i1/i32)
VARIANT_PTR: t.CDefine = 8 # 自定义指针类型
class Variant:
"""通用变体类型,存储类型标签 + 无类型指针。
用于 dict/list 的万能对象存储,支持嵌套和 JSON 序列化。
用法:
v: Variant = Variant(VARIANT_INT, t.CNeedPtr(42))
v2: Variant = Variant(VARIANT_STR, t.CNeedPtr("hello"))
# 获取值
ptr: t.CPtr = v.ptr
i: int = c.Deref(ptr)
"""
vtype: t.CInt
ptr: t.CPtr
def __init__(self, vtype: t.CInt, val: t.CNeedPtr):
"""构造 Variant。
val 使用 t.CNeedPtr 自动取地址(非指针值自动 alloca+store)。
注意: val 的生命周期由调用者管理,Variant 仅存储指针。
"""
self.vtype = vtype
self.ptr = val
def is_none(self) -> t.CInt:
return self.vtype == VARIANT_NONE
def is_int(self) -> t.CInt:
return self.vtype == VARIANT_INT
def is_float(self) -> t.CInt:
return self.vtype == VARIANT_FLOAT
def is_double(self) -> t.CInt:
return self.vtype == VARIANT_DOUBLE
def is_str(self) -> t.CInt:
return self.vtype == VARIANT_STR
def is_dict(self) -> t.CInt:
return self.vtype == VARIANT_DICT
def is_list(self) -> t.CInt:
return self.vtype == VARIANT_LIST
def is_bool(self) -> t.CInt:
return self.vtype == VARIANT_BOOL
def is_ptr(self) -> t.CInt:
return self.vtype == VARIANT_PTR
+67
View File
@@ -0,0 +1,67 @@
import t, c
from stdint import *
from w32.win32process import TlsAlloc, TlsGetValue, TlsSetValue
import stdlib
import stdio
import string
# 最大提供者栈深度(编译器会检查是否够用,不够再往上提)
_MAX_PROVIDER_DEPTH: t.CDefine = 32
@t.Object
class _ProviderStack:
"""提供者栈,存储字段名和指针对。"""
names: t.CArray[VOIDPTR, 32]
ptrs: t.CArray[VOIDPTR, 32]
top: UINT64
# TLS 索引(全局,所有线程共享同一个索引)
_tls_index: ULONG = 0
@t.TLS
def _init_tls():
"""初始化 TLS 索引(一次性执行,后续调用跳过)。"""
global _tls_index
_tls_index = TlsAlloc()
def _get_stack() -> _ProviderStack | t.CPtr:
"""获取当前线程的提供者栈,不存在则分配。"""
_init_tls()
stack: _ProviderStack | t.CPtr = TlsGetValue(_tls_index)
if stack == None:
stack = stdlib.malloc(_ProviderStack.__sizeof__())
string.memset(stack, 0, _ProviderStack.__sizeof__())
TlsSetValue(_tls_index, stack)
return stack
def _push_provider(field_name: str, ptr: t.CPtr):
"""压入提供者 (field_name, ptr) 到栈中。"""
stack: _ProviderStack | t.CPtr = _get_stack()
if stack.top >= _MAX_PROVIDER_DEPTH:
stdio.printf("[with] ERROR: provider stack overflow (depth=%lu, max=%d), field '%s' not injected\n", stack.top, _MAX_PROVIDER_DEPTH, field_name)
return
stack.names[stack.top] = field_name
stack.ptrs[stack.top] = ptr
stack.top = stack.top + 1
def _pop_provider():
"""弹出栈顶提供者。"""
stack: _ProviderStack | t.CPtr = _get_stack()
if stack.top > 0:
stack.top = stack.top - 1
def _find_provider(field_name: str) -> t.CPtr:
"""从栈顶向下查找匹配 field_name 的提供者,返回对应的指针。找不到返回 NULL。"""
stack: _ProviderStack | t.CPtr = _get_stack()
for i in range(stack.top - 1, -1, -1):
if stack.names[i] == field_name:
return stack.ptrs[i]
return None
+458
View File
@@ -0,0 +1,458 @@
import t, c
from stdint import *
import string
import memhub
import stdio
import hashtable
# ============================================================
# argparse.py — 命令行参数解析库(Python argparse 风格)
#
# 用法:
# argparse._mbuddy = mb
# parser = argparse.ArgumentParser("myprog", "A test", pool=mb)
# parser.add_argument("--input", "-i", arg_type=argparse.STRING,
# required=True, help="input file")
# parser.add_argument("--count", "-c", arg_type=argparse.INT,
# default=0, help="repeat count")
# parser.add_argument("--verbose", "-v", action=argparse.STORE_TRUE,
# help="verbose mode")
# parser.add_argument("output", arg_type=argparse.STRING,
# help="output path")
# args = parser.parse_args(argc, argv)
# if args is not None:
# inp: str = args.get_str("input")
# cnt: INT = args.get_int("count")
# verb: bool = args.get_bool("verbose")
# out: str = args.get_str("output")
# argparse.release(args)
# ============================================================
# 类型常量
STRING: t.CDefine = 0
INT: t.CDefine = 1
BOOL: t.CDefine = 2
# 动作常量
STORE: t.CDefine = 0
STORE_TRUE: t.CDefine = 1
STORE_FALSE: t.CDefine = 2
COUNT: t.CDefine = 3
# 限制
MAX_ARGS: t.CDefine = 32
# 模块级 mbuddy 指针(由用户在 main 中赋值)
_mbuddy: memhub.MemBuddy | t.CPtr
# ============================================================
# Argument — 参数定义结构体
# ============================================================
class Argument:
name: str # "--input" 或 "output"(位置参数)
short_name: str # "-i" 或 None
help_text: str # 帮助文本
arg_type: INT # STRING, INT, BOOL
action: INT # STORE, STORE_TRUE, STORE_FALSE, COUNT
default_int: INT # INT 类型默认值
default_str: str # STRING 类型默认值
required: bool # 是否必须
is_positional: bool # 是否位置参数
dest: str # 查找键名("--input" → "input")
# ============================================================
# ParsedArgs — 解析结果
# ============================================================
class ParsedArgs:
_ht: hashtable.HashTable | t.CPtr
__mbuddy__: memhub.MemBuddy | t.CPtr
def __new__(self, mb: memhub.MemBuddy | t.CPtr) -> t.CPtr:
return mb.alloc(16)
def __init__(self, mb: memhub.MemBuddy | t.CPtr):
self.__mbuddy__ = mb
self._ht = hashtable.HashTable(mb)
def get_str(self, name: str) -> str:
"""获取字符串值。键不存在返回 None。"""
if self._ht.__contains__(name) == 0: return None
return self._ht[name]
def get_int(self, name: str) -> INT:
"""获取整数值。键不存在返回 0。"""
if self._ht.__contains__(name) == 0: return 0
ptr: t.CPtr = self._ht[name]
return c.Deref(t.CInt(t.CUInt64T(ptr), t.CPtr))
def get_bool(self, name: str) -> INT:
"""获取布尔值(返回 1 或 0)。键不存在返回 0。"""
if self._ht.__contains__(name) == 0: return 0
ptr: t.CPtr = self._ht[name]
return 1 if c.Deref(t.CInt(t.CUInt64T(ptr), t.CPtr)) != 0 else 0
def has(self, name: str) -> bool:
"""检查键是否存在。"""
return self._ht.__contains__(name) != 0
def _set_str(self, name: str, val: str):
self._ht.set_str(name, val)
def _set_int(self, name: str, val: INT):
self._ht.set_int(name, val)
def _set_bool(self, name: str, val: bool):
if val:
self._ht.set_int(name, 1)
else:
self._ht.set_int(name, 0)
# ============================================================
# ArgumentParser — 命令行参数解析器
# ============================================================
class ArgumentParser:
_prog: str
_description: str
_args: Argument | t.CPtr
_arg_count: INT
__mbuddy__: memhub.MemBuddy | t.CPtr
def __new__(self, prog: str = "", description: str = "",
pool: memhub.MemBuddy | t.CPtr = None) -> t.CPtr:
mb: memhub.MemBuddy | t.CPtr = pool
if mb is None: mb = _mbuddy
return mb.alloc(40)
def __init__(self, prog: str = "", description: str = "",
pool: memhub.MemBuddy | t.CPtr = None):
mb: memhub.MemBuddy | t.CPtr = pool
if mb is None: mb = _mbuddy
self.__mbuddy__ = mb
self._prog = prog
self._description = description
self._arg_count = 0
self._args = mb.alloc(MAX_ARGS * Argument.__sizeof__())
def add_argument(self, name: str = "", short: str = None,
arg_type: INT = 0, default: INT = 0,
default_str: str = None, required: bool = False,
action: INT = 0, help: str = None):
"""注册一个命令行参数。
Args:
name: 参数名("--input" 或 "output")
short: 短选项("-i"),可选
arg_type: 类型(STRING/INT/BOOL)
default: INT 默认值
default_str: STRING 默认值
required: 是否必须
action: 动作(STORE/STORE_TRUE/STORE_FALSE/COUNT)
help: 帮助文本
"""
if self._arg_count >= MAX_ARGS: return
idx: INT = self._arg_count
arg: Argument | t.CPtr = t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())
arg.name = name
arg.short_name = short
arg.help_text = help
arg.arg_type = arg_type
arg.action = action
arg.default_int = default
arg.default_str = default_str
arg.required = required
# 判断是否位置参数
if name is not None and name[0] != '-':
arg.is_positional = True
arg.dest = name
else:
arg.is_positional = False
if name is not None and name[0] == '-' and name[1] == '-':
arg.dest = name + 2
else:
arg.dest = name + 1
self._arg_count = idx + 1
def _get_arg(self, idx: INT) -> Argument | t.CPtr:
return t.CPtr(t.CUInt64T(self._args) + idx * Argument.__sizeof__())
def _find_long(self, token: str) -> INT:
"""精确匹配长选项名"""
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
if string.strcmp(arg.name, token) == 0:
return i
i += 1
return -1
def _find_long_prefix(self, token: str) -> INT:
"""匹配 --name=value 中的 name 前缀"""
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
name_len: INT = string.strlen(arg.name)
if string.strncmp(token, arg.name, name_len) == 0:
if token[name_len] == '=':
return i
i += 1
return -1
def _find_short(self, token: str) -> INT:
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
if arg.short_name is not None:
if string.strcmp(arg.short_name, token) == 0:
return i
i += 1
return -1
def _find_positional(self, pos_idx: INT) -> INT:
count: INT = 0
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
if arg.is_positional:
if count == pos_idx:
return i
count += 1
i += 1
return -1
def _store_value(self, args: ParsedArgs | t.CPtr,
arg: Argument | t.CPtr, value: str):
if arg.arg_type == INT:
args._set_int(arg.dest, string.atoi(value))
elif arg.arg_type == STRING:
args._set_str(arg.dest, value)
elif arg.arg_type == BOOL:
v: INT = string.atoi(value)
if v != 0:
args._set_bool(arg.dest, True)
else:
args._set_bool(arg.dest, False)
def _apply_action(self, args: ParsedArgs | t.CPtr, arg: Argument | t.CPtr):
if arg.action == STORE_TRUE:
args._set_bool(arg.dest, True)
elif arg.action == STORE_FALSE:
args._set_bool(arg.dest, False)
elif arg.action == COUNT:
cur: INT = args.get_int(arg.dest)
args._set_int(arg.dest, cur + 1)
def parse_args(self, argc: INT, argv: str | t.CPtr) -> ParsedArgs | t.CPtr:
"""解析命令行参数。
Args:
argc: 参数个数
argv: 参数数组(char**,argv[0] 为程序名)
Returns:
ParsedArgs 指针,失败返回 None
"""
if self.__mbuddy__ is None: return None
args: ParsedArgs | t.CPtr = ParsedArgs(self.__mbuddy__)
if args is None: return None
# 初始化默认值
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
if arg.action == STORE:
if arg.arg_type == INT:
args._set_int(arg.dest, arg.default_int)
elif arg.arg_type == STRING:
args._set_str(arg.dest, arg.default_str)
elif arg.action == STORE_TRUE:
args._set_bool(arg.dest, False)
elif arg.action == STORE_FALSE:
args._set_bool(arg.dest, True)
elif arg.action == COUNT:
args._set_int(arg.dest, 0)
i += 1
# 解析 argv
idx: INT = 1
pos_idx: INT = 0
token: str = None
found: INT = 0
arg: Argument | t.CPtr = None
value: str = None
entry: str | t.CPtr = None
name_len: INT = 0
while idx < argc:
entry = t.CPtr(t.CUInt64T(argv) + idx * 8)
token = entry[0]
if token is None: break
# "--" 结束符:后续全部为位置参数
if token[0] == '-' and token[1] == '-' and token[2] == 0:
idx += 1
while idx < argc:
entry = t.CPtr(t.CUInt64T(argv) + idx * 8)
token = entry[0]
found = self._find_positional(pos_idx)
if found < 0:
stdio.printf("error: unexpected argument '%s'\n", token)
release(args)
return None
arg = self._get_arg(found)
self._store_value(args, arg, token)
pos_idx += 1
idx += 1
break
# 长选项 --name 或 --name=value
if token[0] == '-' and token[1] == '-':
# 检查是否含 =
has_eq: bool = False
p: str = token
while p[0] != 0:
if p[0] == '=':
has_eq = True
break
p += 1
if has_eq:
# --name=value
found = self._find_long_prefix(token)
if found < 0:
stdio.printf(
"error: unrecognized argument '%s'\n", token)
release(args)
return None
arg = self._get_arg(found)
# 提取 = 后的值
arg_name_len: INT = string.strlen(arg.name)
value = token + arg_name_len + 1
self._store_value(args, arg, value)
idx += 1
else:
# --name(值在下一个 argv 或标志)
found = self._find_long(token)
if found < 0:
stdio.printf(
"error: unrecognized argument '%s'\n", token)
release(args)
return None
arg = self._get_arg(found)
if arg.action == STORE:
if idx + 1 >= argc:
stdio.printf(
"error: %s requires a value\n", arg.name)
release(args)
return None
entry = t.CPtr(t.CUInt64T(argv) + (idx + 1) * 8)
value = entry[0]
self._store_value(args, arg, value)
idx += 2
else:
self._apply_action(args, arg)
idx += 1
# 短选项 -x
elif token[0] == '-':
found = self._find_short(token)
if found < 0:
stdio.printf(
"error: unrecognized argument '%s'\n", token)
release(args)
return None
arg = self._get_arg(found)
if arg.action == STORE:
if idx + 1 >= argc:
stdio.printf(
"error: %s requires a value\n", arg.name)
release(args)
return None
entry = t.CPtr(t.CUInt64T(argv) + (idx + 1) * 8)
value = entry[0]
self._store_value(args, arg, value)
idx += 2
else:
self._apply_action(args, arg)
idx += 1
# 位置参数
else:
found = self._find_positional(pos_idx)
if found < 0:
stdio.printf(
"error: unexpected argument '%s'\n", token)
release(args)
return None
arg = self._get_arg(found)
self._store_value(args, arg, token)
pos_idx += 1
idx += 1
# 检查必须参数
i = 0
while i < self._arg_count:
arg = self._get_arg(i)
if arg.required:
if not args.has(arg.dest):
stdio.printf(
"error: missing required argument '%s'\n",
arg.name)
release(args)
return None
i += 1
return args
def print_help(self):
"""打印帮助信息"""
stdio.printf("usage: %s [options]\n", self._prog)
if self._description is not None and self._description[0] != 0:
stdio.printf("\n%s\n", self._description)
stdio.printf("\npositional arguments:\n")
i: INT = 0
while i < self._arg_count:
arg: Argument | t.CPtr = self._get_arg(i)
if arg.is_positional:
ht: str = arg.help_text
if ht is None: ht = ""
stdio.printf(" %-20s %s\n", arg.name, ht)
i += 1
stdio.printf("\noptional arguments:\n")
i = 0
while i < self._arg_count:
arg = self._get_arg(i)
if not arg.is_positional:
ht: str = arg.help_text
if ht is None: ht = ""
if arg.short_name is not None:
stdio.printf(" %s, %-18s %s\n",
arg.short_name, arg.name, ht)
else:
stdio.printf(" %-22s %s\n", arg.name, ht)
i += 1
def print_usage(self):
"""打印用法简述"""
stdio.printf("usage: %s [options]\n", self._prog)
# ============================================================
# release — 释放 ParsedArgs 及其内部资源
# ============================================================
def release(args: ParsedArgs | t.CPtr):
"""释放 ParsedArgs 对象及其内部 HashTable。"""
if args is None: return
if args.__mbuddy__ is None: return
if args._ht is not None:
if args._ht.__slots__ is not None:
args.__mbuddy__.free(args._ht.__slots__)
args.__mbuddy__.free(t.CVoid(t.CUInt64T(args._ht), t.CPtr))
args.__mbuddy__.free(t.CVoid(t.CUInt64T(args), t.CPtr))
+153
View File
@@ -0,0 +1,153 @@
import t, c
def cli():
c.Asm("cli", [t.ASM_DESCR.CLOBBER_MEMORY])
def sti():
c.Asm("sti", [t.ASM_DESCR.CLOBBER_MEMORY])
def hlt():
c.Asm("hlt", [t.ASM_DESCR.CLOBBER_MEMORY])
def nop():
c.Asm("nop", [t.ASM_DESCR.CLOBBER_MEMORY])
def pause():
c.Asm("pause", op=[t.ASM_DESCR.CLOBBER_MEMORY])
def inb(port: t.CUInt16T) -> t.CUInt8T:
value: t.CUInt32T
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in al, dx
movzx eax, al""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX])
return t.CUInt8T(value)
def outb(port: t.CUInt16T, value: t.CUInt8T):
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(t.CUInt32T(value), t.ASM_DESCR.REG_ANY)}
out dx, al""",
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
def inw(port: t.CUInt16T) -> t.CUInt16T:
value: t.CUInt32T
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in ax, dx
movzx eax, ax""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX])
return t.CUInt16T(value)
def outw(port: t.CUInt16T, value: t.CUInt16T):
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(t.CUInt32T(value), t.ASM_DESCR.REG_ANY)}
out dx, ax""",
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
def inl(port: t.CUInt16T) -> t.CUInt32T:
value: t.CUInt32T
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
in eax, dx""",
out = [c.AsmOut(value, t.ASM_DESCR.OUTPUT_REG)],
op =[t.ASM_DESCR.CLOBBER_RDX])
return value
def outl(port: t.CUInt16T, value: t.CUInt32T):
c.Asm(f"""mov edx, {c.AsmInp(t.CUInt32T(port), t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
out dx, eax""",
op = [t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_RAX])
def io_wait():
c.Asm(f"mov dx, 0x80; out dx, al",
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_DX])
def pushall() -> t.CInline | t.CVoid:
c.Asm(f"""
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15""",
[t.ASM_DESCR.CLOBBER_MEMORY]
)
def popall() -> t.CInline | t.CVoid:
c.Asm(f"""
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax""",
[t.ASM_DESCR.CLOBBER_MEMORY]
)
def cpu_switch_context(old_stack: t.CUInt64T | t.CPtr, new_stack: t.CUInt64T):
c.Asm(f"""
push rax
push rbx
push rcx
push rdx
push rsi
push rdi
push rbp
push r8
push r9
push r10
push r11
push r12
push r13
push r14
push r15
mov [{c.AsmInp(old_stack, t.ASM_DESCR.REG_ANY)}], rsp
mov rsp, {c.AsmInp(new_stack, t.ASM_DESCR.REG_ANY)}
pop r15
pop r14
pop r13
pop r12
pop r11
pop r10
pop r9
pop r8
pop rbp
pop rdi
pop rsi
pop rdx
pop rcx
pop rbx
pop rax""",
op=[t.ASM_DESCR.CLOBBER_MEMORY])
def BSSClean():
c.Asm(
"lea rdi, [rip + __bss_start]\n"
"lea rcx, [rip + __bss_end]\n"
"sub rcx, rdi\n"
"xor eax, eax\n"
"cld\n"
"rep stosb",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RAX]
)
+105
View File
@@ -0,0 +1,105 @@
import t, c
from stdint import *
import memhub
import string
# 导入子模块
from .tokens import (
Token, TokenType, Keyword, TokOp, _init_tables,
)
# 公共部分:基类、枚举、常量、辅助函数、dump
from .base import (
AST, ASTKind, ASTCtx, OpKind, ASTFlag,
# 常量
CONST_INT, CONST_FLOAT, CONST_STR, CONST_BOOL, CONST_NONE,
FLAG_IS_ASYNC, FLAG_SIMPLE, FLAG_HAS_STAR,
# 辅助函数
_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,
)
# 语句节点
from .stmts import (
# 模块层
Module, Expression, Interactive, FunctionType,
# 语句
FunctionDef, ClassDef, Return, Delete, Assign, AugAssign, AnnAssign,
For, While, If, With, Raise, Try, Assert, Global, Nonlocal,
Pass, Break, Continue, Expr, Import, ImportFrom, Match,
)
# 表达式节点
from .exprs import (
# 表达式
BoolOp, BinOp, UnaryOp, Lambda, IfExp, Dict, Set,
ListComp, SetComp, DictComp, GeneratorExp,
Await, Yield, YieldFrom, FormattedValue, JoinedStr,
Constant, NamedExpr, Attribute, Subscript, Starred, Name,
List, Tuple, Slice,
Call, Compare, OpNode,
)
# 辅助节点
from .astaux import (
ExceptHandler, Arguments, Arg, Keyword, Alias, WithItem,
Comprehension,
)
# 模式匹配
from .match import (
MatchCase, MatchValue, MatchSingleton, MatchSequence,
MatchMapping, MatchClass, MatchStar, MatchAs, MatchOr,
)
from .visitor import ASTVisitor
from .lexer import Lexer, _lexer_init, tokenize, new_lexer
from .parser import Parser, _parser_init, parse_tokens, new_parser
from .parser import _parse_test
# ============================================================
# 全局内存池指针(遵循项目规则:声明 _mbuddy)
# 用户在 main 中初始化:ast._mbuddy = memhub.MemBuddy(arena, size)
# ============================================================
_mbuddy: memhub.MemBuddy | t.CPtr
# ============================================================
# 公共 API: parse
# ============================================================
def parse(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr:
"""解析 Python 源代码,返回 AST Module 节点。
参数:
src: NUL 结尾的源代码字符串
pool: memhub.MemManager 实例,用于分配 AST 节点
返回:
AST Module 节点,失败返回 None
"""
if src is None or pool is None:
return None
_init_tables(pool)
lx: Lexer | t.CPtr = new_lexer(pool)
if lx is None:
return None
_lexer_init(lx, src, pool)
tokens: Token | t.CPtr = tokenize(lx)
if tokens is None:
return None
tree: AST | t.CPtr = parse_tokens(pool, tokens)
return tree
def parse_expression(src: str, pool: memhub.MemManager | t.CPtr) -> AST | t.CPtr:
"""解析单个表达式,返回 Expression 节点"""
if src is None or pool is None:
return None
_init_tables(pool)
lx: Lexer | t.CPtr = new_lexer(pool)
if lx is None: return None
_lexer_init(lx, src, pool)
tokens: Token | t.CPtr = tokenize(lx)
if tokens is None: return None
ps: Parser | t.CPtr = new_parser(pool)
if ps is None: return None
_parser_init(ps, tokens, pool)
body: AST | t.CPtr = _parse_test(ps)
return Expression(pool, body)
+337
View File
@@ -0,0 +1,337 @@
import t, c
from stdint import *
import memhub
import string
from .base import (
AST, ASTKind,
_init_ast, _copy_str, _set_parent_list,
_emit, _emit_str, _emit_int, _dump_list,
)
# ============================================================
# ExceptHandler 节点
# ============================================================
class ExceptHandler(AST):
"""ExceptHandler(type: AST, name: str)"""
type: AST | t.CPtr
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
type: AST | t.CPtr, name: str):
ptr: ExceptHandler | t.CPtr = pool.alloc(ExceptHandler.__sizeof__())
if ptr:
string.memset(ptr, 0, ExceptHandler.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
type: AST | t.CPtr, name: str):
_init_ast(self, pool, 0, 0)
self.type = type
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
return ASTKind.ExceptHandler
def type_name(self) -> str:
return "ExceptHandler"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "ExceptHandler(type=")
if self.type is not None:
pos = self.type.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", name='")
pos = _emit_str(buf, size, pos, self.name)
pos = _emit(buf, size, pos, "', body=")
pos = _dump_list(self.children, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# Arguments 节点
# ============================================================
class Arguments(AST):
"""Arguments(args: list[AST | CPtr], vararg: AST, kwarg: AST,
defaults: list[AST | CPtr], kw_defaults: list[AST | CPtr])"""
args: list[AST | t.CPtr] | t.CPtr
vararg: AST | t.CPtr
kwarg: AST | t.CPtr
defaults: list[AST | t.CPtr] | t.CPtr
kw_defaults: list[AST | t.CPtr] | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
args: list[AST | t.CPtr] | t.CPtr,
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
defaults: list[AST | t.CPtr] | t.CPtr,
kw_defaults: list[AST | t.CPtr] | t.CPtr):
ptr: Arguments | t.CPtr = pool.alloc(Arguments.__sizeof__())
if ptr:
string.memset(ptr, 0, Arguments.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
args: list[AST | t.CPtr] | t.CPtr,
vararg: AST | t.CPtr, kwarg: AST | t.CPtr,
defaults: list[AST | t.CPtr] | t.CPtr,
kw_defaults: list[AST | t.CPtr] | t.CPtr):
_init_ast(self, pool, 0, 0)
self.args = args
self.vararg = vararg
self.kwarg = kwarg
self.defaults = defaults
self.kw_defaults = kw_defaults
_set_parent_list(args, self)
_set_parent_list(defaults, self)
_set_parent_list(kw_defaults, self)
def kind(self) -> t.CInt:
return ASTKind.Arguments
def type_name(self) -> str:
return "Arguments"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "Arguments(args=")
pos = _dump_list(self.args, buf, size, pos)
pos = _emit(buf, size, pos, ", vararg=")
if self.vararg is not None:
pos = self.vararg.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", kwarg=")
if self.kwarg is not None:
pos = self.kwarg.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", defaults=")
pos = _dump_list(self.defaults, buf, size, pos)
pos = _emit(buf, size, pos, ", kw_defaults=")
pos = _dump_list(self.kw_defaults, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# Arg 节点
# ============================================================
class Arg(AST):
"""Arg(arg: str, annotation: AST)"""
arg: str
annotation: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
arg: str, annotation: AST | t.CPtr):
ptr: Arg | t.CPtr = pool.alloc(Arg.__sizeof__())
if ptr:
string.memset(ptr, 0, Arg.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
arg: str, annotation: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.arg = _copy_str(pool, arg)
self.annotation = annotation
def kind(self) -> t.CInt:
return ASTKind.Arg
def type_name(self) -> str:
return "Arg"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "Arg(arg='")
pos = _emit_str(buf, size, pos, self.arg)
pos = _emit(buf, size, pos, "', annotation=")
if self.annotation is not None:
pos = self.annotation.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# Keyword 节点
# ============================================================
class Keyword(AST):
"""Keyword(arg: str, value: AST)"""
arg: str
value: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
arg: str, value: AST | t.CPtr):
ptr: Keyword | t.CPtr = pool.alloc(Keyword.__sizeof__())
if ptr:
string.memset(ptr, 0, Keyword.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
arg: str, value: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.arg = _copy_str(pool, arg)
self.value = value
def kind(self) -> t.CInt:
return ASTKind.Keyword
def type_name(self) -> str:
return "Keyword"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "Keyword(arg='")
pos = _emit_str(buf, size, pos, self.arg)
pos = _emit(buf, size, pos, "', value=")
if self.value is not None:
pos = self.value.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# Alias 节点
# ============================================================
class Alias(AST):
"""Alias(name: str, asname: str)"""
name: str
asname: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
name: str, asname: str):
ptr: Alias | t.CPtr = pool.alloc(Alias.__sizeof__())
if ptr:
string.memset(ptr, 0, Alias.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
name: str, asname: str):
_init_ast(self, pool, 0, 0)
self.name = _copy_str(pool, name)
self.asname = _copy_str(pool, asname)
def kind(self) -> t.CInt:
return ASTKind.Alias
def type_name(self) -> str:
return "Alias"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "Alias(name='")
pos = _emit_str(buf, size, pos, self.name)
pos = _emit(buf, size, pos, "', asname='")
pos = _emit_str(buf, size, pos, self.asname)
pos = _emit(buf, size, pos, "')")
return pos
# ============================================================
# WithItem 节点
# ============================================================
class WithItem(AST):
"""WithItem(context_expr: AST, optional_vars: AST)"""
context_expr: AST | t.CPtr
optional_vars: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
ptr: WithItem | t.CPtr = pool.alloc(WithItem.__sizeof__())
if ptr:
string.memset(ptr, 0, WithItem.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
context_expr: AST | t.CPtr, optional_vars: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.context_expr = context_expr
self.optional_vars = optional_vars
def kind(self) -> t.CInt:
return ASTKind.WithItem
def type_name(self) -> str:
return "WithItem"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "WithItem(context_expr=")
if self.context_expr is not None:
pos = self.context_expr.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", optional_vars=")
if self.optional_vars is not None:
pos = self.optional_vars.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# Comprehension 节点
# ============================================================
class Comprehension(AST):
"""Comprehension(target: AST, iter: AST, ifs: list[AST | CPtr], is_async: CInt)"""
target: AST | t.CPtr
iter: AST | t.CPtr
ifs: list[AST | t.CPtr] | t.CPtr
is_async: t.CInt
def __new__(self, pool: memhub.MemManager | t.CPtr,
target: AST | t.CPtr, iter: AST | t.CPtr,
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
ptr: Comprehension | t.CPtr = pool.alloc(Comprehension.__sizeof__())
if ptr:
string.memset(ptr, 0, Comprehension.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
target: AST | t.CPtr, iter: AST | t.CPtr,
ifs: list[AST | t.CPtr] | t.CPtr, is_async: t.CInt):
_init_ast(self, pool, 0, 0)
self.target = target
self.iter = iter
self.ifs = ifs
self.is_async = is_async
_set_parent_list(ifs, self)
def kind(self) -> t.CInt:
return ASTKind.Comprehension
def type_name(self) -> str:
return "Comprehension"
def dump(self, buf: bytes, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "Comprehension(target=")
if self.target is not None:
pos = self.target.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", iter=")
if self.iter is not None:
pos = self.iter.dump(buf, size, pos)
else:
pos = _emit(buf, size, pos, "None")
pos = _emit(buf, size, pos, ", ifs=")
pos = _dump_list(self.ifs, buf, size, pos)
pos = _emit(buf, size, pos, ", is_async=")
pos = _emit_int(buf, size, pos, t.CInt64T(self.is_async))
pos = _emit(buf, size, pos, ")")
return pos
+474
View File
@@ -0,0 +1,474 @@
import t, c
from stdint import *
import memhub
import string
import viperlib
from .tokens import TokOp
# ============================================================
# ASTKind - 节点类型枚举(kind() 虚函数返回值)
# ============================================================
class ASTKind(t.CEnum):
# 核心 15 节点
Module: t.State
FunctionDef: t.State
ClassDef: t.State
Assign: t.State
If: t.State
For: t.State
While: t.State
Return: t.State
Expr: t.State
Name: t.State
Constant: t.State
BinOp: t.State
UnaryOp: t.State
Call: t.State
Compare: t.State
# 模块层
Expression: t.State
Interactive: t.State
FunctionType: t.State
# 语句
Delete: t.State
AugAssign: t.State
AnnAssign: t.State
With: t.State
Raise: t.State
Try: t.State
Assert: t.State
Global: t.State
Nonlocal: t.State
Pass: t.State
Break: t.State
Continue: t.State
Import: t.State
ImportFrom: t.State
Match: t.State
# 表达式
BoolOp: t.State
Lambda: t.State
IfExp: t.State
Dict: t.State
Set: t.State
ListComp: t.State
SetComp: t.State
DictComp: t.State
GeneratorExp: t.State
Await: t.State
Yield: t.State
YieldFrom: t.State
FormattedValue: t.State
JoinedStr: t.State
Attribute: t.State
Subscript: t.State
Starred: t.State
List: t.State
Tuple: t.State
Slice: t.State
NamedExpr: t.State
# 辅助节点
ExceptHandler: t.State
Arguments: t.State
Arg: t.State
Keyword: t.State
Alias: t.State
WithItem: t.State
Comprehension: t.State
OpNode: t.State
# 模式匹配
MatchCase: t.State
MatchValue: t.State
MatchSingleton: t.State
MatchSequence: t.State
MatchMapping: t.State
MatchClass: t.State
MatchStar: t.State
MatchAs: t.State
MatchOr: t.State
# ============================================================
# ASTCtx - 名称上下文(Load/Store/Del)
# ============================================================
class ASTCtx(t.CEnum):
Load: t.State
Store: t.State
Del: t.State
# ============================================================
# OpKind - 运算符枚举(BinOp/UnaryOp/Compare 共用)
# ============================================================
class OpKind(t.CEnum):
# 二元算术/位运算
Add: t.State
Sub: t.State
Mult: t.State
MatMult: t.State
Div: t.State
Mod: t.State
Pow: t.State
LShift: t.State
RShift: t.State
BitOr: t.State
BitXor: t.State
BitAnd: t.State
FloorDiv: t.State
# 布尔运算
And: t.State
Or: t.State
# 比较运算
Eq: t.State
Ne: t.State
Lt: t.State
Le: t.State
Gt: t.State
Ge: t.State
Is: t.State
IsNot: t.State
In: t.State
NotIn: t.State
# 一元运算
Not: t.State
UAdd: t.State
USub: t.State
Invert: t.State
# 空
NoneOp: t.State
# Constant 子类型标识
CONST_INT: t.CDefine = 1
CONST_FLOAT: t.CDefine = 2
CONST_STR: t.CDefine = 3
CONST_BOOL: t.CDefine = 4
CONST_NONE: t.CDefine = 5
# 标志位
FLAG_IS_ASYNC: t.CDefine = 1
FLAG_SIMPLE: t.CDefine = 2
FLAG_HAS_STAR: t.CDefine = 4
# ============================================================
# ASTFlag - 节点标志位枚举
# ============================================================
class ASTFlag(t.CEnum):
IsAsync: t.State
Simple: t.State
HasStar: t.State
# ============================================================
# 辅助函数
# ============================================================
def _copy_str(pool: memhub.MemManager | t.CPtr, src: str) -> str:
"""从 pool 分配并复制 C 字符串"""
if src is None: return None
slen: t.CSizeT = string.strlen(src)
buf: str = pool.alloc(slen + 1)
if buf is None: return None
string.memcpy(buf, src, slen + 1)
return buf
def _set_pos(node: AST | t.CPtr, lineno: t.CInt, col_offset: t.CInt,
end_lineno: t.CInt, end_col_offset: t.CInt):
if node is None: return
node.lineno = lineno
node.col_offset = col_offset
node.end_lineno = end_lineno
node.end_col_offset = end_col_offset
def _inherit_pos(node: AST | t.CPtr, ref: AST | t.CPtr):
if node is None or ref is None: return
node.lineno = ref.lineno
node.col_offset = ref.col_offset
node.end_lineno = ref.end_lineno
node.end_col_offset = ref.end_col_offset
def _init_ast(node: AST | t.CPtr, pool: memhub.MemManager | t.CPtr,
lineno: t.CInt, col: t.CInt):
"""初始化 AST 基类字段"""
node.parent = None
node.pool = pool
node.lineno = lineno
node.col_offset = col
node.end_lineno = lineno
node.end_col_offset = col
node.children = None
def _set_parent_list(lst: list[AST | t.CPtr] | t.CPtr, parent: AST | t.CPtr):
"""为 list 中的每个子节点设置 parent 指针"""
if lst is None: return
n: t.CSizeT = lst.__len__()
i: t.CSizeT = 0
while i < n:
child: AST | t.CPtr = lst.get(i)
if child is not None:
child.parent = parent
i += 1
def _append_child(lst: list[AST | t.CPtr] | t.CPtr, node: AST | t.CPtr,
pool: memhub.MemManager | t.CPtr):
"""向 list 追加子节点(模块级函数,避免与 AST.append 方法名冲突)。
在 AST.append 方法中调用此函数,绕过编译器把 list.append 误解析为
AST.append 虚函数调用的类型推断问题。"""
if lst is None or node is None:
return
lst.append(node)
# ============================================================
# 运算符映射:TokOp -> OpKind
# ============================================================
def _binop_from_op(op_id: t.CInt) -> t.CInt:
if op_id == TokOp.Plus: return OpKind.Add
if op_id == TokOp.Minus: return OpKind.Sub
if op_id == TokOp.Star: return OpKind.Mult
if op_id == TokOp.At: return OpKind.MatMult
if op_id == TokOp.Slash: return OpKind.Div
if op_id == TokOp.Percent: return OpKind.Mod
if op_id == TokOp.StarStar: return OpKind.Pow
if op_id == TokOp.LtLt: return OpKind.LShift
if op_id == TokOp.GtGt: return OpKind.RShift
if op_id == TokOp.VBar: return OpKind.BitOr
if op_id == TokOp.Caret: return OpKind.BitXor
if op_id == TokOp.Amp: return OpKind.BitAnd
if op_id == TokOp.DSlash: return OpKind.FloorDiv
return OpKind.NoneOp
def _augop_from_op(op_id: t.CInt) -> t.CInt:
if op_id == TokOp.PlusEq: return OpKind.Add
if op_id == TokOp.MinusEq: return OpKind.Sub
if op_id == TokOp.StarEq: return OpKind.Mult
if op_id == TokOp.AtEq: return OpKind.MatMult
if op_id == TokOp.SlashEq: return OpKind.Div
if op_id == TokOp.PercentEq: return OpKind.Mod
if op_id == TokOp.StarEqEq: return OpKind.Pow
if op_id == TokOp.LtLtEq: return OpKind.LShift
if op_id == TokOp.GtGtEq: return OpKind.RShift
if op_id == TokOp.VBarEq: return OpKind.BitOr
if op_id == TokOp.CaretEq: return OpKind.BitXor
if op_id == TokOp.AmpEq: return OpKind.BitAnd
if op_id == TokOp.DSlashEq: return OpKind.FloorDiv
return OpKind.NoneOp
def _cmpop_from_op(op_id: t.CInt) -> t.CInt:
if op_id == TokOp.EqEq: return OpKind.Eq
if op_id == TokOp.ExclaimEq: return OpKind.Ne
if op_id == TokOp.Less: return OpKind.Lt
if op_id == TokOp.LessEq: return OpKind.Le
if op_id == TokOp.Greater: return OpKind.Gt
if op_id == TokOp.GreaterEq: return OpKind.Ge
return OpKind.NoneOp
# ============================================================
# dump 辅助函数
# ============================================================
def _emit(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
text: str) -> t.CSizeT:
"""追加字面量到 buf+pos,返回新 pos"""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%s", text)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _emit_str(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
text: str) -> t.CSizeT:
"""追加字符串值到 buf+pos(用 %s 格式)"""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%s", text)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _emit_int(buf: t.CChar | t.CPtr, size: t.CSizeT, pos: t.CSizeT,
val: t.CInt64T) -> t.CSizeT:
"""追加整数值到 buf+pos"""
if buf is None or pos >= size:
return pos
cur: t.CChar | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(buf) + pos)
rem: t.CSizeT = size - pos
n: t.CInt = viperlib.snprintf(cur, rem, "%lld", val)
if n < 0:
return pos
return pos + t.CSizeT(n)
def _op_name(op: t.CInt) -> str:
"""返回 OpKind 的字符串名称"""
if op == OpKind.Add: return "Add"
if op == OpKind.Sub: return "Sub"
if op == OpKind.Mult: return "Mult"
if op == OpKind.MatMult: return "MatMult"
if op == OpKind.Div: return "Div"
if op == OpKind.Mod: return "Mod"
if op == OpKind.Pow: return "Pow"
if op == OpKind.LShift: return "LShift"
if op == OpKind.RShift: return "RShift"
if op == OpKind.BitOr: return "BitOr"
if op == OpKind.BitXor: return "BitXor"
if op == OpKind.BitAnd: return "BitAnd"
if op == OpKind.FloorDiv: return "FloorDiv"
if op == OpKind.And: return "And"
if op == OpKind.Or: return "Or"
if op == OpKind.Eq: return "Eq"
if op == OpKind.Ne: return "Ne"
if op == OpKind.Lt: return "Lt"
if op == OpKind.Le: return "Le"
if op == OpKind.Gt: return "Gt"
if op == OpKind.Ge: return "Ge"
if op == OpKind.Is: return "Is"
if op == OpKind.IsNot: return "IsNot"
if op == OpKind.In: return "In"
if op == OpKind.NotIn: return "NotIn"
if op == OpKind.Not: return "Not"
if op == OpKind.UAdd: return "UAdd"
if op == OpKind.USub: return "USub"
if op == OpKind.Invert: return "Invert"
return "NoneOp"
def _dump_list(lst: list[AST | t.CPtr] | t.CPtr, buf: t.CChar | t.CPtr,
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
"""遍历 list[AST | CPtr] 容器,多态 dump 每个元素"""
if lst is None:
pos = _emit(buf, size, pos, "[]")
return pos
pos = _emit(buf, size, pos, "[")
n: t.CSizeT = lst.__len__()
i: t.CSizeT = 0
while i < n:
if i > 0:
pos = _emit(buf, size, pos, ", ")
child: AST | t.CPtr = lst.get(i)
if child is not None:
pos = child.dump(buf, size, pos)
i += 1
pos = _emit(buf, size, pos, "]")
return pos
def _dump_op_list(lst: t.CPtr, buf: t.CChar | t.CPtr,
size: t.CSizeT, pos: t.CSizeT) -> t.CSizeT:
"""遍历 list[CInt] (OpKind 值),输出 op 名称列表"""
if lst is None:
pos = _emit(buf, size, pos, "[]")
return pos
ops_list: list[t.CInt] | t.CPtr = (list[t.CInt] | t.CPtr)(lst)
pos = _emit(buf, size, pos, "[")
n: t.CSizeT = ops_list.__len__()
i: t.CSizeT = 0
while i < n:
if i > 0:
pos = _emit(buf, size, pos, ", ")
op: t.CInt = ops_list.get(i)
pos = _emit(buf, size, pos, _op_name(op))
i += 1
pos = _emit(buf, size, pos, "]")
return pos
# ============================================================
# AST - 多态基类
#
# @t.CVTable 启用 vtable,支持 kind()/type_name()/dump()/accept() 虚函数
# 子节点用 list[AST | CPtr] 容器存储(O(1) 随机访问,比链表高效)
# parent 字段维护父指针(用于向上遍历)
# ============================================================
@t.CVTable
class AST:
"""AST 节点基类。所有具体节点类继承此类。
字段:
parent: 父节点指针(向上遍历)
pool: 分配器(用于子节点/字符串分配)
lineno/col_offset: 起始位置
end_lineno/end_col_offset: 结束位置
children: 子节点列表(body 语句块,通过 append 添加)
"""
parent: AST | t.CPtr
pool: memhub.MemManager | t.CPtr
lineno: t.CInt
col_offset: t.CInt
end_lineno: t.CInt
end_col_offset: t.CInt
children: list[AST | t.CPtr] | t.CPtr
def kind(self) -> t.CInt:
"""返回节点类型(ASTKind 值),子类覆盖"""
return 0
def type_name(self) -> str:
"""返回节点类型名,子类覆盖"""
return "AST"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
"""多态 dump:子类覆盖以自定义格式。返回写入后的 pos"""
return pos
def accept(self, visitor: t.CPtr):
"""访问者模式入口(待实现):ASTVisitor 在 __visitor.py 定义后,
子类覆盖此方法分派到 visitor.visit_X(self)。当前为空实现。"""
pass
def append(self, node: AST | t.CPtr):
"""将 node 追加为子节点(添加到 children 列表),设置 parent 指针。
用于 parser 构建语句块:module.append(stmt), if_node.append(stmt) 等。
首次调用时懒初始化 children 列表。
注意:list[AST|CPtr] 当前按值复制存储(编译器限制),所以必须先设置
node.parent 再 append,这样副本中的 parent 才是正确的。"""
if self is None or node is None:
return
if self.children is None:
self.children = list[AST | t.CPtr](self.pool, 8)
node.parent = self
_append_child(self.children, node, self.pool)
# ============================================================
# 模块级 dump 函数(供 ast.dump(node, buf, size) 调用)
# ============================================================
def dump(node: AST | t.CPtr, buf: t.CChar | t.CPtr, size: t.CSizeT):
"""将 AST 节点序列化到 buf(容量 size)"""
if node is None or buf is None or size == 0:
return
buf[0] = '\0'
final_pos: t.CSizeT = node.dump(buf, size, 0)
# NUL 终止,防止 printf 越界
if final_pos < size:
buf[final_pos] = '\0'
else:
buf[size - 1] = '\0'
File diff suppressed because it is too large. Load diff
+743
View File
@@ -0,0 +1,743 @@
import t, c
from stdint import *
import memhub
import string
from .tokens import (
Token, TokenType, TokOp, _init_tables, _kw_lookup, _op_head,
OpEntry, new_token, token_set_str, token_set_str_literal,
)
# 缩进栈最大深度
LEXER_MAX_INDENT: t.CDefine = 256
# ============================================================
# Lexer 状态结构体
# ============================================================
class Lexer:
src: str # 源代码(NUL 结尾)
pos: t.CSizeT # 当前位置
len: t.CSizeT # 源代码长度
lineno: t.CInt # 当前行号(从 1 开始)
col: t.CInt # 当前列号(从 0 开始)
pool: memhub.MemManager | t.CPtr # 内存池
indent_stack: t.CInt | t.CPtr # 缩进栈(int 数组,从 pool 分配)
indent_top: t.CInt # 栈顶索引(-1 表示空栈)
paren_depth: t.CInt # 括号深度(>0 时不产生 TokenType.NewLine)
tokens_head: Token | t.CPtr # token 链表头
tokens_tail: Token | t.CPtr # token 链表尾
at_line_start: t.CInt # 1=行首(需处理缩进)
error_count: t.CInt # 错误计数
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: Lexer | t.CPtr = pool.alloc(Lexer.__sizeof__())
if ptr:
string.memset(ptr, 0, Lexer.__sizeof__())
return ptr
def new_lexer(pool: memhub.MemManager | t.CPtr) -> Lexer | t.CPtr:
"""从 pool 分配并返回 Lexer(跨模块安全包装)"""
return Lexer(pool)
def _lexer_init(lx: Lexer | t.CPtr, src: str,
pool: memhub.MemManager | t.CPtr):
"""初始化 Lexer"""
if lx == None: return
lx.src = src
lx.pos = 0
lx.len = string.strlen(src) if src != None else 0
lx.lineno = 1
lx.col = 0
lx.pool = pool
# 分配缩进栈
lx.indent_stack = pool.alloc(LEXER_MAX_INDENT * 8)
if lx.indent_stack != None:
string.memset(lx.indent_stack, 0, LEXER_MAX_INDENT * 8)
lx.indent_top = -1
# 栈底压入 0(基础缩进)
if lx.indent_stack != None:
lx.indent_stack[0] = 0
lx.indent_top = 0
lx.paren_depth = 0
lx.tokens_head = None
lx.tokens_tail = None
lx.at_line_start = 1
lx.error_count = 0
_init_tables(pool)
# ============================================================
# 辅助函数
# ============================================================
def _peek(lx: Lexer | t.CPtr, offset: t.CSizeT) -> t.CChar:
"""查看 pos+offset 处字符,越界返回 '\0'"""
p: t.CSizeT = lx.pos + offset
if p >= lx.len:
return '\0'
return lx.src[p]
def _peek_cur(lx: Lexer | t.CPtr) -> t.CChar:
if lx.pos >= lx.len:
return '\0'
return lx.src[lx.pos]
def _advance(lx: Lexer | t.CPtr) -> t.CChar:
"""前进一个字符,返回该字符"""
if lx.pos >= lx.len:
return '\0'
ch: t.CChar = lx.src[lx.pos]
lx.pos += 1
if ch == '\n':
lx.lineno += 1
lx.col = 0
else:
lx.col += 1
return ch
def _is_alpha(ch: t.CChar) -> t.CInt:
if ch >= 'a' and ch <= 'z': return 1
if ch >= 'A' and ch <= 'Z': return 1
if ch == '_': return 1
return 0
def _is_digit(ch: t.CChar) -> t.CInt:
if ch >= '0' and ch <= '9': return 1
return 0
def _is_alnum(ch: t.CChar) -> t.CInt:
if _is_alpha(ch): return 1
if _is_digit(ch): return 1
return 0
def _is_hex(ch: t.CChar) -> t.CInt:
if ch >= '0' and ch <= '9': return 1
if ch >= 'a' and ch <= 'f': return 1
if ch >= 'A' and ch <= 'F': return 1
return 0
def _is_space(ch: t.CChar) -> t.CInt:
if ch == ' ': return 1
if ch == '\t': return 1
if ch == '\f': return 1
if ch == '\v': return 1
if ch == '\r': return 1
return 0
def _emit(lx: Lexer | t.CPtr, tok: Token | t.CPtr):
"""将 token 追加到链表"""
if tok == None: return
if lx.tokens_head == None:
lx.tokens_head = tok
lx.tokens_tail = tok
else:
lx.tokens_tail.next = tok
lx.tokens_tail = tok
def _make_op_token(lx: Lexer | t.CPtr, op_id: t.CInt, length: t.CInt,
lineno: t.CInt, col: t.CInt) -> Token | t.CPtr:
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Op, lineno, col)
if tok == None: return None
tok.op_subtype = op_id
tok.end_col_offset = col + length
return tok
# ============================================================
# 缩进处理
# ============================================================
def _handle_indent(lx: Lexer | t.CPtr):
"""处理行首缩进,生成 TokenType.Indent/TokenType.Dedent。
跳过空行和注释行(不产生缩进变化)。"""
# 先跳过空行和注释行
while lx.pos < lx.len:
# 记住行首位置,用于非空行回退
line_start_pos: t.CSizeT = lx.pos
line_start_col: t.CInt = lx.col
# 跳过空白(不跨行)
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == ' ' or ch == '\t' or ch == '\f' or ch == '\v':
lx.pos += 1
lx.col += 1
elif ch == '\r':
# CRLF 行尾符的 \r,跳过(让 \n 触发空行处理)
lx.pos += 1
else:
break
if lx.pos >= lx.len:
break
ch = lx.src[lx.pos]
if ch == '\n':
# 空行,跳过
lx.pos += 1
lx.lineno += 1
lx.col = 0
continue
if ch == '\r':
# CRLF 空行(\r 后跟 \n),跳过 \r
lx.pos += 1
if lx.pos < lx.len and lx.src[lx.pos] == '\n':
lx.pos += 1
lx.lineno += 1
lx.col = 0
continue
if ch == '#':
# 注释行,跳过到行尾
while lx.pos < lx.len and lx.src[lx.pos] != '\n':
lx.pos += 1
continue
# 非空行:回退到行首,让后续缩进计算能读到前导空格
lx.pos = line_start_pos
lx.col = line_start_col
break
if lx.pos >= lx.len:
# 文件末尾,不再处理缩进
lx.at_line_start = 0
return
# 计算当前行缩进
indent: t.CInt = 0
save_pos: t.CSizeT = lx.pos
save_col: t.CInt = lx.col
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == ' ':
indent += 1
lx.pos += 1
lx.col += 1
elif ch == '\t':
indent += 8 - (indent % 8)
lx.pos += 1
lx.col += 1
else:
break
# 如果行尾(空行),不处理
if lx.pos < lx.len:
ch = lx.src[lx.pos]
if ch == '\n' or ch == '\r' or ch == '#':
# 空行或注释行,回退位置让主循环处理
lx.pos = save_pos
lx.col = save_col
lx.at_line_start = 0
return
# 与缩进栈比较
top_indent: t.CInt = lx.indent_stack[lx.indent_top]
if indent > top_indent:
# TokenType.Indent
if lx.indent_top + 1 >= LEXER_MAX_INDENT:
lx.error_count += 1
return
lx.indent_top += 1
lx.indent_stack[lx.indent_top] = indent
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Indent, lx.lineno, 0)
_emit(lx, tok)
else:
while indent < lx.indent_stack[lx.indent_top] and lx.indent_top > 0:
lx.indent_top -= 1
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
_emit(lx, tok)
lx.at_line_start = 0
# ============================================================
# 标识符/关键字
# ============================================================
def _read_name(lx: Lexer | t.CPtr):
start: t.CSizeT = lx.pos
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_alnum(ch):
lx.pos += 1
lx.col += 1
else:
break
length: t.CSizeT = lx.pos - start
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Name, start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, start, length)
tok.end_lineno = lx.lineno
tok.end_col_offset = start_col + t.CInt(length)
# 查找关键字
kw_id: t.CInt = _kw_lookup(tok.str_val)
if kw_id:
tok.kw_subtype = kw_id
_emit(lx, tok)
# ============================================================
# 数字
# ============================================================
def _read_number(lx: Lexer | t.CPtr):
start: t.CSizeT = lx.pos
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
is_float: t.CInt = 0
is_complex: t.CInt = 0
ch0: t.CChar = lx.src[lx.pos]
# 处理 0x/0o/0b 前缀
if ch0 == '0' and lx.pos + 1 < lx.len:
ch1: t.CChar = lx.src[lx.pos + 1]
if ch1 == 'x' or ch1 == 'X':
lx.pos += 2
lx.col += 2
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_hex(ch) or ch == '_':
lx.pos += 1
lx.col += 1
else:
break
_emit_number(lx, start, start_lineno, start_col, 0, 0, 0)
return
if ch1 == 'o' or ch1 == 'O':
lx.pos += 2
lx.col += 2
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch >= '0' and ch <= '7':
lx.pos += 1
lx.col += 1
elif ch == '_':
lx.pos += 1
lx.col += 1
else:
break
_emit_number(lx, start, start_lineno, start_col, 0, 0, 0)
return
if ch1 == 'b' or ch1 == 'B':
lx.pos += 2
lx.col += 2
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == '0' or ch == '1' or ch == '_':
lx.pos += 1
lx.col += 1
else:
break
_emit_number(lx, start, start_lineno, start_col, 0, 0, 0)
return
# 十进制整数/浮点
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_digit(ch) or ch == '_':
lx.pos += 1
lx.col += 1
else:
break
# 小数部分
if lx.pos < lx.len and lx.src[lx.pos] == '.':
is_float = 1
lx.pos += 1
lx.col += 1
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_digit(ch) or ch == '_':
lx.pos += 1
lx.col += 1
else:
break
# 指数部分
if lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == 'e' or ch == 'E':
is_float = 1
lx.pos += 1
lx.col += 1
if lx.pos < lx.len:
ch = lx.src[lx.pos]
if ch == '+' or ch == '-':
lx.pos += 1
lx.col += 1
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if _is_digit(ch) or ch == '_':
lx.pos += 1
lx.col += 1
else:
break
# 虚数后缀
if lx.pos < lx.len and lx.src[lx.pos] == 'j':
is_complex = 1
is_float = 1
lx.pos += 1
lx.col += 1
_emit_number(lx, start, start_lineno, start_col, is_float, is_complex, 0)
def _emit_number(lx: Lexer | t.CPtr, start: t.CSizeT,
start_lineno: t.CInt, start_col: t.CInt,
is_float: t.CInt, is_complex: t.CInt, is_hex: t.CInt):
length: t.CSizeT = lx.pos - start
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Number, start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, start, length)
tok.is_float = is_float
tok.is_complex = is_complex
tok.end_lineno = lx.lineno
tok.end_col_offset = start_col + t.CInt(length)
# 解析数值
if is_float:
tok.float_val = string.atof(tok.str_val)
else:
tok.int_val = string.atoll(tok.str_val)
_emit(lx, tok)
# ============================================================
# 字符串
# ============================================================
def _read_string(lx: Lexer | t.CPtr):
"""读取字符串字面量。
支持前缀: r, b, u, f, rb, br, rf, fr(大小写不敏感)
支持引号: ', ", ''', """
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
prefix_start: t.CSizeT = lx.pos
# 读取前缀(r/b/u/f)
is_raw: t.CInt = 0
is_bytes: t.CInt = 0
is_fstring: t.CInt = 0
while lx.pos < lx.len:
ch: t.CChar = lx.src[lx.pos]
if ch == 'r' or ch == 'R':
is_raw = 1
lx.pos += 1
lx.col += 1
elif ch == 'b' or ch == 'B':
is_bytes = 1
lx.pos += 1
lx.col += 1
elif ch == 'u' or ch == 'U':
lx.pos += 1
lx.col += 1
elif ch == 'f' or ch == 'F':
is_fstring = 1
lx.pos += 1
lx.col += 1
else:
break
if lx.pos >= lx.len:
lx.error_count += 1
return
# 确定引号
quote: t.CChar = lx.src[lx.pos]
if quote != '\'' and quote != '"':
lx.error_count += 1
return
# 检查三引号
is_triple: t.CInt = 0
if lx.pos + 2 < lx.len:
if lx.src[lx.pos] == quote and lx.src[lx.pos + 1] == quote and lx.src[lx.pos + 2] == quote:
is_triple = 1
content_start: t.CSizeT = lx.pos
if is_triple:
lx.pos += 3
lx.col += 3
else:
lx.pos += 1
lx.col += 1
# 读取字符串内容
content_buf_start: t.CSizeT = lx.pos
while lx.pos < lx.len:
ch = lx.src[lx.pos]
if is_triple:
if ch == quote:
if lx.pos + 2 < lx.len:
if lx.src[lx.pos + 1] == quote and lx.src[lx.pos + 2] == quote:
break
elif lx.pos + 2 == lx.len:
break
if ch == '\\':
lx.pos += 1
lx.col += 1
if lx.pos < lx.len:
if lx.src[lx.pos] == '\n':
lx.lineno += 1
lx.col = 0
lx.pos += 1
lx.col += 1
continue
if ch == '\n':
lx.lineno += 1
lx.col = 0
lx.pos += 1
lx.col += 1
else:
if ch == quote:
break
if ch == '\n':
# 单引号字符串不能跨行(除非续行)
lx.error_count += 1
return
if ch == '\\' and not is_raw:
lx.pos += 1
lx.col += 1
if lx.pos < lx.len:
lx.pos += 1
lx.col += 1
continue
lx.pos += 1
lx.col += 1
content_end: t.CSizeT = lx.pos
# 跳过结束引号
if is_triple:
if lx.pos + 2 < lx.len:
lx.pos += 3
lx.col += 3
else:
lx.pos = lx.len
else:
if lx.pos < lx.len:
lx.pos += 1
lx.col += 1
# 创建 token
tok: Token | t.CPtr = new_token(lx.pool, TokenType.String, start_lineno, start_col)
if tok == None: return
content_len: t.CSizeT = content_end - content_buf_start
# 处理转义序列(非 raw 字符串)
if is_raw == 0 and content_len > 0:
# 分配转换缓冲区(最大情况:每个字符都是普通字符,无需扩展)
conv_buf: str = lx.pool.alloc(content_len + 1)
if conv_buf == None:
token_set_str(lx.pool, tok, lx.src, content_buf_start, content_len)
else:
wpos: t.CSizeT = 0
rpos: t.CSizeT = 0
while rpos < content_len:
ch: t.CChar = lx.src[content_buf_start + rpos]
if ch == '\\' and rpos + 1 < content_len:
rpos += 1
next_ch: t.CChar = lx.src[content_buf_start + rpos]
if next_ch == 'n':
conv_buf[wpos] = '\n'
elif next_ch == 't':
conv_buf[wpos] = '\t'
elif next_ch == 'r':
conv_buf[wpos] = '\r'
elif next_ch == '\\':
conv_buf[wpos] = '\\'
elif next_ch == '\'':
conv_buf[wpos] = '\''
elif next_ch == '"':
conv_buf[wpos] = '"'
elif next_ch == '0':
conv_buf[wpos] = '\0'
else:
# 未知转义,保留原样(包括 \xNN 等以后再处理)
conv_buf[wpos] = '\\'
wpos += 1
conv_buf[wpos] = next_ch
wpos += 1
rpos += 1
else:
conv_buf[wpos] = ch
wpos += 1
rpos += 1
conv_buf[wpos] = '\0'
token_set_str_literal(lx.pool, tok, conv_buf)
else:
token_set_str(lx.pool, tok, lx.src, content_buf_start, content_len)
tok.end_lineno = lx.lineno
tok.end_col_offset = lx.col
# flags 字段复用:bit0=raw, bit1=bytes, bit2=fstring, bit3=triple
if is_raw: tok.kw_subtype = tok.kw_subtype | 1
if is_bytes: tok.kw_subtype = tok.kw_subtype | 2
if is_fstring: tok.kw_subtype = tok.kw_subtype | 4
if is_triple: tok.kw_subtype = tok.kw_subtype | 8
_emit(lx, tok)
# ============================================================
# 运算符
# ============================================================
def _read_operator(lx: Lexer | t.CPtr):
"""贪婪匹配运算符"""
start_lineno: t.CInt = lx.lineno
start_col: t.CInt = lx.col
remaining: t.CSizeT = lx.len - lx.pos
# 遍历运算符表,找最长匹配
best_entry: OpEntry | t.CPtr = None
best_len: t.CInt = 0
cur: OpEntry | t.CPtr = _op_head
while cur != None:
if cur.length <= t.CInt(remaining):
# 比较 cur.name 与 src[pos:pos+cur.length]
match: t.CInt = 1
i: t.CSizeT = 0
while i < t.CSizeT(cur.length):
if lx.src[lx.pos + i] != cur.name[i]:
match = 0
break
i += 1
if match:
if cur.length > best_len:
best_len = cur.length
best_entry = cur
cur = cur.next
if best_entry == None:
# 未知字符,报错并跳过
lx.error_count += 1
lx.pos += 1
lx.col += 1
return
# 更新括号深度
if best_entry.op_id == TokOp.LPar or best_entry.op_id == TokOp.Lsqb or best_entry.op_id == TokOp.LBrace:
lx.paren_depth += 1
elif best_entry.op_id == TokOp.RPar or best_entry.op_id == TokOp.Rsqb or best_entry.op_id == TokOp.RBrace:
if lx.paren_depth > 0:
lx.paren_depth -= 1
tok: Token | t.CPtr = _make_op_token(lx, best_entry.op_id, best_entry.length,
start_lineno, start_col)
if tok == None: return
token_set_str(lx.pool, tok, lx.src, lx.pos, t.CSizeT(best_len))
lx.pos += t.CSizeT(best_len)
lx.col += best_len
_emit(lx, tok)
# ============================================================
# 主词法分析入口
# ============================================================
def tokenize(lx: Lexer | t.CPtr) -> Token | t.CPtr:
"""执行词法分析,返回 token 链表头"""
if lx == None: return None
while lx.pos < lx.len:
# 行首缩进处理
if lx.at_line_start and lx.paren_depth == 0:
_handle_indent(lx)
if lx.pos >= lx.len:
break
ch: t.CChar = _peek_cur(lx)
if ch == '\0':
break
# 换行
if ch == '\n':
if lx.paren_depth > 0:
# 括号内,产生 TokenType.Nl
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Nl, lx.lineno, lx.col)
_emit(lx, tok)
else:
# 逻辑换行
tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
_emit(lx, tok)
lx.at_line_start = 1
lx.pos += 1
lx.lineno += 1
lx.col = 0
continue
# 反斜线续行
if ch == '\\' and lx.pos + 1 < lx.len and lx.src[lx.pos + 1] == '\n':
lx.pos += 2
lx.lineno += 1
lx.col = 0
continue
# 空白
if _is_space(ch):
lx.pos += 1
lx.col += 1
continue
# 注释
if ch == '#':
while lx.pos < lx.len and lx.src[lx.pos] != '\n':
lx.pos += 1
continue
# 字符串前缀(如 r"...")或字符串
if ch == '\'' or ch == '"':
_read_string(lx)
continue
# 字符串前缀字母后跟引号(必须在 _is_alpha 之前检测,否则 f/r/b/u 会被当作 TokenType.Name)
if (ch == 'r' or ch == 'R' or ch == 'b' or ch == 'B' or
ch == 'u' or ch == 'U' or ch == 'f' or ch == 'F'):
if lx.pos + 1 < lx.len:
ch1: t.CChar = lx.src[lx.pos + 1]
if ch1 == '\'' or ch1 == '"':
_read_string(lx)
continue
# 双前缀如 rb, br, rf, fr
if lx.pos + 2 < lx.len:
ch2: t.CChar = lx.src[lx.pos + 2]
if ((ch1 == 'r' or ch1 == 'R' or ch1 == 'b' or ch1 == 'B' or
ch1 == 'f' or ch1 == 'F' or ch1 == 'u' or ch1 == 'U') and
(ch2 == '\'' or ch2 == '"')):
_read_string(lx)
continue
# 标识符/关键字
if _is_alpha(ch):
_read_name(lx)
continue
# 数字
if _is_digit(ch):
_read_number(lx)
continue
# 运算符
_read_operator(lx)
# 文件结尾:产生 TokenType.NewLine(如果有内容)
if lx.tokens_tail != None:
if lx.tokens_tail.type != TokenType.NewLine and lx.tokens_tail.type != TokenType.Nl:
tok: Token | t.CPtr = new_token(lx.pool, TokenType.NewLine, lx.lineno, lx.col)
_emit(lx, tok)
# 产生剩余 TokenType.Dedent
while lx.indent_top > 0:
lx.indent_top -= 1
tok: Token | t.CPtr = new_token(lx.pool, TokenType.Dedent, lx.lineno, 0)
_emit(lx, tok)
# TokenType.EndMarker
tok: Token | t.CPtr = new_token(lx.pool, TokenType.EndMarker, lx.lineno, 0)
_emit(lx, tok)
return lx.tokens_head
+363
View File
@@ -0,0 +1,363 @@
import t, c
from stdint import *
import memhub
import string
from .base import (
AST, ASTKind,
_init_ast, _copy_str, _set_parent_list,
_emit, _emit_str, _emit_int, _dump_list,
)
# ============================================================
# MatchCase 节点
# ============================================================
class MatchCase(AST):
"""MatchCase(pattern: AST, guard: AST)"""
pattern: AST | t.CPtr
guard: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, guard: AST | t.CPtr):
ptr: MatchCase | t.CPtr = pool.alloc(MatchCase.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchCase.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, guard: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.pattern = pattern
self.guard = guard
def kind(self) -> t.CInt:
return ASTKind.MatchCase
def type_name(self) -> str:
return "MatchCase"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchCase(pattern=")
if self.pattern is not None:
pos = self.pattern.dump(buf, size, pos)
pos = _emit(buf, size, pos, ", guard=")
if self.guard is not None:
pos = self.guard.dump(buf, size, pos)
pos = _emit(buf, size, pos, ", body=")
pos = _dump_list(self.children, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# MatchValue 节点
# ============================================================
class MatchValue(AST):
"""MatchValue(value: AST)"""
value: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
ptr: MatchValue | t.CPtr = pool.alloc(MatchValue.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchValue.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.value = value
def kind(self) -> t.CInt:
return ASTKind.MatchValue
def type_name(self) -> str:
return "MatchValue"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchValue(value=")
if self.value is not None:
pos = self.value.dump(buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# MatchSingleton 节点
# ============================================================
class MatchSingleton(AST):
"""MatchSingleton(value: AST)"""
value: AST | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
ptr: MatchSingleton | t.CPtr = pool.alloc(MatchSingleton.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchSingleton.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, value: AST | t.CPtr):
_init_ast(self, pool, 0, 0)
self.value = value
def kind(self) -> t.CInt:
return ASTKind.MatchSingleton
def type_name(self) -> str:
return "MatchSingleton"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchSingleton(value=")
if self.value is not None:
pos = self.value.dump(buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# MatchSequence 节点
# ============================================================
class MatchSequence(AST):
"""MatchSequence(patterns: list[AST | t.CPtr])"""
patterns: list[AST | t.CPtr] | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchSequence | t.CPtr = pool.alloc(MatchSequence.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchSequence.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
_init_ast(self, pool, 0, 0)
self.patterns = patterns
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
return ASTKind.MatchSequence
def type_name(self) -> str:
return "MatchSequence"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchSequence(patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# MatchMapping 节点
# ============================================================
class MatchMapping(AST):
"""MatchMapping(keys: list[AST | t.CPtr], patterns: list[AST | t.CPtr], rest: str)"""
keys: list[AST | t.CPtr] | t.CPtr
patterns: list[AST | t.CPtr] | t.CPtr
rest: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
keys: list[AST | t.CPtr] | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
rest: str):
ptr: MatchMapping | t.CPtr = pool.alloc(MatchMapping.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchMapping.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
keys: list[AST | t.CPtr] | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
rest: str):
_init_ast(self, pool, 0, 0)
self.keys = keys
self.patterns = patterns
self.rest = _copy_str(pool, rest)
_set_parent_list(keys, self)
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
return ASTKind.MatchMapping
def type_name(self) -> str:
return "MatchMapping"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchMapping(keys=")
pos = _dump_list(self.keys, buf, size, pos)
pos = _emit(buf, size, pos, ", patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
pos = _emit(buf, size, pos, ", rest='")
pos = _emit_str(buf, size, pos, self.rest)
pos = _emit(buf, size, pos, "')")
return pos
# ============================================================
# MatchClass 节点
# ============================================================
class MatchClass(AST):
"""MatchClass(cls: AST, patterns: list[AST | t.CPtr],
kwd_attrs: list[AST | t.CPtr], kwd_patterns: list[AST | t.CPtr])"""
cls: AST | t.CPtr
patterns: list[AST | t.CPtr] | t.CPtr
kwd_attrs: list[AST | t.CPtr] | t.CPtr
kwd_patterns: list[AST | t.CPtr] | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
cls: AST | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchClass | t.CPtr = pool.alloc(MatchClass.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchClass.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
cls: AST | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr,
kwd_attrs: list[AST | t.CPtr] | t.CPtr,
kwd_patterns: list[AST | t.CPtr] | t.CPtr):
_init_ast(self, pool, 0, 0)
self.cls = cls
self.patterns = patterns
self.kwd_attrs = kwd_attrs
self.kwd_patterns = kwd_patterns
_set_parent_list(patterns, self)
_set_parent_list(kwd_attrs, self)
_set_parent_list(kwd_patterns, self)
def kind(self) -> t.CInt:
return ASTKind.MatchClass
def type_name(self) -> str:
return "MatchClass"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchClass(cls=")
if self.cls is not None:
pos = self.cls.dump(buf, size, pos)
pos = _emit(buf, size, pos, ", patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
pos = _emit(buf, size, pos, ", kwd_attrs=")
pos = _dump_list(self.kwd_attrs, buf, size, pos)
pos = _emit(buf, size, pos, ", kwd_patterns=")
pos = _dump_list(self.kwd_patterns, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
# ============================================================
# MatchStar 节点
# ============================================================
class MatchStar(AST):
"""MatchStar(name: str)"""
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr, name: str):
ptr: MatchStar | t.CPtr = pool.alloc(MatchStar.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchStar.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr, name: str):
_init_ast(self, pool, 0, 0)
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
return ASTKind.MatchStar
def type_name(self) -> str:
return "MatchStar"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchStar(name='")
pos = _emit_str(buf, size, pos, self.name)
pos = _emit(buf, size, pos, "')")
return pos
# ============================================================
# MatchAs 节点
# ============================================================
class MatchAs(AST):
"""MatchAs(pattern: AST, name: str)"""
pattern: AST | t.CPtr
name: str
def __new__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, name: str):
ptr: MatchAs | t.CPtr = pool.alloc(MatchAs.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchAs.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
pattern: AST | t.CPtr, name: str):
_init_ast(self, pool, 0, 0)
self.pattern = pattern
self.name = _copy_str(pool, name)
def kind(self) -> t.CInt:
return ASTKind.MatchAs
def type_name(self) -> str:
return "MatchAs"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchAs(pattern=")
if self.pattern is not None:
pos = self.pattern.dump(buf, size, pos)
pos = _emit(buf, size, pos, ", name='")
pos = _emit_str(buf, size, pos, self.name)
pos = _emit(buf, size, pos, "')")
return pos
# ============================================================
# MatchOr 节点
# ============================================================
class MatchOr(AST):
"""MatchOr(patterns: list[AST | t.CPtr])"""
patterns: list[AST | t.CPtr] | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
ptr: MatchOr | t.CPtr = pool.alloc(MatchOr.__sizeof__())
if ptr:
string.memset(ptr, 0, MatchOr.__sizeof__())
return ptr
def __init__(self, pool: memhub.MemManager | t.CPtr,
patterns: list[AST | t.CPtr] | t.CPtr):
_init_ast(self, pool, 0, 0)
self.patterns = patterns
_set_parent_list(patterns, self)
def kind(self) -> t.CInt:
return ASTKind.MatchOr
def type_name(self) -> str:
return "MatchOr"
def dump(self, buf: t.CChar | t.CPtr, size: t.CSizeT,
pos: t.CSizeT) -> t.CSizeT:
pos = _emit(buf, size, pos, "MatchOr(patterns=")
pos = _dump_list(self.patterns, buf, size, pos)
pos = _emit(buf, size, pos, ")")
return pos
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+391
View File
@@ -0,0 +1,391 @@
import t, c
from stdint import *
import memhub
import string
# ============================================================
# Token 类型枚举(参考 CPython Lib/token.py)
# 用 t.CEnum 组织为类型安全枚举;旧名 XXX 保留为兼容别名
# ============================================================
class TokenType(t.CEnum):
EndMarker: t.State
NewLine: t.State
Indent: t.State
Dedent: t.State
Name: t.State
Number: t.State
String: t.State
FStringStart: t.State
FStringMiddle: t.State
FStringEnd: t.State
Op: t.State
Nl: t.State
Comment: t.State
Encoding: t.State
# ============================================================
# 关键字枚举(参考 CPython Lib/keyword.py)
# 用 t.CEnum 组织为类型安全枚举;旧名 KW_XXX 保留为兼容别名
# NotKeyword(0) 表示非关键字(哨兵,避免 False_=0 与 kw_subtype=0 冲突)
# ============================================================
class Keyword(t.CEnum):
NotKeyword: t.State
False_: t.State
None_: t.State
True_: t.State
And: t.State
As: t.State
Assert: t.State
Async: t.State
Await: t.State
Break: t.State
Class: t.State
Continue: t.State
Def: t.State
Del: t.State
Elif: t.State
Else: t.State
Except: t.State
Finally: t.State
For: t.State
From: t.State
Global: t.State
If: t.State
Import: t.State
In: t.State
Is: t.State
Lambda: t.State
Nonlocal: t.State
Not: t.State
Or: t.State
Pass: t.State
Raise: t.State
Return: t.State
Try: t.State
While: t.State
With: t.State
Yield: t.State
Match: t.State
Case: t.State
Type: t.State
# ============================================================
# 运算符/分隔符枚举
# 用 t.CEnum 组织为类型安全枚举;旧名 OP_XXX 保留为兼容别名
# 存储在 token.op_subtype 字段
# ============================================================
class TokOp(t.CEnum):
LPar: t.State # (
RPar: t.State # )
Lsqb: t.State # [
Rsqb: t.State # ]
LBrace: t.State # {
RBrace: t.State # }
Comma: t.State # ,
Colon: t.State # :
Dot: t.State # .
Semi: t.State # ;
At: t.State # @
Equal: t.State # =
RArrow: t.State # ->
PlusEq: t.State # +=
MinusEq: t.State # -=
StarEq: t.State # *=
SlashEq: t.State # /=
DSlashEq: t.State # //=
PercentEq: t.State # %=
AtEq: t.State # @=
AmpEq: t.State # &=
VBarEq: t.State # |=
CaretEq: t.State # ^=
GtGtEq: t.State # >>=
LtLtEq: t.State # <<=
StarEqEq: t.State # **=
DSlash: t.State # //
StarStar: t.State # **
LtLt: t.State # <<
GtGt: t.State # >>
LessEq: t.State # <=
GreaterEq: t.State # >=
EqEq: t.State # ==
ExclaimEq: t.State # !=
Less: t.State # <
Greater: t.State # >
Plus: t.State # +
Minus: t.State # -
Star: t.State # *
Slash: t.State # /
Percent: t.State # %
Amp: t.State # &
VBar: t.State # |
Caret: t.State # ^
Tilde: t.State # ~
ColonEq: t.State # :=
Ellipsis: t.State # ...
Bang: t.State # ! (非标准,用于解析容错)
# ============================================================
# Token 结构体
# ============================================================
class Token:
type: t.CInt # Token 类型(TokenType.EndMarker/TokenType.NewLine/TokenType.Name/...)
op_subtype: t.CInt # 运算符子类型(OP_*),仅 type==TokenType.Op 时有效
kw_subtype: t.CInt # 关键字子类型(KW_*),仅 type==TokenType.Name 且是关键字时有效
str_val: str # token 文本(NUL 结尾,从 pool 分配)
int_val: t.CInt64T # 整数值(TokenType.Number 用)
float_val: t.CDouble # 浮点值(TokenType.Number 用)
is_float: t.CInt # 1=浮点数, 0=整数
is_complex: t.CInt # 1=复数, 0=实数
lineno: t.CInt # 起始行号
col_offset: t.CInt # 起始列偏移
end_lineno: t.CInt # 结束行号
end_col_offset: t.CInt # 结束列偏移
next: Token | t.CPtr # 链表下一个 token
def __new__(self, pool: memhub.MemManager | t.CPtr):
"""从 mpool 分配 Token 结构体内存并零初始化"""
ptr: Token | t.CPtr = pool.alloc(Token.__sizeof__())
if ptr:
string.memset(ptr, 0, Token.__sizeof__())
return ptr
# ============================================================
# 关键字查找表
# 由于 TransPyC 无 dict 字面量,用链表实现
# ============================================================
class KwEntry:
name: str
kw_id: t.CInt
next: KwEntry | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: KwEntry | t.CPtr = pool.alloc(KwEntry.__sizeof__())
if ptr:
string.memset(ptr, 0, KwEntry.__sizeof__())
return ptr
# 全局关键字链表头(懒初始化)
_kw_head: KwEntry | t.CPtr = None
_kw_pool: memhub.MemManager | t.CPtr = None
def _kw_intern(pool: memhub.MemManager | t.CPtr, name: str, kw_id: t.CInt):
"""将关键字名注册到链表"""
global _kw_head
entry: KwEntry | t.CPtr = KwEntry(pool)
if entry == None: return
slen: t.CSizeT = string.strlen(name)
buf: str = pool.alloc(slen + 1)
if buf == None: return
string.memcpy(buf, name, slen + 1)
entry.name = buf
entry.kw_id = kw_id
entry.next = _kw_head
_kw_head = entry
def _kw_lookup(name: str) -> t.CInt:
"""查找关键字,返回 kw_id(0 表示非关键字)"""
cur: KwEntry | t.CPtr = _kw_head
while cur != None:
if string.strcmp(cur.name, name) == 0:
return cur.kw_id
cur = cur.next
return 0
def _init_keywords(pool: memhub.MemManager | t.CPtr):
"""初始化关键字表(仅一次)"""
global _kw_head, _kw_pool
if _kw_head != None: return
_kw_pool = pool
_kw_intern(pool, "False", Keyword.False_)
_kw_intern(pool, "None", Keyword.None_)
_kw_intern(pool, "True", Keyword.True_)
_kw_intern(pool, "and", Keyword.And)
_kw_intern(pool, "as", Keyword.As)
_kw_intern(pool, "assert", Keyword.Assert)
_kw_intern(pool, "async", Keyword.Async)
_kw_intern(pool, "await", Keyword.Await)
_kw_intern(pool, "break", Keyword.Break)
_kw_intern(pool, "class", Keyword.Class)
_kw_intern(pool, "continue", Keyword.Continue)
_kw_intern(pool, "def", Keyword.Def)
_kw_intern(pool, "del", Keyword.Del)
_kw_intern(pool, "elif", Keyword.Elif)
_kw_intern(pool, "else", Keyword.Else)
_kw_intern(pool, "except", Keyword.Except)
_kw_intern(pool, "finally", Keyword.Finally)
_kw_intern(pool, "for", Keyword.For)
_kw_intern(pool, "from", Keyword.From)
_kw_intern(pool, "global", Keyword.Global)
_kw_intern(pool, "if", Keyword.If)
_kw_intern(pool, "import", Keyword.Import)
_kw_intern(pool, "in", Keyword.In)
_kw_intern(pool, "is", Keyword.Is)
_kw_intern(pool, "lambda", Keyword.Lambda)
_kw_intern(pool, "nonlocal", Keyword.Nonlocal)
_kw_intern(pool, "not", Keyword.Not)
_kw_intern(pool, "or", Keyword.Or)
_kw_intern(pool, "pass", Keyword.Pass)
_kw_intern(pool, "raise", Keyword.Raise)
_kw_intern(pool, "return", Keyword.Return)
_kw_intern(pool, "try", Keyword.Try)
_kw_intern(pool, "while", Keyword.While)
_kw_intern(pool, "with", Keyword.With)
_kw_intern(pool, "yield", Keyword.Yield)
_kw_intern(pool, "match", Keyword.Match)
_kw_intern(pool, "case", Keyword.Case)
_kw_intern(pool, "type", Keyword.Type)
# ============================================================
# 运算符查找表
# 由于 TransPyC 无 dict,用数组+线性查找
# 运算符按长度降序排列,以便贪婪匹配
# ============================================================
class OpEntry:
name: str # 运算符文本(如 "==", "+=")
op_id: t.CInt
length: t.CInt
next: OpEntry | t.CPtr
def __new__(self, pool: memhub.MemManager | t.CPtr):
ptr: OpEntry | t.CPtr = pool.alloc(OpEntry.__sizeof__())
if ptr:
string.memset(ptr, 0, OpEntry.__sizeof__())
return ptr
_op_head: OpEntry | t.CPtr = None
def _op_intern(pool: memhub.MemManager | t.CPtr, name: str, op_id: t.CInt):
global _op_head
slen: t.CSizeT = string.strlen(name)
entry: OpEntry | t.CPtr = OpEntry(pool)
if entry == None: return
buf: str = pool.alloc(slen + 1)
if buf == None: return
string.memcpy(buf, name, slen + 1)
entry.name = buf
entry.op_id = op_id
entry.length = t.CInt(slen)
entry.next = _op_head
_op_head = entry
def _init_operators(pool: memhub.MemManager | t.CPtr):
"""初始化运算符表(按长度降序注册,便于贪婪匹配)"""
global _op_head
if _op_head != None: return
# 3 字符运算符
_op_intern(pool, "**=", TokOp.StarEqEq)
_op_intern(pool, "//=", TokOp.DSlashEq)
_op_intern(pool, ">>=", TokOp.GtGtEq)
_op_intern(pool, "<<=", TokOp.LtLtEq)
_op_intern(pool, "...", TokOp.Ellipsis)
# 2 字符运算符
_op_intern(pool, "->", TokOp.RArrow)
_op_intern(pool, "+=", TokOp.PlusEq)
_op_intern(pool, "-=", TokOp.MinusEq)
_op_intern(pool, "*=", TokOp.StarEq)
_op_intern(pool, "/=", TokOp.SlashEq)
_op_intern(pool, "%=", TokOp.PercentEq)
_op_intern(pool, "@=", TokOp.AtEq)
_op_intern(pool, "&=", TokOp.AmpEq)
_op_intern(pool, "|=", TokOp.VBarEq)
_op_intern(pool, "^=", TokOp.CaretEq)
_op_intern(pool, "//", TokOp.DSlash)
_op_intern(pool, "**", TokOp.StarStar)
_op_intern(pool, "<<", TokOp.LtLt)
_op_intern(pool, ">>", TokOp.GtGt)
_op_intern(pool, "<=", TokOp.LessEq)
_op_intern(pool, ">=", TokOp.GreaterEq)
_op_intern(pool, "==", TokOp.EqEq)
_op_intern(pool, "!=", TokOp.ExclaimEq)
_op_intern(pool, ":=", TokOp.ColonEq)
# 1 字符运算符
_op_intern(pool, "(", TokOp.LPar)
_op_intern(pool, ")", TokOp.RPar)
_op_intern(pool, "[", TokOp.Lsqb)
_op_intern(pool, "]", TokOp.Rsqb)
_op_intern(pool, "{", TokOp.LBrace)
_op_intern(pool, "}", TokOp.RBrace)
_op_intern(pool, ",", TokOp.Comma)
_op_intern(pool, ":", TokOp.Colon)
_op_intern(pool, ".", TokOp.Dot)
_op_intern(pool, ";", TokOp.Semi)
_op_intern(pool, "@", TokOp.At)
_op_intern(pool, "=", TokOp.Equal)
_op_intern(pool, "<", TokOp.Less)
_op_intern(pool, ">", TokOp.Greater)
_op_intern(pool, "+", TokOp.Plus)
_op_intern(pool, "-", TokOp.Minus)
_op_intern(pool, "*", TokOp.Star)
_op_intern(pool, "/", TokOp.Slash)
_op_intern(pool, "%", TokOp.Percent)
_op_intern(pool, "&", TokOp.Amp)
_op_intern(pool, "|", TokOp.VBar)
_op_intern(pool, "^", TokOp.Caret)
_op_intern(pool, "~", TokOp.Tilde)
def _init_tables(pool: memhub.MemManager | t.CPtr):
"""初始化所有查找表(幂等)"""
_init_keywords(pool)
_init_operators(pool)
# ============================================================
# Token 创建辅助函数
# ============================================================
def new_token(pool: memhub.MemManager | t.CPtr, ttype: t.CInt, lineno: t.CInt,
col_offset: t.CInt) -> Token | t.CPtr:
"""创建一个空 Token,调用方填充字段"""
tok: Token | t.CPtr = Token(pool)
if tok == None: return None
tok.type = ttype
tok.lineno = lineno
tok.col_offset = col_offset
tok.end_lineno = lineno
tok.end_col_offset = col_offset
return tok
def token_set_str(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
src: str, start: t.CSizeT, length: t.CSizeT):
"""从 src[start:start+length] 复制文本到 token.str_val
注意:length == 0 时也分配 1 字节存 NUL,让空字符串与 NULL 指针区分开。
"""
if tok == None: return
buf: str = pool.alloc(length + 1)
if buf == None: return
i: t.CSizeT = 0
while i < length:
buf[i] = src[start + i]
i += 1
buf[length] = '\0'
tok.str_val = buf
def token_set_str_literal(pool: memhub.MemManager | t.CPtr, tok: Token | t.CPtr,
text: str):
"""直接复制一个 C 字符串到 token.str_val"""
if tok == None or text == None: return
slen: t.CSizeT = string.strlen(text)
buf: str = pool.alloc(slen + 1)
if buf == None: return
string.memcpy(buf, text, slen + 1)
tok.str_val = buf
+42
View File
@@ -0,0 +1,42 @@
import t, c
ATOMIC_RELAXED: t.CDefine = 0
ATOMIC_CONSUME: t.CDefine = 1
ATOMIC_ACQUIRE: t.CDefine = 2
ATOMIC_RELEASE: t.CDefine = 3
ATOMIC_ACQ_REL: t.CDefine = 4
ATOMIC_SEQ_CST: t.CDefine = 5
def __atomic_test_and_set(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CBool:
result: t.CUInt8T = 1
c.Asm(f"""mov al, 1
xchg byte ptr [{c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}], al
mov {c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)}, al""",
out = [c.AsmOut(result, t.ASM_DESCR.OUTPUT_REG)],
inp = [c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)],
op = [t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
return t.CBool(result)
def __atomic_clear(ptr: t.CUInt64T | t.CPtr, order: t.CInt) -> t.CVoid:
c.Asm(f"""mov byte ptr [{c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}], 0""",
inp = [c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)],
op = [t.ASM_DESCR.CLOBBER_MEMORY])
def __atomic_thread_fence(order: t.CInt) -> t.CVoid:
c.Asm("mfence", op=[t.ASM_DESCR.CLOBBER_MEMORY])
def __atomic_signal_fence(order: t.CInt) -> t.CVoid:
pass
def __atomic_always_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool:
return t.CBool(1)
def __atomic_is_lock_free(size: t.CSizeT, ptr: t.CVoid | t.CPtr) -> t.CBool:
return t.CBool(1)
+78
View File
@@ -0,0 +1,78 @@
import t, c
# ==============================================
# Base64 编解码 纯裸实现
# ==============================================
# Base64 编码对照表
b64_tab: t.CArray[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
# Base64 反向解码表,映射字符到索引值
b64_dec_tab: t.CArray[t.CInt8T, 80] = [
62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
-1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
-1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
]
# * @brief Base64 编码
# * @param in: 输入二进制数据
# * @param in_len: 输入长度
# * @param out: 输出Base64字符串缓冲区
# * @retval 编码后字符串长度
def b64encode(s: str, out: str) -> t.CSizeT:
_s = t.CUInt8T(s, t.CPtr)
length: t.CSizeT = len(s)
i: t.CSizeT = 0
j: t.CSizeT = 0
val: t.CUInt32T = 0
# 每3字节一组转4字节Base64
for i in range(0, length, 3):
# 拼接24bit分组
val = ((t.CUInt32T(_s[i + 0]) << 16 ) |
(t.CUInt32T(_s[i + 1]) << 8 if (i + 1 < length) else 0) |
(t.CUInt32T(_s[i + 2]) << 0 if (i + 2 < length) else 0))
# 拆分4个6bit 查表
out[j + 0] = b64_tab[(val >> 18) & 0x3F]
out[j + 1] = b64_tab[(val >> 12) & 0x3F]
out[j + 2] = b64_tab[(val >> 6) & 0x3F] if (i + 1 < length) else '='
out[j + 3] = b64_tab[(val >> 0) & 0x3F] if (i + 2 < length) else '='
j += 4
out[j] = '\0' # 字符串结尾
return j
# * @brief Base64 解码
# * @param in: Base64字符串
# * @param out: 输出二进制缓冲区
# * @retval 解码后二进制长度
def b64decode(s: str, out: t.CUInt8T | t.CPtr) -> t.CSizeT:
length: t.CSizeT = len(s)
i: t.CSizeT = 0
j: t.CSizeT = 0
val: t.CUInt32T = 0
c: t.CInt
# 每4个Base64字符还原3字节
for i in range(0, length, 4):
if s[i] == '=': break
val = 0
# 逐个解析6bit
c = s[i] - 43
val |= (b64_dec_tab[c] & 0x3F) << 18
c = s[i+1] - 43
val |= (b64_dec_tab[c] & 0x3F) << 12
c = s[i+2] - 43
if s[i+2] != '=': val |= (b64_dec_tab[c] & 0x3F) << 6
c = s[i+3] - 43
if s[i+3] != '=': val |= (b64_dec_tab[c] & 0x3F)
# 还原3字节
out[j] = (val >> 16) & 0xFF
j += 1
if s[i+2] != '=':
out[j] = (val >> 8) & 0xFF
j += 1
if s[i+3] != '=':
out[j] = val & 0xFF
j += 1
return j
+348
View File
@@ -0,0 +1,348 @@
import t, c
HEX_CHARS: t.CArray[t.CChar, None] = "0123456789abcdef"
HEX_VALS: t.CArray[t.CInt, 256]
B64_CHARS: t.CArray[t.CChar, None] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
B64_VALS: t.CArray[t.CInt, 256]
HQX_CHARS: t.CArray[t.CChar, 64] = [
' ', '!', chr(34), '#', '$', '%', '&', "'", '(', ')', '*', '+', ',', '-', '.', '/',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'@',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'X', 'Y', 'Z',
'[', chr(92), '`',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm'
]
HQX_VALS: t.CArray[t.CInt, 256]
UU_CHARS: t.CArray[t.CChar, None] = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
CRC32_TABLE: t.CArray[t.CUnsignedInt, 256] = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
]
CRC_HQX_TABLE: t.CArray[t.CUnsignedShort, 256] = [
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
]
def init_binascii():
i: t.CInt
for i in range(256):
HEX_VALS[i] = -1
B64_VALS[i] = -1
HQX_VALS[i] = -1
for i in range(16):
HEX_VALS[t.CInt(HEX_CHARS[i])] = i
HEX_VALS[t.CInt(HEX_CHARS[i] - 32)] = i
for i in range(64):
B64_VALS[t.CInt(B64_CHARS[i])] = i
for i in range(64):
HQX_CHARS[i] = t.CChar(32 + i)
for i in range(64):
HQX_VALS[t.CUnsignedChar(HQX_CHARS[i])] = i
def crc32(data: str, length: t.CInt, crc: t.CUnsignedInt) -> t.CUnsignedInt:
i: t.CInt
s: t.CUnsignedInt = crc ^ 0xFFFFFFFF
for i in range(length):
s = CRC32_TABLE[(s ^ t.CUnsignedChar(data[i])) & 0xFF] ^ (s >> 8)
return s ^ 0xFFFFFFFF
def crc_hqx(data: str, length: t.CInt, crc: t.CUnsignedShort) -> t.CUnsignedShort:
i: t.CInt
s: t.CUnsignedShort = crc
for i in range(length):
s = CRC_HQX_TABLE[t.CUnsignedChar(s >> 8)] ^ (s << 1 | (data[i] & 0xFF))
return s
def hexlify(data: str, length: t.CInt) -> str:
if not data or length < 0: return None
out: str = str(malloc(length * 2 + 1))
if not out: return None
oi: t.CInt = 0
for i in range(length):
s: t.CUnsignedChar = t.CUnsignedChar(data[i])
out[oi] = HEX_CHARS[(s >> 4) & 0x0F]
oi += 1
out[oi] = HEX_CHARS[(s >> 0) & 0x0F]
oi += 1
out[oi] = '\0'
return out
def b2a_hex(data: str, length: t.CInt) -> str:
return hexlify(data, length)
def a2b_hex(hexstr: str, length: t.CInt) -> str:
if not hexstr or length < 0 or length % 2 != 0: return None
out_len: t.CInt = length // 2
out: str = str(malloc(out_len + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 2):
hi: t.CInt = HEX_VALS[t.CUnsignedChar(hexstr[i])]
lo: t.CInt = HEX_VALS[t.CUnsignedChar(hexstr[i + 1])]
if hi < 0 or lo < 0:
free(out)
return None
out[oi] = t.CChar((hi << 4) | lo)
oi += 1
out[oi] = '\0'
return out
def unhexlify(data: str, length: t.CInt):
return a2b_hex(data, length)
def b2a_base64(data: str, length: t.CInt) -> str:
if not data or length < 0: return None
olen: t.CInt = (length // 3) * 4
if length % 3 != 0:
olen += 4
olen += 1
out: str = str(malloc(olen + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 3):
b0: t.CUnsignedChar = t.CUnsignedChar(data[i])
b1: t.CUnsignedChar = 0
b2: t.CUnsignedChar = 0
if i + 1 < length:
b1 = t.CUnsignedChar(data[i + 1])
if i + 2 < length:
b2 = t.CUnsignedChar(data[i + 2])
out[oi] = B64_CHARS[(b0 >> 2) & 0x3F]
oi += 1
out[oi] = B64_CHARS[((b0 & 0x03) << 4) | ((b1 >> 4) & 0x0F)]
oi += 1
if i + 1 < length:
out[oi] = B64_CHARS[((b1 & 0x0F) << 2) | ((b2 >> 6) & 0x03)]
else:
out[oi] = '='
oi += 1
if i + 2 < length:
out[oi] = B64_CHARS[b2 & 0x3F]
else:
out[oi] = '='
oi += 1
out[oi] = '\0'
return out
def a2b_base64(data: str, length: t.CInt) -> str:
if not data or length < 4: return None
olen: t.CInt = (length // 4) * 3
if length >= 4 and data[length - 1] == '=':
olen -= 1
if length >= 4 and data[length - 2] == '=':
olen -= 1
out: str = str(malloc(olen + 1))
if not out: return None
oi: t.CInt = 0
for i in range(0, length, 4):
v0: t.CInt = 0
v1: t.CInt = 0
v2: t.CInt = 0
v3: t.CInt = 0
j: t.CInt
for j in range(4):
c: t.CChar = data[i + j]
if c == '=':
pass
else:
k: t.CInt
for k in range(64):
if B64_CHARS[k] == c:
if j == 0: v0 = k
elif j == 1: v1 = k
elif j == 2: v2 = k
elif j == 3: v3 = k
break
out[oi] = t.CChar((v0 << 2) | (v1 >> 4))
oi += 1
if data[i + 2] != '=':
out[oi] = t.CChar(((v1 & 0x0F) << 4) | (v2 >> 2))
oi += 1
if data[i + 3] != '=':
out[oi] = t.CChar(((v2 & 0x03) << 6) | v3)
oi += 1
out[oi] = '\0'
return out
def b2a_uu(data: str, length: t.CInt) -> str:
if not data or length < 1 or length > 45: return None
out: str = str(malloc(length * 2 + 2))
if not out: return None
oi: t.CInt = 0
out[oi] = UU_CHARS[length]
oi += 1
for i in range(0, length, 3):
b0: t.CUnsignedChar = t.CUnsignedChar(data[i])
b1: t.CUnsignedChar = 0
b2: t.CUnsignedChar = 0
if i + 1 < length:
b1 = t.CUnsignedChar(data[i + 1])
if i + 2 < length:
b2 = t.CUnsignedChar(data[i + 2])
m: t.CUnsignedInt = (t.CUnsignedInt(b0) << 16) | (t.CUnsignedInt(b1) << 8) | t.CUnsignedInt(b2)
out[oi] = UU_CHARS[(m >> 18) & 0x3F]
oi += 1
out[oi] = UU_CHARS[(m >> 12) & 0x3F]
oi += 1
out[oi] = UU_CHARS[(m >> 6) & 0x3F]
oi += 1
out[oi] = UU_CHARS[m & 0x3F]
oi += 1
out[oi] = '\n'
oi += 1
out[oi] = '\0'
return out
def a2b_uu(data: str) -> str:
if not data or data[0] == ' ' or data[0] == '`': return None
length: t.CInt = t.CInt(data[0]) - 32
if length < 0 or length > 45: return None
out: str = str(malloc(length + 1))
if not out: return None
oi: t.CInt = 0
i: t.CInt = 1
while oi < length:
v0: t.CInt = data[i] - 32
v1: t.CInt = data[i + 1] - 32
v2: t.CInt = data[i + 2] - 32
v3: t.CInt = data[i + 3] - 32
if v0 < 0 or v0 > 63: v0 = 0
if v1 < 0 or v1 > 63: v1 = 0
if v2 < 0 or v2 > 63: v2 = 0
if v3 < 0 or v3 > 63: v3 = 0
m: t.CUnsignedInt = (t.CUnsignedInt(v0) << 18) | (t.CUnsignedInt(v1) << 12) | (t.CUnsignedInt(v2) << 6) | t.CUnsignedInt(v3)
if oi < length:
out[oi] = t.CChar((m >> 16) & 0xFF)
oi += 1
if oi < length:
out[oi] = t.CChar((m >> 8) & 0xFF)
oi += 1
if oi < length:
out[oi] = t.CChar(m & 0xFF)
oi += 1
i += 4
out[oi] = '\0'
return out
def b2a_hqx(data: str, length: t.CInt, crc: t.CUnsignedShort = 0) -> tuple[str, t.CUnsignedShort]:
if not data or length != 3:
return None, crc
out: str = str(malloc(5))
if not out:
return None, crc
# 3字节 → 4字节 HQX
m: t.CUnsignedInt = (t.CUnsignedChar(data[0]) << 16) | (t.CUnsignedChar(data[1]) << 8) | t.CUnsignedChar(data[2])
out[0] = HQX_CHARS[(m >> 18) & 0x3F]
out[1] = HQX_CHARS[(m >> 12) & 0x3F]
out[2] = HQX_CHARS[(m >> 6) & 0x3F]
out[3] = HQX_CHARS[m & 0x3F]
out[4] = '\0'
# CRC 初始化 + 正确计算
s: t.CUnsignedShort = crc
for i in range(3):
byte: t.CUnsignedChar = t.CUnsignedChar(data[i])
s = (s << 8) ^ CRC_HQX_TABLE[((s >> 8) ^ byte) & 0xFF]
return out, s
def a2b_hqx(data: str, crc: t.CUnsignedShort = 0) -> tuple[str, t.CUnsignedShort]:
if not data:
return None, crc
# 检查字符是否有效
for i in range(4):
cchar: t.CUnsignedChar = t.CUnsignedChar(data[i])
if HQX_VALS[cchar] < 0:
return None, crc
# 解码
m: t.CUnsignedInt = 0
for i in range(4):
m = (m << 6) | t.CUnsignedInt(HQX_VALS[t.CUnsignedChar(data[i])])
out: str = str(malloc(4))
if not out:
return None, crc
out[0] = t.CChar((m >> 16) & 0xFF)
out[1] = t.CChar((m >> 8) & 0xFF)
out[2] = t.CChar(m & 0xFF)
out[3] = '\0'
# CRC 初始化 + 正确计算
s: t.CUnsignedShort = crc
for i in range(3):
byte: t.CUnsignedChar = t.CUnsignedChar(out[i])
s = (s << 8) ^ CRC_HQX_TABLE[((s >> 8) ^ byte) & 0xFF]
return out, s
def adler32(data: str, length: t.CInt, adler: t.CUnsignedInt) -> t.CUnsignedInt:
a: t.CUnsignedInt = adler & 0xFFFF
b: t.CUnsignedInt = (adler >> 16) & 0xFFFF
i: t.CInt
for i in range(length):
a = (a + t.CUnsignedChar(data[i])) % 65521
b = (b + a) % 65521
return (b << 16) | a
+11
View File
@@ -0,0 +1,11 @@
import t
def print(*args, sep: str = " ", end: str = "\n") -> t.State:
...
def input(prompt: str = "") -> str | t.State:
...
class type:
def __init__(self): ...
def __str__(self): ...
+53
View File
@@ -0,0 +1,53 @@
import t, c
from stdint import *
from w32.win32base import *
from w32.win32sync import (
CRITICAL_SECTION,
InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection,
InitializeConditionVariable, SleepConditionVariableCS,
WakeConditionVariable, WakeAllConditionVariable
)
@t.Object
class Condition:
"""基于 Windows 条件变量的条件变量,内部包含 CRITICAL_SECTION。
用法:
cond: Condition = Condition()
with cond:
while not ready:
cond.wait()
cond.notify()
"""
cond_var: VOIDPTR
cs: CRITICAL_SECTION
def __init__(self):
InitializeCriticalSection(c.Addr(self.cs))
InitializeConditionVariable(c.Addr(self.cond_var))
def wait(self, timeout_ms: ULONG = INFINITE) -> BOOL:
return SleepConditionVariableCS(c.Addr(self.cond_var), c.Addr(self.cs), timeout_ms)
def notify(self):
WakeConditionVariable(c.Addr(self.cond_var))
def notify_all(self):
WakeAllConditionVariable(c.Addr(self.cond_var))
def acquire(self):
EnterCriticalSection(c.Addr(self.cs))
def release(self):
LeaveCriticalSection(c.Addr(self.cs))
def __enter__(self) -> 'Condition' | t.CPtr:
self.acquire()
return self
def __exit__(self):
self.release()
def delete(self):
DeleteCriticalSection(c.Addr(self.cs))
+20
View File
@@ -0,0 +1,20 @@
"""ctraits — 编译时类型特征库
提供编译时类型判断函数,不纳入运行时编译。
所有函数仅在编译时求值,可与 c.CIf 等编译时条件配合使用。
"""
import t
def isptr(x: t.CType) -> bool:
"""编译时判断 x 的类型是否为指针类型。
返回 True 如果 x 是指针(ptr_count > 0),否则返回 False。
可与 c.CIf 配合使用实现条件编译。
示例:
if c.CIf(ctraits.isptr(my_var)):
# 仅当 my_var 是指针类型时编译此分支
...
"""
pass
+36
View File
@@ -0,0 +1,36 @@
import t, c
from stdint import *
from w32.win32base import *
from w32.win32sync import CreateEventA, SetEvent, ResetEvent, WaitForSingleObject
@t.Object
class Event:
"""基于 Windows Event 的事件对象,支持手动/自动重置。
用法:
evt: Event = Event(FALSE, FALSE)
evt.set()
evt.wait()
"""
handle: HANDLE
manual_reset: BOOL
def __init__(self, manual_reset: BOOL = FALSE, initial_state: BOOL = FALSE):
self.manual_reset = manual_reset
self.handle = CreateEventA(NULL, manual_reset, initial_state, NULL)
def set(self):
SetEvent(self.handle)
def clear(self):
ResetEvent(self.handle)
def is_set(self) -> BOOL:
return WaitForSingleObject(self.handle, 0) == WAIT_OBJECT_0
def wait(self, timeout_ms: ULONG = INFINITE) -> BOOL:
return WaitForSingleObject(self.handle, timeout_ms) == WAIT_OBJECT_0
def close(self):
CloseHandle(self.handle)
+4
View File
@@ -0,0 +1,4 @@
from .__md5 import md5, MD5_DIGEST_LEN
from .__sha1 import sha1, SHA1_DIGEST_LEN
from .__sha256 import sha256, SHA256_DIGEST_LEN
from .__sha512 import sha512, SHA512_DIGEST_LEN
+131
View File
@@ -0,0 +1,131 @@
import string
import t, c
# ==============================================
# MD5 哈希算法
# ==============================================
MD5_BLOCK_LEN: t.CDefine = 64 # 分组块大小
MD5_DIGEST_LEN: t.CDefine = 16 # 摘要输出长度
# MD5 四轮非线性函数
def md5_F(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) | (~x & z)
def md5_G(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & z) | (y & ~z)
def md5_H(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return x ^ y ^ z
def md5_I(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return y ^ (x | ~z)
# 循环左移
def md5_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n))
# MD5 常量表、移位表
md5_T: t.CArray[t.CUInt32T, 64] = [
0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
]
md5_S: t.CArray[t.CInt, 64] = [
7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
]
# MD5 上下文结构体
@t.Object
class md5:
state: t.CArray[t.CUInt32T, 4] # 4个32位状态寄存器
count: t.CUInt64T # 已处理比特数
buf: t.CArray[t.CUInt8T, MD5_BLOCK_LEN] # 分组缓冲区
# 初始化MD5上下文
def __init__(self):
string.memset(self.buf, 0, MD5_BLOCK_LEN)
self.state[0] = 0x67452301
self.state[1] = 0xefcdab89
self.state[2] = 0x98badcfe
self.state[3] = 0x10325476
self.count = 0
# MD5 单分组压缩变换
def transform(self, block: t.CUInt8T | t.CPtr):
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
w: t.CArray[t.CUInt32T, 16]
# 字节序转32位字
for i in range(16):
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 0) |
(t.CUInt32T(block[i * 4 + 1]) << 8) |
(t.CUInt32T(block[i * 4 + 2]) << 16) |
(t.CUInt32T(block[i * 4 + 3]) << 24))
# 4轮64步迭代
for i in range(16):
tmp: t.CUInt32T = md5_F(b, c, d) + a + md5_T[i] + w[i]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
# 在 C 中的 for i<end 的循环退出后的值就是 range 的 end 参数
for i in range(16, 32):
tmp: t.CUInt32T = md5_G(b, c, d) + a + md5_T[i] + w[(5 * i + 1) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
for i in range(32, 48):
tmp: t.CUInt32T = md5_H(b, c, d) + a + md5_T[i] + w[(3 * i + 5) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
for i in range(48, 64):
tmp: t.CUInt32T = md5_I(b, c, d) + a + md5_T[i] + w[(7 * i + 0) % 16]
a = d; d = c; c = b
b += md5_rotl(tmp, md5_S[i])
# 累加到状态
self.state[0] += a
self.state[1] += b
self.state[2] += c
self.state[3] += d
# 分批输入数据
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
self.count += length
if idx > 0:
left: t.CSizeT = MD5_BLOCK_LEN - idx
if length >= left:
string.memcpy(self.buf + idx, data, left)
self.transform(self.buf)
data += left
length -= left
idx = 0
while length >= MD5_BLOCK_LEN:
self.transform(data)
data += MD5_BLOCK_LEN
length -= MD5_BLOCK_LEN
if length > 0:
string.memcpy(self.buf + idx, data, length)
# 结束计算,输出16字节摘要
def final(self, out: t.CArray[t.CUInt8T, MD5_DIGEST_LEN]):
idx: t.CSizeT = self.count % MD5_BLOCK_LEN
# 填充0x80结尾
self.buf[idx] = 0x80
idx += 1
# 空间不够则先压缩一次
if idx > MD5_BLOCK_LEN - 8:
string.memset(self.buf + idx, 0, MD5_BLOCK_LEN - idx)
self.transform(self.buf)
idx = 0
# 补0到末尾8字节
string.memset(self.buf + idx, 0, MD5_BLOCK_LEN - 8 - idx)
# 写入总比特数
bits: t.CUInt64T = self.count << 3
for i in range(8):
self.buf[MD5_BLOCK_LEN - 8 + i] = (bits >> (i * 8)) & 0xFF
self.transform(self.buf)
# 状态转小端字节输出
for i in range(4):
out[i * 4 + 0] = (self.state[i] >> 0) & 0xFF
out[i * 4 + 1] = (self.state[i] >> 8) & 0xFF
out[i * 4 + 2] = (self.state[i] >> 16) & 0xFF
out[i * 4 + 3] = (self.state[i] >> 24) & 0xFF
+120
View File
@@ -0,0 +1,120 @@
import string
import t, c
# ==============================================
# SHA1 哈希算法
# ==============================================
SHA1_BLOCK_LEN: t.CDefine = 64
SHA1_DIGEST_LEN: t.CDefine = 20
def sha1_rotl(x: t.CUInt32T, n: t.CInt) -> t.CUInt32T: return (x << n) | (x >> (32 - n))
# 三轮逻辑函数
def sha1_f1(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (~b & d)
def sha1_f2(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return b ^ c ^ d
def sha1_f3(b: t.CUInt32T, c: t.CUInt32T, d: t.CUInt32T) -> t.CUInt32T: return (b & c) | (b & d) | (c & d)
# SHA1 上下文
@t.Object
class sha1:
state: t.CArray[t.CUInt32T, 5]
count: t.CUInt64T
buf: t.CArray[t.CUInt8T, SHA1_BLOCK_LEN]
def __init__(self):
memset(self.buf, 0, SHA1_BLOCK_LEN)
self.state[0] = 0x67452301
self.state[1] = 0xefcdab89
self.state[2] = 0x98badcfe
self.state[3] = 0x10325476
self.state[4] = 0xc3d2e1f0
self.count = 0
# 单分组压缩
def transform(self, block: t.CUInt8T | t.CPtr):
w: t.CArray[t.CUInt32T, 80]
data: t.CUInt8T | t.CPtr = block
# 前16个字
for i in range(16):
w[i] = (((t.CUInt32T(data[i * 4 + 0])) << 24) |
((t.CUInt32T(data[i * 4 + 1])) << 16) |
((t.CUInt32T(data[i * 4 + 2])) << 8) |
((t.CUInt32T(data[i * 4 + 3])) << 0))
# 扩展到80个字
for i in range(16, 80):
w[i] = sha1_rotl(w[i-3] ^ w[i-8] ^ w[i-14] ^ w[i-16],1)
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
e: t.CUInt32T = self.state[4]
k: t.CUInt32T
tmp: t.CUInt32T
# 4轮迭代
for i in range(0, 20):
k = 0x5a827999
tmp = sha1_rotl(a,5) + sha1_f1(b, c, d) + e + k + w[i]
e = d; d = c
c = sha1_rotl(b, 30)
b = a; a = tmp
for i in range(20, 40):
k = 0x6ed9eba1
tmp = sha1_rotl(a,5) + sha1_f2(b, c, d) + e + k + w[i]
e = d; d = c
c = sha1_rotl(b, 30)
b = a; a = tmp
for i in range(40, 60):
k = 0x8f1bbcdc
tmp = sha1_rotl(a,5) + sha1_f3(b, c, d) + e + k + w[i]
e = d; d = c
c = sha1_rotl(b, 30)
b = a; a = tmp
for i in range(60, 80):
k = 0xca62c1d6
tmp = sha1_rotl(a,5) + sha1_f2(b, c, d) + e + k + w[i]
e = d; d = c
c = sha1_rotl(b, 30)
b = a; a = tmp
self.state[0] += a
self.state[1] += b
self.state[2] += c
self.state[3] += d
self.state[4] += e
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
self.count += length
if idx > 0:
left: t.CSizeT = SHA1_BLOCK_LEN - idx
if length >= left:
memcpy(self.buf + idx, data, left)
self.transform(self.buf)
data += left
length -= left
idx = 0
while length >= SHA1_BLOCK_LEN:
self.transform(data)
data += SHA1_BLOCK_LEN
length -= SHA1_BLOCK_LEN
if length > 0:
memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA1_DIGEST_LEN]):
idx: t.CSizeT = self.count % SHA1_BLOCK_LEN
self.buf[idx] = 0x80
idx += 1
if idx > SHA1_BLOCK_LEN - 8:
memset(self.buf + idx, 0, SHA1_BLOCK_LEN - idx)
self.transform(self.buf)
idx = 0
memset(self.buf + idx,0,SHA1_BLOCK_LEN-8-idx)
bits: t.CUInt64T = self.count << 3
# SHA1 大端写入长度
for i in range(8):
self.buf[SHA1_BLOCK_LEN - 8 + i] = (bits >> (56 - i * 8)) & 0xFF
self.transform(self.buf)
# 大端输出摘要
for i in range(5):
out[i * 4 + 0] = (self.state[i] >> 24) & 0xFF
out[i * 4 + 1] = (self.state[i] >> 16) & 0xFF
out[i * 4 + 2] = (self.state[i] >> 8) & 0xFF
out[i * 4 + 3] = (self.state[i] >> 0) & 0xFF
+123
View File
@@ -0,0 +1,123 @@
import t, c
# ==============================================
# SHA256 哈希算法
# ==============================================
SHA256_BLOCK_LEN: t.CDefine = 64
SHA256_DIGEST_LEN: t.CDefine = 32
# SHA256 常量K
sha256_K: t.CArray[t.CUInt32T, 64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
]
# SHA256 辅助函数
def s0(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ ((x >> 3))
def s1(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ ((x >> 10))
def S0(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
def S1(x: t.CUInt32T) -> t.CUInt32T: return ((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
def Ch(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) ^ (~x & z)
def Maj(x: t.CUInt32T, y: t.CUInt32T, z: t.CUInt32T) -> t.CUInt32T: return (x & y) ^ (x & z) ^ (y & z)
# SHA256 上下文
@t.Object
class sha256:
state: t.CArray[t.CUInt32T, 8]
count: t.CUInt64T
buf: t.CArray[t.CUInt8T, SHA256_BLOCK_LEN]
def __init__(self):
memset(self, 0, sha256.__sizeof__())
self.state[0] = 0x6a09e667
self.state[1] = 0xbb67ae85
self.state[2] = 0x3c6ef372
self.state[3] = 0xa54ff53a
self.state[4] = 0x510e527f
self.state[5] = 0x9b05688c
self.state[6] = 0x1f83d9ab
self.state[7] = 0x5be0cd19
self.count = 0
# memset(self.buf, 0, SHA256_BLOCK_LEN)
# 单分组压缩
def transform(self, block: t.CUInt8T | t.CPtr):
w: t.CArray[t.CUInt32T, 64]
for i in range(16):
w[i] = ((t.CUInt32T(block[i * 4 + 0]) << 24) |
(t.CUInt32T(block[i * 4 + 1]) << 16) |
(t.CUInt32T(block[i * 4 + 2]) << 8 ) |
(t.CUInt32T(block[i * 4 + 3]) << 0 ))
# 扩展64字
for i in range(16, 64):
w[i] = w[i-16] + s0(w[i-15]) + w[i-7] + s1(w[i-2])
a: t.CUInt32T = self.state[0]
b: t.CUInt32T = self.state[1]
c: t.CUInt32T = self.state[2]
d: t.CUInt32T = self.state[3]
e: t.CUInt32T = self.state[4]
f: t.CUInt32T = self.state[5]
g: t.CUInt32T = self.state[6]
h: t.CUInt32T = self.state[7]
t1: t.CUInt32T
t2: t.CUInt32T
# 64步迭代
for i in range(64):
t1 = h + S1(e) + Ch(e,f,g) + sha256_K[i] + w[i]
t2 = S0(a) + Maj(a,b,c)
h = g; g = f; f = e
e = d + t1
d = c; c = b; b = a
a = t1 + t2
# 累加状态
self.state[0] += a
self.state[1] += b
self.state[2] += c
self.state[3] += d
self.state[4] += e
self.state[5] += f
self.state[6] += g
self.state[7] += h
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
self.count += length
if idx > 0:
left: t.CSizeT = SHA256_BLOCK_LEN - idx
if length >= left:
memcpy(self.buf + idx, data, left)
self.transform(self.buf)
data += left
length -= left
idx = 0
while length >= SHA256_BLOCK_LEN:
self.transform(data)
data += SHA256_BLOCK_LEN
length -= SHA256_BLOCK_LEN
if length > 0:
memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA256_DIGEST_LEN]):
idx: t.CSizeT = self.count % SHA256_BLOCK_LEN
self.buf[idx] = 0x80
idx += 1
if idx > SHA256_BLOCK_LEN - 8:
memset(self.buf + idx, 0, SHA256_BLOCK_LEN - idx)
self.transform(self.buf)
idx = 0
memset(self.buf + idx, 0, SHA256_BLOCK_LEN - 8 - idx)
bits: t.CUInt64T = self.count << 3
for i in range(8):
self.buf[SHA256_BLOCK_LEN-8+i] = (bits >> (56 - i*8)) & 0xFF
self.transform(self.buf)
# 大端输出32字节摘要
for i in range(8):
out[i * 4 + 0] = (self.state[i] >> 24) & 0xFF
out[i * 4 + 1] = (self.state[i] >> 16) & 0xFF
out[i * 4 + 2] = (self.state[i] >> 8) & 0xFF
out[i * 4 + 3] = (self.state[i] >> 0) & 0xFF
+148
View File
@@ -0,0 +1,148 @@
import t, c
# ==============================================
# SHA512 哈希算法
# ==============================================
SHA512_BLOCK_LEN: t.CDefine = 128
SHA512_DIGEST_LEN: t.CDefine = 64
def sha512_ror(x: t.CUInt64T, n: int) -> t.CUInt64T: return (x >> n) | (x << (64 - n))
def sha512_shr(x: t.CUInt64T, n: int) -> t.CUInt64T: return x >> n
def sha512_Ch (x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: return (x & y) ^ (~x & z)
def sha512_Maj(x: t.CUInt64T, y: t.CUInt64T, z: t.CUInt64T) -> t.CUInt64T: return (x & y) ^ (x & z) ^ (y & z)
def sha512_BigSigma0(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 28) ^ sha512_ror(x, 34) ^ sha512_ror(x, 39)
def sha512_BigSigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 14) ^ sha512_ror(x, 18) ^ sha512_ror(x, 41)
def sha512_Sigma0(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 1) ^ sha512_ror(x, 8) ^ sha512_shr(x, 7)
def sha512_Sigma1(x: t.CUInt64T) -> t.CUInt64T: return sha512_ror(x, 19) ^ sha512_ror(x, 61) ^ sha512_shr(x, 6)
sha512_K: t.CArray[t.CUInt64T, 80] = [
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817
]
@t.Object
class sha512:
state: t.CArray[t.CUInt64T, 8]
count: t.CArray[t.CUInt64T, 2]
buf: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]
def __init__(self):
memset(self, 0, sha512.__sizeof__())
self.state[0] = 0x6a09e667f3bcc908
self.state[1] = 0xbb67ae8584caa73b
self.state[2] = 0x3c6ef372fe94f82b
self.state[3] = 0xa54ff53a5f1d36f1
self.state[4] = 0x510e527fade682d1
self.state[5] = 0x9b05688c2b3e6c1f
self.state[6] = 0x1f83d9abfb41bd6b
self.state[7] = 0x5be0cd19137e2179
def transform(self, block: t.CArray[t.CUInt8T, SHA512_BLOCK_LEN]):
w: t.CArray[t.CUInt64T, 80]
a: t.CUInt64T
b: t.CUInt64T
c: t.CUInt64T
d: t.CUInt64T
e: t.CUInt64T
f: t.CUInt64T
g: t.CUInt64T
h: t.CUInt64T
t1: t.CUInt64T
t2: t.CUInt64T
for i in range(16):
w[i] = t.CUInt64T(block[i * 8 + 0]) << 56
w[i] |= t.CUInt64T(block[i * 8 + 1]) << 48
w[i] |= t.CUInt64T(block[i * 8 + 2]) << 40
w[i] |= t.CUInt64T(block[i * 8 + 3]) << 32
w[i] |= t.CUInt64T(block[i * 8 + 4]) << 24
w[i] |= t.CUInt64T(block[i * 8 + 5]) << 16
w[i] |= t.CUInt64T(block[i * 8 + 6]) << 8
w[i] |= t.CUInt64T(block[i * 8 + 7]) << 0
for i in range(16, 80):
w[i] = sha512_Sigma1(w[i-2]) + w[i-7] + sha512_Sigma0(w[i-15]) + w[i-16]
a = self.state[0]
b = self.state[1]
c = self.state[2]
d = self.state[3]
e = self.state[4]
f = self.state[5]
g = self.state[6]
h = self.state[7]
for i in range(80):
t1 = h + sha512_BigSigma1(e) + sha512_Ch(e, f, g) + sha512_K[i] + w[i]
t2 = sha512_BigSigma0(a) + sha512_Maj(a, b, c)
h = g; g = f; f = e
e = d + t1
d = c; c = b; b = a
a = t1 + t2
self.state[0] += a
self.state[1] += b
self.state[2] += c
self.state[3] += d
self.state[4] += e
self.state[5] += f
self.state[6] += g
self.state[7] += h
def update(self, s: str):
data: t.CUInt8T | t.CPtr = t.CUInt8T(s, t.CPtr)
length: t.CSizeT = len(s)
idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN)
self.count[0] += length
if self.count[0] < length:
self.count[1] += 1
if idx > 0:
left: t.CSizeT = SHA512_BLOCK_LEN - idx
if length >= left:
memcpy(self.buf + idx, data, left)
self.transform(self.buf)
data += left
length -= left
idx = 0
while length >= SHA512_BLOCK_LEN:
self.transform(data)
data += SHA512_BLOCK_LEN
length -= SHA512_BLOCK_LEN
if length > 0:
memcpy(self.buf + idx, data, length)
def final(self, out: t.CArray[t.CUInt8T, SHA512_DIGEST_LEN]):
bits_lo: t.CUInt64T = self.count[0] << 3
bits_hi: t.CUInt64T = (self.count[1] << 3) | (self.count[0] >> 61)
idx: t.CUInt32T = t.CUInt32T(self.count[0] % SHA512_BLOCK_LEN)
self.buf[idx] = 0x80
idx += 1
if idx > SHA512_BLOCK_LEN - 16:
memset(self.buf + idx, 0, SHA512_BLOCK_LEN - idx)
self.transform(self.buf)
idx = 0
memset(self.buf + idx, 0, SHA512_BLOCK_LEN - 16 - idx)
for i in range(8):
self.buf[SHA512_BLOCK_LEN - 16 + i] = t.CUInt8T(bits_hi >> (56 - i * 8))
for i in range(8):
self.buf[SHA512_BLOCK_LEN - 8 + i] = t.CUInt8T(bits_lo >> (56 - i * 8))
self.transform(self.buf)
for i in range(8):
out[i * 8 + 0] = t.CUInt8T(self.state[i] >> 56)
out[i * 8 + 1] = t.CUInt8T(self.state[i] >> 48)
out[i * 8 + 2] = t.CUInt8T(self.state[i] >> 40)
out[i * 8 + 3] = t.CUInt8T(self.state[i] >> 32)
out[i * 8 + 4] = t.CUInt8T(self.state[i] >> 24)
out[i * 8 + 5] = t.CUInt8T(self.state[i] >> 16)
out[i * 8 + 6] = t.CUInt8T(self.state[i] >> 8)
out[i * 8 + 7] = t.CUInt8T(self.state[i] >> 0)
+240
View File
@@ -0,0 +1,240 @@
# hashtable - 开放寻址哈希表库
# 使用线性探测处理冲突,支持自动扩容和墓碑删除
# 键类型固定为 str (i8*),值类型为 void* (通用指针)
import t, c
import string
import memhub
from stdint import *
# 空槽标记 (hash == 0)
_HT_EMPTY: t.CDefine = 0
# 墓碑标记 (hash == 1)
_HT_TOMBSTONE: t.CDefine = 1
# 默认初始容量 (必须是 2 的幂)
_HT_INIT_CAP: t.CDefine = 16
# 槽大小: hash(8) + key(8) + value(8) = 24 字节
_HT_SLOT_SIZE: t.CDefine = 24
# FNV-1a 64-bit 常量
_FNV_OFFSET: t.CUInt64T = 0xcbf29ce484222325
_FNV_PRIME: t.CUInt64T = 0x100000001b3
def _fnv1a_hash(key: str) -> t.CUInt64T:
"""FNV-1a 64-bit 哈希函数"""
h: t.CUInt64T = _FNV_OFFSET
k: str = key
while k[0] != 0:
h = h ^ t.CUInt64T(k[0])
h = h * _FNV_PRIME
k += 1
# 保证 h >= 2 (避开空槽 0 和墓碑 1)
if h < 2:
h = 2
return h
class HashTable:
"""开放寻址哈希表,使用线性探测处理冲突。
键类型固定为 str (i8*),值类型为 void* (通用指针)。
使用 mbuddy 分配器管理内存。负载因子超过 0.75 时自动扩容。
用法:
mb: memhub.MemBuddy = memhub.MemBuddy(arena, arena_size)
ht: HashTable = HashTable(mb)
ht.set_int("x", 42)
p: t.CPtr = ht["x"]
v: int = c.Deref(p)
"""
__slots__: t.CVoid | t.CPtr # 槽位数组基址
__count__: t.CSizeT = 0 # 已用条目数
__capacity__: t.CSizeT = 16 # 槽位总数 (2 的幂)
__tombstones__: t.CSizeT = 0 # 墓碑数
__mbuddy__: memhub.MemBuddy | t.CPtr
__iter_index__: t.CSizeT = 0
def __new__(self, mb: memhub.MemBuddy | t.CPtr) -> t.CPtr:
# 堆分配 HashTable 对象 (6 字段 x 8 字节 = 48 字节)
return mb.alloc(48)
def __init__(self, mb: memhub.MemBuddy | t.CPtr):
self.__mbuddy__ = mb
self.__capacity__ = _HT_INIT_CAP
self.__count__ = 0
self.__tombstones__ = 0
self.__slots__ = mb.alloc(self.__capacity__ * _HT_SLOT_SIZE)
# 初始化所有槽为空 (hash = 0)
string.memset(self.__slots__, 0, self.__capacity__ * _HT_SLOT_SIZE)
def _slot_hash(self, idx: t.CSizeT) -> t.CUInt64T:
"""读取槽位的 hash 值"""
ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE)
return ptr[0]
def _slot_key(self, idx: t.CSizeT) -> str:
"""读取槽位的 key 指针"""
ptr: str | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8)
return ptr[0]
def _slot_value(self, idx: t.CSizeT) -> t.CPtr:
"""读取槽位的 value 指针"""
ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16)
return ptr[0]
def _set_slot(self, idx: t.CSizeT, h: t.CUInt64T, key: str, val: t.CPtr):
"""设置槽位的三个字段"""
h_ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE)
h_ptr[0] = h
k_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 8)
k_ptr[0] = key
v_ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE + 16)
v_ptr[0] = val
def _find_slot(self, key: str, h: t.CUInt64T) -> t.CSizeT:
"""查找 key 应该插入或已存在的槽位索引。
返回: 如果找到 key,返回其索引;否则返回第一个可插入的空槽/墓碑索引。
"""
mask: t.CSizeT = self.__capacity__ - 1
idx: t.CSizeT = t.CSizeT(h) & mask
first_tombstone: t.CSizeT = self.__capacity__
i: t.CSizeT = 0
while i < self.__capacity__:
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY:
if first_tombstone < self.__capacity__:
return first_tombstone
return idx
if sh == _HT_TOMBSTONE:
if first_tombstone >= self.__capacity__:
first_tombstone = idx
else:
if sh == h:
sk: str = self._slot_key(idx)
if sk == key:
return idx
idx = (idx + 1) & mask
i += 1
if first_tombstone < self.__capacity__:
return first_tombstone
return self.__capacity__
def _resize(self, new_cap: t.CSizeT):
"""扩容并重新哈希所有条目"""
old_slots: t.CVoid | t.CPtr = self.__slots__
old_cap: t.CSizeT = self.__capacity__
new_slots: t.CVoid | t.CPtr = self.__mbuddy__.alloc(new_cap * _HT_SLOT_SIZE)
if new_slots == None:
return
string.memset(new_slots, 0, new_cap * _HT_SLOT_SIZE)
self.__slots__ = new_slots
self.__capacity__ = new_cap
self.__count__ = 0
self.__tombstones__ = 0
i: t.CSizeT = 0
while i < old_cap:
old_h_ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE)
h: t.CUInt64T = old_h_ptr[0]
if h != _HT_EMPTY and h != _HT_TOMBSTONE:
old_k_ptr: str | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 8)
old_v_ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(old_slots) + i * _HT_SLOT_SIZE + 16)
k: str = old_k_ptr[0]
v: t.CPtr = old_v_ptr[0]
idx: t.CSizeT = self._find_slot(k, h)
self._set_slot(idx, h, k, v)
self.__count__ += 1
i += 1
def __setitem__(self, key: str, val: t.CNeedPtr):
"""插入或更新键值对。val 自动取地址 (t.CNeedPtr: 已是指针则不取)。"""
h: t.CUInt64T = _fnv1a_hash(key)
idx: t.CSizeT = self._find_slot(key, h)
if idx >= self.__capacity__:
return
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY or sh == _HT_TOMBSTONE:
if sh == _HT_TOMBSTONE:
self.__tombstones__ -= 1
self._set_slot(idx, h, key, val)
self.__count__ += 1
# 负载因子 > 0.75 时扩容
load: t.CSizeT = self.__count__ + self.__tombstones__
if load * 4 >= self.__capacity__ * 3:
self._resize(self.__capacity__ * 2)
else:
self._set_slot(idx, h, key, val)
def __getitem__(self, key: str) -> t.CPtr:
"""查找 key,返回值指针。不存在返回 None。"""
h: t.CUInt64T = _fnv1a_hash(key)
idx: t.CSizeT = self._find_slot(key, h)
if idx >= self.__capacity__:
return None
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY or sh == _HT_TOMBSTONE:
return None
return self._slot_value(idx)
def __contains__(self, key: str) -> t.CInt:
"""检查 key 是否存在。"""
h: t.CUInt64T = _fnv1a_hash(key)
idx: t.CSizeT = self._find_slot(key, h)
if idx >= self.__capacity__:
return 0
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY or sh == _HT_TOMBSTONE:
return 0
return 1
def __delitem__(self, key: str) -> t.CInt:
"""删除 key。成功返回 1,key 不存在返回 0。"""
h: t.CUInt64T = _fnv1a_hash(key)
idx: t.CSizeT = self._find_slot(key, h)
if idx >= self.__capacity__:
return 0
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY or sh == _HT_TOMBSTONE:
return 0
h_ptr: t.CUInt64T | t.CPtr = (t.CVoid | t.CPtr)(t.CUInt64T(self.__slots__) + idx * _HT_SLOT_SIZE)
h_ptr[0] = _HT_TOMBSTONE
self.__count__ -= 1
self.__tombstones__ += 1
return 1
def __len__(self) -> t.CSizeT:
return self.__count__
def __iter__(self) -> HashTable | t.CPtr:
self.__iter_index__ = 0
return self
def __next__(self) -> str:
while self.__iter_index__ < self.__capacity__:
idx: t.CSizeT = self.__iter_index__
self.__iter_index__ = idx + 1
sh: t.CUInt64T = self._slot_hash(idx)
if sh != _HT_EMPTY and sh != _HT_TOMBSTONE:
return self._slot_key(idx)
raise StopIteration
def get(self, key: str, default: t.CPtr) -> t.CPtr:
"""返回值指针,不存在则返回 default。"""
h: t.CUInt64T = _fnv1a_hash(key)
idx: t.CSizeT = self._find_slot(key, h)
if idx >= self.__capacity__:
return default
sh: t.CUInt64T = self._slot_hash(idx)
if sh == _HT_EMPTY or sh == _HT_TOMBSTONE:
return default
return self._slot_value(idx)
def set_int(self, key: str, val: int):
"""存储 int 值。值复制到 mbuddy 持久存储。"""
storage: t.CVoid | t.CPtr = self.__mbuddy__.alloc(8)
int_ptr: int | t.CPtr = t.CVoid(t.CUInt64T(storage), t.CPtr)
int_ptr[0] = val
self[key] = storage
def set_str(self, key: str, val: str):
"""存储 str 值。直接存储字符串指针。"""
self[key] = val
+237
View File
@@ -0,0 +1,237 @@
import t, c
from stdint import *
import memhub
import string
import viperio
# ============================================================
# JSON 值类型枚举
# ============================================================
JSON_NULL: t.CDefine = 0
JSON_BOOL: t.CDefine = 1
JSON_INT: t.CDefine = 2
JSON_FLOAT: t.CDefine = 3
JSON_STRING: t.CDefine = 4
JSON_ARRAY: t.CDefine = 5
JSON_OBJECT: t.CDefine = 6
# ============================================================
# JsonValue - JSON 值节点
# 使用 mpool 分配:JsonValue(pool) 从池中分配内存
# ============================================================
class JsonValue:
vtype: t.CInt
bool_val: t.CInt
int_val: t.CInt64T
float_val: t.CDouble
str_val: t.CChar | t.CPtr
next: 'JsonValue' | t.CPtr
key: t.CChar | t.CPtr
child: 'JsonValue' | t.CPtr
child_count: t.CSizeT
def __new__(self, pool: memhub.MemManager | t.CPtr):
"""从 mpool 分配 JsonValue 结构体内存并零初始化"""
ptr: JsonValue | t.CPtr = pool.alloc(JsonValue.__sizeof__())
if ptr:
string.memset(ptr, 0, JsonValue.__sizeof__())
return ptr
def type(self) -> t.CInt:
return self.vtype
def is_null(self) -> bool:
return self.vtype == JSON_NULL
def is_bool(self) -> bool:
return self.vtype == JSON_BOOL
def is_int(self) -> bool:
return self.vtype == JSON_INT
def is_float(self) -> bool:
return self.vtype == JSON_FLOAT
def is_string(self) -> bool:
return self.vtype == JSON_STRING
def is_array(self) -> bool:
return self.vtype == JSON_ARRAY
def is_object(self) -> bool:
return self.vtype == JSON_OBJECT
def as_bool(self) -> bool:
return self.bool_val != 0
def as_int(self) -> t.CInt64T:
return self.int_val
def as_float(self) -> t.CDouble:
return self.float_val
def as_string(self) -> t.CChar | t.CPtr:
return self.str_val
def __len__(self) -> t.CSizeT:
return self.child_count
def __getitem__(self, key: t.CChar | t.CPtr) -> 'JsonValue' | t.CPtr:
"""Python风格取值:v["key"] 取对象字段"""
if self.vtype != JSON_OBJECT:
return None
if key == None:
return None
cur: JsonValue | t.CPtr = self.child
while cur != None:
if cur.key != None:
if cur.key == key:
return cur
cur = cur.next
return None
def __setitem__(self, key: t.CChar | t.CPtr, val: 'JsonValue' | t.CPtr):
"""Python风格赋值:v["key"] = val"""
if self.vtype != JSON_OBJECT or key == None or val == None:
return
cur: JsonValue | t.CPtr = self.child
while cur != None:
if cur.key != None:
if cur.key == key:
cur.vtype = val.vtype
cur.bool_val = val.bool_val
cur.int_val = val.int_val
cur.float_val = val.float_val
cur.str_val = val.str_val
cur.child = val.child
cur.child_count = val.child_count
return
cur = cur.next
# key 不存在,追加新子节点
klen: t.CSizeT = string.strlen(key)
kbuf: t.CChar | t.CPtr = self._pool_alloc(klen + 1)
if kbuf != None:
string.memcpy(kbuf, key, klen + 1)
val.key = kbuf
self._append_child(val)
def get_item(self, index: t.CSizeT) -> 'JsonValue' | t.CPtr:
"""按索引取数组元素:v.get_item(0)"""
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
return None
cur: JsonValue | t.CPtr = self.child
i: t.CSizeT = 0
while cur != None:
if i == index:
return cur
cur = cur.next
i += 1
return None
def _pool_alloc(self, size: t.CSizeT) -> t.CChar | t.CPtr:
"""内部方法:从当前对象的 mpool 分配内存(预留,暂返回 None)"""
return None
def _append_child(self, child: 'JsonValue' | t.CPtr):
if self.child == None:
self.child = child
else:
cur: JsonValue | t.CPtr = self.child
while cur.next != None:
cur = cur.next
cur.next = child
self.child_count += 1
# ============================================================
# 构造函数:创建各类 JsonValue(从 mpool 分配)
# ============================================================
def null(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_NULL
return v
def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_BOOL
v.bool_val = 1 if val else 0
return v
def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_INT
v.int_val = val
return v
def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_FLOAT
v.float_val = val
return v
def string_val(pool: memhub.MemManager | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_STRING
if val != None:
slen: t.CSizeT = string.strlen(val)
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
if buf != None:
string.memcpy(buf, val, slen + 1)
v.str_val = buf
return v
def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_ARRAY
return v
def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
v: JsonValue | t.CPtr = JsonValue(pool)
if v == None: return None
v.vtype = JSON_OBJECT
return v
# 向数组追加元素
def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr):
if arr == None or item == None: return
if arr.vtype != JSON_ARRAY: return
arr._append_child(item)
# 向对象设置键值对
def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr):
if obj == None or key == None or val == None: return
if obj.vtype != JSON_OBJECT: return
cur: JsonValue | t.CPtr = obj.child
while cur != None:
if cur.key != None:
if cur.key == key:
cur.vtype = val.vtype
cur.bool_val = val.bool_val
cur.int_val = val.int_val
cur.float_val = val.float_val
cur.str_val = val.str_val
cur.child = val.child
cur.child_count = val.child_count
return
cur = cur.next
klen: t.CSizeT = string.strlen(key)
kbuf: t.CChar | t.CPtr = pool.alloc(klen + 1)
if kbuf != None:
string.memcpy(kbuf, key, klen + 1)
val.key = kbuf
obj._append_child(val)
# ============================================================
# 导入子模块
# ============================================================
from .__parser import parse
from .__writer import write
+291
View File
@@ -0,0 +1,291 @@
import t, c
from stdint import *
import memhub
import string
from . import (
JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT,
JSON_STRING, JSON_ARRAY, JSON_OBJECT,
null, bool_val, int_val, float_val, string_val, array, object,
)
class ParseState:
src: t.CChar | t.CPtr
pos: t.CSizeT
len: t.CSizeT
pool: memhub.MemManager | t.CPtr
def __init__(self, src: t.CChar | t.CPtr, pool: memhub.MemManager | t.CPtr):
self.src = src
self.pos = 0
self.len = string.strlen(src) if src != None else 0
self.pool = pool
def _peek(s: ParseState | t.CPtr) -> t.CChar:
if s.pos >= s.len:
return '\0'
return s.src[s.pos]
def _advance(s: ParseState | t.CPtr) -> t.CChar:
if s.pos >= s.len:
return '\0'
ch: t.CChar = s.src[s.pos]
s.pos += 1
return ch
def _skip_whitespace(s: ParseState | t.CPtr):
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
s.pos += 1
else:
break
def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
_skip_whitespace(s)
if s.pos >= s.len:
return False
if s.src[s.pos] != ch:
return False
s.pos += 1
return True
def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr:
if _peek(s) != '"':
return None
_advance(s)
start: t.CSizeT = s.pos
slen: t.CSizeT = 0
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch == '"':
break
if ch == '\\':
s.pos += 1
slen += 1
slen += 1
s.pos += 1
buf: t.CChar | t.CPtr = s.pool.alloc(slen + 1)
if buf == None:
return None
s.pos = start
di: t.CSizeT = 0
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch == '"':
s.pos += 1
break
if ch == '\\':
s.pos += 1
if s.pos < s.len:
esc: t.CChar = s.src[s.pos]
if esc == 'n':
buf[di] = '\n'
elif esc == 't':
buf[di] = '\t'
elif esc == 'r':
buf[di] = '\r'
elif esc == '\\':
buf[di] = '\\'
elif esc == '"':
buf[di] = '"'
elif esc == '/':
buf[di] = '/'
else:
buf[di] = esc
di += 1
s.pos += 1
continue
buf[di] = ch
di += 1
s.pos += 1
buf[di] = '\0'
return buf
def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
_skip_whitespace(s)
is_float: bool = False
start: t.CSizeT = s.pos
if s.pos < s.len and s.src[s.pos] == '-':
s.pos += 1
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
if s.pos < s.len and s.src[s.pos] == '.':
is_float = True
s.pos += 1
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
if s.pos < s.len and (s.src[s.pos] == 'e' or s.src[s.pos] == 'E'):
is_float = True
s.pos += 1
if s.pos < s.len and (s.src[s.pos] == '+' or s.src[s.pos] == '-'):
s.pos += 1
while s.pos < s.len:
ch: t.CChar = s.src[s.pos]
if ch >= '0' and ch <= '9':
s.pos += 1
else:
break
num_len: t.CSizeT = s.pos - start
buf: t.CChar | t.CPtr = s.pool.alloc(num_len + 1)
if buf == None:
return null(s.pool)
i: t.CSizeT = 0
while i < num_len:
buf[i] = s.src[start + i]
i += 1
buf[num_len] = '\0'
if is_float:
val: t.CDouble = string.atof(buf)
return float_val(s.pool, val)
else:
ival: t.CInt64T = string.atoll(buf)
return int_val(s.pool, ival)
def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
_skip_whitespace(s)
if s.pos >= s.len:
return null(s.pool)
ch: t.CChar = _peek(s)
if ch == '"':
sv: t.CChar | t.CPtr = _parse_string(s)
return string_val(s.pool, sv)
if ch == '{':
return _parse_object(s)
if ch == '[':
return _parse_array(s)
if ch == '-' or (ch >= '0' and ch <= '9'):
return _parse_number(s)
if ch == 't':
if s.pos + 3 < s.len:
if s.src[s.pos + 1] == 'r' and s.src[s.pos + 2] == 'u' and s.src[s.pos + 3] == 'e':
s.pos += 4
return bool_val(s.pool, True)
return null(s.pool)
if ch == 'f':
if s.pos + 4 < s.len:
if s.src[s.pos + 1] == 'a' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 's' and s.src[s.pos + 4] == 'e':
s.pos += 5
return bool_val(s.pool, False)
return null(s.pool)
if ch == 'n':
if s.pos + 3 < s.len:
if s.src[s.pos + 1] == 'u' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 'l':
s.pos += 4
return null(s.pool)
return null(s.pool)
return null(s.pool)
def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
if not _expect(s, '['):
return null(s.pool)
arr: JsonValue | t.CPtr = array(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == ']':
_advance(s)
return arr
item: JsonValue | t.CPtr = _parse_value(s)
arr._append_child(item)
while True:
_skip_whitespace(s)
if s.pos >= s.len:
break
if _peek(s) != ',':
break
_advance(s)
item = _parse_value(s)
arr._append_child(item)
_expect(s, ']')
return arr
def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
if not _expect(s, '{'):
return null(s.pool)
obj: JsonValue | t.CPtr = object(s.pool)
_skip_whitespace(s)
if s.pos < s.len and _peek(s) == '}':
_advance(s)
return obj
_skip_whitespace(s)
key: t.CChar | t.CPtr = _parse_string(s)
_expect(s, ':')
val: JsonValue | t.CPtr = _parse_value(s)
if key != None and val != None:
klen: t.CSizeT = string.strlen(key)
kbuf: t.CChar | t.CPtr = s.pool.alloc(klen + 1)
if kbuf != None:
string.memcpy(kbuf, key, klen + 1)
val.key = kbuf
obj._append_child(val)
while True:
_skip_whitespace(s)
if s.pos >= s.len:
break
if _peek(s) != ',':
break
_advance(s)
_skip_whitespace(s)
key = _parse_string(s)
_expect(s, ':')
val = _parse_value(s)
if key != None and val != None:
klen2: t.CSizeT = string.strlen(key)
kbuf2: t.CChar | t.CPtr = s.pool.alloc(klen2 + 1)
if kbuf2 != None:
string.memcpy(kbuf2, key, klen2 + 1)
val.key = kbuf2
obj._append_child(val)
_expect(s, '}')
return obj
def parse(pool: memhub.MemManager | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr:
"""解析 JSON 字符串,返回 JsonValue 树"""
if src == None:
return null(pool)
s: ParseState | t.CPtr = ParseState(src, pool)
return _parse_value(s)
+119
View File
@@ -0,0 +1,119 @@
import t, c
from stdint import *
import memhub
import string
from stdio import snprintf
from . import (
JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT,
JSON_STRING, JSON_ARRAY, JSON_OBJECT,
)
def _write_char(buf: t.CChar | t.CPtr, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT:
buf[pos] = ch
return pos + 1
def _write_str(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT:
if s == None: return pos
slen: t.CSizeT = string.strlen(s)
string.memcpy(t.CChar(t.CUInt64T(buf) + pos, t.CPtr), s, slen)
return pos + slen
def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT:
if s == None:
pos = _write_str(buf, pos, "null")
return pos
pos = _write_char(buf, pos, '"')
i: t.CSizeT = 0
slen: t.CSizeT = string.strlen(s)
while i < slen:
ch: t.CChar = s[i]
if ch == '"':
pos = _write_str(buf, pos, "\\\"")
elif ch == '\\':
pos = _write_str(buf, pos, "\\\\")
elif ch == '\n':
pos = _write_str(buf, pos, "\\n")
elif ch == '\r':
pos = _write_str(buf, pos, "\\r")
elif ch == '\t':
pos = _write_str(buf, pos, "\\t")
else:
pos = _write_char(buf, pos, ch)
i += 1
pos = _write_char(buf, pos, '"')
return pos
def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT:
if val == None:
pos = _write_str(buf, pos, "null")
return pos
if val.vtype == JSON_NULL:
pos = _write_str(buf, pos, "null")
elif val.vtype == JSON_BOOL:
if val.bool_val != 0:
pos = _write_str(buf, pos, "true")
else:
pos = _write_str(buf, pos, "false")
elif val.vtype == JSON_INT:
tmp: t.CChar | t.CPtr = pool.alloc(32)
if tmp != None:
snprintf(tmp, 32, "%lld", val.int_val)
pos = _write_str(buf, pos, tmp)
elif val.vtype == JSON_FLOAT:
tmp2: t.CChar | t.CPtr = pool.alloc(32)
if tmp2 != None:
snprintf(tmp2, 32, "%.6g", val.float_val)
pos = _write_str(buf, pos, tmp2)
elif val.vtype == JSON_STRING:
pos = _write_string_escaped(buf, pos, val.str_val)
elif val.vtype == JSON_ARRAY:
if val.child == None:
pos = _write_str(buf, pos, "[]")
return pos
pos = _write_char(buf, pos, '[')
cur: JsonValue | t.CPtr = val.child
first: bool = True
while cur != None:
if not first:
pos = _write_char(buf, pos, ',')
pos = _write_value(buf, pos, cur, pool)
first = False
cur = cur.next
pos = _write_char(buf, pos, ']')
elif val.vtype == JSON_OBJECT:
if val.child == None:
pos = _write_str(buf, pos, "{}")
return pos
pos = _write_char(buf, pos, '{')
cur2: JsonValue | t.CPtr = val.child
first2: bool = True
while cur2 != None:
if not first2:
pos = _write_char(buf, pos, ',')
pos = _write_string_escaped(buf, pos, cur2.key)
pos = _write_char(buf, pos, ':')
pos = _write_value(buf, pos, cur2, pool)
first2 = False
cur2 = cur2.next
pos = _write_char(buf, pos, '}')
return pos
def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr:
"""将 JsonValue 序列化为 JSON 字符串"""
buf: t.CChar | t.CPtr = pool.alloc(4096)
if buf == None:
return None
end_pos: t.CSizeT = _write_value(buf, 0, val, pool)
buf[end_pos] = '\0'
return buf
+450
View File
@@ -0,0 +1,450 @@
import t, c
from stdint import *
# ============================================================
# LinkedNode: 非多态继承基类(@t.NoVTable)
#
# 子类继承此类即"启用"标准链表/树形结构能力:
# - 双向兄弟链表(next/prev)→ O(1) 删除
# - 父子树结构(child/last_child/parent)→ O(1) 追加子节点
# - 子节点计数(child_count)
#
# 字段展平嵌入子类,无 vtable 开销(对应 C++ 非多态继承)。
# OOP 方法通过 _generate_inherited_method_wrappers 自动生成子类包装
# (self bitcast 为父类指针后调用),子类可直接调用继承的方法。
#
# 用法:
# class MyNode(LinkedNode):
# value: t.CInt
# root: MyNode = MyNode()
# child: MyNode = MyNode()
# root.append(child) # OOP 调用,self = root
# child.detach() # 从兄弟链摘除(分离自己)
# ============================================================
@t.NoVTable
class LinkedNode:
next: "LinkedNode" | t.CPtr # 下一个兄弟节点
prev: "LinkedNode" | t.CPtr # 上一个兄弟节点(双向链表,O(1) 删除)
child: "LinkedNode" | t.CPtr # 第一个子节点
last_child: "LinkedNode" | t.CPtr # 最后一个子节点(O(1) 追加)
parent: "LinkedNode" | t.CPtr # 父节点
child_count: t.CSizeT # 子节点数
def append(self, node: "LinkedNode" | t.CPtr):
"""将 node 追加为 self 的最后一个子节点(O(1))。
若 node 已在某链表中,调用方应先 node.detach() 再 append。
"""
if self is None or node is None: return
node.parent = self
node.next = None
node.prev = self.last_child
if self.child is None:
self.child = node
else:
self.last_child.next = node
self.last_child = node
self.child_count += 1
def prepend(self, node: "LinkedNode" | t.CPtr):
"""将 node 插入为 self 的第一个子节点(O(1))"""
if self is None or node is None: return
node.parent = self
node.prev = None
node.next = self.child
if self.child is not None:
self.child.prev = node
else:
self.last_child = node
self.child = node
self.child_count += 1
def insert_before(self, node: "LinkedNode" | t.CPtr,
new_node: "LinkedNode" | t.CPtr):
"""在 node 之前插入 new_node(node 必须是 self 的子节点,O(1))"""
if self is None or node is None or new_node is None: return
new_node.parent = self
new_node.prev = node.prev
new_node.next = node
if node.prev is not None:
node.prev.next = new_node
else:
self.child = new_node
node.prev = new_node
self.child_count += 1
def insert_after(self, node: "LinkedNode" | t.CPtr,
new_node: "LinkedNode" | t.CPtr):
"""在 node 之后插入 new_node(node 必须是 self 的子节点,O(1))"""
if self is None or node is None or new_node is None: return
new_node.parent = self
new_node.prev = node
new_node.next = node.next
if node.next is not None:
node.next.prev = new_node
else:
self.last_child = new_node
node.next = new_node
self.child_count += 1
def remove_child(self, node: "LinkedNode" | t.CPtr):
"""从 self 的子链表中摘除 node(O(1))。node 必须是 self 的直接子节点。"""
if self is None or node is None: return
# 修复 prev.next
if node.prev is not None:
node.prev.next = node.next
else:
self.child = node.next
# 修复 next.prev
if node.next is not None:
node.next.prev = node.prev
else:
self.last_child = node.prev
# 清除 node 的兄弟/父链接
node.next = None
node.prev = None
node.parent = None
if self.child_count > 0:
self.child_count -= 1
def detach(self):
"""将 self 从其所在兄弟链表中摘除(O(1))。
调用后 self 的 next/prev/parent 被清空,child 链不受影响。
"""
if self is None: return
# 修复 prev.next
if self.prev is not None:
self.prev.next = self.next
elif self.parent is not None:
self.parent.child = self.next
# 修复 next.prev
if self.next is not None:
self.next.prev = self.prev
elif self.parent is not None:
self.parent.last_child = self.prev
# 递减父节点计数
if self.parent is not None:
if self.parent.child_count > 0:
self.parent.child_count -= 1
# 清除 self 链接
self.next = None
self.prev = None
self.parent = None
def unlink(self):
"""断开 self 的所有连接(兄弟 + 父子),不递归处理子节点。
调用后 self 成为孤立节点,但其 child 链仍指向原子节点
(子节点的 parent 仍指向 self)。若需完全隔离,调用方应
先逐个 self.remove_child 子节点。
"""
if self is None: return
# 先从兄弟链摘除
self.detach()
# 再断开父子链接
self.child = None
self.last_child = None
self.child_count = 0
def has_children(self) -> t.CInt:
"""返回 1 若有子节点,否则 0"""
if self is None: return 0
if self.child is not None: return 1
return 0
def child_at(self, index: t.CSizeT) -> "LinkedNode" | t.CPtr:
"""返回第 index 个子节点(O(n),从 0 开始),越界返回 None"""
if self is None: return None
cur: "LinkedNode" | t.CPtr = self.child
i: t.CSizeT = 0
while cur is not None:
if i == index: return cur
i += 1
cur = cur.next
return None
def count_children(self) -> t.CSizeT:
"""遍历计算子节点数(O(n)),用于校验 child_count"""
if self is None: return 0
n: t.CSizeT = 0
cur: "LinkedNode" | t.CPtr = self.child
while cur is not None:
n += 1
cur = cur.next
return n
def first_sibling(self) -> "LinkedNode" | t.CPtr:
"""返回兄弟链表的头节点(沿 prev 回溯)"""
if self is None: return None
cur: "LinkedNode" | t.CPtr = self
while cur.prev is not None:
cur = cur.prev
return cur
def last_sibling(self) -> "LinkedNode" | t.CPtr:
"""返回兄弟链表的尾节点(沿 next 前进)"""
if self is None: return None
cur: "LinkedNode" | t.CPtr = self
while cur.next is not None:
cur = cur.next
return cur
# ============================================================
# SListNode: 单向链表节点(@t.NoVTable)
#
# 轻量级单向链表,仅 Next 指针,无 prev/parent/child。
# 适用于队列/栈/简单链场景(如 llvmlite 的 Param/BasicBlock/Function/Line/Value)。
# O(1) 追加需调用方维护 tail 指针(append_after);
# O(n) 追加仅需 head(append)。
# ============================================================
@t.NoVTable
class SListNode:
Next: "SListNode" | t.CPtr # 下一个节点
def append(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
"""将 node 追加到链表末尾(O(n)),返回 self(head)。
若 self 为 None,应直接使用 node 作为 head(调用方需自行处理)。
"""
if self is None: return node
if node is None: return self
node.Next = None
cur: "SListNode" | t.CPtr = self
while cur.Next is not None:
cur = cur.Next
cur.Next = node
return self
def append_after(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
"""将 node 追加到 self 之后(O(1)),返回新的 tail(即 node)。
调用方需自行维护 head 指针。若 self 为 None,返回 node 作为首节点。
"""
if node is None: return self
node.Next = None
if self is not None:
self.Next = node
return node
def count(self) -> t.CSizeT:
"""遍历计算链表长度(O(n))"""
if self is None: return 0
n: t.CSizeT = 0
cur: "SListNode" | t.CPtr = self
while cur is not None:
n += 1
cur = cur.Next
return n
def at(self, index: t.CSizeT) -> "SListNode" | t.CPtr:
"""返回第 index 个节点(O(n),从 0 开始),越界返回 None"""
if self is None: return None
cur: "SListNode" | t.CPtr = self
i: t.CSizeT = 0
while cur is not None:
if i == index: return cur
i += 1
cur = cur.Next
return None
def remove(self, node: "SListNode" | t.CPtr) -> "SListNode" | t.CPtr:
"""从链表中移除 node(O(n)),返回新的 head(self)。
node 的 Next 被清空。若 node 是 head,返回 head.Next。
"""
if self is None or node is None: return self
if self is node:
new_head: "SListNode" | t.CPtr = self.Next
self.Next = None
return new_head
cur: "SListNode" | t.CPtr = self
while cur.Next is not None:
if cur.Next is node:
cur.Next = node.Next
node.Next = None
break
cur = cur.Next
return self
# ============================================================
# GSListNode[T]: 泛型单向链表节点(@t.NoVTable + PEP 695 泛型)
#
# 相比 SListNode(非泛型,Next: SListNode|CPtr),GSListNode[T] 的 Next
# 字段类型为 T|CPtr,特化后直接是具体节点类型,无需向下转型。
#
# 递归泛型用法(子类继承自身特化版本):
# class GNode(GSListNode[GNode]):
# value: t.CInt
# # 此时 GNode.Next: GNode|CPtr(强类型,无转型)
#
# 技术验证点:
# 1. 递归泛型 class GNode(GSListNode[GNode])
# 2. @t.NoVTable + 泛型组合
# 3. 泛型类作字段类型 list: GSList[GNode]
# 4. 泛型方法继承(GSList[T].append 在特化后可用)
# ============================================================
@t.NoVTable
class GSListNode[T]:
Next: T | t.CPtr
# ============================================================
# GSList[T]: 泛型单向链表容器(@t.NoVTable + PEP 695 泛型)
#
# 持有 Head/Tail/Count,提供 O(1) append 和 O(n) at。
# 节点类型 T 必须继承 GSListNode[T](以获得 Next 字段)。
#
# 用法:
# list: GSList[GNode] | t.CPtr = GSList[GNode]()
# list.append(node) # 方法调用,非全局函数
# ============================================================
@t.NoVTable
class GSList[T]:
Head: T | t.CPtr
Tail: T | t.CPtr
Count: t.CSizeT
def __init__(self):
self.Head = None
self.Tail = None
self.Count = 0
def append(self, node: T):
"""将 node 追加到链表末尾(O(1))"""
if node is None: return
node.Next = None
if self.Head is None:
self.Head = node
else:
self.Tail.Next = node
self.Tail = node
self.Count += 1
def count(self) -> t.CSizeT:
"""返回节点数(O(1))"""
return self.Count
def at(self, index: t.CSizeT) -> T | t.CPtr:
"""返回第 index 个节点(O(n),从 0 开始),越界返回 None"""
if self.Head is None: return None
cur: T | t.CPtr = self.Head
i: t.CSizeT = 0
while cur is not None:
if i == index: return cur
i += 1
cur = cur.Next
return None
# ============================================================
# GTreeNode[T]: 泛型树节点(@t.NoVTable + PEP 695 泛型)
#
# 强类型版本的 LinkedNode,所有指针字段类型为 T|t.CPtr。
# 提供:
# - 双向兄弟链表(Next/Prev)→ O(1) 删除
# - 父子树结构(Child/LastChild/Parent)→ O(1) 追加子节点
# - 子节点计数(Count)
#
# 递归泛型用法(子类继承自身特化版本):
# @t.CVTable
# class AST(GTreeNode[AST]):
# def kind(self) -> t.CInt:
# return 0
# # 此时 AST.Next/Prev/Child/LastChild/Parent 均为 AST|t.CPtr(强类型)
#
# 字段展平嵌入子类,无 vtable 开销(对应 C++ 非多态继承)。
# 子类若为 @t.CVTable,则获得自己的 vtable(offset 0),
# GTreeNode 字段展平在 vtable 之后。
#
# OOP 方法通过 _generate_inherited_method_wrappers 自动生成子类包装
# (self bitcast 为父类指针后调用),子类可直接调用继承的方法。
# ============================================================
@t.NoVTable
class GTreeNode[T]:
Next: T | t.CPtr # 下一个兄弟节点
Prev: T | t.CPtr # 上一个兄弟节点(双向链表,O(1) 删除)
Child: T | t.CPtr # 第一个子节点
LastChild: T | t.CPtr # 最后一个子节点(O(1) 追加)
Parent: T | t.CPtr # 父节点
Count: t.CSizeT # 子节点数
def append(self, node: T | t.CPtr):
"""将 node 追加为 self 的最后一个子节点(O(1))。
若 node 已在某链表中,调用方应先 node.detach() 再 append。
"""
if self is None or node is None: return
node.Parent = self
node.Next = None
node.Prev = self.LastChild
if self.Child is None:
self.Child = node
else:
self.LastChild.Next = node
self.LastChild = node
self.Count += 1
def prepend(self, node: T | t.CPtr):
"""将 node 插入为 self 的第一个子节点(O(1))"""
if self is None or node is None: return
node.Parent = self
node.Prev = None
node.Next = self.Child
if self.Child is not None:
self.Child.Prev = node
else:
self.LastChild = node
self.Child = node
self.Count += 1
def detach(self):
"""将 self 从其所在兄弟链表中摘除(O(1))。
调用后 self 的 Next/Prev/Parent 被清空,Child 链不受影响。
"""
if self is None: return
if self.Prev is not None:
self.Prev.Next = self.Next
elif self.Parent is not None:
self.Parent.Child = self.Next
if self.Next is not None:
self.Next.Prev = self.Prev
elif self.Parent is not None:
self.Parent.LastChild = self.Prev
if self.Parent is not None:
if self.Parent.Count > 0:
self.Parent.Count -= 1
self.Next = None
self.Prev = None
self.Parent = None
def has_children(self) -> t.CInt:
"""返回 1 若有子节点,否则 0"""
if self is None: return 0
if self.Child is not None: return 1
return 0
def child_at(self, index: t.CSizeT) -> T | t.CPtr:
"""返回第 index 个子节点(O(n),从 0 开始),越界返回 None"""
if self is None: return None
cur: T | t.CPtr = self.Child
i: t.CSizeT = 0
while cur is not None:
if i == index: return cur
i += 1
cur = cur.Next
return None
def count_children(self) -> t.CSizeT:
"""遍历计算子节点数(O(n)),用于校验 Count"""
if self is None: return 0
n: t.CSizeT = 0
cur: T | t.CPtr = self.Child
while cur is not None:
n += 1
cur = cur.Next
return n
+301
View File
@@ -0,0 +1,301 @@
# llvmlite 设计方案
用 TransPyC 自身实现的轻量级 LLVM IR 文本生成库,替代 Python `llvmlite` 依赖,为自举(见 `wiki/13-bootstrapping.md` 路径 B)铺路。
## 1. 目标与定位
- **输入**:类型/值/指令的语义对象
- **输出**:合法的 LLVM IR 文本(`.ll`),可直接喂给 `llc`
- **不做什么**:不解析 IR、不做优化、不绑定 LLVM C API(纯文本生成)
- **自举约束**:本库必须能用当前 TransPyC 编译器完整编译,不得依赖任何 Python 运行时
## 2. 核心设计决策
### 2.1 类型系统用 `t.REnum`(tagged union)
LLVM 类型变体少、无通用字段、字段都是指针/小整数、操作主要通过 `match` 分派 —— 完全契合 REnum 的 tag+union 模型。
### 2.2 指令 opcode 用 `t.CEnum`
指令类别(Binary/Unary/Cast/Memory/Terminator/Compare)与具体 opcode(Add/Sub/Load/Store/Br/Ret/...)用 `t.CEnum` 组织,类型安全且零开销。
### 2.3 IR 文本生成用 `viperlib.snprintf`
所有 IR 文本通过 `viperlib.snprintf(buf, size, fmt, *args)` 格式化写入缓冲区,避免手写逐字符拼接。`snprintf` 已支持宽度/精度/符号/`%s`/`%d`/`%x` 等,足够覆盖 IR 语法。
### 2.4 对象分配用普通类 + `mpool`
像 `mbuddy` 一样用普通类(无 `__new__`),由调用方注入 `mpool.MPool` 做批量分配。库内部不持有全局 `mbuddy`,遵循项目约定(`_mbuddy` 指针由 `os.py` 或调用方设置)。
---
## 3. 为什么 AST 不用 REnum,而 llvmlite 用?
用户质疑:REnum 是 tag+union(Rust enum),配合 `match` 模式匹配,按理很适合 AST。下面解释两者的适配性差异。
### 3.1 REnum 的硬限制(来自 `HandlesClassDef._EmitREnumLlvm`)
1. **无通用字段共享**:每个 variant 独立声明字段,通用字段(如 `lineno`/`child`/`next`)必须在每 variant 重复声明。
2. **共享最大变体尺寸**:布局为 `{ i32 __tag, <max_variant_payload> }`,小变体浪费内存。
3. **payload 仅位置绑定**:`match` 通过位置绑定 payload,不能直接 `node.child` 属性访问 payload 字段。
4. **无方法**:variant 不能挂方法。
### 3.2 AST 不适合 REnum 的四个原因
| 维度 | AST 需求 | REnum 限制 | 冲突 |
|------|----------|------------|------|
| 变体数量 | 70+ 节点类型 | 共享最大变体尺寸 | 内存膨胀(每节点都占最大变体空间) |
| 通用字段 | lineno/child/next/parent 等 ~8 个字段全节点共享 | 无通用字段共享 | 要么每 variant 重复声明(冗长),要么放弃统一访问 |
| 访问模式 | 频繁直接 `node.child`/`node.next`/`node.lineno` | payload 仅位置绑定,需 match 分派 | 遍历代码爆炸(每次访问都要 match) |
| 字段复用 | `int_val`/`str_val`/`op` 等字段按 vtype 复用语义 | 每 variant 独立 payload | 无法复用 |
AST 采用"胖节点"设计(所有节点共用一个 `AST` struct,用 `vtype` 区分):一次 `malloc`、统一链表遍历(`child`/`next`)、字段复用。这与 REnum"每变体独立 payload"的哲学根本冲突。
### 3.3 llvmlite 的 LLVMType 适合 REnum 的原因
| 维度 | LLVMType 需求 | REnum 特性 | 契合度 |
|------|---------------|------------|--------|
| 变体数量 | ~10 个(Int/Ptr/Func/Array/Struct/Void/Float/Label/...) | 共享最大变体尺寸 | 浪费可接受(最大变体 ~24 字节) |
| 通用字段 | 无(每变体字段不同) | 无通用字段共享 | 完美匹配 |
| 访问模式 | 类型操作天然通过 match 分派("是 Int 取 bits,是 Ptr 取 pointee") | payload 位置绑定 + match | 天然契合 |
| 字段尺寸 | 都是指针(8B)或小整数(4B) | 共享最大变体 | 浪费小 |
**结论**:REnum 是"少变体、无共性、match 分派"场景的最佳工具 —— llvmlite 类型系统正好如此,AST 正好相反。
---
## 4. 文件结构
```
includes/llvmlite/
├── __init__.py # 公共导出 + 便捷工厂函数
├── __types.py # LLVMType (REnum) + 类型构造/打印
├── __values.py # Value/Constant/SSA 值表示
├── __module.py # Module 容器(函数列表 + 目标三元组 + 输出 .ll)
├── __function.py # Function + BasicBlock + 参数管理
├── __builder.py # IRBuilder(指令发射 + SSA 命名 + 块跳转)
└── README.md # 本文件
```
### 职责划分
- `__types.py`:`LLVMType` REnum 定义 + `TypePrint(buf, ty)` 将类型序列化为 IR 文本(如 `i32`/`i32*`/`{i32, i8*}`)
- `__values.py`:`Value` 表示一个 SSA 值(`%0`/`%result`/常量),含类型指针 + 名字 + 是否常量
- `__module.py`:`Module` 持有函数链表 + 目标三元组 + 数据布局,`ModulePrint` 输出完整 `.ll`
- `__function.py`:`Function` 持有基本块链表 + 参数 + 返回类型;`BasicBlock` 持有指令文本缓冲
- `__builder.py`:`IRBuilder` 游标式 API,`build_add`/`build_load`/`build_br`/... 发射指令到当前块
---
## 5. 类型系统设计(REnum)
```python
import t
from stdint import *
class LLVMType(t.REnum):
# 变体 Int:整数类型
IntBits: t.CInt # 位宽 1/8/16/32/64/128
# 变体 Ptr:指针类型
PtrPointee: LLVMType | t.CPtr # 指向的类型(自引用用指针)
# 变体 Func:函数类型
FuncRet: LLVMType | t.CPtr # 返回类型
FuncParams: LLVMType | t.CPtr # 参数类型链表头
FuncPCount: t.CInt # 参数数量
# 变体 Array:数组类型
ArrayElem: LLVMType | t.CPtr # 元素类型
ArrayCount: t.CInt # 元素数量
# 变体 Struct:结构体类型
StructHead: LLVMType | t.CPtr # 字段类型链表头
StructCount: t.CInt # 字段数量
# 变体 Float:浮点类型
FloatBits: t.CInt # 16/32/64/128
# 变体 Void / Label / Metadata:无 payload
# (REnum 允许空变体,仅靠 __tag 区分)
```
### 类型工厂(`__init__.py` 导出)
```python
def Int1() -> LLVMType | t.CPtr: ... # i1
def Int8() -> LLVMType | t.CPtr: ... # i8
def Int32() -> LLVMType | t.CPtr: ... # i32
def Int64() -> LLVMType | t.CPtr: ... # i64
def Ptr(pointee: LLVMType | t.CPtr) -> LLVMType | t.CPtr: ...
def Func(ret: LLVMType | t.CPtr, params: LLVMType | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr: ...
def Void() -> LLVMType | t.CPtr: ...
```
### 类型打印(match 分派)
```python
def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT, ty: LLVMType | t.CPtr):
match ty:
case LLVMType.Int: # 位置绑定 IntBits
viperlib.snprintf(buf, size, "i%d", ty.IntBits)
case LLVMType.Ptr: # 位置绑定 PtrPointee
TypePrint(inner, size2, ty.PtrPointee)
# 拼接 "*"
case LLVMType.Func:
# 打印 ret (params)
case LLVMType.Void:
string.strcpy(buf, "void")
...
```
---
## 6. Value / SSA 设计
```python
class Value:
Ty: LLVMType | t.CPtr # 值的类型
Name: t.CChar | t.CPtr # SSA 名("%0"/"%result")或常量文本
IsConst: t.CInt # 1=常量字面量,0=SSA 临时值
Next: Value | t.CPtr # 链表(函数内的值池)
```
`IRBuilder` 维护一个递增的 `%N` 计数器,每发射一条产生结果的指令就分配一个新名。
---
## 7. IRBuilder 设计
游标式 API,跟踪当前 `BasicBlock`,发射指令文本到块的缓冲区。
```python
class IRBuilder:
Func: Function | t.CPtr # 所属函数
CurBlock: BasicBlock | t.CPtr # 当前插入点
Counter: t.CInt # SSA 名计数器
def build_add(self, lhs: Value | t.CPtr, rhs: Value | t.CPtr) -> Value | t.CPtr:
# 1. 分配 SSA 名 %N
# 2. snprintf(buf, size, " %%%d = add %s %s, %s\n", N, ty, lhs, rhs)
# 3. 追加到 CurBlock 缓冲
# 4. 返回新 Value
def build_load(self, ty: LLVMType | t.CPtr, ptr: Value | t.CPtr) -> Value | t.CPtr: ...
def build_store(self, val: Value | t.CPtr, ptr: Value | t.CPtr): ...
def build_br(self, target: BasicBlock | t.CPtr): ...
def build_cond_br(self, cond: Value | t.CPtr, then: BasicBlock | t.CPtr, else_: BasicBlock | t.CPtr): ...
def build_ret(self, val: Value | t.CPtr): ...
def build_alloca(self, ty: LLVMType | t.CPtr) -> Value | t.CPtr: ...
def build_gep(self, ptr: Value | t.CPtr, idx: Value | t.CPtr) -> Value | t.CPtr: ...
def build_call(self, callee: t.CChar | t.CPtr, args: Value | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Value | t.CPtr: ...
```
### 指令 opcode(CEnum)
```python
class IROp(t.CEnum):
# Terminator
Ret: t.CEnum = 1
Br: t.CEnum = 2
CondBr: t.CEnum = 3
Switch: t.CEnum = 4
# Binary
Add: t.CEnum = 10
Sub: t.CEnum = 11
Mul: t.CEnum = 12
SDiv: t.CEnum = 13
# Memory
Load: t.CEnum = 20
Store: t.CEnum = 21
Alloca: t.CEnum = 22
Gep: t.CEnum = 23
# Cast
BitCast: t.CEnum = 30
SExt: t.CEnum = 31
Trunc: t.CEnum = 32
# Compare
ICmp: t.CEnum = 40
# Call
Call: t.CEnum = 50
```
---
## 8. IR 文本生成(snprintf 用法)
每条指令发射用 `viperlib.snprintf` 格式化到块缓冲区。示例:
```python
import viperlib
def _emit_add(block: BasicBlock | t.CPtr, name: t.CChar | t.CPtr,
ty_str: t.CChar | t.CPtr, lhs: t.CChar | t.CPtr, rhs: t.CChar | t.CPtr):
line: t.CChar | t.CPtr = mpool.alloc(128) # 行缓冲
viperlib.snprintf(line, 128, " %s = add %s %s, %s\n", name, ty_str, lhs, rhs)
_block_append(block, line)
```
### Module 输出
```python
def ModulePrint(mod: Module | t.CPtr, out_path: t.CChar | t.CPtr):
# 1. 写头部:target triple / datalayout
# 2. 遍历函数,写 declare/define
# 3. 每函数:签名 + 基本块 + 指令
# 用 snprintf 拼接,写到文件(viperio 或 w32/win32file)
```
---
## 9. 内存管理
- 库内所有对象从 `mpool.MPool` 分配(像 `ast` 库一样)
- `IRBuilder`/`Module`/`Function` 不持有 `mbuddy`,由调用方传入 `mpool`
- 文本缓冲区按行分配(每指令一行,128 字节起步),避免频繁 realloc
---
## 10. 基础构建范围(第一阶段)
最小可用集,能生成一个完整的小程序 IR:
1. **类型**:`IntType`(1/8/16/32/64) + `PointerType` + `FunctionType` + `VoidType` + `StructType`
2. **值**:`Value` + 常量整数字面量
3. **Module/Function/BasicBlock**:容器与链表
4. **IRBuilder** 指令子集:
- `alloca` / `load` / `store`
- `add` / `sub` / `mul` / `sdiv`
- `icmp` (eq/ne/sgt/sge/slt/sle)
- `br` / `cond_br` / `ret`
- `call`(外部函数)
- `bitcast` / `sext` / `trunc`
- `getelementptr`
5. **ModulePrint**:输出完整 `.ll` 文件
### 后续扩展路线
- **第二阶段**:浮点指令、`phi` 节点、`switch`、字符串常量全局、属性(`nounwind`/`nocapture`)
- **第三阶段**:内联汇编、`atomic` 指令、`va_arg`、精确的 SSA 验证(支配边界、phi 完整性)
- **第四阶段**:对接 TransPyC 的 `LLVMCG`,替换 Python `llvmlite`,完成路径 B 自举
---
## 11. 测试计划
独立测试项目(`Test/LLvmLiteTest/`):
1. **类型打印测试**:构造各 `LLVMType`,`TypePrint` 输出,对比预期字符串
2. **小函数生成**:用 `IRBuilder` 生成 `i32 add(i32 a, i32 b) { ret i32 %r }`,`ModulePrint` 写 `.ll`,用 `llc` 编译验证语法合法
3. **match 分派测试**:构造各变体 `LLVMType`,`match` 正确绑定 payload
4. **snprintf 格式测试**:验证 `%d`/`%s`/`%x` 在 IR 文本中的正确性
---
## 12. 与现有架构的对接点
- **`lib/core/Codegen/LLVMCG.py`**:当前用 Python `llvmlite` 生成 IR,自举时改用本库
- **`includes/viperlib.py`**:提供 `snprintf` / `sprintf`
- **`includes/mpool.py`**:提供 `MPool` 内存池
- **`includes/string.py`**:提供 `strcpy`/`strlen`/`memcpy`
- **`includes/ast/`**:参考其"胖节点 + mpool + CEnum 常量"的组织方式(但类型系统用 REnum 而非胖节点)
File diff suppressed because it is too large. Load diff
+456
View File
@@ -0,0 +1,456 @@
import t, c
from stdint import *
import string
import viperlib
import memhub
import stdio
from linkedlist import GSListNode, GSList
from .__types import LLVMType, ParamNode, TypePrint
# ============================================================
# Line: 指令文本行
#
# 每条 LLVM IR 指令序列化为一行文本,通过链表组织。
# 继承 GSListNode[Line] 获取强类型 Next: Line|CPtr
# ============================================================
class Line(GSListNode[Line]):
Buf: t.CChar | t.CPtr # 行文本(NUL 结尾)
Len: t.CSizeT # 文本长度(不含 NUL)
# ============================================================
# BasicBlock: 基本块
#
# 持有名称 + 指令行链表 + 终止指令标志。
# 继承 GSListNode[BasicBlock] 获取强类型 Next: BasicBlock|CPtr
# Lines 为 GSList[Line] 指针,提供 O(1) 追加。
# ============================================================
class BasicBlock(GSListNode[BasicBlock]):
Name: t.CChar | t.CPtr # 块名(如 "entry"/"if.then")
Lines: GSList[Line] | t.CPtr # 指令行链表容器(Head/Tail/Count)
IsTerminated: t.CInt # 1=已有终止指令(br/ret)
# ============================================================
# Param: 函数参数
#
# 继承 GSListNode[Param] 获取强类型 Next: Param|CPtr
# Attrs 存储参数属性文本(如 "noundef"/"nocapture"/"readonly"),None=无属性
# ============================================================
class Param(GSListNode[Param]):
Ty: LLVMType | t.CPtr # 参数类型
Name: t.CChar | t.CPtr # 参数名(如 "%0"/"%a")
Attrs: t.CChar | t.CPtr # 参数属性文本(None=无属性)
# ============================================================
# Function: 函数
#
# 持有名称 + 返回类型 + 参数链表 + 基本块链表。
# 继承 GSListNode[Function] 获取强类型 Next: Function|CPtr
# Params/Blocks 为 GSList 指针,提供 O(1) 追加。
# Attrs 存储函数级属性文本(如 "nounwind"/"noinline"),None=无属性
# ============================================================
class Function(GSListNode[Function]):
Name: t.CChar | t.CPtr # 函数名
RetTy: LLVMType | t.CPtr # 返回类型
Params: GSList[Param] | t.CPtr # 参数链表容器
Blocks: GSList[BasicBlock] | t.CPtr # 基本块链表容器
IsDeclared: t.CInt # 1=仅声明(declare), 0=定义(define)
IsVarArg: t.CInt # 1=变参函数(...)
Attrs: t.CChar | t.CPtr # 函数属性文本(None=无属性)
# ============================================================
# 工厂函数
# ============================================================
# Line 硬编码大小: Next(8) + Buf(8) + Len(8) = 24 字节
LINE_SIZE: t.CDefine = 24
def new_line(pool: memhub.MemBuddy | t.CPtr, text: t.CChar | t.CPtr) -> Line | t.CPtr:
"""创建一个指令行,复制 text 到新分配的缓冲区"""
ptr: Line | t.CPtr = pool.alloc(LINE_SIZE)
if ptr is None: return None
string.memset(ptr, 0, LINE_SIZE)
if text is not None:
slen: t.CSizeT = string.strlen(text)
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
if buf is not None:
string.strcpy(buf, text)
ptr.Buf = buf
ptr.Len = slen
return ptr
def _new_gslist(pool: memhub.MemBuddy | t.CPtr, list_size: t.CSizeT) -> t.CPtr:
"""从 pool 分配并零初始化一个 GSList 容器(Head/Tail/Count 全零)"""
gsl: t.CPtr = pool.alloc(list_size)
if gsl is None: return None
string.memset(gsl, 0, list_size)
return gsl
# BasicBlock 硬编码大小: Next(8) + Name(8) + Lines(8) + IsTerminated(4) = 32 字节
BLOCK_SIZE: t.CDefine = 32
def new_basic_block(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
"""创建一个基本块"""
ptr: BasicBlock | t.CPtr = pool.alloc(BLOCK_SIZE)
if ptr is None: return None
string.memset(ptr, 0, BLOCK_SIZE)
ptr.Name = name
ptr.Lines = _new_gslist(pool, 24) # GSList: Head+Tail+Count
ptr.IsTerminated = 0
return ptr
# Param 硬编码大小: Next(8) + Ty(8) + Name(8) + Attrs(8) = 32 字节
PARAM_SIZE: t.CDefine = 32
def new_param(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Param | t.CPtr:
"""创建一个函数参数"""
ptr: Param | t.CPtr = pool.alloc(PARAM_SIZE)
if ptr is None: return None
string.memset(ptr, 0, PARAM_SIZE)
ptr.Ty = ty
ptr.Name = name
ptr.Attrs = None
return ptr
# Function 硬编码大小: Next(8) + Name(8) + RetTy(8) + Params(8) + Blocks(8) + IsDeclared(4) + IsVarArg(4) + Attrs(8) = 56 字节
FUNC_SIZE: t.CDefine = 56
def new_function(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
"""创建一个函数"""
ptr: Function | t.CPtr = pool.alloc(FUNC_SIZE)
if ptr is None: return None
string.memset(ptr, 0, FUNC_SIZE)
ptr.Name = name
ptr.RetTy = ret_ty
ptr.Params = _new_gslist(pool, 24) # GSList: Head+Tail+Count
ptr.Blocks = _new_gslist(pool, 24)
ptr.IsDeclared = 0
ptr.Attrs = None
return ptr
# ============================================================
# 链表操作(委托 GSList.append)
# ============================================================
def function_add_param(func: Function | t.CPtr, param: Param | t.CPtr):
"""将参数追加到函数参数链表"""
if func is None or param is None: return
if func.Params is None: return
func.Params.append(param)
def function_add_block(func: Function | t.CPtr, block: BasicBlock | t.CPtr):
"""将基本块追加到函数块链表"""
if func is None or block is None: return
if func.Blocks is None: return
func.Blocks.append(block)
def function_move_block_to_end(func: Function | t.CPtr, block: BasicBlock | t.CPtr):
"""将 block 移动到函数块链表末尾(保证 BB 文本顺序与控制流顺序一致)。
用于解决 SSA 名非单调问题:BB 按创建顺序排列,但指令按控制流顺序生成,
导致 SSA 编号在文本输出时非单调递增,llc 报错。
在 position_at_end 时调用此函数,使 BB 顺序与 position 顺序一致。
"""
if func is None or block is None: return
blocks: GSList | t.CPtr = func.Blocks
if blocks is None: return
# 已经是 Tail,无需移动
if blocks.Tail is block:
return
# 从链表中移除 block
if blocks.Head is block:
# block 是 Head,直接后移 Head
blocks.Head = block.Next
else:
# 遍历找前驱
prev: BasicBlock | t.CPtr = blocks.Head
while prev is not None and prev.Next is not block:
prev = prev.Next
if prev is None:
# block 不在链表中,直接 append
blocks.append(block)
return
prev.Next = block.Next
# block.Next 由移除逻辑处理,重置为 None
block.Next = None
# append 到末尾(不调用 blocks.append 以避免 Count 重复递增)
if blocks.Tail is not None:
blocks.Tail.Next = block
blocks.Tail = block
def block_append_line(block: BasicBlock | t.CPtr, line: Line | t.CPtr):
"""将指令行追加到基本块"""
if block is None or line is None: return
if block.Lines is None: return
block.Lines.append(line)
def block_append_text(pool: memhub.MemBuddy | t.CPtr, block: BasicBlock | t.CPtr,
text: t.CChar | t.CPtr):
"""创建指令行并追加到基本块"""
if block is None or text is None: return
line: Line | t.CPtr = new_line(pool, text)
if line is not None:
block_append_line(block, line)
# ============================================================
# 属性设置
# ============================================================
def function_set_attrs(func: Function | t.CPtr, attrs: t.CChar | t.CPtr):
"""设置函数级属性文本(如 "nounwind"/"noinline")"""
if func is None: return
func.Attrs = attrs
def param_set_attrs(param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
"""设置参数属性文本(如 "noundef"/"nocapture"/"readonly")"""
if param is None: return
param.Attrs = attrs
# ============================================================
# _ll_name_needs_quote - 检查 LLVM 标识符是否需要加引号
#
# LLVM IR 规范:标识符以数字开头或含特殊字符(如 '.')时必须
# 用双引号包围。SHA1 命名空间的函数名格式为 "sha1hex.funcname"
# (含 '.'),以 hex 字符开头(可能以数字开头),因此需要加引号。
# 普通函数名(如 printf/malloc/main)不含特殊字符,不加引号。
# ============================================================
def _ll_name_needs_quote(name: str) -> t.CInt:
"""检查 LLVM 标识符是否需要加引号(以数字开头或含 '.')
例外: LLVM 内联函数名(如 llvm.memcpy/llvm.memset)以 'llvm.' 开头,
虽含 '.',但不能加引号——加引号后 LLVM 解析器不识别为内联函数,
导致 declare/call 签名不匹配(Intrinsic called with incompatible signature)。
"""
if name is None:
return 0
c0: t.CChar = name[0]
if c0 >= '0' and c0 <= '9':
return 1
name_len: t.CSizeT = string.strlen(name)
# 豁免 llvm.* 前缀的内联函数名
if name_len >= 5:
if name[0] == 'l' and name[1] == 'l' and name[2] == 'v' and name[3] == 'm' and name[4] == '.':
return 0
i: t.CSizeT = 0
while i < name_len:
if name[i] == '.':
return 1
i += 1
return 0
# ============================================================
# FunctionPrint: 将函数序列化为 IR 文本
#
# 格式:
# define <ret_ty> @<name>(<params>) {
# <block_name>:
# <instruction>
# <instruction>
# <block_name>:
# <instruction>
# }
# ============================================================
def FunctionPrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
func: Function | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""将函数 func 序列化为 IR 文本写入 buf"""
if func is None or buf is None or size == 0: return
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
if ty_buf is None: return
ty_buf[0] = '\0'
# define <ret_ty> @<name>(<params>)
if func.IsDeclared == 1:
_append_cstr(buf, size, "declare ")
else:
_append_cstr(buf, size, "define ")
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, func.RetTy, pool)
_append_cstr(buf, size, ty_buf)
_append_cstr(buf, size, " @")
if func.Name is not None:
if _ll_name_needs_quote(func.Name) != 0:
_append_cstr(buf, size, "\"")
_append_cstr(buf, size, func.Name)
_append_cstr(buf, size, "\"")
else:
_append_cstr(buf, size, func.Name)
_append_cstr(buf, size, "(")
# 参数列表(从 GSList[Param].Head 遍历)
cur: Param | t.CPtr = None
if func.Params is not None:
cur = func.Params.Head
first: t.CInt = 1
while cur is not None:
if first == 0:
_append_cstr(buf, size, ", ")
# 参数属性(如 "noundef"/"nocapture")在类型之前
if cur.Attrs is not None:
_append_cstr(buf, size, cur.Attrs)
_append_cstr(buf, size, " ")
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, cur.Ty, pool)
_append_cstr(buf, size, ty_buf)
# declare 声明不打印参数名
if func.IsDeclared == 0 and cur.Name is not None:
_append_cstr(buf, size, " ")
# LLVM IR 要求参数名以 % 开头
if cur.Name[0] != '%':
_append_cstr(buf, size, "%")
_append_cstr(buf, size, cur.Name)
cur = cur.Next
first = 0
# 变参函数追加 ...
if func.IsVarArg == 1:
if func.Params is not None and func.Params.Head is not None:
_append_cstr(buf, size, ", ...")
else:
_append_cstr(buf, size, "...")
_append_cstr(buf, size, ")")
# 函数级属性(如 "nounwind"/"noinline")在 ) 之后
if func.Attrs is not None:
_append_cstr(buf, size, " ")
_append_cstr(buf, size, func.Attrs)
if func.IsDeclared == 1:
_append_cstr(buf, size, "\n")
return
# 函数体
_append_cstr(buf, size, " {\n")
blk: BasicBlock | t.CPtr = None
if func.Blocks is not None:
blk = func.Blocks.Head
while blk is not None:
# 块标签
if blk.Name is not None:
_append_cstr(buf, size, blk.Name)
_append_cstr(buf, size, ":\n")
# 指令行(从 GSList[Line].Head 遍历)
line: Line | t.CPtr = None
if blk.Lines is not None:
line = blk.Lines.Head
while line is not None:
if line.Buf is not None:
_append_cstr(buf, size, " ")
_append_cstr(buf, size, line.Buf)
_append_cstr(buf, size, "\n")
line = line.Next
blk = blk.Next
_append_cstr(buf, size, "}\n")
# ============================================================
# 内部辅助
# ============================================================
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
"""将 C 字符串 src 追加到 dst 末尾"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
slen: t.CSizeT = string.strlen(src)
remain: t.CSizeT = dst_size - dlen
if remain <= 0: return
i: t.CSizeT = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
dst[dlen + i] = '\0'
# ============================================================
# 字段访问器(供其他模块绕过 stub 类型限制使用)
#
# 跨模块编译时,使用方模块只有 Function/Param 的 stub 类型
# (字段不足且字段类型可能错误),导致 TransPyC 静默跳过
# 字段访问(不生成 GEP,不报错),字段值永远为 null。
#
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问
# 所有字段。其他模块通过函数调用获取字段值,绕过 stub 限制。
# ============================================================
def function_get_name(func: Function | t.CPtr) -> t.CChar | t.CPtr:
"""获取函数名"""
if func is None:
return None
return func.Name
def function_get_ret_ty(func: Function | t.CPtr) -> LLVMType | t.CPtr:
"""获取函数返回类型"""
if func is None:
return None
return func.RetTy
def function_get_params(func: Function | t.CPtr) -> GSList[Param] | t.CPtr:
"""获取函数参数链表容器"""
if func is None:
return None
return func.Params
def function_get_param_head(func: Function | t.CPtr) -> Param | t.CPtr:
"""获取函数参数链表头节点(一步到位,避免调用方访问 GSList.Head)"""
if func is None:
return None
if func.Params is None:
return None
return func.Params.Head
def function_get_next(func: Function | t.CPtr) -> Function | t.CPtr:
"""获取链表下一个函数"""
if func is None:
return None
return func.Next
def function_is_declared(func: Function | t.CPtr) -> t.CInt:
"""获取函数是否为声明(1=declare 仅声明, 0=define 定义)"""
if func is None:
return 0
return func.IsDeclared
def param_get_name(param: Param | t.CPtr) -> t.CChar | t.CPtr:
"""获取参数名"""
if param is None:
return None
return param.Name
def param_get_ty(param: Param | t.CPtr) -> LLVMType | t.CPtr:
"""获取参数类型"""
if param is None:
return None
return param.Ty
def param_get_next(param: Param | t.CPtr) -> Param | t.CPtr:
"""获取链表下一个参数"""
if param is None:
return None
return param.Next
+403
View File
@@ -0,0 +1,403 @@
import t, c
from stdint import *
import memhub
import string
import viperlib
# 导入子模块
from .__types import (
LLVMType, ParamNode, LLVMTypeCore,
Int1, Int8, Int16, Int32, Int64, Ptr, Func, Void, Array, Struct,
Half, Float, Double, FP128, Label,
new_param_node, param_list_append,
paramnode_get_ty, paramnode_get_next, paramnode_set_ty, paramnode_set_next,
TypePrint, PrintStructDefinition, get_struct_name,
)
from .__values import (
Value, new_value, ConstInt, ConstNull, ConstZero, ConstFloat, SSAValue, ValuePrint,
value_get_ty, value_get_next,
value_set_ty, value_set_next, value_set_name, value_set_isconst,
)
from .__function import (
Line, BasicBlock, Param, Function,
new_line, new_basic_block, new_param, new_function,
function_add_param, function_add_block,
block_append_line, block_append_text,
function_set_attrs, param_set_attrs,
function_get_name, function_get_ret_ty, function_get_params,
function_get_param_head, function_get_next, function_is_declared,
param_get_name, param_get_ty, param_get_next,
FunctionPrint,
)
from .__module import (
LLVMModule, GlobalVariable, NamedTypeNode, new_module, new_global_variable,
module_add_function, module_add_global, module_add_named_type,
module_set_target, module_set_datalayout,
global_set_constant, global_set_linkage, global_set_unnamed_addr, global_set_section,
LLVMModulePrint, OUTPUT_FULL, OUTPUT_STUB, OUTPUT_TEXT,
module_ensure_opaque_for_type,
)
from .__builder import (
IRBuilder, new_builder, position_at_end,
build_alloca, build_load, build_store,
build_add, build_sub, build_mul, build_sdiv, build_udiv, build_srem, build_urem,
build_and, build_or, build_xor, build_shl, build_lshr, build_ashr,
build_fadd, build_fsub, build_fmul, build_fdiv, build_frem, build_fneg,
build_icmp, build_fcmp,
build_br, build_cond_br, build_ret, build_ret_void,
build_call, build_call_indirect, build_bitcast, build_sext, build_trunc, build_zext,
build_ptrtoint, build_inttoptr,
build_fpext, build_fptrunc, build_fp2si, build_si2fp, build_fp2ui, build_ui2fp,
build_gep, build_gep_array, build_gep_struct,
build_phi, build_switch, build_select, build_unreachable,
build_atomicrmw, build_cmpxchg, build_inline_asm,
PhiIncoming, new_phi_incoming, SwitchCase, new_switch_case,
ICMP_EQ, ICMP_NE, ICMP_SGT, ICMP_SGE, ICMP_SLT, ICMP_SLE,
ICMP_UGT, ICMP_UGE, ICMP_ULT, ICMP_ULE,
FCMP_FALSE, FCMP_OEQ, FCMP_OGT, FCMP_OGE, FCMP_OLT, FCMP_OLE,
FCMP_ONE, FCMP_ORD, FCMP_UNO, FCMP_UEQ, FCMP_UGT, FCMP_UGE,
FCMP_ULT, FCMP_ULE, FCMP_UNE, FCMP_TRUE,
ATOMIC_XCHG, ATOMIC_ADD, ATOMIC_SUB, ATOMIC_AND, ATOMIC_NAND,
ATOMIC_OR, ATOMIC_XOR, ATOMIC_MAX, ATOMIC_MIN, ATOMIC_UMAX, ATOMIC_UMIN,
ATOMIC_ORDER_NOTATOMIC, ATOMIC_ORDER_UNORDERED, ATOMIC_ORDER_MONOTONIC,
ATOMIC_ORDER_ACQUIRE, ATOMIC_ORDER_RELEASE, ATOMIC_ORDER_ACQ_REL,
ATOMIC_ORDER_SEQ_CST,
)
from .__verify import (
VerifyResult, NameEntry,
verify_function, verify_module,
VERIFY_OK, VERIFY_ERR_NO_TERMINATOR, VERIFY_ERR_DUPLICATE_DEF,
VERIFY_ERR_UNDEFINED_USE, VERIFY_ERR_PHI_NOT_FIRST,
_new_verify_result,
)
# ============================================================
# 便捷工厂: 字符串复制
# ============================================================
def _str_dup(pool: memhub.MemBuddy | t.CPtr, src: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
"""从 pool 分配并复制一个 C 字符串"""
if src is None: return None
slen: t.CSizeT = string.strlen(src)
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
if buf is None: return None
string.strcpy(buf, src)
return buf
# ============================================================
# 便捷工厂: 创建带名称的基本块
# ============================================================
def create_block(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
"""创建基本块并添加到函数"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
blk: BasicBlock | t.CPtr = new_basic_block(pool, name_dup)
if blk is not None:
function_add_block(func, blk)
return blk
# ============================================================
# 便捷工厂: 创建整数常量值
# ============================================================
def const_int(pool: memhub.MemBuddy | t.CPtr, bits: t.CInt,
val: t.CInt64T) -> Value | t.CPtr:
"""创建整数常量值(自动创建类型 + 名字文本)
参数:
bits: 位宽 (1/8/16/32/64)
val: 整数值
"""
# 创建类型
ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
# 创建名字文本
name: t.CChar | t.CPtr = pool.alloc(32)
if name is None: return None
viperlib.snprintf(name, 32, "%lld", val)
return ConstInt(pool, ty, val, name)
def const_int32(pool: memhub.MemBuddy | t.CPtr, val: t.CInt64T) -> Value | t.CPtr:
"""便捷: 创建 i32 整数常量"""
return const_int(pool, 32, val)
def const_int64(pool: memhub.MemBuddy | t.CPtr, val: t.CInt64T) -> Value | t.CPtr:
"""便捷: 创建 i64 整数常量"""
return const_int(pool, 64, val)
# ============================================================
# 便捷工厂: 创建函数并添加到模块
# ============================================================
def create_function(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
"""创建函数并添加到模块"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
if func is not None:
module_add_function(mod, func)
return func
def add_param(pool: memhub.MemBuddy | t.CPtr, func: Function | t.CPtr,
ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Param | t.CPtr:
"""创建参数并添加到函数"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
param: Param | t.CPtr = new_param(pool, ty, name_dup)
if param is not None:
function_add_param(func, param)
return param
# ============================================================
# 便捷工厂: 创建函数声明(declare)
# ============================================================
def create_declare(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
"""创建函数声明(declare,无函数体)并添加到模块
与 create_function 不同,声明不生成函数体,仅生成:
declare <ret_ty> @<name>(<params>)
"""
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
func: Function | t.CPtr = new_function(pool, name_dup, ret_ty)
if func is not None:
func.IsDeclared = 1
module_add_function(mod, func)
return func
# ============================================================
# 便捷工厂: 创建字符串常量全局变量
#
# 生成 LLVM IR:
# @.str = private unnamed_addr constant [N x i8] c"contents\00"
# ============================================================
def create_global_string(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
"""创建字符串常量全局变量并添加到模块
参数:
name: 全局变量名(如 ".str")
text: 字符串内容(C 字符串,不含末尾 NUL,NUL 由本函数自动添加)
返回: GlobalVariable 指针,其类型为 [len+1 x i8]
"""
if text is None: return None
slen: t.CSizeT = string.strlen(text)
count: t.CInt = slen + 1 # 含末尾 NUL
# 创建 i8 类型
i8_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if i8_ty is None: return None
string.memset(i8_ty, 0, LLVMType.__sizeof__())
c.DerefAs(i8_ty, LLVMType.Int(8))
# 创建 [count x i8] 数组类型
arr_ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if arr_ty is None: return None
string.memset(arr_ty, 0, LLVMType.__sizeof__())
c.DerefAs(arr_ty, LLVMType.Array(i8_ty, count))
# 创建全局变量
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, arr_ty)
if gv is None: return None
# 设置属性: private + unnamed_addr + constant
global_set_linkage(gv, "private")
global_set_unnamed_addr(gv, 1)
global_set_constant(gv, 1)
# 构造初始化值文本: c"contents\00"
# LLVM IR 字符串字面量格式: c"<chars>" 其中非打印字符用 \xx 转义
# 这里简单处理: 直接复制原始字节,末尾加 \00
init_buf: t.CChar | t.CPtr = pool.alloc(slen + 8) # c"..." + \00 + "
if init_buf is None: return None
pos: t.CSizeT = 0
init_buf[pos] = 'c'
pos += 1
init_buf[pos] = '"'
pos += 1
i: t.CSizeT = 0
while i < slen:
init_buf[pos] = text[i]
pos += 1
i += 1
# 末尾 NUL 字节
init_buf[pos] = '\\'
pos += 1
init_buf[pos] = '0'
pos += 1
init_buf[pos] = '0'
pos += 1
init_buf[pos] = '"'
pos += 1
init_buf[pos] = '\0'
gv.Initializer = init_buf
module_add_global(mod, gv)
return gv
# ============================================================
# 便捷工厂: 创建带初始化值的整数全局变量
# ============================================================
def create_global_int(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr,
name: t.CChar | t.CPtr, bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
"""创建整数全局变量并添加到模块
生成 LLVM IR:
@<name> = global i<bits> <val>
"""
# 创建整数类型
ty: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if ty is None: return None
string.memset(ty, 0, LLVMType.__sizeof__())
c.DerefAs(ty, LLVMType.Int(bits))
name_dup: t.CChar | t.CPtr = _str_dup(pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(pool, name_dup, ty)
if gv is None: return None
# 构造初始化值文本: "42" (类型由 _print_global 单独打印)
init_buf: t.CChar | t.CPtr = pool.alloc(48)
if init_buf is None: return None
viperlib.snprintf(init_buf, 48, "%lld", val)
gv.Initializer = init_buf
module_add_global(mod, gv)
return gv
# ============================================================
# LLVMModuleCore: 模块/函数/值创建核心,封装 pool 避免重复传参
#
# 用法:
# mcore: LLVMModuleCore | t.CPtr = LLVMModuleCore(pool)
# mod: LLVMModule | t.CPtr = mcore.NewModule("test")
# func: Function | t.CPtr = mcore.CreateFunction(mod, "add", ty_i32)
# val: Value | t.CPtr = mcore.ConstInt32(42)
# ============================================================
@t.NoVTable
class LLVMModuleCore:
"""模块/函数/值创建核心,封装 pool 避免每次创建都传 pool"""
Pool: memhub.MemBuddy | t.CPtr
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
self.Pool = pool
# ---- 模块操作 ----
def NewModule(self, name: t.CChar | t.CPtr) -> LLVMModule | t.CPtr:
return new_module(self.Pool, name)
def CreateFunction(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
return create_function(self.Pool, mod, name, ret_ty)
def CreateDeclare(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ret_ty: LLVMType | t.CPtr) -> Function | t.CPtr:
"""创建函数声明(declare,无函数体)"""
return create_declare(self.Pool, mod, name, ret_ty)
def AddParam(self, func: Function | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Param | t.CPtr:
return add_param(self.Pool, func, ty, name)
def FunctionSetAttrs(self, func: Function | t.CPtr, attrs: t.CChar | t.CPtr):
"""设置函数级属性文本"""
function_set_attrs(func, attrs)
def ParamSetAttrs(self, param: Param | t.CPtr, attrs: t.CChar | t.CPtr):
"""设置参数属性文本"""
param_set_attrs(param, attrs)
def CreateBlock(self, func: Function | t.CPtr,
name: t.CChar | t.CPtr) -> BasicBlock | t.CPtr:
return create_block(self.Pool, func, name)
def NewBuilder(self, func: Function | t.CPtr) -> IRBuilder | t.CPtr:
return new_builder(self.Pool, func)
# ---- 全局变量 ----
def NewGlobal(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
"""创建全局变量并添加到模块"""
name_dup: t.CChar | t.CPtr = _str_dup(self.Pool, name)
gv: GlobalVariable | t.CPtr = new_global_variable(self.Pool, name_dup, ty)
if gv is not None:
module_add_global(mod, gv)
return gv
def CreateGlobalString(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
text: t.CChar | t.CPtr) -> GlobalVariable | t.CPtr:
"""创建字符串常量全局变量"""
return create_global_string(self.Pool, mod, name, text)
def CreateGlobalInt(self, mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr,
bits: t.CInt, val: t.CInt64T) -> GlobalVariable | t.CPtr:
"""创建带初始化值的整数全局变量"""
return create_global_int(self.Pool, mod, name, bits, val)
def GlobalSetConstant(self, gv: GlobalVariable | t.CPtr, is_const: t.CInt):
global_set_constant(gv, is_const)
def GlobalSetLinkage(self, gv: GlobalVariable | t.CPtr, linkage: t.CChar | t.CPtr):
global_set_linkage(gv, linkage)
def GlobalSetUnnamedAddr(self, gv: GlobalVariable | t.CPtr, level: t.CInt):
global_set_unnamed_addr(gv, level)
def GlobalSetSection(self, gv: GlobalVariable | t.CPtr, section: t.CChar | t.CPtr):
global_set_section(gv, section)
# ---- 值创建 ----
def ConstInt(self, bits: t.CInt, val: t.CInt64T) -> Value | t.CPtr:
return const_int(self.Pool, bits, val)
def ConstInt32(self, val: t.CInt64T) -> Value | t.CPtr:
return const_int32(self.Pool, val)
def ConstInt64(self, val: t.CInt64T) -> Value | t.CPtr:
return const_int64(self.Pool, val)
def ConstFloat(self, ty: LLVMType | t.CPtr, val: t.CDouble) -> Value | t.CPtr:
return ConstFloat(self.Pool, ty, val)
def SSAValue(self, ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Value | t.CPtr:
return SSAValue(self.Pool, ty, name)
def ConstNull(self, ty: LLVMType | t.CPtr, name: t.CChar | t.CPtr) -> Value | t.CPtr:
return ConstNull(self.Pool, ty, name)
# ---- 打印 ----
def PrintValue(self, buf: t.CChar | t.CPtr, size: t.CSizeT, val: Value | t.CPtr):
ValuePrint(buf, size, val, self.Pool)
def PrintFunction(self, buf: t.CChar | t.CPtr, size: t.CSizeT, func: Function | t.CPtr):
FunctionPrint(buf, size, func, self.Pool)
def PrintModule(self, buf: t.CChar | t.CPtr, size: t.CSizeT, mod: LLVMModule | t.CPtr):
LLVMModulePrint(buf, size, mod, self.Pool, OUTPUT_FULL)
# ---- SSA 验证 ----
def NewVerifyResult(self, buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
"""创建验证结果对象(buf_size 为错误消息缓冲区大小)"""
return _new_verify_result(self.Pool, buf_size)
def VerifyFunction(self, func: Function | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
"""验证单个函数的 SSA 正确性,返回错误数(0=通过)"""
return verify_function(self.Pool, func, result)
def VerifyModule(self, mod: LLVMModule | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
"""验证模块中所有函数的 SSA 正确性,返回错误数(0=通过)"""
return verify_module(self.Pool, mod, result)
+504
View File
@@ -0,0 +1,504 @@
import t, c
from stdint import *
import string
import stdio
import viperlib
import memhub
from linkedlist import GSList, GSListNode
from .__types import LLVMType, TypePrint, Array, PrintStructDefinition, get_struct_name, Struct
from .__function import Function, FunctionPrint, _ll_name_needs_quote, Param
# ============================================================
# GlobalVariable: LLVM IR 全局变量
#
# 持有名称 + 类型 + 初始化值 + 常量标志 + 链接类型。
# 继承 GSListNode[GlobalVariable] 获取强类型 Next。
# ============================================================
@t.NoVTable
class GlobalVariable(GSListNode[GlobalVariable]):
Name: t.CChar | t.CPtr # 全局变量名(如 ".str" / "my_global")
Ty: LLVMType | t.CPtr # 变量类型
Initializer: t.CVoid | t.CPtr # 初始化值 Value*(None = 无初始化)
IsConstant: t.CInt # 1=constant, 0=variable
Linkage: t.CChar | t.CPtr # 链接类型("private"/"internal"/"external"/...)
Section: t.CChar | t.CPtr # 段名(None = 默认)
UnnamedAddr: t.CInt # 1=unnamed_addr, 2=local_unnamed_addr, 0=none
# ============================================================
# NamedTypeNode: 命名结构体类型链表节点
#
# 持有 LLVMType* 指针(必须是命名 Struct 类型)。
# 继承 GSListNode[NamedTypeNode] 获取强类型 Next。
# ============================================================
@t.NoVTable
class NamedTypeNode(GSListNode[NamedTypeNode]):
Ty: LLVMType | t.CPtr # 命名结构体类型指针
# ============================================================
# LLVMModule: LLVM IR 模块容器
#
# 使用嵌入式 Head/Tail/Count 字段代替 GSList 指针,
# 避免泛型 GSList 的 __sizeof__ 返回 0 和 vtable 偏移不一致问题。
# LLVMModulePrint 输出完整 .ll 文件内容。
# 注意: 类名必须为 LLVMModule 而非 Module,避免与 ast.Module 命名冲突
# ============================================================
@t.NoVTable
class LLVMModule:
Name: t.CChar | t.CPtr # 模块名
FuncHead: Function | t.CPtr # 函数链表头
FuncTail: Function | t.CPtr # 函数链表尾
FuncCount: t.CSizeT # 函数计数
GlobalHead: GlobalVariable | t.CPtr # 全局变量链表头
GlobalTail: GlobalVariable | t.CPtr # 全局变量链表尾
GlobalCount: t.CSizeT # 全局变量计数
TargetTriple: t.CChar | t.CPtr # 目标三元组(如 "x86_64-pc-linux-gnu")
DataLayout: t.CChar | t.CPtr # 数据布局(如 "e-m:e-p270:32:32-...")
NamedTypeHead: NamedTypeNode | t.CPtr # 命名结构体类型链表头
NamedTypeTail: NamedTypeNode | t.CPtr # 命名结构体类型链表尾
NamedTypeCount: t.CSizeT # 命名结构体类型计数
# 总计: 12 字段 * 8 = 96 字节(无 vtable)
# ============================================================
# 工厂函数
# ============================================================
def new_module(pool: memhub.MemBuddy | t.CPtr, name: t.CChar | t.CPtr) -> LLVMModule | t.CPtr:
"""创建一个模块"""
# 硬编码 96 字节:12 字段 * 8 字节(无 vtable,@t.NoVTable)
ptr: LLVMModule | t.CPtr = pool.alloc(96)
if ptr is None: return None
string.memset(ptr, 0, 96)
ptr.Name = name
ptr.FuncHead = None
ptr.FuncTail = None
ptr.FuncCount = 0
ptr.GlobalHead = None
ptr.GlobalTail = None
ptr.GlobalCount = 0
ptr.TargetTriple = None
ptr.DataLayout = None
ptr.NamedTypeHead = None
ptr.NamedTypeTail = None
ptr.NamedTypeCount = 0
return ptr
# GlobalVariable 硬编码大小: Next(8) + Name(8) + Ty(8) + Initializer(8) + IsConstant(4) + Linkage(8) + Section(8) + UnnamedAddr(4) = 64 字节
GV_SIZE: t.CDefine = 64
# NamedTypeNode 硬编码大小: Next(8) + Ty(8) = 16 字节
NAMED_TYPE_NODE_SIZE: t.CDefine = 16
def new_global_variable(pool: memhub.MemBuddy | t.CPtr,
name: t.CChar | t.CPtr, ty: LLVMType | t.CPtr) -> GlobalVariable | t.CPtr:
"""创建一个全局变量"""
ptr: GlobalVariable | t.CPtr = pool.alloc(GV_SIZE)
if ptr is None: return None
string.memset(ptr, 0, GV_SIZE)
ptr.Name = name
ptr.Ty = ty
ptr.Initializer = None
ptr.IsConstant = 0
ptr.Linkage = "external"
ptr.Section = None
ptr.UnnamedAddr = 0
return ptr
# ============================================================
# 链表操作(嵌入式 Head/Tail/Count,O(1) 追加)
# ============================================================
def module_add_function(mod: LLVMModule | t.CPtr, func: Function | t.CPtr):
"""将函数追加到模块函数链表(O(1))"""
if mod is None or func is None: return
func.Next = None
if mod.FuncHead is None:
mod.FuncHead = func
else:
mod.FuncTail.Next = func
mod.FuncTail = func
mod.FuncCount += 1
def module_add_global(mod: LLVMModule | t.CPtr, gv: GlobalVariable | t.CPtr):
"""将全局变量追加到模块全局变量链表(O(1))"""
if mod is None or gv is None: return
gv.Next = None
if mod.GlobalHead is None:
mod.GlobalHead = gv
else:
mod.GlobalTail.Next = gv
mod.GlobalTail = gv
mod.GlobalCount += 1
def module_set_target(mod: LLVMModule | t.CPtr, triple: t.CChar | t.CPtr):
"""设置目标三元组"""
if mod is None: return
mod.TargetTriple = triple
def module_set_datalayout(mod: LLVMModule | t.CPtr, layout: t.CChar | t.CPtr):
"""设置数据布局"""
if mod is None: return
mod.DataLayout = layout
# ============================================================
# 命名结构体类型管理
# ============================================================
def module_add_named_type(mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
"""将命名结构体类型添加到模块(用于输出 %"name" = type { ... } 定义行)
非命名结构体(Name 为 None 或非 Struct 类型)会被忽略。
按 Name 去重,相同名称的类型只保留第一个。
"""
if mod is None or pool is None or ty is None:
return
name: t.CChar | t.CPtr = get_struct_name(ty)
if name is None:
return
# 去重检查
cur: NamedTypeNode | t.CPtr = mod.NamedTypeHead
while cur is not None:
if cur.Ty is not None:
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
if existing_name is not None:
if string.strcmp(existing_name, name) == 0:
return
cur = cur.Next
# 创建新节点并追加到链表尾部
node: NamedTypeNode | t.CPtr = pool.alloc(NAMED_TYPE_NODE_SIZE)
if node is None:
return
string.memset(node, 0, NAMED_TYPE_NODE_SIZE)
node.Ty = ty
node.Next = None
if mod.NamedTypeHead is None:
mod.NamedTypeHead = node
else:
mod.NamedTypeTail.Next = node
mod.NamedTypeTail = node
mod.NamedTypeCount += 1
# ============================================================
# module_ensure_opaque_for_type - 为类型中的跨模块结构体引用添加 opaque 声明
#
# 递归扫描 LLVMType 树,当遇到 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
# 如果该名称未在模块中定义,则添加 opaque 声明(%"name" = type opaque)。
# 这解决了跨模块结构体引用导致的 llc "use of undefined type" 错误。
# ============================================================
def _is_type_defined_in_module(mod: LLVMModule | t.CPtr, name: t.CChar | t.CPtr) -> int:
"""检查模块中是否已定义指定名称的结构体类型,返回 1=已定义 / 0=未定义"""
if mod is None or name is None:
return 0
cur: NamedTypeNode | t.CPtr = mod.NamedTypeHead
while cur is not None:
if cur.Ty is not None:
existing_name: t.CChar | t.CPtr = get_struct_name(cur.Ty)
if existing_name is not None:
if string.strcmp(existing_name, name) == 0:
return 1
cur = cur.Next
return 0
def _scan_type_for_cross_module_refs(pool: memhub.MemBuddy | t.CPtr,
mod: LLVMModule | t.CPtr,
ty: LLVMType | t.CPtr):
"""递归扫描类型树,为跨模块结构体引用添加 opaque 声明"""
if ty is None or mod is None or pool is None:
return
match ty:
case LLVMType.Ptr(pointee):
if pointee is not None:
match pointee:
case LLVMType.Struct(sfields, sfcount, sname):
if sname is not None:
# 检查是否为跨模块引用(名称包含 '.')
if string.strchr(sname, 46) is not None:
# 检查是否已在模块中定义
if _is_type_defined_in_module(mod, sname) == 0:
# 创建 opaque 类型并添加到模块
opaque_ty: LLVMType | t.CPtr = Struct(pool, None, 0, sname)
if opaque_ty is not None:
module_add_named_type(mod, pool, opaque_ty)
case _:
_scan_type_for_cross_module_refs(pool, mod, pointee)
case LLVMType.Array(elem_ty, acount):
if elem_ty is not None:
_scan_type_for_cross_module_refs(pool, mod, elem_ty)
case _:
pass
def module_ensure_opaque_for_type(mod: LLVMModule | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
ty: LLVMType | t.CPtr):
"""为类型中的跨模块结构体引用添加 opaque 声明
当类型引用了 Ptr(Struct(name)) 且 name 包含 '.'(SHA1 限定名)时,
如果该名称未在模块中定义,则添加 opaque 声明。
"""
_scan_type_for_cross_module_refs(pool, mod, ty)
# ============================================================
# 全局变量属性设置
# ============================================================
def global_set_constant(gv: GlobalVariable | t.CPtr, is_const: t.CInt):
"""设置全局变量是否为常量"""
if gv is None: return
gv.IsConstant = is_const
def global_set_linkage(gv: GlobalVariable | t.CPtr, linkage: t.CChar | t.CPtr):
"""设置链接类型 (private/internal/external/... )"""
if gv is None: return
gv.Linkage = linkage
def global_set_unnamed_addr(gv: GlobalVariable | t.CPtr, level: t.CInt):
"""设置 unnamed_addr 属性 (0=none, 1=unnamed_addr, 2=local_unnamed_addr)"""
if gv is None: return
gv.UnnamedAddr = level
def global_set_section(gv: GlobalVariable | t.CPtr, section: t.CChar | t.CPtr):
"""设置段名"""
if gv is None: return
gv.Section = section
# ============================================================
# 输出模式常量
# ============================================================
OUTPUT_FULL: t.CDefine = 0 # 完整 IR(stub + text)
OUTPUT_STUB: t.CDefine = 1 # 仅声明(header + 类型定义 + declare + external global)
OUTPUT_TEXT: t.CDefine = 2 # 仅代码(define + global 带初值)
# ============================================================
# LLVMModulePrint: 将模块序列化为 .ll 文本
#
# mode: OUTPUT_FULL=完整, OUTPUT_STUB=仅声明, OUTPUT_TEXT=仅代码
# ============================================================
def LLVMModulePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
mod: LLVMModule | t.CPtr, pool: memhub.MemBuddy | t.CPtr,
mode: t.CInt):
"""将模块 mod 序列化为 .ll 文本写入 buf"""
if mod is None or buf is None or size == 0: return
# 头部注释(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
_append_cstr(buf, size, "; ModuleID = '")
if mod.Name is not None:
_append_cstr(buf, size, mod.Name)
_append_cstr(buf, size, "'\n")
# 目标三元组
if mod.TargetTriple is not None:
_append_cstr(buf, size, "target triple = \"")
_append_cstr(buf, size, mod.TargetTriple)
_append_cstr(buf, size, "\"\n")
# 数据布局
if mod.DataLayout is not None:
_append_cstr(buf, size, "target datalayout = \"")
_append_cstr(buf, size, mod.DataLayout)
_append_cstr(buf, size, "\"\n")
# 空行
_append_cstr(buf, size, "\n")
# 命名结构体类型定义(stub 和 full 模式输出,text 模式不输出)
if mode == OUTPUT_FULL or mode == OUTPUT_STUB:
# 扫描所有函数签名,为跨模块结构体引用添加 opaque 定义
# 确保 stub.ll 包含被 declare/define 引用的跨模块类型定义
# 修复:alloc_buf 返回 viperio.Buf,但 Buf 类型未在 NamedTypeHead 中注册
func_scan: Function | t.CPtr = mod.FuncHead
while func_scan is not None:
if func_scan.RetTy is not None:
module_ensure_opaque_for_type(mod, pool, func_scan.RetTy)
if func_scan.Params is not None:
param_scan: Param | t.CPtr = func_scan.Params.Head
while param_scan is not None:
if param_scan.Ty is not None:
module_ensure_opaque_for_type(mod, pool, param_scan.Ty)
param_scan = param_scan.Next
func_scan = func_scan.Next
nt: NamedTypeNode | t.CPtr = mod.NamedTypeHead
while nt is not None:
if nt.Ty is not None:
ty_buf: t.CChar | t.CPtr = pool.alloc(256)
if ty_buf is not None:
ty_buf[0] = '\0'
PrintStructDefinition(ty_buf, 256, nt.Ty, pool)
_append_cstr(buf, size, ty_buf)
_append_cstr(buf, size, "\n")
nt = nt.Next
if mod.NamedTypeHead is not None:
_append_cstr(buf, size, "\n")
# 全局变量
gv: GlobalVariable | t.CPtr = mod.GlobalHead
if mode == OUTPUT_STUB:
# stub 模式:输出 external global(无初值)
while gv is not None:
_print_global_stub(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
else:
# full 和 text 模式:输出完整全局变量
# text 模式跳过无初值的全局变量(纯声明)
gv_idx: t.CInt = 0
while gv is not None:
if mode == OUTPUT_TEXT and gv.Initializer is None:
gv = gv.Next
gv_idx += 1
continue
_print_global(buf, size, gv, pool)
_append_cstr(buf, size, "\n")
gv = gv.Next
gv_idx += 1
if mod.GlobalHead is not None and (mode == OUTPUT_FULL or mode == OUTPUT_STUB):
_append_cstr(buf, size, "\n")
elif mod.GlobalHead is not None and mode == OUTPUT_TEXT:
# text 模式下如果输出了全局变量,也加空行
had_global: t.CInt = 0
gv2: GlobalVariable | t.CPtr = mod.GlobalHead
while gv2 is not None:
if gv2.Initializer is not None:
had_global = 1
break
gv2 = gv2.Next
if had_global != 0:
_append_cstr(buf, size, "\n")
# 遍历函数
func: Function | t.CPtr = mod.FuncHead
func_idx: t.CInt = 0
while func is not None:
if mode == OUTPUT_STUB:
# stub 模式:仅输出 declare(IsDeclared==1)
if func.IsDeclared == 1:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
elif mode == OUTPUT_TEXT:
# text 模式:仅输出 define(IsDeclared==0)
if func.IsDeclared == 0:
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
else:
# full 模式:输出所有函数
FunctionPrint(buf, size, func, pool)
_append_cstr(buf, size, "\n")
func = func.Next
func_idx += 1
# ============================================================
# 全局变量打印
# ============================================================
def _print_global(buf: t.CChar | t.CPtr, size: t.CSizeT,
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""打印单个全局变量: @<name> = [linkage] [unnamed_addr] [constant] <ty> <init>"""
if gv is None: return
_append_cstr(buf, size, "@")
if gv.Name is not None:
if _ll_name_needs_quote(gv.Name) != 0:
_append_cstr(buf, size, "\"")
_append_cstr(buf, size, gv.Name)
_append_cstr(buf, size, "\"")
else:
_append_cstr(buf, size, gv.Name)
_append_cstr(buf, size, " = ")
# 链接类型(有初始值时不输出 external,因为 external + 初始值是非法 IR)
if gv.Linkage is not None:
if gv.Initializer is not None and string.strcmp(gv.Linkage, "external") == 0:
pass
else:
_append_cstr(buf, size, gv.Linkage)
_append_cstr(buf, size, " ")
# unnamed_addr
if gv.UnnamedAddr == 1:
_append_cstr(buf, size, "unnamed_addr ")
elif gv.UnnamedAddr == 2:
_append_cstr(buf, size, "local_unnamed_addr ")
# constant / global
if gv.IsConstant == 1:
_append_cstr(buf, size, "constant ")
else:
_append_cstr(buf, size, "global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
# 初始化值
if gv.Initializer is not None:
_append_cstr(buf, size, " ")
_append_cstr(buf, size, gv.Initializer)
# 段名
if gv.Section is not None:
_append_cstr(buf, size, ", section \"")
_append_cstr(buf, size, gv.Section)
_append_cstr(buf, size, "\"")
# ============================================================
# _print_global_stub - 打印全局变量的声明形式(external global,无初值)
# ============================================================
def _print_global_stub(buf: t.CChar | t.CPtr, size: t.CSizeT,
gv: GlobalVariable | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""打印全局变量声明: @<name> = external global <ty>"""
if gv is None: return
_append_cstr(buf, size, "@")
if gv.Name is not None:
if _ll_name_needs_quote(gv.Name) != 0:
_append_cstr(buf, size, "\"")
_append_cstr(buf, size, gv.Name)
_append_cstr(buf, size, "\"")
else:
_append_cstr(buf, size, gv.Name)
_append_cstr(buf, size, " = external global ")
# 类型
ty_buf: t.CChar | t.CPtr = pool.alloc(128)
if ty_buf is not None:
ty_buf[0] = '\0'
TypePrint(ty_buf, 128, gv.Ty, pool)
_append_cstr(buf, size, ty_buf)
# ============================================================
# 内部辅助
# ============================================================
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
"""将 C 字符串 src 追加到 dst 末尾"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
slen: t.CSizeT = string.strlen(src)
remain: t.CSizeT = dst_size - dlen
if remain <= 0: return
i: t.CSizeT = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
dst[dlen + i] = '\0'
+524
View File
@@ -0,0 +1,524 @@
import t, c
from stdint import *
import viperlib
import string
import memhub
from linkedlist import GSListNode
# ============================================================
# ParamNode: 函数参数类型链表节点
# 继承 GSListNode[ParamNode] 获取强类型 Next: ParamNode|CPtr
# Ty 用 t.CVoid | t.CPtr 前向引用,使用时转型为 (LLVMType | t.CPtr)
# ============================================================
class ParamNode(GSListNode[ParamNode]):
Ty: t.CVoid | t.CPtr # LLVMType*(前向引用,使用时转型)
# ============================================================
# LLVMType: LLVM IR 类型系统(t.REnum tagged union)
#
# 变体少、无通用字段、操作通过 match 分派 —— 契合 REnum 模型。
# 布局: { i32 __tag, <max_variant_payload> }
# ============================================================
class LLVMType(t.REnum):
# 整数类型: i1/i8/i16/i32/i64
class Int:
Bits: t.CInt
# 指针类型: pointee*
class Ptr:
Pointee: LLVMType | t.CPtr
# 函数类型: ret (params)
class Func:
Ret: LLVMType | t.CPtr
Params: ParamNode | t.CPtr
PCount: t.CInt
# 数组类型: [N x elem_ty]
class Array:
ElemTy: LLVMType | t.CPtr
Count: t.CInt
# 结构体类型: {ty1, ty2, ...} 或 %"name" = type {ty1, ty2, ...}
# Fields 复用 ParamNode 链表(ParamNode.Ty 即字段类型)
# Name 非 None 时为命名结构体,TypePrint 输出 %"name" 而非 {...}
class Struct:
Fields: ParamNode | t.CPtr
FCount: t.CInt
Name: t.CChar | t.CPtr
# 浮点类型: half/float/double/fp128
class Float:
Bits: t.CInt # 16=half, 32=float, 64=double, 128=fp128
# 无值类型
class Void:
pass
# 标签类型
class Label:
pass
# 元数据类型
class Metadata:
pass
# ============================================================
# 内部分配辅助
# ============================================================
def _new_type(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""从 mpool 分配一个零初始化的 LLVMType"""
ptr: LLVMType | t.CPtr = pool.alloc(LLVMType.__sizeof__())
if ptr:
string.memset(ptr, 0, LLVMType.__sizeof__())
return ptr
# ============================================================
# 类型工厂函数
# ============================================================
def Int1(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(1))
return ptr
def Int8(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(8))
return ptr
def Int16(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(16))
return ptr
def Int32(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(32))
return ptr
def Int64(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Int(64))
return ptr
def Ptr(pool: memhub.MemBuddy | t.CPtr, pointee: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Ptr(pointee))
return ptr
def Func(pool: memhub.MemBuddy | t.CPtr, ret: LLVMType | t.CPtr,
params: ParamNode | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Func(ret, params, count))
return ptr
def Void(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Void())
return ptr
def Array(pool: memhub.MemBuddy | t.CPtr, elem_ty: LLVMType | t.CPtr,
count: t.CInt) -> LLVMType | t.CPtr:
"""创建数组类型 [count x elem_ty]"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Array(elem_ty, count))
return ptr
def Struct(pool: memhub.MemBuddy | t.CPtr, fields: ParamNode | t.CPtr,
fcount: t.CInt, name: t.CChar | t.CPtr) -> LLVMType | t.CPtr:
"""创建结构体类型 {ty1, ty2, ...}
fields 为 ParamNode 链表头,fcount 为字段数量。
name 非 None 时为命名结构体(如 "sha1.ClassName"),TypePrint 输出 %"name"。
name 为 None 时为匿名结构体,TypePrint 输出 {ty1, ty2, ...}。
"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Struct(fields, fcount, name))
return ptr
def Half(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""创建半精度浮点类型 half (16-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(16))
return ptr
def Float(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""创建单精度浮点类型 float (32-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(32))
return ptr
def Double(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""创建双精度浮点类型 double (64-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(64))
return ptr
def FP128(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""创建四精度浮点类型 fp128 (128-bit)"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Float(128))
return ptr
def Label(pool: memhub.MemBuddy | t.CPtr) -> LLVMType | t.CPtr:
"""创建标签类型 label"""
ptr: LLVMType | t.CPtr = _new_type(pool)
if ptr is None: return None
c.DerefAs(ptr, LLVMType.Label())
return ptr
# ============================================================
# ParamNode 辅助
# ============================================================
# ParamNode 硬编码大小: Next(8) + Ty(8) = 16 字节
PNODE_SIZE: t.CDefine = 16
def new_param_node(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
"""创建一个参数节点,Ty 设为给定类型指针"""
ptr: ParamNode | t.CPtr = pool.alloc(PNODE_SIZE)
if ptr is None: return None
string.memset(ptr, 0, PNODE_SIZE)
ptr.Ty = ty
ptr.Next = None
return ptr
def param_list_append(head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
"""将 node 追加到参数链表尾部,返回 head 和更新后的 tail"""
if node is None: return head
node.Next = None
if head is None:
return node
if tail is not None:
tail.Next = node
return node
# ============================================================
# ParamNode 字段访问器(供其他模块绕过 stub 类型限制使用)
#
# 跨模块编译时,使用方模块只有 ParamNode 的 stub 类型,
# 导致 TransPyC 静默跳过字段访问。这些访问器在拥有完整类型定义的
# 本模块内执行,能正确访问所有字段。
# ============================================================
def paramnode_get_ty(node: ParamNode | t.CPtr) -> LLVMType | t.CPtr:
"""获取参数节点的类型"""
if node is None:
return None
return (LLVMType | t.CPtr)(node.Ty)
def paramnode_get_next(node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
"""获取链表下一个参数节点"""
if node is None:
return None
return node.Next
def paramnode_set_ty(node: ParamNode | t.CPtr, ty: LLVMType | t.CPtr):
"""设置参数节点的类型"""
if node is None:
return
node.Ty = ty
def paramnode_set_next(node: ParamNode | t.CPtr, nxt: ParamNode | t.CPtr):
"""设置链表下一个参数节点"""
if node is None:
return
node.Next = nxt
# ============================================================
# LLVMTypeCore: 类型创建核心,封装 pool 避免重复传参
#
# 用法:
# core: LLVMTypeCore | t.CPtr = LLVMTypeCore(pool)
# ty_i32: LLVMType | t.CPtr = core.Int32()
# ty_ptr: LLVMType | t.CPtr = core.Ptr(ty_i32)
# ty_void: LLVMType | t.CPtr = core.Void()
# ============================================================
@t.NoVTable
class LLVMTypeCore:
"""类型创建核心,封装 pool 避免每次创建类型都传 pool"""
Pool: memhub.MemBuddy | t.CPtr
def __init__(self, pool: memhub.MemBuddy | t.CPtr):
self.Pool = pool
def Int1(self) -> LLVMType | t.CPtr:
return Int1(self.Pool)
def Int8(self) -> LLVMType | t.CPtr:
return Int8(self.Pool)
def Int16(self) -> LLVMType | t.CPtr:
return Int16(self.Pool)
def Int32(self) -> LLVMType | t.CPtr:
return Int32(self.Pool)
def Int64(self) -> LLVMType | t.CPtr:
return Int64(self.Pool)
def Ptr(self, pointee: LLVMType | t.CPtr) -> LLVMType | t.CPtr:
return Ptr(self.Pool, pointee)
def Func(self, ret: LLVMType | t.CPtr, params: ParamNode | t.CPtr,
count: t.CInt) -> LLVMType | t.CPtr:
return Func(self.Pool, ret, params, count)
def Array(self, elem_ty: LLVMType | t.CPtr, count: t.CInt) -> LLVMType | t.CPtr:
return Array(self.Pool, elem_ty, count)
def Struct(self, fields: ParamNode | t.CPtr, fcount: t.CInt,
name: t.CChar | t.CPtr) -> LLVMType | t.CPtr:
return Struct(self.Pool, fields, fcount, name)
def Void(self) -> LLVMType | t.CPtr:
return Void(self.Pool)
def Half(self) -> LLVMType | t.CPtr:
return Half(self.Pool)
def Float(self) -> LLVMType | t.CPtr:
return Float(self.Pool)
def Double(self) -> LLVMType | t.CPtr:
return Double(self.Pool)
def FP128(self) -> LLVMType | t.CPtr:
return FP128(self.Pool)
def Label(self) -> LLVMType | t.CPtr:
return Label(self.Pool)
def NewParamNode(self, ty: LLVMType | t.CPtr) -> ParamNode | t.CPtr:
return new_param_node(self.Pool, ty)
# ---- 链表辅助 ----
def ParamListAppend(self, head: ParamNode | t.CPtr, tail: ParamNode | t.CPtr,
node: ParamNode | t.CPtr) -> ParamNode | t.CPtr:
"""将 node 追加到参数/字段链表,返回新的 tail"""
return param_list_append(head, tail, node)
# ---- 打印 ----
def PrintType(self, buf: t.CChar | t.CPtr, size: t.CSizeT, ty: LLVMType | t.CPtr):
TypePrint(buf, size, ty, self.Pool)
# ============================================================
# TypePrint: 将 LLVMType 序列化为 IR 文本
#
# 示例:
# Int(32) -> "i32"
# Int(8) -> "i8"
# Ptr(Int(32)) -> "i32*"
# Void -> "void"
# Array(Int(32),4) -> "[4 x i32]"
# Struct(...) -> "{i32, i8*}"
# Func(...) -> "i32 (i32, i8*)"
#
# pool 用于复杂类型(Array/Struct/Func)递归打印子类型时分配临时缓冲区。
# ============================================================
def TypePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""将类型 ty 序列化为 IR 文本写入 buf(容量 size)
pool 用于递归打印子类型时分配临时缓冲区。
"""
if ty is None or buf is None or size == 0:
return
buf[0] = '\0'
match ty:
case LLVMType.Int(bits):
viperlib.snprintf(buf, size, "i%d", bits)
case LLVMType.Ptr(pointee):
# 先打印 pointee,再追加 '*'
TypePrint(buf, size, pointee, pool)
pos: t.CSizeT = string.strlen(buf)
if pos + 1 < size:
buf[pos] = '*'
buf[pos + 1] = '\0'
case LLVMType.Array(elem_ty, count):
# [N x elem_ty]
viperlib.snprintf(buf, size, "[%d x ", count)
tmp: t.CChar | t.CPtr = pool.alloc(128)
if tmp is not None:
TypePrint(tmp, 128, elem_ty, pool)
_strappend(buf, size, tmp)
_strappend(buf, size, "]")
case LLVMType.Struct(fields, fcount, name):
if name is not None:
# 命名结构体: %"name"
buf[0] = '%'
buf[1] = '"'
buf[2] = '\0'
_strappend(buf, size, name)
_strappend(buf, size, "\"")
else:
# 匿名结构体: {ty1, ty2, ...}
_print_struct_body(buf, size, fields, pool)
case LLVMType.Func(ret, params, count):
# ret (ty1, ty2, ...)
TypePrint(buf, size, ret, pool)
_strappend(buf, size, " (")
cur2: ParamNode | t.CPtr = params
first2: t.CInt = 1
tmp3: t.CChar | t.CPtr = pool.alloc(128)
while cur2 is not None:
if first2 == 0:
_strappend(buf, size, ", ")
if tmp3 is not None:
TypePrint(tmp3, 128, cur2.Ty, pool)
_strappend(buf, size, tmp3)
cur2 = cur2.Next
first2 = 0
_strappend(buf, size, ")")
case LLVMType.Void():
string.strcpy(buf, "void")
case LLVMType.Label():
string.strcpy(buf, "label")
case LLVMType.Metadata():
string.strcpy(buf, "metadata")
case LLVMType.Float(bits):
if bits == 16:
string.strcpy(buf, "half")
elif bits == 32:
string.strcpy(buf, "float")
elif bits == 64:
string.strcpy(buf, "double")
elif bits == 128:
string.strcpy(buf, "fp128")
else:
viperlib.snprintf(buf, size, "float%x", bits)
case _:
string.strcpy(buf, "void")
# ============================================================
# 内部辅助
# ============================================================
def _strappend(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
"""将 src 追加到 dst 末尾(不超过 dst_size)"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
slen: t.CSizeT = string.strlen(src)
remain: t.CSizeT = dst_size - dlen
if remain <= 0: return
i: t.CSizeT = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
dst[dlen + i] = '\0'
# ============================================================
# _print_struct_body - 打印结构体字段部分 {ty1, ty2, ...}
#
# 供 TypePrint(匿名结构体)和 PrintStructDefinition(命名结构体定义行)复用
# ============================================================
def _print_struct_body(buf: t.CChar | t.CPtr, size: t.CSizeT,
fields: ParamNode | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""打印 {ty1, ty2, ...} 到 buf(追加模式,不覆盖已有内容)"""
if buf is None or size == 0:
return
_strappend(buf, size, "{")
cur: ParamNode | t.CPtr = fields
first: t.CInt = 1
tmp: t.CChar | t.CPtr = pool.alloc(128)
while cur is not None:
if first == 0:
_strappend(buf, size, ", ")
if tmp is not None:
TypePrint(tmp, 128, cur.Ty, pool)
_strappend(buf, size, tmp)
cur = cur.Next
first = 0
_strappend(buf, size, "}")
# ============================================================
# PrintStructDefinition - 打印命名结构体类型定义行
#
# 输出格式: %"name" = type { ty1, ty2, ... }
# 供 LLVMModulePrint 在全局变量/函数之前输出类型定义
# ============================================================
def PrintStructDefinition(buf: t.CChar | t.CPtr, size: t.CSizeT,
ty: LLVMType | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""打印命名结构体类型定义行 %"name" = type { ty1, ty2, ... }
当 fcount==0 且 fields is None 时,输出 opaque 声明: %"name" = type opaque
"""
if ty is None or buf is None or size == 0:
return
match ty:
case LLVMType.Struct(fields, fcount, name):
if name is None:
return
buf[0] = '%'
buf[1] = '"'
buf[2] = '\0'
_strappend(buf, size, name)
# opaque 类型: fcount==0 且 fields is None(跨模块前向声明)
if fcount == 0 and fields is None:
_strappend(buf, size, "\" = type opaque")
else:
_strappend(buf, size, "\" = type ")
_print_struct_body(buf, size, fields, pool)
case _:
return
# ============================================================
# get_struct_name - 获取命名结构体的名称
#
# 返回 Name 字段(如 "sha1.ClassName"),非 Struct 类型或匿名 Struct 返回 None
# 供 module_add_named_type 检查是否为命名结构体及去重
# ============================================================
def get_struct_name(ty: LLVMType | t.CPtr) -> t.CChar | t.CPtr:
"""获取命名结构体的名称,非命名结构体返回 None"""
if ty is None:
return None
match ty:
case LLVMType.Struct(fields, fcount, name):
return name
case _:
return None
+212
View File
@@ -0,0 +1,212 @@
import t, c
from stdint import *
import string
import viperlib
import memhub
from linkedlist import GSListNode
from .__types import LLVMType, TypePrint
# ============================================================
# Value: SSA 值表示
#
# 表示一个 LLVM IR 值:SSA 临时值(%0/%result)或常量字面量(42/0)。
# 每个值有类型指针、名字、是否常量标志。
# 继承 GSListNode[Value] 获取强类型 Next: Value|CPtr(值池链表)
# ============================================================
class Value(GSListNode[Value]):
Ty: LLVMType | t.CPtr # 值的类型
Name: t.CChar | t.CPtr # SSA 名("%0"/"%result")或常量文本("42"/"1.5e+00")
IsConst: t.CInt # 1=常量字面量, 0=SSA 临时值
IntVal: t.CInt64T # 整数常量值(当 IsConst=1 时使用)
FloatVal: t.CDouble # 浮点常量值(当 IsConst=1 且 Ty 为 Float 时使用)
# ============================================================
# 工厂函数
# ============================================================
# Value 硬编码大小: Next(8) + Ty(8) + Name(8) + IsConst(4) + IntVal(8) + FloatVal(8) = 48 字节
VALUE_SIZE: t.CDefine = 48
def new_value(pool: memhub.MemBuddy | t.CPtr) -> Value | t.CPtr:
"""从 mpool 分配一个零初始化的 Value"""
ptr: Value | t.CPtr = pool.alloc(VALUE_SIZE)
if ptr:
string.memset(ptr, 0, VALUE_SIZE)
return ptr
def ConstInt(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: t.CInt64T, name: t.CChar | t.CPtr) -> Value | t.CPtr:
"""创建整数常量值
参数:
ty: 整数类型(Int1/Int8/Int32/Int64)
val: 整数值
name: 常量文本(如 "42"),由调用方提供
"""
v: Value | t.CPtr = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
v.IsConst = 1
v.IntVal = val
return v
def ConstNull(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Value | t.CPtr:
"""创建 null 指针常量"""
v: Value | t.CPtr = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
v.IsConst = 1
v.IntVal = 0
return v
def ConstZero(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr) -> Value | t.CPtr:
"""创建 zeroinitializer 常量(零初始化聚合类型:结构体/数组)"""
v: Value | t.CPtr = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = "zeroinitializer"
v.IsConst = 1
v.IntVal = 0
return v
def ConstFloat(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
val: t.CDouble) -> Value | t.CPtr:
"""创建浮点常量值
参数:
ty: 浮点类型(Half/Float/Double/FP128)
val: 浮点数值
名字自动格式化为 LLVM IR 科学计数法文本(如 "1.500000e+00")。
"""
v: Value | t.CPtr = new_value(pool)
if v is None: return None
v.Ty = ty
v.IsConst = 1
v.FloatVal = val
v.IntVal = 0
# 格式化名字: LLVM IR 使用 "%e" 科学计数法(6 位小数)
name_buf: t.CChar | t.CPtr = pool.alloc(32)
if name_buf is not None:
viperlib.snprintf(name_buf, 32, "%e", val)
v.Name = name_buf
return v
def SSAValue(pool: memhub.MemBuddy | t.CPtr, ty: LLVMType | t.CPtr,
name: t.CChar | t.CPtr) -> Value | t.CPtr:
"""创建 SSA 临时值
参数:
ty: 值类型
name: SSA 名(如 "%0"/"%result"),由调用方提供
"""
v: Value | t.CPtr = new_value(pool)
if v is None: return None
v.Ty = ty
v.Name = name
v.IsConst = 0
v.IntVal = 0
return v
# ============================================================
# ValuePrint: 将值序列化为 IR 文本
#
# 示例:
# ConstInt(i32, 42, "42") -> "i32 42"
# SSAValue(i32, "%0") -> "i32 %0"
# ============================================================
def ValuePrint(buf: t.CChar | t.CPtr, size: t.CSizeT,
val: Value | t.CPtr, pool: memhub.MemBuddy | t.CPtr):
"""将值 val 序列化为 IR 文本写入 buf
格式: <type> <name>
pool 用于复杂类型(Array/Struct/Func)递归打印时分配临时缓冲区。
"""
if val is None or buf is None or size == 0:
return
# 先写类型
TypePrint(buf, size, val.Ty, pool)
# 追加空格
pos: t.CSizeT = string.strlen(buf)
if pos + 1 < size:
buf[pos] = ' '
buf[pos + 1] = '\0'
# 追加名字
if val.Name is not None:
pos = string.strlen(buf)
_append_str(buf, size, val.Name)
# ============================================================
# Value 字段访问器(供其他模块绕过 stub 类型限制使用)
#
# 跨模块编译时,使用方模块只有 Value 的 stub 类型(字段不足或偏移错误),
# 导致 TransPyC 静默跳过字段访问(不生成 GEP,不报错)。
# 这些访问器在拥有完整类型定义的本模块内执行,能正确访问所有字段。
# ============================================================
def value_get_ty(val: Value | t.CPtr) -> LLVMType | t.CPtr:
"""获取值的类型"""
if val is None:
return None
return val.Ty
def value_get_next(val: Value | t.CPtr) -> Value | t.CPtr:
"""获取链表下一个值"""
if val is None:
return None
return val.Next
def value_set_ty(val: Value | t.CPtr, ty: LLVMType | t.CPtr):
"""设置值的类型"""
if val is None:
return
val.Ty = ty
def value_set_next(val: Value | t.CPtr, nxt: Value | t.CPtr):
"""设置链表下一个值"""
if val is None:
return
val.Next = nxt
def value_set_name(val: Value | t.CPtr, name: t.CChar | t.CPtr):
"""设置值的名字"""
if val is None:
return
val.Name = name
def value_set_isconst(val: Value | t.CPtr, is_const: t.CInt):
"""设置是否为常量"""
if val is None:
return
val.IsConst = is_const
# ============================================================
# 内部辅助
# ============================================================
def _append_str(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
"""将 src 追加到 dst 末尾"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
slen: t.CSizeT = string.strlen(src)
remain: t.CSizeT = dst_size - dlen
if remain <= 0: return
i: t.CSizeT = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
dst[dlen + i] = '\0'
+396
View File
@@ -0,0 +1,396 @@
import t, c
from stdint import *
import string
import viperlib
import memhub
from linkedlist import GSListNode, GSList
from .__function import Function, BasicBlock, Line, Param
from .__module import LLVMModule
# ============================================================
# SSA 验证器
#
# 检查项:
# 1. 块终止: 每个基本块必须以终止指令结尾 (ret/br/switch/unreachable)
# 2. SSA 唯一性: 每个 %name 只能被定义一次
# 3. 未定义引用: 所有 %name 使用必须有对应定义
# 4. Phi 位置: phi 指令只能出现在块首(非 phi 指令之前)
# ============================================================
# 错误码
VERIFY_OK: t.CDefine = 0
VERIFY_ERR_NO_TERMINATOR: t.CDefine = 1
VERIFY_ERR_DUPLICATE_DEF: t.CDefine = 2
VERIFY_ERR_UNDEFINED_USE: t.CDefine = 3
VERIFY_ERR_PHI_NOT_FIRST: t.CDefine = 4
# ============================================================
# NameEntry: 已定义 SSA 名条目(链表节点)
# ============================================================
class NameEntry(GSListNode[NameEntry]):
Name: t.CChar | t.CPtr # SSA 名(如 "%0"/"%result")
# ============================================================
# VerifyResult: 验证结果
# ============================================================
class VerifyResult:
ErrorCount: t.CInt # 错误总数
WarningCount: t.CInt # 警告总数
ErrorCode: t.CInt # 第一个错误码
ErrorBuf: t.CChar | t.CPtr # 错误消息缓冲区
ErrorBufSize: t.CSizeT # 缓冲区大小
# ============================================================
# 辅助函数
# ============================================================
def _new_verify_result(pool: memhub.MemBuddy | t.CPtr,
buf_size: t.CSizeT) -> VerifyResult | t.CPtr:
"""创建验证结果对象"""
ptr: VerifyResult | t.CPtr = pool.alloc(VerifyResult.__sizeof__())
if ptr is None: return None
string.memset(ptr, 0, VerifyResult.__sizeof__())
ptr.ErrorCount = 0
ptr.WarningCount = 0
ptr.ErrorCode = VERIFY_OK
buf: t.CChar | t.CPtr = pool.alloc(buf_size)
if buf is not None:
buf[0] = '\0'
ptr.ErrorBuf = buf
ptr.ErrorBufSize = buf_size
return ptr
def _report_error(result: VerifyResult | t.CPtr, code: t.CInt, msg: t.CChar | t.CPtr):
"""记录一个错误"""
if result is None: return
result.ErrorCount += 1
if result.ErrorCode == VERIFY_OK:
result.ErrorCode = code
if result.ErrorBuf is not None and msg is not None:
_append_cstr(result.ErrorBuf, result.ErrorBufSize, msg)
_append_cstr(result.ErrorBuf, result.ErrorBufSize, "\n")
def _append_cstr(dst: t.CChar | t.CPtr, dst_size: t.CSizeT, src: t.CChar | t.CPtr):
"""将 src 追加到 dst 末尾"""
if dst is None or src is None: return
dlen: t.CSizeT = string.strlen(dst)
slen: t.CSizeT = string.strlen(src)
remain: t.CSizeT = dst_size - dlen
if remain <= 0: return
i: t.CSizeT = 0
while i < slen and i + 1 < remain:
dst[dlen + i] = src[i]
i += 1
dst[dlen + i] = '\0'
# ============================================================
# SSA 名表操作
# ============================================================
def _new_name_table(pool: memhub.MemBuddy | t.CPtr) -> GSList[NameEntry] | t.CPtr:
"""创建空名表"""
gsl: GSList[NameEntry] | t.CPtr = pool.alloc(24) # GSList: Head+Tail+Count
if gsl is None: return None
string.memset(gsl, 0, 24)
return gsl
# NameEntry 硬编码大小: Next(8) + Name(8) = 16 字节
NENTRY_SIZE: t.CDefine = 16
def _name_table_add(table: GSList[NameEntry] | t.CPtr,
pool: memhub.MemBuddy | t.CPtr,
name: t.CChar | t.CPtr) -> t.CInt:
"""添加名到表。返回 1=重复, 0=成功添加"""
if table is None or name is None: return 0
# 检查重复
cur: NameEntry | t.CPtr = table.Head
while cur is not None:
if string.strcmp(cur.Name, name) == 0:
return 1
cur = cur.Next
# 添加新条目
entry: NameEntry | t.CPtr = pool.alloc(NENTRY_SIZE)
if entry is None: return 0
string.memset(entry, 0, NENTRY_SIZE)
entry.Name = name
table.append(entry)
return 0
def _name_table_contains(table: GSList[NameEntry] | t.CPtr,
name: t.CChar | t.CPtr) -> t.CInt:
"""检查名是否在表中。返回 1=存在, 0=不存在"""
if table is None or name is None: return 0
cur: NameEntry | t.CPtr = table.Head
while cur is not None:
if string.strcmp(cur.Name, name) == 0:
return 1
cur = cur.Next
return 0
# ============================================================
# 文本分析辅助
# ============================================================
def _is_char_name(ch: t.CChar) -> t.CInt:
"""判断字符是否为 SSA 名字符 [a-zA-Z0-9._]"""
if ch >= 'a' and ch <= 'z': return 1
if ch >= 'A' and ch <= 'Z': return 1
if ch >= '0' and ch <= '9': return 1
if ch == '.' or ch == '_': return 1
return 0
def _extract_def_name(pool: memhub.MemBuddy | t.CPtr,
text: t.CChar | t.CPtr) -> t.CChar | t.CPtr:
"""从定义行提取被定义的 SSA 名。
定义行格式: "%<name> = <instruction>"
返回分配的 NUL 结尾名串(如 "%0"),或 None 若非定义行。
"""
if text is None: return None
if text[0] != '%': return None
# 扫描 " = " 模式
i: t.CInt = 1
while text[i] != '\0':
if text[i] == ' ' and text[i + 1] == '=' and text[i + 2] == ' ':
# 找到 " = " 在位置 i
name_len: t.CInt = i
name: t.CChar | t.CPtr = pool.alloc(name_len + 1)
if name is None: return None
j: t.CInt = 0
while j < name_len:
name[j] = text[j]
j += 1
name[name_len] = '\0'
return name
i += 1
return None
def _is_terminator(text: t.CChar | t.CPtr) -> t.CInt:
"""判断文本是否为终止指令"""
if text is None: return 0
if string.strncmp(text, "ret", 3) == 0: return 1
if string.strncmp(text, "br ", 3) == 0: return 1
if string.strncmp(text, "switch ", 7) == 0: return 1
if string.strncmp(text, "unreachable", 11) == 0: return 1
if string.strncmp(text, "indirectbr ", 11) == 0: return 1
if string.strncmp(text, "resume ", 7) == 0: return 1
return 0
def _is_phi(text: t.CChar | t.CPtr) -> t.CInt:
"""判断文本是否为 phi 指令"""
if text is None: return 0
if string.strstr(text, " = phi ") is not None: return 1
return 0
def _check_uses_in_line(table: GSList[NameEntry] | t.CPtr,
text: t.CChar | t.CPtr,
def_name: t.CChar | t.CPtr) -> t.CInt:
"""检查行中所有 SSA 名使用是否已定义。
跳过 def_name(定义位置的名字)。
返回未定义使用数量。
"""
if text is None: return 0
i: t.CInt = 0
undef_count: t.CInt = 0
while text[i] != '\0':
if text[i] == '%':
# 提取名
name_start: t.CInt = i
i += 1
while text[i] != '\0' and _is_char_name(text[i]) == 1:
i += 1
name_len: t.CInt = i - name_start
if name_len > 1:
# 构建临时名串进行比较
# 由于无法在栈上分配,用 strstr 进行简化检查
# 这里采用逐字符比较方式
if _name_matches_at(text, name_start, name_len, table) == 0:
# 检查是否是 def_name(定义本身的位置)
if def_name is not None:
if _str_matches_at(text, name_start, name_len, def_name) == 0:
undef_count += 1
else:
undef_count += 1
else:
i += 1
return undef_count
def _name_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
table: GSList[NameEntry] | t.CPtr) -> t.CInt:
"""检查 text[start:start+length] 是否匹配名表中的某个条目。
返回 1=匹配, 0=不匹配
"""
if table is None: return 0
cur: NameEntry | t.CPtr = table.Head
while cur is not None:
if cur.Name is not None:
if _str_matches_at(text, start, length, cur.Name) == 1:
return 1
cur = cur.Next
return 0
def _str_matches_at(text: t.CChar | t.CPtr, start: t.CInt, length: t.CInt,
target: t.CChar | t.CPtr) -> t.CInt:
"""检查 text[start:start+length] 是否等于 target 字符串。
返回 1=匹配, 0=不匹配
"""
if text is None or target is None: return 0
# 检查 target 长度
target_len: t.CInt = string.strlen(target)
if target_len != length: return 0
i: t.CInt = 0
while i < length:
if text[start + i] != target[i]: return 0
i += 1
return 1
# ============================================================
# 主验证函数
# ============================================================
def verify_function(pool: memhub.MemBuddy | t.CPtr,
func: Function | t.CPtr,
result: VerifyResult | t.CPtr) -> t.CInt:
"""验证函数的 SSA 正确性。
参数:
pool: 内存池
func: 要验证的函数
result: 验证结果(调用前需用 _new_verify_result 创建)
返回: 错误数量(0 = 验证通过)
"""
if func is None or result is None: return 1
# 创建名表
name_table: GSList[NameEntry] | t.CPtr = _new_name_table(pool)
if name_table is None: return 1
# 1. 将函数参数加入名表(参数是已定义的)
param: Param | t.CPtr = None
if func.Params is not None:
param = func.Params.Head
while param is not None:
if param.Name is not None:
_name_table_add(name_table, pool, param.Name)
param = param.Next
# 1b. 将基本块名加入名表(块标签如 %then 是 br/phi 的合法引用目标)
blk_iter: BasicBlock | t.CPtr = None
if func.Blocks is not None:
blk_iter = func.Blocks.Head
while blk_iter is not None:
if blk_iter.Name is not None:
blk_name_len: t.CSizeT = string.strlen(blk_iter.Name)
blk_ref: t.CChar | t.CPtr = pool.alloc(blk_name_len + 2)
if blk_ref is not None:
# 构造 "%<name>" 字符串
blk_ref[0] = '%'
k: t.CSizeT = 0
while k < blk_name_len:
blk_ref[k + 1] = blk_iter.Name[k]
k += 1
blk_ref[blk_name_len + 1] = '\0'
_name_table_add(name_table, pool, blk_ref)
blk_iter = blk_iter.Next
# 2. 遍历所有块
blk: BasicBlock | t.CPtr = None
if func.Blocks is not None:
blk = func.Blocks.Head
while blk is not None:
# 检查终止指令
if blk.IsTerminated == 0:
# 进一步检查最后一行是否为终止指令
has_term: t.CInt = 0
line_check: Line | t.CPtr = None
if blk.Lines is not None:
line_check = blk.Lines.Head
while line_check is not None:
if line_check.Buf is not None:
if _is_terminator(line_check.Buf) == 1:
has_term = 1
line_check = line_check.Next
if has_term == 0:
blk_name: t.CChar | t.CPtr = "<unnamed>"
if blk.Name is not None:
blk_name = blk.Name
err_buf: t.CChar | t.CPtr = pool.alloc(128)
if err_buf is not None:
viperlib.snprintf(err_buf, 128, "ERROR: block '%s' missing terminator", blk_name)
_report_error(result, VERIFY_ERR_NO_TERMINATOR, err_buf)
# 遍历块内指令行
seen_non_phi: t.CInt = 0
line: Line | t.CPtr = None
if blk.Lines is not None:
line = blk.Lines.Head
while line is not None:
if line.Buf is not None:
text: t.CChar | t.CPtr = line.Buf
# 检查 phi 位置
if _is_phi(text) == 1:
if seen_non_phi == 1:
phi_err: t.CChar | t.CPtr = pool.alloc(128)
if phi_err is not None:
viperlib.snprintf(phi_err, 128, "ERROR: phi not at block start")
_report_error(result, VERIFY_ERR_PHI_NOT_FIRST, phi_err)
else:
# 非空行且非 phi 标记为已见非 phi
if string.strlen(text) > 0:
seen_non_phi = 1
# 提取定义名
def_name: t.CChar | t.CPtr = _extract_def_name(pool, text)
if def_name is not None:
# 检查重复定义
dup: t.CInt = _name_table_add(name_table, pool, def_name)
if dup == 1:
dup_err: t.CChar | t.CPtr = pool.alloc(128)
if dup_err is not None:
viperlib.snprintf(dup_err, 128, "ERROR: duplicate definition '%s'", def_name)
_report_error(result, VERIFY_ERR_DUPLICATE_DEF, dup_err)
# 检查未定义使用
undef: t.CInt = _check_uses_in_line(name_table, text, def_name)
if undef > 0:
use_err: t.CChar | t.CPtr = pool.alloc(128)
if use_err is not None:
viperlib.snprintf(use_err, 128, "ERROR: %d undefined use(s) in: %s", undef, text)
_report_error(result, VERIFY_ERR_UNDEFINED_USE, use_err)
line = line.Next
blk = blk.Next
return result.ErrorCount
def verify_module(pool: memhub.MemBuddy | t.CPtr, mod: LLVMModule | t.CPtr, result: VerifyResult | t.CPtr) -> t.CInt:
"""验证模块中所有函数的 SSA 正确性。
返回: 错误总数
"""
if mod is None or result is None: return 1
func: Function | t.CPtr = mod.FuncHead
while func is not None:
if func.IsDeclared == 0:
# 只验证有函数体的定义,跳过声明
verify_function(pool, func, result)
func = func.Next
return result.ErrorCount
+39
View File
@@ -0,0 +1,39 @@
import t, c
from stdint import *
from w32.win32base import *
from w32.win32sync import CRITICAL_SECTION, InitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection, DeleteCriticalSection, TryEnterCriticalSection
@t.Object
class Lock:
"""基于 CRITICAL_SECTION 的互斥锁,支持递归加锁。
用法:
lock: Lock = Lock()
with lock:
# 临界区
pass
"""
cs: CRITICAL_SECTION
def __init__(self):
InitializeCriticalSection(c.Addr(self.cs))
def acquire(self):
EnterCriticalSection(c.Addr(self.cs))
def release(self):
LeaveCriticalSection(c.Addr(self.cs))
def try_acquire(self) -> BOOL:
return TryEnterCriticalSection(c.Addr(self.cs))
def __enter__(self) -> 'Lock' | t.CPtr:
self.acquire()
return self
def __exit__(self):
self.release()
def delete(self):
DeleteCriticalSection(c.Addr(self.cs))
+479
View File
@@ -0,0 +1,479 @@
import t, c
from stdint import *
import string
import atom
import viperio
# ============================================================
# memhub - 统一内存管理库
# MemManager (多态基类, vtable)
# ├─ MemPool (arena bump 分配器, 不支持单个 free)
# ├─ MemSlab (定长块池, 支持 alloc/free 位图跟踪)
# └─ MemBuddy (伙伴系统, 支持 alloc/free/realloc 合并)
# 所有子类通过 vtable 覆盖 alloc/free/reset, 可用 MemManager 指针多态调用
# ============================================================
MEMHUB_ALIGN: t.CDefine = 8
# MemSlab 位图常量
MEMSLAB_MIN_BLOCK: t.CDefine = 16
MEMSLAB_BITMAP_BYTES: t.CDefine = 256
# MemBuddy 伙伴系统常量
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)
def _largest_pow2_le(val: t.CSizeT) -> t.CSizeT:
if val == 0: return 0
p: t.CSizeT = 1
while p * 2 <= val:
p = p * 2
return p
def _block_size_at_order(order: t.CInt) -> t.CSizeT:
bs: t.CSizeT = MEMBUDDY_MIN_BLOCK
i: t.CInt
for i in range(order):
bs = bs << 1
return bs
# ============================================================
# MemManager - 多态基类
# @t.CVTable 显式标记, 确保跨模块导入时也被识别为 vtable 类
# (HandlesImports 只通过装饰器检测 IsCVTable, 不像同模块自动推断)
# ============================================================
@t.CVTable
class MemManager:
__provides__: list[str] = ['__memmgr__']
base: t.CVoid | t.CPtr # 内存区起始地址
size: t.CSizeT # 内存区总大小
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
self.base = base
self.size = size
# === 虚函数 (子类覆盖) ===
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
# 默认: 不支持分配
return None
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
# 默认: 无操作
return 0
def reset(self) -> t.CInt:
# 默认: 无操作
return 0
# === 具体方法 (调用虚函数, 自动多态分派) ===
def calloc(self, count: t.CSizeT, size: t.CSizeT) -> t.CVoid | t.CPtr:
total: t.CSizeT = count * size
ptr: t.CVoid | t.CPtr = self.alloc(total)
if ptr is not None:
string.memset(ptr, 0, total)
return ptr
def realloc(self, ptr: t.CVoid | t.CPtr, old_size: t.CSizeT, new_size: t.CSizeT) -> t.CVoid | t.CPtr:
if ptr is None:
return self.alloc(new_size)
if new_size == 0:
self.free(ptr)
return None
new_ptr: t.CVoid | t.CPtr = self.alloc(new_size)
if new_ptr is None:
return ptr
copy_size: t.CSizeT = old_size
if new_size < old_size:
copy_size = new_size
string.memcpy(new_ptr, ptr, copy_size)
self.free(ptr)
return new_ptr
def __enter__(self) -> 'MemManager' | t.CPtr:
return self
def __exit__(self):
self.reset()
def alloc_buf(self, capacity: t.CSizeT) -> viperio.Buf | t.CPtr:
buf: viperio.Buf | t.CPtr = self.alloc(viperio.Buf.__sizeof__())
if buf is None:
return None
data_ptr: t.CVoid | t.CPtr = self.alloc(capacity)
if data_ptr is None:
return None
buf.__before_init__()
buf.__init__(t.CChar(t.CUInt64T(data_ptr), t.CPtr), capacity)
return buf
# ============================================================
# MemPool - arena bump 分配器
# 不支持单个 free, reset 一次性回收全部
# ============================================================
class MemPool(MemManager):
offset: t.CSizeT # bump 游标
high_water: t.CSizeT # 峰值水位
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
self.base = base
self.size = size
self.offset = 0
self.high_water = 0
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
ptr: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(self.base) + self.offset, t.CPtr)
self.offset += aligned
if self.offset > self.high_water:
self.high_water = self.offset
return ptr
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
# bump 分配器不支持单个 free
return 1
def reset(self) -> t.CInt:
self.offset = 0
self.high_water = 0
return 1
# ============================================================
# MemSlab - 定长块池
# arena 开头存位图, 后续区域按 block_size 切分, 空闲链管理
# ============================================================
class MemSlab(MemManager):
block_size: t.CSizeT # 每块大小 (对齐后)
block_count: t.CSizeT # 总块数
used_count: t.CSizeT # 已用块数
free_list: t.CVoid | t.CPtr # 空闲链头
alloc_map: t.CUInt8T | t.CPtr # 分配位图 (位于 arena 开头)
alloc_map_size: t.CSizeT # 位图字节数
usable: t.CVoid | t.CPtr # 可用块区起始 (跳过位图)
usable_size: t.CSizeT # 可用块区大小
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT, block_size: t.CSizeT):
self.base = base
self.size = size
self.block_size = 0
self.block_count = 0
self.used_count = 0
self.free_list = None
self.alloc_map = None
self.alloc_map_size = 0
self.usable = None
self.usable_size = 0
if base is None: return
bs: t.CSizeT = _align_up(block_size, MEMHUB_ALIGN)
if bs < MEMSLAB_MIN_BLOCK: bs = MEMSLAB_MIN_BLOCK
map_bytes: t.CSizeT = _align_up(MEMSLAB_BITMAP_BYTES, MEMHUB_ALIGN)
if size < map_bytes + bs: return
self.alloc_map = base
self.alloc_map_size = map_bytes
self.usable = t.CVoid(t.CUInt64T(base) + map_bytes, t.CPtr)
self.usable_size = size - map_bytes
self.block_size = bs
# 清零位图
idx: t.CSizeT = 0
while idx < map_bytes:
self.alloc_map[idx] = 0
idx += 1
self.block_count = self.usable_size / bs
if self.block_count == 0: return
# 构建空闲链: 每块首 8 字节存下一块指针
self.free_list = None
i: t.CSizeT = 0
while i < self.block_count:
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(self.usable) + i * bs, t.CPtr)
c.DerefAs(block, self.free_list)
self.free_list = block
i += 1
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
# slab 模式: 仅当请求 <= block_size 时分配一块
if self.free_list is None: return None
if size > self.block_size: return None
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
idx: t.CSizeT = (t.CUInt64T(block) - t.CUInt64T(self.usable)) / self.block_size
self.alloc_map[idx / 8] = self.alloc_map[idx / 8] | t.CUInt8T(1 << (idx % 8))
return block
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
if ptr is None: return 0
p: t.CUInt64T = t.CUInt64T(ptr)
if p < t.CUInt64T(self.usable): return 0
if p >= t.CUInt64T(self.usable) + self.block_count * self.block_size: return 0
if (p - t.CUInt64T(self.usable)) % self.block_size != 0: return 0
idx: t.CSizeT = (p - t.CUInt64T(self.usable)) / self.block_size
byte_idx: t.CSizeT = idx / 8
bit_idx: t.CInt = t.CInt(idx % 8)
if (self.alloc_map[byte_idx] >> bit_idx) & 1 == 0: return 0
self.alloc_map[byte_idx] = self.alloc_map[byte_idx] & t.CUInt8T(~(1 << bit_idx))
c.DerefAs(ptr, self.free_list)
self.free_list = ptr
self.used_count -= 1
return 1
def reset(self) -> t.CInt:
self.used_count = 0
self.free_list = None
i: t.CSizeT = 0
while i < self.block_count:
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(self.usable) + i * self.block_size, t.CPtr)
c.DerefAs(block, self.free_list)
self.free_list = block
if i / 8 < self.alloc_map_size:
self.alloc_map[i / 8] = 0
i += 1
return 1
# ============================================================
# MemBuddy - 伙伴系统分配器
# arena 开头存空闲链头数组, 后续区域按 2 的幂管理
# 线程安全 (自旋锁), 支持合并
# ============================================================
class MemBuddy(MemManager):
max_order: t.CInt # 最大阶数
free_lists: t.CUInt64T | t.CPtr # 空闲链头数组 (位于 arena 开头)
lock_val: t.CVolatile | t.CInt # 自旋锁
usable: t.CVoid | t.CPtr # 可用区起始 (跳过 free_lists)
usable_size: t.CSizeT # 可用区大小 (2 的幂)
def __init__(self, base: t.CVoid | t.CPtr, size: t.CSizeT):
self.base = base
self.size = size
self.max_order = 0
self.free_lists = None
self.lock_val = 0
self.usable = None
self.usable_size = 0
self.lock_val = 0
fl_bytes: t.CSizeT = (MEMBUDDY_MAX_ORDERS + 1) * 8
self.free_lists = base
# 初始化所有空闲链头为 0
i: t.CInt
for i in range(MEMBUDDY_MAX_ORDERS + 1):
self.free_lists[i] = 0
if size <= fl_bytes:
self.usable = None
self.usable_size = 0
self.max_order = 0
return
remaining: t.CSizeT = size - fl_bytes
usable: t.CSizeT = _largest_pow2_le(remaining)
if usable < MEMBUDDY_MIN_BLOCK:
self.usable = None
self.usable_size = 0
self.max_order = 0
return
self.usable = t.CVoid(t.CUInt64T(base) + fl_bytes, t.CPtr)
self.usable_size = usable
# 计算 max_order: log2(usable / MIN_BLOCK)
self.max_order = 0
bs: t.CSizeT = MEMBUDDY_MIN_BLOCK
while bs < usable:
bs = bs << 1
self.max_order += 1
# 整个可用区作为 max_order 阶空闲块
self._fl_push(self.max_order, self.usable)
# === 空闲链操作 ===
def _fl_push(self, order: t.CInt, block: t.CVoid | t.CPtr):
old_head: t.CUInt64T = self.free_lists[order]
c.DerefAs(block, t.CVoid(old_head, t.CPtr))
self.free_lists[order] = t.CUInt64T(block)
def _fl_pop(self, order: t.CInt) -> t.CVoid | t.CPtr:
head_val: t.CUInt64T = self.free_lists[order]
if head_val == 0:
return None
block: t.CVoid | t.CPtr = t.CVoid(head_val, t.CPtr)
next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
self.free_lists[order] = t.CUInt64T(next_ptr)
return block
def _fl_find_and_remove(self, order: t.CInt, target: t.CVoid | t.CPtr) -> t.CInt:
head_val: t.CUInt64T = self.free_lists[order]
if head_val == 0:
return 0
head: t.CVoid | t.CPtr = t.CVoid(head_val, t.CPtr)
if t.CUInt64T(head) == t.CUInt64T(target):
next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(head, t.CPtr)), t.CPtr)
self.free_lists[order] = t.CUInt64T(next_ptr)
return 1
prev: t.CVoid | t.CPtr = head
cur: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(head, t.CPtr)), t.CPtr)
while cur is not None:
if t.CUInt64T(cur) == t.CUInt64T(target):
next_ptr: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr)
c.DerefAs(prev, next_ptr)
return 1
prev = cur
cur = t.CVoid(c.Deref(t.CUInt64T(cur, t.CPtr)), t.CPtr)
return 0
# === 伙伴系统核心 ===
def _buddy_of(self, block: t.CVoid | t.CPtr, order: t.CInt) -> t.CVoid | t.CPtr:
offset: t.CSizeT = t.CUInt64T(block) - t.CUInt64T(self.usable)
bs: t.CSizeT = _block_size_at_order(order)
buddy_offset: t.CSizeT = offset ^ bs
return t.CVoid(t.CUInt64T(self.usable) + buddy_offset, t.CPtr)
def _order_for_size(self, size: t.CSizeT) -> t.CInt:
order: t.CInt = 0
bs: t.CSizeT = MEMBUDDY_MIN_BLOCK
while bs < size:
bs = bs << 1
order += 1
return order
def _split_to_order(self, to_order: t.CInt) -> t.CVoid | t.CPtr:
found_order: t.CInt = to_order
while found_order <= self.max_order:
if self.free_lists[found_order] != 0:
break
found_order += 1
if found_order > self.max_order:
return None
block: t.CVoid | t.CPtr = self._fl_pop(found_order)
while found_order > to_order:
found_order -= 1
bs: t.CSizeT = _block_size_at_order(found_order)
buddy: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(block) + bs, t.CPtr)
self._fl_push(found_order, buddy)
return block
def _coalesce(self, block: t.CVoid | t.CPtr, order: t.CInt):
while order < self.max_order:
buddy: t.CVoid | t.CPtr = self._buddy_of(block, order)
found: t.CInt = self._fl_find_and_remove(order, buddy)
if found == 0:
break
if t.CUInt64T(buddy) < t.CUInt64T(block):
block = buddy
order += 1
self._fl_push(order, block)
def _is_valid_ptr(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
if ptr is None: return 0
if self.usable is None: return 0
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MEMBUDDY_HEADER_SIZE, t.CPtr)
if t.CUInt64T(block) < t.CUInt64T(self.usable): return 0
if t.CUInt64T(block) >= t.CUInt64T(self.usable) + self.usable_size: return 0
offset: t.CSizeT = t.CUInt64T(block) - t.CUInt64T(self.usable)
if offset % MEMBUDDY_MIN_BLOCK != 0: return 0
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: return 0
order: t.CInt = t.CInt(stored_val >> 1)
if order < 0: return 0
if order > self.max_order: return 0
return 1
# === 锁 ===
def _lock(self):
while atom.__atomic_test_and_set(c.Addr(self.lock_val), atom.ATOMIC_ACQUIRE):
pass
def _unlock(self):
atom.__atomic_clear(c.Addr(self.lock_val), atom.ATOMIC_RELEASE)
# === 虚函数覆盖 ===
def alloc(self, size: t.CSizeT) -> t.CVoid | t.CPtr:
self._lock()
result: t.CVoid | t.CPtr = None
if self.usable is not None:
if size != 0:
needed: t.CSizeT = size + MEMBUDDY_HEADER_SIZE
order: t.CInt = self._order_for_size(needed)
if order <= self.max_order:
block: t.CVoid | t.CPtr = self._split_to_order(order)
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)
self._unlock()
return result
def free(self, ptr: t.CVoid | t.CPtr) -> t.CInt:
self._lock()
if ptr is not None:
if self._is_valid_ptr(ptr) != 0:
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MEMBUDDY_HEADER_SIZE, t.CPtr)
stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
stored_val: t.CUInt64T = t.CUInt64T(stored)
order: t.CInt = t.CInt(stored_val >> 1)
c.DerefAs(block, t.CVoid(0, t.CPtr))
self._coalesce(block, order)
self._unlock()
return 1
def reset(self) -> t.CInt:
if self.usable is None:
return 0
i: t.CInt
for i in range(MEMBUDDY_MAX_ORDERS + 1):
self.free_lists[i] = 0
self._fl_push(self.max_order, self.usable)
return 1
# realloc 覆盖: 伙伴系统从块头读取旧阶数, 无需 old_size
def realloc(self, ptr: t.CVoid | t.CPtr, old_size: t.CSizeT, new_size: t.CSizeT) -> t.CVoid | t.CPtr:
if ptr is None:
return self.alloc(new_size)
if new_size == 0:
self.free(ptr)
return None
if self._is_valid_ptr(ptr) == 0:
return None
block: t.CVoid | t.CPtr = t.CVoid(t.CUInt64T(ptr) - MEMBUDDY_HEADER_SIZE, t.CPtr)
stored: t.CVoid | t.CPtr = t.CVoid(c.Deref(t.CUInt64T(block, t.CPtr)), t.CPtr)
stored_val: t.CUInt64T = t.CUInt64T(stored)
old_order: t.CInt = t.CInt(stored_val >> 1)
needed: t.CSizeT = new_size + MEMBUDDY_HEADER_SIZE
new_order: t.CInt = self._order_for_size(needed)
if new_order <= old_order:
return ptr
new_ptr: t.CVoid | t.CPtr = self.alloc(new_size)
if new_ptr is None:
return ptr
old_block_size: t.CSizeT = _block_size_at_order(old_order)
old_data_size: t.CSizeT = old_block_size - MEMBUDDY_HEADER_SIZE
string.memcpy(new_ptr, ptr, old_data_size)
self.free(ptr)
return new_ptr
File diff suppressed because it is too large. Load diff
+133
View File
@@ -0,0 +1,133 @@
import t, c
from stdint import *
import platmacro
import memhub
import os.path
import os._win32
import os._posix
# os 包入口
# 根据 platmacro.IS_WINDOWS 分派到 _win32 或 _posix 后端
# os.path 为跨平台纯字符串操作,直接可用
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# =============================================================================
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
if platmacro.IS_WINDOWS:
return os._win32.exists(path)
return os._posix.exists(path)
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
if platmacro.IS_WINDOWS:
return os._win32.isdir(path)
return os._posix.isdir(path)
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
if platmacro.IS_WINDOWS:
return os._win32.isfile(path)
return os._posix.isfile(path)
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
if platmacro.IS_WINDOWS:
return os._win32.getsize(path)
return os._posix.getsize(path)
# =============================================================================
# 工作目录
# =============================================================================
def getcwd() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
if platmacro.IS_WINDOWS:
return os._win32.getcwd()
return os._posix.getcwd_impl()
def chdir(path: str) -> int:
"""切换当前工作目录。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return os._win32.chdir(path)
return os._posix.chdir_impl(path)
# =============================================================================
# 文件/目录操作
# =============================================================================
def mkdir(path: str) -> int:
"""创建目录。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return os._win32.mkdir(path)
return os._posix.mkdir_impl(path)
def remove(path: str) -> int:
"""删除文件。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return os._win32.remove(path)
return os._posix.remove(path)
def rmdir(path: str) -> int:
"""删除空目录。成功返回 0,失败返回 -1。"""
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。"""
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 上使用完整权限位。"""
if platmacro.IS_WINDOWS:
return os._win32.chmod(path, mode)
return os._posix.chmod_impl(path, mode)
# =============================================================================
# 目录列举
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
"""列举目录下的文件/子目录名。
out_names 为调用者提供的字符串指针数组(char**),每个元素指向一个文件名。
文件名通过 _mbuddy 分配内存。
max_count 为 out_names 数组最大容量。
返回实际列举的条目数。失败返回 0。"""
if platmacro.IS_WINDOWS:
return os._win32.listdir(path, out_names, max_count)
return os._posix.listdir(path, out_names, max_count)
# =============================================================================
# 命令执行
# =============================================================================
def system(cmd: str) -> int:
"""执行命令行命令(通过 C 运行时 system())。
命令输出直接到终端(继承父进程 stdout/stderr)。
返回命令的退出码(0 表示成功)。"""
if platmacro.IS_WINDOWS:
return os._win32.system(cmd)
return os._posix.system_impl(cmd)
+190
View File
@@ -0,0 +1,190 @@
import t, c
from stdint import *
import posix
import memhub
import stdlib
# POSIX 路径最大长度
MAX_PATH_LEN: t.CDefine = 4096
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# =============================================================================
def _stat(path: str) -> posix.Stat | t.CPtr:
"""调用 stat 并返回 Stat 结构体指针。失败返回 None。
注意:Stat 结构体通过 _mbuddy 分配,调用者负责释放。"""
st: posix.Stat = posix.Stat()
result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
if result != 0:
return None
return t.CPtr(c.Addr(st))
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
result: INT = posix.access(path, posix.F_OK)
if result == 0:
return True
return False
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
st: posix.Stat = posix.Stat()
result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
if result != 0:
return False
if posix.S_ISDIR(st.st_mode):
return True
return False
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
st: posix.Stat = posix.Stat()
result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
if result != 0:
return False
if posix.S_ISREG(st.st_mode):
return True
return False
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
st: posix.Stat = posix.Stat()
result: INT = posix.stat(path, t.CPtr(c.Addr(st)))
if result != 0:
return -1
return st.st_size
# =============================================================================
# 工作目录
# =============================================================================
def getcwd_impl() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
buf: bytes = _mbuddy.alloc(MAX_PATH_LEN)
if buf == None: return None
result: CHARPTR = posix.getcwd(buf, MAX_PATH_LEN)
if result == None:
return None
return str(buf)
def chdir_impl(path: str) -> int:
"""切换当前工作目录。成功返回 0,失败返回 -1。"""
result: INT = posix.chdir(path)
if result != 0:
return -1
return 0
# =============================================================================
# 文件/目录操作
# =============================================================================
def mkdir_impl(path: str) -> int:
"""创建目录。成功返回 0,失败返回 -1。
默认权限 0o755(rwxr-xr-x)。"""
result: INT = posix.mkdir(path, 0o755)
if result != 0:
return -1
return 0
def remove(path: str) -> int:
"""删除文件。成功返回 0,失败返回 -1。"""
result: INT = posix.unlink(path)
if result != 0:
return -1
return 0
def rmdir_impl(path: str) -> int:
"""删除空目录。成功返回 0,失败返回 -1。"""
result: INT = posix.rmdir(path)
if result != 0:
return -1
return 0
def rename_impl(old_path: str, new_path: str) -> int:
"""重命名/移动文件或目录。成功返回 0,失败返回 -1。"""
result: INT = posix.rename(old_path, new_path)
if result != 0:
return -1
return 0
def chmod_impl(path: str, mode: int) -> int:
"""修改文件权限。成功返回 0,失败返回 -1。
mode 为 POSIX 权限位(如 0o755)。"""
result: INT = posix.chmod(path, posix.mode_t(mode))
if result != 0:
return -1
return 0
# =============================================================================
# 目录列举(opendir / readdir / closedir)
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
"""列举目录下的文件/子目录名。
out_names 为调用者提供的字符串指针数组(char**),每个元素指向一个文件名。
文件名通过 _mbuddy 分配内存。
max_count 为 out_names 数组最大容量。
返回实际列举的条目数。失败返回 0。"""
dirp: posix.DIR | t.CPtr = posix.opendir(path)
if dirp == None:
return 0
count: ULONG = 0
while count < max_count:
entry: posix.Dirent | t.CPtr = posix.readdir(dirp)
if entry == None:
break
# 读取 d_name 字段
name: str = entry.d_name
if name[0] == '.':
if name[1] == 0:
# "."
continue
if name[1] == '.' and name[2] == 0:
# ".."
continue
# 复制文件名到新分配的内存
name_len: t.CSizeT = len(name)
name_buf: bytes = _mbuddy.alloc(name_len + 1)
if name_buf == None: break
i: t.CSizeT = 0
for ch in name:
name_buf[i] = ch
i += 1
name_buf[name_len] = 0
out_names[count] = str(name_buf)
count += 1
posix.closedir(dirp)
return count
# =============================================================================
# 命令执行
# =============================================================================
def system_impl(cmd: str) -> int:
"""执行命令行命令(通过 C 运行时 system())。
命令输出直接到子进程的终端(继承父进程 stdout/stderr)。
返回命令的退出码(0 表示成功)。"""
return stdlib.system(cmd)
+234
View File
@@ -0,0 +1,234 @@
import t, c
from stdint import *
import w32.win32base
import w32.win32file
import memhub
import stdlib
# Windows 路径最大长度
MAX_PATH_LEN: t.CDefine = 260
# INVALID_FILE_ATTRIBUTES
INVALID_FILE_ATTRIBUTES: t.CDefine = 0xFFFFFFFF
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 文件/目录属性查询
# =============================================================================
def _get_attrs(path: str) -> ULONG:
"""获取文件属性。失败返回 INVALID_FILE_ATTRIBUTES。"""
return w32.win32file.GetFileAttributesA(path)
def exists(path: str) -> bool:
"""检查文件/目录是否存在"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
return True
def isdir(path: str) -> bool:
"""检查路径是否为目录"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
return True
return False
def isfile(path: str) -> bool:
"""检查路径是否为普通文件"""
attrs: ULONG = _get_attrs(path)
if attrs == INVALID_FILE_ATTRIBUTES:
return False
if (attrs & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
return False
return True
def getsize(path: str) -> t.CInt64T:
"""返回文件大小(字节)。失败返回 -1。"""
handle: w32.win32base.HANDLE = w32.win32file.CreateFileA(
path, w32.win32file.GENERIC_READ, w32.win32file.FILE_SHARE_READ,
t.CPtr(0), w32.win32file.OPEN_EXISTING, w32.win32file.FILE_ATTRIBUTE_NORMAL, t.CPtr(0)
)
if handle == w32.win32base.INVALID_HANDLE_VALUE:
return -1
li: w32.win32base.LARGE_INTEGER = w32.win32base.LARGE_INTEGER()
result: BOOL = w32.win32file.GetFileSizeEx(handle, t.CPtr(c.Addr(li)))
w32.win32base.CloseHandle(handle)
if result == 0:
return -1
return li.QuadPart
# =============================================================================
# 工作目录
# =============================================================================
def getcwd() -> str:
"""返回当前工作目录(通过 _mbuddy 分配内存)"""
buf: bytes = _mbuddy.alloc(MAX_PATH_LEN + 1)
if buf == None: return None
length: ULONG = w32.win32file.GetCurrentDirectoryA(MAX_PATH_LEN + 1, buf)
if length == 0:
return None
if length > MAX_PATH_LEN:
# 缓冲区不够,重新分配
buf2: bytes = _mbuddy.alloc(length + 1)
if buf2 == None: return None
w32.win32file.GetCurrentDirectoryA(length + 1, buf2)
buf2[length] = 0
return str(buf2)
buf[length] = 0
return str(buf)
def chdir(path: str) -> int:
"""切换当前工作目录。成功返回 0,失败返回 -1。"""
result: BOOL = w32.win32file.SetCurrentDirectoryA(path)
if result == 0:
return -1
return 0
# =============================================================================
# 文件/目录操作
# =============================================================================
def mkdir(path: str) -> int:
"""创建目录。成功返回 0,失败返回 -1。"""
result: BOOL = w32.win32file.CreateDirectoryA(path, t.CPtr(0))
if result == 0:
return -1
return 0
def remove(path: str) -> int:
"""删除文件。成功返回 0,失败返回 -1。"""
result: BOOL = w32.win32file.DeleteFileA(path)
if result == 0:
return -1
return 0
def rmdir(path: str) -> int:
"""删除空目录。成功返回 0,失败返回 -1。"""
result: BOOL = w32.win32file.RemoveDirectoryA(path)
if result == 0:
return -1
return 0
def rename(old_path: str, new_path: str) -> int:
"""重命名/移动文件或目录。成功返回 0,失败返回 -1。"""
result: BOOL = w32.win32file.MoveFileExA(
old_path, new_path,
w32.win32file.MOVEFILE_REPLACE_EXISTING | w32.win32file.MOVEFILE_COPY_ALLOWED
)
if result == 0:
return -1
return 0
def chmod(path: str, mode: int) -> int:
"""修改文件属性(Windows 简化版:只处理只读位)。
mode 的 S_IWUSR 位(0o200)为 0 时设为只读,为 1 时设为可写。
成功返回 0,失败返回 -1。"""
if (mode & 0o200) != 0:
# 可写:清除只读属性
result: BOOL = w32.win32file.SetFileAttributesA(
path, w32.win32file.FILE_ATTRIBUTE_NORMAL
)
else:
# 只读:设置只读属性
result: BOOL = w32.win32file.SetFileAttributesA(
path, w32.win32file.FILE_ATTRIBUTE_READONLY
)
if result == 0:
return -1
return 0
# =============================================================================
# 目录列举(FindFirstFile / FindNextFile)
# =============================================================================
def listdir(path: str, out_names: str, max_count: ULONG) -> ULONG:
"""列举目录下的文件/子目录名。
out_names 为调用者提供的字符串指针数组(char**),每个元素指向一个文件名。
文件名通过 _mbuddy 分配内存。
max_count 为 out_names 数组最大容量。
返回实际列举的条目数。失败返回 0。"""
# 构造搜索模式:path\*
path_len: t.CSizeT = len(path)
pattern: bytes = _mbuddy.alloc(path_len + 3)
if pattern == None: return 0
i: t.CSizeT = 0
for ch in path:
pattern[i] = ch
i += 1
# 添加 \* 后缀
if path[path_len - 1] != '\\' and path[path_len - 1] != '/':
pattern[i] = '\\'
i += 1
pattern[i] = '*'
i += 1
pattern[i] = 0
find_data: w32.win32file.WIN32_FIND_DATAA = w32.win32file.WIN32_FIND_DATAA()
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, t.CPtr(c.Addr(find_data)))
if handle == w32.win32base.INVALID_HANDLE_VALUE:
return 0
count: ULONG = 0
while count < max_count:
# 跳过 . 和 ..
name: str = find_data.cFileName
if name[0] == '.':
if name[1] == 0:
# "."
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
continue
if name[1] == '.' and name[2] == 0:
# ".."
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
continue
# 复制文件名到新分配的内存
name_len: t.CSizeT = len(name)
name_buf: bytes = _mbuddy.alloc(name_len + 1)
if name_buf == None: break
j: t.CSizeT = 0
for ch in name:
name_buf[j] = ch
j += 1
name_buf[name_len] = 0
out_names[count] = str(name_buf)
count += 1
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
break
w32.win32file.FindClose(handle)
return count
# =============================================================================
# 命令执行
# =============================================================================
def system(cmd: str) -> int:
"""执行命令行命令(通过 C 运行时 system())。
命令输出直接到子进程的终端(继承父进程 stdout/stderr)。
返回命令的退出码(0 表示成功)。"""
return stdlib.system(cmd)
+316
View File
@@ -0,0 +1,316 @@
import t, c
from stdint import *
import string
import memhub
import platmacro
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# 路径分隔符
# =============================================================================
def sep() -> t.CChar:
"""返回当前平台的路径分隔符(Windows: \\,POSIX: /)"""
if platmacro.IS_WINDOWS:
return '\\'
return '/'
def _is_sep(ch: t.CChar) -> bool:
"""判断字符是否为路径分隔符(/ 或 \\,跨平台识别)"""
return ch == '/' or ch == '\\'
# =============================================================================
# 内部辅助函数
# =============================================================================
def _dup_str(s: str) -> str:
"""复制字符串(通过全局 MBuddy 分配内存)"""
if s == None: return None
length: t.CSizeT = len(s)
buf: bytes = _mbuddy.alloc(length + 1)
if buf == None: return None
i: t.CSizeT = 0
for ch in s:
buf[i] = ch
i += 1
buf[length] = 0
return str(buf)
def _substr(s: str, start: t.CSizeT, end: t.CSizeT) -> str:
"""提取子串 s[start:end](通过全局 MBuddy 分配内存)"""
if s == None: return None
if start >= end: return _dup_str("")
result_len: t.CSizeT = end - start
buf: bytes = _mbuddy.alloc(result_len + 1)
if buf == None: return None
i: t.CSizeT = 0
k: t.CSizeT = start
while k < end:
buf[i] = s[k]
i += 1
k += 1
buf[i] = 0
return str(buf)
# =============================================================================
# 路径判断
# =============================================================================
def isabs(path: str) -> bool:
"""判断路径是否为绝对路径。
POSIX: 以 / 开头。
Windows: 以 \\ 开头(UNC)或 X:\\ / X:/ 开头(盘符)。"""
if path == None: return False
if path[0] == 0: return False
if path[0] == '/' or path[0] == '\\': return True
if platmacro.IS_WINDOWS:
# 检查 X:\ 或 X:/ 模式
c0: t.CChar = path[0]
if (c0 >= 'A' and c0 <= 'Z') or (c0 >= 'a' and c0 <= 'z'):
if path[1] == ':':
if path[2] == '\\' or path[2] == '/':
return True
return False
# =============================================================================
# 路径拼接与分割
# =============================================================================
def join(path1: str, path2: str) -> str:
"""拼接两个路径。如果 path2 是绝对路径,返回 path2 的副本。"""
if path1 == None or path1[0] == 0:
return _dup_str(path2)
if path2 == None or path2[0] == 0:
return _dup_str(path1)
if isabs(path2):
return _dup_str(path2)
len1: t.CSizeT = len(path1)
len2: t.CSizeT = len(path2)
# 检查 path1 是否以分隔符结尾
need_sep: bool = True
if _is_sep(path1[len1 - 1]):
need_sep = False
total: t.CSizeT = len1 + len2 + 1
if need_sep:
total += 1
buf: bytes = _mbuddy.alloc(total)
if buf == None: return None
# 复制 path1
i: t.CSizeT = 0
for ch in path1:
buf[i] = ch
i += 1
# 添加分隔符
if need_sep:
buf[i] = sep()
i += 1
# 复制 path2
for ch in path2:
buf[i] = ch
i += 1
buf[i] = 0
return str(buf)
def basename(path: str) -> str:
"""返回路径的文件名部分(最后一个分隔符之后的内容)"""
if path == None: return None
length: t.CSizeT = len(path)
if length == 0: return _dup_str("")
# 从后向前找分隔符
i: t.CSizeT = length
while i > 0:
i -= 1
if _is_sep(path[i]):
return _substr(path, i + 1, length)
# 没有分隔符,返回整个路径的副本
return _dup_str(path)
def dirname(path: str) -> str:
"""返回路径的目录部分(最后一个分隔符之前的内容)"""
if path == None: return None
length: t.CSizeT = len(path)
if length == 0: return _dup_str("")
# 从后向前找分隔符
i: t.CSizeT = length
while i > 0:
i -= 1
if _is_sep(path[i]):
if i == 0:
# 路径以分隔符开头,返回根目录
return _dup_str("/")
return _substr(path, 0, i)
# 没有分隔符,返回空字符串
return _dup_str("")
# =============================================================================
# 扩展名处理
# =============================================================================
def splitext_name(path: str) -> str:
"""返回路径去除扩展名后的主名部分。
扩展名从最后一个 '.' 开始(该 '.' 不能是路径最后一个组件的第一个字符)。"""
if path == None: return None
length: t.CSizeT = len(path)
if length == 0: return _dup_str("")
# 从后向前找 '.',遇到分隔符停止
i: t.CSizeT = length
while i > 0:
i -= 1
if path[i] == '.':
return _substr(path, 0, i)
if _is_sep(path[i]):
break
# 没有扩展名,返回整个路径的副本
return _dup_str(path)
def splitext_ext(path: str) -> str:
"""返回路径的扩展名部分(包含 '.')。无扩展名时返回空字符串。"""
if path == None: return None
length: t.CSizeT = len(path)
if length == 0: return _dup_str("")
# 从后向前找 '.',遇到分隔符停止
i: t.CSizeT = length
while i > 0:
i -= 1
if path[i] == '.':
return _substr(path, i, length)
if _is_sep(path[i]):
break
# 没有扩展名,返回空字符串
return _dup_str("")
# =============================================================================
# 路径规范化
# =============================================================================
def normpath(path: str) -> str:
"""规范化路径:统一分隔符、消除多余的 . 和 .. 组件、合并连续分隔符。
注意:不解析符号链接,不调用系统 API。"""
if path == None: return None
length: t.CSizeT = len(path)
if length == 0: return _dup_str(".")
# 分配输出缓冲区(最坏情况:长度不变 + 前缀 /)
buf: bytes = _mbuddy.alloc(length + 2)
if buf == None: return None
out_pos: t.CSizeT = 0
i: t.CSizeT = 0
s: str = sep()
# 处理绝对路径前缀
is_absolute: bool = False
if _is_sep(path[0]):
is_absolute = True
buf[out_pos] = s
out_pos += 1
i = 1
# Windows 盘符前缀(X:\ 或 X:/)
drive_prefix_len: t.CSizeT = 0
if platmacro.IS_WINDOWS:
if length >= 3:
c0: t.CChar = path[0]
if (c0 >= 'A' and c0 <= 'Z') or (c0 >= 'a' and c0 <= 'z'):
if path[1] == ':':
if _is_sep(path[2]):
buf[out_pos] = path[0]
out_pos += 1
buf[out_pos] = ':'
out_pos += 1
buf[out_pos] = s
out_pos += 1
drive_prefix_len = 3
i = 3
is_absolute = True
# 逐组件处理
while i < length:
# 跳过连续分隔符
while i < length and _is_sep(path[i]):
i += 1
if i >= length:
break
# 提取组件
comp_start: t.CSizeT = i
while i < length and not _is_sep(path[i]):
i += 1
comp_len: t.CSizeT = i - comp_start
# 处理 "." 组件:跳过
if comp_len == 1 and path[comp_start] == '.':
continue
# 处理 ".." 组件:回退一级
if comp_len == 2 and path[comp_start] == '.' and path[comp_start + 1] == '.':
if out_pos > drive_prefix_len:
# 回退到上一个分隔符前
out_pos -= 1
while out_pos > drive_prefix_len and not _is_sep(buf[out_pos - 1]):
out_pos -= 1
# 如果回退到了根目录前缀,不删除前缀
if out_pos == drive_prefix_len and is_absolute:
out_pos = drive_prefix_len
if drive_prefix_len == 0:
# POSIX 根:保留 /
buf[out_pos] = s
out_pos += 1
continue
# 普通组件:复制到输出
if out_pos > drive_prefix_len and not (drive_prefix_len == 0 and out_pos == 1 and is_absolute):
buf[out_pos] = s
out_pos += 1
elif out_pos == 0 and not is_absolute:
pass # 第一个组件,不需要前导分隔符
elif is_absolute and out_pos == drive_prefix_len:
# 已经有前导分隔符,不重复添加
pass
else:
buf[out_pos] = s
out_pos += 1
j: t.CSizeT = comp_start
while j < comp_start + comp_len:
buf[out_pos] = path[j]
out_pos += 1
j += 1
# 处理空结果
if out_pos == 0:
buf[out_pos] = '.'
out_pos += 1
buf[out_pos] = 0
return str(buf)
+57
View File
@@ -0,0 +1,57 @@
import t, c
IS_WINDOWS: t.CDefine = 1
IS_WIN64: t.CDefine = 1
IS_X86_64: t.CDefine = 1
IS_LP64: t.CDefine = 1
IS_LITTLE_ENDIAN: t.CDefine = 1
IS_LINUX: t.CDefine = 0
IS_MACOS: t.CDefine = 0
IS_ARM64: t.CDefine = 0
IS_BIG_ENDIAN: t.CDefine = 0
IS_ILP32: t.CDefine = 0
PTR_SIZE: t.CDefine = t.CSizeT().Size
INT_SIZE: t.CDefine = 4
LONG_SIZE: t.CDefine = t.CLong().Size
WORD_SIZE: t.CDefine = t.CSizeT().Size
CACHE_LINE_SIZE: t.CDefine = 64
PAGE_SIZE: t.CDefine = 4096
STACK_ALIGN: t.CDefine = 16
MAX_PATH_LEN: t.CDefine = 260
PLATFORM_NAME: t.CDefine = 1
ARCH_NAME: t.CDefine = 1
WINVER: t.CDefine = 0x0A00
_WIN32_WINNT: t.CDefine = 0x0A00
NTDDI_VERSION: t.CDefine = 0x0A000006
HAS_SSE2: t.CDefine = 1
HAS_AVX: t.CDefine = 1
HAS_AVX2: t.CDefine = 1
HAS_FMA: t.CDefine = 1
HAS_NEON: t.CDefine = 0
ALIGNOF_INT: t.CDefine = 4
ALIGNOF_LONG: t.CDefine = t.CLong().Size // 8
ALIGNOF_PTR: t.CDefine = t.CSizeT().Size // 8
ALIGNOF_DOUBLE: t.CDefine = 8
ALIGNOF_LONG_DOUBLE: t.CDefine = 16
SIZEOF_SHORT: t.CDefine = 2
SIZEOF_INT: t.CDefine = 4
SIZEOF_LONG: t.CDefine = t.CLong().Size // 8
SIZEOF_LONG_LONG: t.CDefine = 8
SIZEOF_FLOAT: t.CDefine = 4
SIZEOF_DOUBLE: t.CDefine = 8
SIZEOF_LONG_DOUBLE: t.CDefine = 16
SIZEOF_POINTER: t.CDefine = t.CSizeT().Size // 8
SIZEOF_SIZE_T: t.CDefine = t.CSizeT().Size // 8
SIZEOF_PTRDIFF_T: t.CDefine = t.CPtrDiffT().Size // 8
BYTE_ORDER_LE: t.CDefine = 1
BYTE_ORDER_BE: t.CDefine = 0
+5
View File
@@ -0,0 +1,5 @@
import t, c
#class PList:
# def
+265
View File
@@ -0,0 +1,265 @@
import t, c
from stdint import *
# =============================================================================
# POSIX 类型别名
# 注意:ssize_t 已在 stdint.py 中定义为 t.CPtrDiffT,此处不再重复
# =============================================================================
DIR: t.CTypedef = t.CVoid | t.CPtr # 不透明目录流句柄
mode_t: t.CTypedef = t.CUInt32T # 文件模式/权限位
pid_t: t.CTypedef = t.CInt32T # 进程 ID
off_t: t.CTypedef = t.CInt64T # 文件偏移量(Linux x86_64)
dev_t: t.CTypedef = t.CUInt64T # 设备号
ino_t: t.CTypedef = t.CUInt64T # inode 号
nlink_t: t.CTypedef = t.CUInt64T # 硬链接数
uid_t: t.CTypedef = t.CUInt32T # 用户 ID
gid_t: t.CTypedef = t.CUInt32T # 组 ID
blksize_t: t.CTypedef = t.CInt64T # 文件系统 I/O 块大小
blkcnt_t: t.CTypedef = t.CInt64T # 已分配块数
time_t: t.CTypedef = t.CInt64T # 日历时间秒数
# =============================================================================
# open() 标志位
# =============================================================================
O_RDONLY: t.CDefine = 0
O_WRONLY: t.CDefine = 1
O_RDWR: t.CDefine = 2
O_CREAT: t.CDefine = 0o100
O_EXCL: t.CDefine = 0o200
O_TRUNC: t.CDefine = 0o1000
O_APPEND: t.CDefine = 0o2000
O_NONBLOCK: t.CDefine = 0o4000
O_CLOEXEC: t.CDefine = 0o2000000
# =============================================================================
# access() 测试标志
# =============================================================================
F_OK: t.CDefine = 0 # 文件存在
R_OK: t.CDefine = 4 # 可读
W_OK: t.CDefine = 2 # 可写
X_OK: t.CDefine = 1 # 可执行
# =============================================================================
# stat 结构体的 st_mode 掩码与类型位
# =============================================================================
S_IFMT: t.CDefine = 0o170000 # 类型掩码
S_IFSOCK: t.CDefine = 0o140000 # 套接字
S_IFLNK: t.CDefine = 0o120000 # 符号链接
S_IFREG: t.CDefine = 0o100000 # 普通文件
S_IFBLK: t.CDefine = 0o060000 # 块设备
S_IFDIR: t.CDefine = 0o040000 # 目录
S_IFCHR: t.CDefine = 0o020000 # 字符设备
S_IFIFO: t.CDefine = 0o010000 # FIFO/管道
# 权限位
S_ISUID: t.CDefine = 0o4000 # set-user-ID
S_ISGID: t.CDefine = 0o2000 # set-group-ID
S_ISVTX: t.CDefine = 0o1000 # sticky 位
S_IRWXU: t.CDefine = 0o700 # 用户读写执行
S_IRUSR: t.CDefine = 0o400 # 用户读
S_IWUSR: t.CDefine = 0o200 # 用户写
S_IXUSR: t.CDefine = 0o100 # 用户执行
S_IRWXG: t.CDefine = 0o070 # 组读写执行
S_IRGRP: t.CDefine = 0o040 # 组读
S_IWGRP: t.CDefine = 0o020 # 组写
S_IXGRP: t.CDefine = 0o010 # 组执行
S_IRWXO: t.CDefine = 0o007 # 其他读写执行
S_IROTH: t.CDefine = 0o004 # 其他读
S_IWOTH: t.CDefine = 0o002 # 其他写
S_IXOTH: t.CDefine = 0o001 # 其他执行
# =============================================================================
# lseek() whence 值
# =============================================================================
SEEK_SET: t.CDefine = 0
SEEK_CUR: t.CDefine = 1
SEEK_END: t.CDefine = 2
# =============================================================================
# 路径/名称长度限制
# =============================================================================
PATH_MAX: t.CDefine = 4096
NAME_MAX: t.CDefine = 255
# =============================================================================
# sysconf() 参数
# =============================================================================
_SC_NPROCESSORS_ONLN: t.CDefine = 84
_SC_PAGESIZE: t.CDefine = 30
_SC_CLK_TCK: t.CDefine = 2
# =============================================================================
# dirent 结构体的 d_type 值
# =============================================================================
DT_UNKNOWN: t.CDefine = 0
DT_FIFO: t.CDefine = 1
DT_CHR: t.CDefine = 2
DT_DIR: t.CDefine = 4
DT_BLK: t.CDefine = 6
DT_REG: t.CDefine = 8
DT_LNK: t.CDefine = 10
DT_SOCK: t.CDefine = 12
DT_WHT: t.CDefine = 14
# =============================================================================
# waitpid() 选项
# =============================================================================
WNOHANG: t.CDefine = 1
WUNTRACED: t.CDefine = 2
WCONTINUED: t.CDefine = 8
# =============================================================================
# 结构体:Linux x86_64 布局
# =============================================================================
# struct stat(144 字节,Linux x86_64 glibc 布局)
# 注意:st_atim/st_mtim/st_ctim 在 C 中是 struct timespec { tv_sec; tv_nsec; }
# 此处拆分为 _sec/_nsec 两个 LONGLONG 字段以保持二进制兼容
class Stat():
st_dev: dev_t # @ 0
st_ino: ino_t # @ 8
st_nlink: nlink_t # @ 16
st_mode: mode_t # @ 24
st_uid: uid_t # @ 28
st_gid: gid_t # @ 32
__pad0: INT # @ 36
st_rdev: dev_t # @ 40
st_size: off_t # @ 48
st_blksize: blksize_t # @ 56
st_blocks: blkcnt_t # @ 64
st_atim_sec: time_t # @ 72
st_atim_nsec: LONGLONG # @ 80
st_mtim_sec: time_t # @ 88
st_mtim_nsec: LONGLONG # @ 96
st_ctim_sec: time_t # @ 104
st_ctim_nsec: LONGLONG # @ 112
__unused0: LONGLONG # @ 120
__unused1: LONGLONG # @ 128
__unused2: LONGLONG # @ 136
# struct dirent(Linux x86_64,d_name 为 char[256])
# 注意:d_name 实际是定长 char[256],TransPyC 用 CHARPTR 占位(8 字节)。
# 用户通常通过 readdir 返回的只读指针访问,不直接分配 Dirent 结构体。
class Dirent():
d_ino: ino_t # @ 0
d_off: off_t # @ 8
d_reclen: USHORT # @ 16
d_type: BYTE # @ 18
d_name: CHARPTR # @ 19(实际为 char[256],此处占位)
# =============================================================================
# 文件操作函数(10 个)
# =============================================================================
def open(path: t.CConst | str, oflag: INT, *args) -> INT | t.State: pass
def close(fd: INT) -> INT | t.State: pass
def read(fd: INT, buf: bytes, count: t.CSizeT) -> ssize_t | t.State: pass
def write(fd: INT, buf: t.CConst | bytes, count: t.CSizeT) -> ssize_t | t.State: pass
def lseek(fd: INT, offset: off_t, whence: INT) -> off_t | t.State: pass
def unlink(path: t.CConst | str) -> INT | t.State: pass
def access(path: t.CConst | str, amode: INT) -> INT | t.State: pass
def realpath(path: t.CConst | str, resolved: CHARPTR) -> CHARPTR | t.State: pass
def rename(oldpath: t.CConst | str, newpath: t.CConst | str) -> INT | t.State: pass
def chmod(path: t.CConst | str, mode: mode_t) -> INT | t.State: pass
# =============================================================================
# stat 系列(2 个)
# =============================================================================
def stat(path: t.CConst | str, buf: Stat | t.CPtr) -> INT | t.State: pass
def fstat(fd: INT, buf: Stat | t.CPtr) -> INT | t.State: pass
# =============================================================================
# 目录操作(6 个)
# =============================================================================
def opendir(name: t.CConst | str) -> DIR | t.CPtr | t.State: pass
def readdir(dirp: DIR | t.CPtr) -> Dirent | t.CPtr | t.State: pass
def closedir(dirp: DIR | t.CPtr) -> INT | t.State: pass
def mkdir(path: t.CConst | str, mode: mode_t) -> INT | t.State: pass
def rmdir(path: t.CConst | str) -> INT | t.State: pass
def getcwd(buf: CHARPTR, size: t.CSizeT) -> CHARPTR | t.State: pass
def chdir(path: t.CConst | str) -> INT | t.State: pass
# =============================================================================
# 进程/管道(8 个)
# =============================================================================
def fork() -> pid_t | t.State: pass
def execvp(file: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT | t.State: pass
def execv(path: t.CConst | str, argv: CHARPTR | t.CPtr) -> INT | t.State: pass
def waitpid(pid: pid_t, status: INT | t.CPtr, options: INT) -> pid_t | t.State: pass
def pipe(fds: INT | t.CPtr) -> INT | t.State: pass
def dup2(oldfd: INT, newfd: INT) -> INT | t.State: pass
def _exit(status: INT) -> t.CVoid | t.State: pass
def getpid() -> pid_t | t.State: pass
# =============================================================================
# 环境/系统(4 个)
# =============================================================================
def getenv(name: t.CConst | str) -> CHARPTR | t.State: pass
def setenv(name: t.CConst | str, value: t.CConst | str, overwrite: INT) -> INT | t.State: pass
def sysconf(name: INT) -> LONG | t.State: pass
def isatty(fd: INT) -> INT | t.State: pass
# =============================================================================
# 内联宏(C 宏,用 TransPyC 普通函数实现,不标记 t.CExtern)
# =============================================================================
# st_mode 类型判定
def S_ISREG(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFREG
def S_ISDIR(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFDIR
def S_ISLNK(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFLNK
def S_ISCHR(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFCHR
def S_ISBLK(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFBLK
def S_ISFIFO(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFIFO
def S_ISSOCK(mode: mode_t) -> bool:
return (mode & S_IFMT) == S_IFSOCK
# waitpid 状态解析
def WIFEXITED(status: INT) -> bool:
return (status & 0x7F) == 0
def WEXITSTATUS(status: INT) -> INT:
return (status >> 8) & 0xFF
def WIFSIGNALED(status: INT) -> bool:
return ((status & 0x7F) != 0) and ((status & 0x7F) != 0x7F)
def WTERMSIG(status: INT) -> INT:
return status & 0x7F
+361
View File
@@ -0,0 +1,361 @@
import t, c
from stdint import *
import string
import socket
import memhub
import stdio
# ============================================================
# requests.py — HTTP 客户端库(Python 原版风格)
#
# 用法:
# requests._mbuddy = my_mbuddy
# resp = requests.get("http://example.com/path")
# if resp is not None:
# print(resp.status_code)
# print(resp.text)
# requests.release(resp)
# ============================================================
# 模块级全局 MBuddy 指针(由用户在 main 中赋值)
_mbuddy: memhub.MemBuddy | t.CPtr
# Socket 初始化标记
_socket_ready: bool = False
HTTP_PORT: t.CDefine = 80
HTTP_BUFSIZ: t.CDefine = 4096
# ============================================================
# Response — HTTP 响应对象
# ============================================================
class Response:
"""HTTP 响应对象,贴近 Python requests.Response 用法。
从 _mbuddy 分配,使用完毕后调用 release(resp) 释放。
"""
status_code: INT # HTTP 状态码(如 200、404)
text: str # 响应体文本(指向 _raw_buf 内部)
body_len: INT # 响应体长度
_raw_buf: str # 原始缓冲区指针
# ============================================================
# 内部辅助函数
# ============================================================
def _EnsureSocketInit() -> INT:
"""确保 Socket 库已初始化(幂等)。"""
global _socket_ready
if _socket_ready: return 0
result: INT = socket.SocketInit()
if result == 0:
_socket_ready = True
return result
def _AllocResponse() -> Response | t.CPtr:
"""从 _mbuddy 分配 Response 结构体并就地初始化。"""
if _mbuddy is None: return None
resp: Response | t.CPtr = _mbuddy.alloc(Response.__sizeof__())
if resp is None: return None
resp.status_code = 0
resp.text = None
resp.body_len = 0
resp._raw_buf = None
return resp
def _ParseUrl(url: str, host_buf: str, host_size: INT, path_buf: str, path_size: INT, port: INT | t.CPtr) -> INT:
"""解析 URL,提取 host、port、path。"""
if url is None: return -1
if host_buf is None or path_buf is None or port is None: return -1
p: str = url
# 跳过 "http://"
if string.strncmp(p, "http://", 7) == 0:
p += 7
# 解析 host
host_start: str = p
host_len: INT = 0
while p[0] != '\0' and p[0] != ':' and p[0] != '/':
host_len += 1
p += 1
if host_len == 0 or host_len >= host_size: return -1
string.strncpy(host_buf, host_start, host_len)
host_buf[host_len] = 0
# 解析 port
if p[0] == ':':
p += 1
port_val: INT = 0
while p[0] >= '0' and p[0] <= '9':
port_val = port_val * 10 + INT(p[0] - '0')
p += 1
c.DerefAs(port, port_val)
else:
c.DerefAs(port, HTTP_PORT)
# 解析 path
if p[0] == '/':
path_start: str = p
path_len: INT = 0
while p[0] != '\0':
path_len += 1
p += 1
if path_len >= path_size: return -1
string.strncpy(path_buf, path_start, path_len)
path_buf[path_len] = 0
else:
if path_size < 2: return -1
path_buf[0] = '/'
path_buf[1] = 0
return 0
def _ParseStatusLine(resp_text: str, out_code: INT | t.CPtr) -> INT:
"""解析 HTTP 状态行,提取状态码。返回状态行结束偏移。"""
if resp_text is None or out_code is None: return -1
p: str = resp_text
# 跳过 "HTTP/x.x "
while p[0] != '\0' and p[0] != ' ':
p += 1
if p[0] == ' ': p += 1
# 解析状态码
code: INT = 0
while p[0] >= '0' and p[0] <= '9':
code = code * 10 + INT(p[0] - '0')
p += 1
c.DerefAs(out_code, code)
# 找到 \n
while p[0] != '\0' and p[0] != '\n':
p += 1
if p[0] == '\n': p += 1
return INT(t.CUInt64T(p) - t.CUInt64T(resp_text))
def _FindBodyStart(resp_text: str, resp_len: INT) -> INT:
"""找到 HTTP 响应体起始位置(\\r\\n\\r\\n 之后)。"""
if resp_text is None: return -1
end_of_headers: str = string.strstr(resp_text, "\r\n\r\n")
if end_of_headers is None:
end_of_headers = string.strstr(resp_text, "\n\n")
if end_of_headers is None:
return -1
return INT(t.CUInt64T(end_of_headers) - t.CUInt64T(resp_text)) + 2
return INT(t.CUInt64T(end_of_headers) - t.CUInt64T(resp_text)) + 4
# ============================================================
# 公共 API
# ============================================================
def get(url: str) -> Response | t.CPtr:
"""HTTP GET 请求。
Args:
url: 完整 URL (如 "http://example.com/path")
Returns:
Response 对象指针(从 _mbuddy 分配),失败返回 None。
使用完毕后调用 release(resp) 释放。
"""
if _mbuddy is None: return None
resp: Response | t.CPtr = _AllocResponse()
if resp is None: return None
if _EnsureSocketInit() != 0:
release(resp)
return None
# 解析 URL
host_buf: t.CArray[t.CChar, 256]
path_buf: t.CArray[t.CChar, 1024]
port: INT = 0
if _ParseUrl(url, host_buf, 256, path_buf, 1024, c.Addr(port)) != 0:
release(resp)
return None
# 创建并连接 Socket
sock = socket.Socket(socket.AF_INET, socket.SOCK_STREAM)
if sock.fd == socket.INVALID_SOCKET:
release(resp)
return None
if sock.connect(host_buf, port) != 0:
sock.close()
release(resp)
return None
# 构建 HTTP 请求
req_buf: str = _mbuddy.alloc(HTTP_BUFSIZ)
if req_buf is None:
sock.close()
release(resp)
return None
stdio.snprintf(req_buf, HTTP_BUFSIZ,
"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n",
path_buf, host_buf)
req_len: INT = INT(string.strlen(req_buf))
sent: INT = sock.send(req_buf, req_len)
_mbuddy.free(req_buf)
if sent <= 0:
sock.close()
release(resp)
return None
# 接收响应
resp_buf: str = _mbuddy.alloc(HTTP_BUFSIZ)
if resp_buf is None:
sock.close()
release(resp)
return None
total: INT = 0
while total < HTTP_BUFSIZ - 1:
n: INT = sock.recv(resp_buf + total, HTTP_BUFSIZ - 1 - total)
if n <= 0: break
total += n
resp_buf[total] = 0
sock.close()
resp._raw_buf = resp_buf
# 解析状态码
_ParseStatusLine(resp_buf, c.Addr(resp.status_code))
# 找到 body
body_offset: INT = _FindBodyStart(resp_buf, total)
if body_offset < 0 or body_offset >= total:
resp.text = None
resp.body_len = 0
else:
resp.text = resp_buf + body_offset
resp.body_len = total - body_offset
return resp
def post(url: str, data: str = None, content_type: str = "application/x-www-form-urlencoded") -> Response | t.CPtr:
"""HTTP POST 请求。
Args:
url: 完整 URL
data: 请求体数据
content_type: Content-Type 头(默认 "application/x-www-form-urlencoded")
Returns:
Response 对象指针(从 _mbuddy 分配),失败返回 None。
"""
if _mbuddy is None: return None
resp: Response | t.CPtr = _AllocResponse()
if resp is None: return None
if _EnsureSocketInit() != 0:
release(resp)
return None
# 解析 URL
host_buf: t.CArray[t.CChar, 256]
path_buf: t.CArray[t.CChar, 1024]
port: INT = 0
if _ParseUrl(url, host_buf, 256, path_buf, 1024, c.Addr(port)) != 0:
release(resp)
return None
body_len: INT = INT(string.strlen(data)) if data is not None else 0
ct: str = content_type if content_type is not None else "application/x-www-form-urlencoded"
# 创建并连接 Socket
sock = socket.Socket(socket.AF_INET, socket.SOCK_STREAM)
if sock.fd == socket.INVALID_SOCKET:
release(resp)
return None
if sock.connect(host_buf, port) != 0:
sock.close()
release(resp)
return None
# 构建 HTTP 请求
req_buf: str = _mbuddy.alloc(HTTP_BUFSIZ)
if req_buf is None:
sock.close()
release(resp)
return None
stdio.snprintf(req_buf, HTTP_BUFSIZ,
"POST %s HTTP/1.1\r\nHost: %s\r\nContent-Type: %s\r\nContent-Length: %d\r\nConnection: close\r\n\r\n",
path_buf, host_buf, ct, body_len)
hdr_len: INT = INT(string.strlen(req_buf))
# 发送头部 + body
sent: INT = sock.send(req_buf, hdr_len)
if sent > 0 and body_len > 0 and data is not None:
sock.send(data, body_len)
_mbuddy.free(req_buf)
# 接收响应
resp_buf: str = _mbuddy.alloc(HTTP_BUFSIZ)
if resp_buf is None:
sock.close()
release(resp)
return None
total: INT = 0
while total < HTTP_BUFSIZ - 1:
n: INT = sock.recv(resp_buf + total, HTTP_BUFSIZ - 1 - total)
if n <= 0: break
total += n
resp_buf[total] = 0
sock.close()
resp._raw_buf = resp_buf
_ParseStatusLine(resp_buf, c.Addr(resp.status_code))
body_offset: INT = _FindBodyStart(resp_buf, total)
if body_offset < 0 or body_offset >= total:
resp.text = None
resp.body_len = 0
else:
resp.text = resp_buf + body_offset
resp.body_len = total - body_offset
return resp
def release(resp: Response | t.CPtr):
"""释放 Response 对象及其内部缓冲区。
Args:
resp: 要释放的 Response 对象
"""
if resp is None: return
if _mbuddy is None: return
if resp._raw_buf is not None:
_mbuddy.free(resp._raw_buf)
_mbuddy.free(t.CVoid(t.CUInt64T(resp), t.CPtr))
+46
View File
@@ -0,0 +1,46 @@
import t, c
from stdint import *
from w32.win32base import *
from w32.win32sync import (
InitializeSRWLock,
AcquireSRWLockExclusive, ReleaseSRWLockExclusive,
AcquireSRWLockShared, ReleaseSRWLockShared
)
@t.Object
class RWLock:
"""基于 SRWLock 的读写锁,支持多读单写,不支持递归。
用法:
rwlock: RWLock = RWLock()
rwlock.acquire_read()
# ... 读取共享数据
rwlock.release_read()
rwlock.acquire_write()
# ... 修改共享数据
rwlock.release_write()
"""
lock: VOIDPTR
def __init__(self):
InitializeSRWLock(c.Addr(self.lock))
def acquire_read(self):
AcquireSRWLockShared(c.Addr(self.lock))
def release_read(self):
ReleaseSRWLockShared(c.Addr(self.lock))
def acquire_write(self):
AcquireSRWLockExclusive(c.Addr(self.lock))
def release_write(self):
ReleaseSRWLockExclusive(c.Addr(self.lock))
def __enter__(self) -> 'RWLock' | t.CPtr:
self.acquire_write()
return self
def __exit__(self):
self.release_write()
+283
View File
@@ -0,0 +1,283 @@
import t, c
from stdint import *
import platmacro
import memhub
import string
# Windows 后端依赖
import w32.win32base
import w32.win32file
# POSIX 后端依赖
import posix
# 文件拷贝缓冲区大小
COPY_BUF_SIZE: t.CDefine = 65536
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# copyfile:拷贝文件内容(不保留权限/元数据)
# =============================================================================
def copyfile(src: str, dst: str) -> int:
"""拷贝文件内容。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return _copyfile_win32(src, dst)
return _copyfile_posix(src, dst)
def _copyfile_win32(src: str, dst: str) -> int:
"""Windows:使用 CopyFileA 内核实现(高效)"""
result: BOOL = w32.win32file.CopyFileA(src, dst, 0)
if result == 0:
return -1
return 0
def _copyfile_posix(src: str, dst: str) -> int:
"""POSIX:手动 read/write 循环拷贝"""
fd_in: INT = posix.open(src, posix.O_RDONLY, 0)
if fd_in < 0:
return -1
fd_out: INT = posix.open(dst, posix.O_WRONLY | posix.O_CREAT | posix.O_TRUNC, 0o644)
if fd_out < 0:
posix.close(fd_in)
return -1
buf: bytes = _mbuddy.alloc(COPY_BUF_SIZE)
if buf == None:
posix.close(fd_in)
posix.close(fd_out)
return -1
n: ssize_t = 0
result: int = 0
n = posix.read(fd_in, buf, COPY_BUF_SIZE)
while n > 0:
written: ssize_t = posix.write(fd_out, buf, t.CSizeT(n))
if written < 0:
result = -1
break
n = posix.read(fd_in, buf, COPY_BUF_SIZE)
if n < 0:
result = -1
_mbuddy.free(buf)
posix.close(fd_in)
posix.close(fd_out)
return result
# =============================================================================
# copy:拷贝文件并保留权限
# =============================================================================
def copy(src: str, dst: str) -> int:
"""拷贝文件并保留权限(POSIX 上调用 stat+chmod)。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return _copy_win32(src, dst)
return _copy_posix(src, dst)
def _copy_win32(src: str, dst: str) -> int:
"""Windows:拷贝文件(CopyFileA,Windows 权限模型简单,直接委托 copyfile)"""
return _copyfile_win32(src, dst)
def _copy_posix(src: str, dst: str) -> int:
"""POSIX:拷贝文件并保留权限(stat+chmod)"""
result: int = _copyfile_posix(src, dst)
if result != 0:
return -1
st: posix.Stat = posix.Stat()
if posix.stat(src, t.CPtr(c.Addr(st))) == 0:
posix.chmod(dst, st.st_mode)
return 0
# =============================================================================
# rmtree:递归删除目录树
# =============================================================================
def rmtree(path: str) -> int:
"""递归删除目录树。成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return _rmtree_win32(path)
return _rmtree_posix(path)
def _rmtree_win32(path: str) -> int:
"""Windows:FindFirstFileA/FindNextFileA 递归删除"""
path_len: t.CSizeT = len(path)
# 构造搜索模式 path\*
pattern: bytes = _mbuddy.alloc(path_len + 3)
if pattern == None:
return -1
i: t.CSizeT = 0
for ch in path:
pattern[i] = ch
i += 1
if path_len > 0:
if path[path_len - 1] != '\\' and path[path_len - 1] != '/':
pattern[i] = '\\'
i += 1
pattern[i] = '*'
i += 1
pattern[i] = 0
find_data: w32.win32file.WIN32_FIND_DATAA = w32.win32file.WIN32_FIND_DATAA()
handle: w32.win32base.HANDLE = w32.win32file.FindFirstFileA(pattern, t.CPtr(c.Addr(find_data)))
_mbuddy.free(pattern)
if handle == w32.win32base.INVALID_HANDLE_VALUE:
return -1
result: int = 0
has_more: int = 1
while has_more == 1:
name: str = find_data.cFileName
# 跳过 . 和 ..
skip: bool = False
if name[0] == '.':
if name[1] == 0:
skip = True
elif name[1] == '.' and name[2] == 0:
skip = True
if not skip:
# 构造完整路径 path\name
name_len: t.CSizeT = len(name)
full_path: bytes = _mbuddy.alloc(path_len + name_len + 2)
if full_path == None:
result = -1
else:
j: t.CSizeT = 0
for ch in path:
full_path[j] = ch
j += 1
if path_len > 0:
if path[path_len - 1] != '\\' and path[path_len - 1] != '/':
full_path[j] = '\\'
j += 1
for ch in name:
full_path[j] = ch
j += 1
full_path[j] = 0
# 判断是文件还是目录
if (find_data.dwFileAttributes & w32.win32file.FILE_ATTRIBUTE_DIRECTORY) != 0:
# 递归删除子目录
sub_result: int = _rmtree_win32(str(full_path))
if sub_result != 0:
result = -1
else:
# 删除文件
if w32.win32file.DeleteFileA(str(full_path)) == 0:
result = -1
_mbuddy.free(full_path)
# 继续搜索下一个条目
if w32.win32file.FindNextFileA(handle, t.CPtr(c.Addr(find_data))) == 0:
has_more = 0
w32.win32file.FindClose(handle)
# 最后删除空目录本身
if result == 0:
if w32.win32file.RemoveDirectoryA(path) == 0:
result = -1
return result
def _rmtree_posix(path: str) -> int:
"""POSIX:opendir/readdir 递归删除"""
dirp: posix.DIR = posix.opendir(path)
if dirp == None:
return -1
path_len: t.CSizeT = len(path)
result: int = 0
entry: posix.Dirent = posix.readdir(dirp)
while entry != None:
name: str = entry.d_name
# 跳过 . 和 ..
skip: bool = False
if name[0] == '.':
if name[1] == 0:
skip = True
elif name[1] == '.' and name[2] == 0:
skip = True
if not skip:
# 构造完整路径 path/name
name_len: t.CSizeT = len(name)
full_path: bytes = _mbuddy.alloc(path_len + name_len + 2)
if full_path == None:
result = -1
else:
j: t.CSizeT = 0
for ch in path:
full_path[j] = ch
j += 1
if path_len > 0:
if path[path_len - 1] != '/':
full_path[j] = '/'
j += 1
for ch in name:
full_path[j] = ch
j += 1
full_path[j] = 0
# 判断条目类型
if entry.d_type == posix.DT_DIR:
# 递归删除子目录
sub_result: int = _rmtree_posix(str(full_path))
if sub_result != 0:
result = -1
else:
# 删除文件/符号链接等
if posix.unlink(str(full_path)) != 0:
result = -1
_mbuddy.free(full_path)
entry = posix.readdir(dirp)
posix.closedir(dirp)
# 最后删除空目录本身
if result == 0:
if posix.rmdir(path) != 0:
result = -1
return result
# =============================================================================
# move:移动文件/目录
# =============================================================================
def move(src: str, dst: str) -> int:
"""移动/重命名文件或目录。同分区时直接 rename,跨分区时 copy+delete。
成功返回 0,失败返回 -1。"""
if platmacro.IS_WINDOWS:
return _move_win32(src, dst)
return _move_posix(src, dst)
def _move_win32(src: str, dst: str) -> int:
"""Windows:MoveFileExA(同分区 rename,跨分区 copy+delete)"""
rename_result: BOOL = w32.win32file.MoveFileExA(
src, dst,
w32.win32file.MOVEFILE_REPLACE_EXISTING | w32.win32file.MOVEFILE_COPY_ALLOWED
)
if rename_result != 0:
return 0
# rename 失败,尝试 copy + remove
if copyfile(src, dst) != 0:
return -1
if w32.win32file.DeleteFileA(src) == 0:
return -1
return 0
def _move_posix(src: str, dst: str) -> int:
"""POSIX:rename(同分区),跨分区 copy+unlink"""
if posix.rename(src, dst) == 0:
return 0
# rename 失败(可能跨分区),尝试 copy + unlink
if copyfile(src, dst) != 0:
return -1
if posix.unlink(src) != 0:
return -1
return 0
+451
View File
@@ -0,0 +1,451 @@
import t, c
from stdint import *
import string
import platmacro
import stdio
import w32.winsock2
# ============================================================
# socket.py — 跨平台 Socket 封装
# Python 风格 OOP API + 兼容旧版过程式函数
#
# 用法示例:
# sock = socket.Socket(socket.AF_INET, socket.SOCK_STREAM)
# sock.connect("example.com", 80)
# sock.send(data, length)
# n = sock.recv(buf, bufsize)
# sock.close()
#
# 仅 3 处平台差异(通过 platmacro.IS_WINDOWS 分支):
# 1. WSAStartup() / WSACleanup()
# 2. closesocket() vs close()
# 3. WSAGetLastError() vs errno
# ============================================================
# ============================================================
# 常量
# ============================================================
AF_INET: t.CDefine = 2
AF_INET6: t.CDefine = 10
SOCK_STREAM: t.CDefine = 1
SOCK_DGRAM: t.CDefine = 2
SOCK_RAW: t.CDefine = 3
IPPROTO_TCP: t.CDefine = 6
IPPROTO_UDP: t.CDefine = 17
SOL_SOCKET: t.CDefine = 1
SO_RCVTIMEO: t.CDefine = 20
SO_SNDTIMEO: t.CDefine = 21
SO_REUSEADDR: t.CDefine = 2
INADDR_ANY: t.CDefine = 0
SOCKET_ERROR: t.CDefine = -1
INVALID_SOCKET: t.CDefine = -1
SOCKET_DEFAULT_TIMEOUT: t.CDefine = 0
# ============================================================
# 结构体
# ============================================================
class SocketAddr:
"""sockaddr_in — IPv4 地址(16 字节,POSIX 布局)"""
family: u16
port: u16
addr: u32
zero: u64
class HostEnt:
"""struct hostent — DNS 解析结果"""
h_name: CHARPTR
h_aliases: CHARPTR
h_addrtype: INT
h_length: INT
h_addr_list: CHARPTR
class timeval:
"""struct timeval — 超时设置"""
tv_sec: INT
tv_usec: INT
# ============================================================
# 外部 C 函数 — 使用 u64 句柄,跨平台兼容
# (Windows SOCKET=u64, POSIX fd=int → u64 零扩展兼容)
# ============================================================
def socket(family: INT, type: INT, protocol: INT) -> u64 | t.CExtern | t.CExport: pass
def connect(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
def send(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
def recv(fd: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.CExtern | t.CExport: pass
def bind(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT) -> INT | t.CExtern | t.CExport: pass
def listen(fd: u64, backlog: INT) -> INT | t.CExtern | t.CExport: pass
def accept(fd: u64, addr: SocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.CExtern | t.CExport: pass
def setsockopt(fd: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.CExtern | t.CExport: pass
def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> HostEnt | t.CPtr | t.CExtern | t.CExport: pass
def ntohs(netshort: u16) -> u16 | t.CExtern | t.CExport: pass
def htons(hostshort: u16) -> u16 | t.CExtern | t.CExport: pass
def close(fd: u64) -> INT | t.CExtern | t.CExport: pass
# ============================================================
# 内部辅助函数
# ============================================================
def _CloseFd(fd: INT) -> INT:
"""平台差异:Windows 用 closesocket,POSIX 用 close。"""
if platmacro.IS_WINDOWS:
return w32.winsock2.closesocket(u64(fd))
return close(fd)
def _MakeAddr(host: str, port: INT) -> SocketAddr:
"""构建 SocketAddr。先尝试点分十进制 IP,失败则 DNS 解析。"""
addr: SocketAddr
string.memset(c.Addr(addr), 0, 16)
addr.family = u16(AF_INET)
addr.port = htons(u16(port))
ip: u32 = 0
if _ParseIPv4(host, c.Addr(ip)):
addr.addr = ip
return addr
# DNS 解析 — gethostbyname 返回 struct hostent*
# h_addr_list 是 char** → h_addr_list[0] 是 char* → *(uint32_t*)h_addr_list[0] 是 IP
if platmacro.IS_WINDOWS:
he_raw: w32.winsock2.WSAHostEnt | t.CPtr = w32.winsock2.gethostbyname(host)
if he_raw is not None:
# he_raw.h_addr_list → he_raw->h_addr_list (char**)
# c.Deref(t.CUInt64T(he_raw.h_addr_list, t.CPtr)) → *(uint64_t*)(he_raw->h_addr_list) → h_addr_list[0]
ip_ptr: u64 = u64(c.Deref(t.CUInt64T(he_raw.h_addr_list, t.CPtr)))
if ip_ptr != 0:
addr.addr = u32(c.Deref(t.CUInt32T(ip_ptr, t.CPtr)))
else:
he: HostEnt | t.CPtr = gethostbyname(host)
if he is not None:
ip_ptr: u64 = u64(c.Deref(t.CUInt64T(he.h_addr_list, t.CPtr)))
if ip_ptr != 0:
addr.addr = u32(c.Deref(t.CUInt32T(ip_ptr, t.CPtr)))
return addr
def _ParseIPv4(ip_str: str, out_addr: u32 | t.CPtr) -> bool:
"""解析点分十进制 IPv4 地址。"""
if ip_str is None or out_addr is None: return False
parts: t.CArray[INT, 4]
part_count: INT = 0
current: INT = 0
started: bool = False
for ch in ip_str:
if ch >= '0' and ch <= '9':
if not started: started = True
current = current * 10 + INT(ch - '0')
if current > 255: return False
elif ch == '.':
if not started: return False
if part_count >= 4: return False
parts[part_count] = current
part_count += 1
current = 0
started = False
else:
break
if started and part_count < 4:
parts[part_count] = current
part_count += 1
if part_count != 4: return False
result: u32 = 0
result = result | (u32(parts[0]) << 24)
result = result | (u32(parts[1]) << 16)
result = result | (u32(parts[2]) << 8)
result = result | u32(parts[3])
c.DerefAs(out_addr, result)
return True
# ============================================================
# Socket 类 — Python 风格 OOP API
# ============================================================
class Socket:
"""跨平台 Socket 封装,贴近 Python socket.socket 用法。
用法:
sock = Socket(AF_INET, SOCK_STREAM)
sock.connect("example.com", 80)
sock.send(data, length)
n = sock.recv(buf, bufsize)
sock.close()
"""
fd: INT
family: INT
type: INT
protocol: INT
def __init__(self, family: INT, type: INT, protocol: INT = 0):
"""创建 Socket。
Args:
family: 地址族 (AF_INET)
type: 套接字类型 (SOCK_STREAM)
protocol: 协议 (默认 0,自动匹配)
"""
self.family = family
self.type = type
self.protocol = protocol
if platmacro.IS_WINDOWS:
self.fd = INT(w32.winsock2.socket(family, type, protocol))
else:
self.fd = socket(family, type, protocol)
def connect(self, host: str, port: INT) -> INT:
"""连接到远程主机。
Args:
host: 主机名或 IP
port: 端口号
Returns:
0 成功,非 0 失败
"""
if self.fd == INVALID_SOCKET: return -1
addr: SocketAddr = _MakeAddr(host, port)
result: INT = 0
if platmacro.IS_WINDOWS:
result = w32.winsock2.connect(u64(self.fd), c.Addr(addr), 16)
if result != 0:
err: INT = w32.winsock2.WSAGetLastError()
else:
result = connect(self.fd, c.Addr(addr), 16)
return result
def send(self, data: t.CVoid | t.CPtr, length: INT) -> INT:
"""发送数据。
Returns:
已发送字节数,SOCKET_ERROR 失败
"""
if self.fd == INVALID_SOCKET: return SOCKET_ERROR
if data is None or length <= 0: return 0
if platmacro.IS_WINDOWS:
return w32.winsock2.send(u64(self.fd), data, length, 0)
return send(self.fd, data, length, 0)
def recv(self, buf: t.CVoid | t.CPtr, bufsize: INT) -> INT:
"""接收数据。
Returns:
已接收字节数,SOCKET_ERROR 失败,0 表示连接关闭
"""
if self.fd == INVALID_SOCKET: return SOCKET_ERROR
if buf is None or bufsize <= 0: return 0
if platmacro.IS_WINDOWS:
return w32.winsock2.recv(u64(self.fd), buf, bufsize, 0)
return recv(self.fd, buf, bufsize, 0)
def sendall(self, data: t.CVoid | t.CPtr, length: INT) -> INT:
"""发送全部数据(循环发送直到完成或出错)。
Returns:
0 成功,SOCKET_ERROR 失败
"""
if self.fd == INVALID_SOCKET: return SOCKET_ERROR
if data is None or length <= 0: return 0
total: INT = 0
while total < length:
n: INT = self.send(t.CVoid(t.CUInt64T(data) + total, t.CPtr), length - total)
if n <= 0: return SOCKET_ERROR
total += n
return 0
def close(self) -> INT:
"""关闭 Socket。"""
if self.fd == INVALID_SOCKET: return 0
result: INT = _CloseFd(self.fd)
self.fd = INVALID_SOCKET
return result
def bind(self, host: str, port: INT) -> INT:
"""绑定地址和端口(服务器端)。
Returns:
0 成功,非 0 失败
"""
if self.fd == INVALID_SOCKET: return -1
addr: SocketAddr = _MakeAddr(host, port)
if platmacro.IS_WINDOWS:
return w32.winsock2.bind(u64(self.fd), c.Addr(addr), 16)
return bind(self.fd, c.Addr(addr), 16)
def listen(self, backlog: INT) -> INT:
"""开始监听连接(服务器端)。
Returns:
0 成功,非 0 失败
"""
if self.fd == INVALID_SOCKET: return -1
if platmacro.IS_WINDOWS:
return w32.winsock2.listen(u64(self.fd), backlog)
return listen(self.fd, backlog)
def accept(self, out_client: 'Socket' | t.CPtr) -> INT:
"""接受一个客户端连接。
Args:
out_client: 输出参数,接收客户端 Socket
Returns:
客户端 fd(>= 0 成功),SOCKET_ERROR 失败
"""
if self.fd == INVALID_SOCKET: return SOCKET_ERROR
if out_client is None: return SOCKET_ERROR
addr: SocketAddr
string.memset(c.Addr(addr), 0, 16)
addrlen: INT = 16
if platmacro.IS_WINDOWS:
client_fd: u64 = w32.winsock2.accept(u64(self.fd), c.Addr(addr), c.Addr(addrlen))
if client_fd == w32.winsock2.INVALID_SOCKET:
return SOCKET_ERROR
out_client.fd = INT(client_fd)
out_client.family = self.family
out_client.type = self.type
out_client.protocol = self.protocol
return INT(client_fd)
client_fd: INT = accept(self.fd, c.Addr(addr), c.Addr(addrlen))
if client_fd == SOCKET_ERROR:
return SOCKET_ERROR
out_client.fd = client_fd
out_client.family = self.family
out_client.type = self.type
out_client.protocol = self.protocol
return client_fd
def settimeout(self, timeout_ms: INT) -> INT:
"""设置接收和发送超时(毫秒)。0 表示无超时。
Returns:
0 成功,非 0 失败
"""
if self.fd == INVALID_SOCKET: return -1
tv: timeval
tv.tv_sec = timeout_ms / 1000
tv.tv_usec = (timeout_ms % 1000) * 1000
optlen: INT = 8
if platmacro.IS_WINDOWS:
r1: INT = w32.winsock2.setsockopt(u64(self.fd), SOL_SOCKET, SO_RCVTIMEO, c.Addr(tv), optlen)
r2: INT = w32.winsock2.setsockopt(u64(self.fd), SOL_SOCKET, SO_SNDTIMEO, c.Addr(tv), optlen)
else:
r1 = setsockopt(self.fd, SOL_SOCKET, SO_RCVTIMEO, c.Addr(tv), optlen)
r2 = setsockopt(self.fd, SOL_SOCKET, SO_SNDTIMEO, c.Addr(tv), optlen)
if r1 != 0: return r1
return r2
def fileno(self) -> INT:
"""返回底层文件描述符 / SOCKET 句柄。"""
return self.fd
# ============================================================
# 平台初始化
# ============================================================
def SocketInit() -> INT:
"""初始化 Socket 库。Windows 下调用 WSAStartup,POSIX 无操作。"""
if platmacro.IS_WINDOWS:
wsa_data: t.CArray[BYTE, 400]
string.memset(c.Addr(wsa_data), 0, 400)
return w32.winsock2.WSAStartup(w32.winsock2.WINSOCK_VERSION, c.Addr(wsa_data))
return 0
def SocketCleanup() -> INT:
"""清理 Socket 库。"""
if platmacro.IS_WINDOWS:
return w32.winsock2.WSACleanup()
return 0
# ============================================================
# 兼容旧版过程式 API(委托到 Socket 方法)
# ============================================================
def SocketCreate(family: INT, type: INT, protocol: INT, out_sock: Socket | t.CPtr) -> INT:
"""创建 Socket 句柄(兼容旧版 API)。建议使用 Socket(...) 构造。"""
if out_sock is None: return -1
out_sock.family = family
out_sock.type = type
out_sock.protocol = protocol
if platmacro.IS_WINDOWS:
fd: u64 = w32.winsock2.socket(family, type, protocol)
out_sock.fd = INT(fd)
if fd == w32.winsock2.INVALID_SOCKET: return -1
else:
fd: INT = socket(family, type, protocol)
out_sock.fd = fd
if fd == INVALID_SOCKET: return -1
return 0
def SocketConnect(sock: Socket | t.CPtr, host: str, port: INT) -> INT:
return sock.connect(host, port)
def SocketSend(sock: Socket | t.CPtr, data: t.CVoid | t.CPtr, length: INT) -> INT:
return sock.send(data, length)
def SocketRecv(sock: Socket | t.CPtr, buf: t.CVoid | t.CPtr, bufsize: INT) -> INT:
return sock.recv(buf, bufsize)
def SocketClose(sock: Socket | t.CPtr) -> INT:
return sock.close()
def SocketBind(sock: Socket | t.CPtr, host: str, port: INT) -> INT:
return sock.bind(host, port)
def SocketListen(sock: Socket | t.CPtr, backlog: INT) -> INT:
return sock.listen(backlog)
def SocketAccept(sock: Socket | t.CPtr, out_client: Socket | t.CPtr) -> INT:
return sock.accept(out_client)
def SocketSetTimeout(sock: Socket | t.CPtr, timeout_ms: INT) -> INT:
return sock.settimeout(timeout_ms)
def SocketIsValid(sock: Socket | t.CPtr) -> bool:
"""检查 Socket 是否有效。"""
if sock is None: return False
return sock.fd != INVALID_SOCKET
+18
View File
@@ -0,0 +1,18 @@
import t, c
import atom
@t.Object
class _spinlock:
locked: t.CVolatile | t.CInt
name: t.CArray[t.CChar, 32]
def __init__(self):
self.locked = 0
def lock(self):
while atom.__atomic_test_and_set(c.Addr(self.locked), atom.ATOMIC_ACQUIRE):
pass
def unlock(self):
atom.__atomic_clear(c.Addr(self.locked), atom.ATOMIC_RELEASE)
+9
View File
@@ -0,0 +1,9 @@
import t
def va_start(args: t.CPtr, last_arg: t.CPtr) -> t.State: pass
def va_arg(args: t.CPtr, type: t.CPtr) -> t.CPtr | t.State: pass
def va_end(args: t.CPtr) -> t.State | t.State: pass
va_list: t.CTypedef = t.CUnsignedChar | t.CPtr
def arg(type: t.CType) -> t.State: pass
+133
View File
@@ -0,0 +1,133 @@
import t
# =============================================================================
# 大写别名(Win32/TransPyC 风格)
# 注意:INTPTR/UINTPTR 在此模块中是 int*/unsigned int* 指针类型(历史命名)。
# 它们与 C 标准的 intptr_t/uintptr_t 整数类型不同,后者见下方小写 _t 区域。
# =============================================================================
INT: t.CTypedef = t.CInt
INTPTR: t.CTypedef = t.CInt | t.CPtr
BOOL: t.CTypedef = t.CInt
UINT: t.CTypedef = t.CUnsignedInt
UINTPTR: t.CTypedef = UINT | t.CPtr
BYTE: t.CTypedef = t.CUnsignedChar
BYTEPTR: t.CTypedef = BYTE | t.CPtr
WORD: t.CTypedef = t.CUInt16T
DWORD: t.CTypedef = t.CUInt32T
QWORD: t.CTypedef = t.CUInt64T
TCHAR: t.CTypedef = t.CChar
CHARLIST: t.CTypedef = str | t.CPtr
VOID: t.CTypedef = t.CVoid
SHORT: t.CTypedef = t.CShort
SHORTPTR: t.CTypedef = t.CShort | t.CPtr
USHORT: t.CTypedef = t.CUnsignedShort
USHORTPTR: t.CTypedef = t.CUnsignedShort | t.CPtr
LONGLONG: t.CTypedef = t.CLongLong
ULONGLONG: t.CTypedef = t.CUnsignedLongLong
LONG: t.CTypedef = t.CLong
ULONG: t.CTypedef = t.CUnsignedLong
WCHAR: t.CTypedef = WORD
WCHARPTR: t.CTypedef = WORD | t.CPtr
CHARPTR: t.CTypedef = t.CChar | t.CPtr
FSIZE_t: t.CTypedef = DWORD
LBA_t: t.CTypedef = DWORD
VOIDPTR: t.CTypedef = t.CVoid | t.CPtr
FLOAT: t.CTypedef = t.CFloat
DOUBLE: t.CTypedef = t.CDouble
FLOAT8: t.CTypedef = t.CFloat8T
FLOAT16: t.CTypedef = t.CFloat16T
FLOAT32: t.CTypedef = t.CFloat32T
FLOAT64: t.CTypedef = t.CFloat64T
FLOAT128: t.CTypedef = t.CFloat128T
# =============================================================================
# 定长整数大写别名
# =============================================================================
INT8: t.CTypedef = t.CInt8T
INT16: t.CTypedef = t.CInt16T
INT32: t.CTypedef = t.CInt32T
INT64: t.CTypedef = t.CInt64T
UINT8: t.CTypedef = t.CUInt8T
UINT16: t.CTypedef = t.CUInt16T
UINT32: t.CTypedef = t.CUInt32T
UINT64: t.CTypedef = t.CUInt64T
INT8PTR: t.CTypedef = t.CInt8T | t.CPtr
INT16PTR: t.CTypedef = t.CInt16T | t.CPtr
INT32PTR: t.CTypedef = t.CInt32T | t.CPtr
INT64PTR: t.CTypedef = t.CInt64T | t.CPtr
UINT8PTR: t.CTypedef = t.CUInt8T | t.CPtr
UINT16PTR: t.CTypedef = t.CUInt16T | t.CPtr
UINT32PTR: t.CTypedef = t.CUInt32T | t.CPtr
UINT64PTR: t.CTypedef = t.CUInt64T | t.CPtr
CHAR8: t.CTypedef = t.CChar8T
CHAR16: t.CTypedef = t.CChar16T
CHAR32: t.CTypedef = t.CChar32T
CHAR8PTR: t.CTypedef = t.CChar8T | t.CPtr
CHAR16PTR: t.CTypedef = t.CChar16T | t.CPtr
CHAR32PTR: t.CTypedef = t.CChar32T | t.CPtr
i8: t.CTypedef = t.CInt8T
i16: t.CTypedef = t.CInt16T
i32: t.CTypedef = t.CInt32T
i64: t.CTypedef = t.CInt64T
u8: t.CTypedef = t.CUInt8T
u16: t.CTypedef = t.CUInt16T
u32: t.CTypedef = t.CUInt32T
u64: t.CTypedef = t.CUInt64T
SIZE_T: t.CTypedef = t.CSizeT
SSIZE_T: t.CTypedef = t.CPtrDiffT
PTRDIFF_T: t.CTypedef = t.CPtrDiffT
# =============================================================================
# C 标准库 <stdint.h> 类型名(小写 _t 后缀)
# 这些是 C 语言标准类型名,从 _CNAME_ALIAS 挪到此处作为 typedef 提供。
# 用户 `from stdint import *` 后即可直接使用 int8_t / size_t 等。
# =============================================================================
int8_t: t.CTypedef = t.CInt8T
int16_t: t.CTypedef = t.CInt16T
int32_t: t.CTypedef = t.CInt32T
int64_t: t.CTypedef = t.CInt64T
uint8_t: t.CTypedef = t.CUInt8T
uint16_t: t.CTypedef = t.CUInt16T
uint32_t: t.CTypedef = t.CUInt32T
uint64_t: t.CTypedef = t.CUInt64T
size_t: t.CTypedef = t.CSizeT
ssize_t: t.CTypedef = t.CPtrDiffT
ptrdiff_t: t.CTypedef = t.CPtrDiffT
# intptr_t/uintptr_t 是足以容纳指针的整数类型(不是指针!)
# 与上方的 INTPTR/UINTPTR(int 指针)语义不同。
intptr_t: t.CTypedef = t.CIntPtrT
uintptr_t: t.CTypedef = t.CUIntPtrT
# 宽字符 / 字符类型
wchar_t: t.CTypedef = t.CWCharT
char8_t: t.CTypedef = t.CChar8T
char16_t: t.CTypedef = t.CChar16T
char32_t: t.CTypedef = t.CChar32T
# 浮点特化类型
float8_t: t.CTypedef = t.CFloat8T
float16_t: t.CTypedef = t.CFloat16T
float32_t: t.CTypedef = t.CFloat32T
float64_t: t.CTypedef = t.CFloat64T
float128_t: t.CTypedef = t.CFloat128T
_Bool: t.CTypedef = t.CBool
+16
View File
@@ -0,0 +1,16 @@
import t, c
def printf(fmt: t.CConst | str, *args) -> t.CInt | t.State: pass
def fprintf(stream: bytes, fmt: t.CConst | str, *args) -> t.CInt | t.State: pass
def sprintf(buf: bytes, fmt: t.CConst | str, *args) -> t.CInt | t.State: pass
def snprintf(buf: bytes, size: t.CSizeT, fmt: t.CConst | str, *args) -> t.CInt | t.State: pass
def puts(s: t.CConst | str) -> t.CInt | t.State: pass
def fputs(s: t.CConst | str, stream: bytes) -> t.CInt | t.State: pass
def fgets(buf: bytes, size: t.CInt, stream: bytes) -> bytes | t.State: pass
def fflush(stream: bytes) -> t.CInt | t.State: pass
# 标准流指针(全局变量,仅声明供 printf 等函数使用)
stdin: bytes = 0
stdout: bytes = 0
stderr: bytes = 0
+10
View File
@@ -0,0 +1,10 @@
from stdint import *
import t
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
+354
View File
@@ -0,0 +1,354 @@
from stdint import *
import t, c
# 字符串复制函数
def strcpy(dest: str, src: str) -> str:
if dest == None or src == None: return None
original_dest: str = dest
for s in src:
dest[0] = s
dest += 1
dest[0] = 0
return original_dest
# 字符串拼接函数: 将 src 追加到 dest 末尾
def strcat(dest: str, src: str) -> str:
if dest == None or src == None: return dest
original_dest: str = dest
# 找到 dest 末尾
while dest[0] != '\0':
dest += 1
# 复制 src
for s in src:
dest[0] = s
dest += 1
dest[0] = 0
return original_dest
# 有限长度字符串复制函数
def strncpy(dest: str, src: str, n: t.CSizeT) -> str:
if dest == None or src == None or n == 0: return dest
original_dest: str = dest
i: t.CSizeT = 0
for s in src:
if i >= n: break
dest[0] = s
dest += 1
i += 1
# 填充剩余空间为 '\0'
while i < n:
dest[0] = 0
dest += 1
i += 1
return original_dest
# 字符串长度函数
def strlen(src: str) -> t.CSizeT | t.CExport:
length: t.CSizeT = 0
for _ in src:
length += 1
return length
# 字符串比较函数
def strcmp(str1: str, str2: str) -> t.CInt:
while str1[0] != '\0' and str2[0] != '\0':
if str1[0] != str2[0]:
return str1[0] - str2[0]
str1 += 1
str2 += 1
return str1[0] - str2[0]
def samestr(str1: str, str2: str) -> bool:
return str1 == str2
# 有限长度字符串比较函数
def strncmp(str1: str, str2: str, n: t.CSizeT) -> t.CInt:
i: t.CSizeT = 0
while str1[0] != '\0' and str2[0] != '\0' and i < n:
if str1[0] != str2[0]:
return str1[0] - str2[0]
str1 += 1
str2 += 1
i += 1
if i < n:
return str1[0] - str2[0]
return 0
# 内存比较函数
def memcmp(ptr1: t.CVoid | t.CPtr, ptr2: t.CVoid | t.CPtr, n: t.CSizeT) -> t.CInt:
p1: BYTEPTR = BYTEPTR(ptr1)
p2: BYTEPTR = BYTEPTR(ptr2)
i: t.CSizeT = 0
while i < n:
if p1[i] != p2[i]:
return t.CInt(p1[i]) - t.CInt(p2[i])
i += 1
return 0
# 字符串查找函数
def strchr(s: str, cr: t.CInt) -> str:
while s[0] != '\0':
if s[0] == t.CChar(cr):
return str(s)
s += 1
if cr == '\0':
return str(s)
return None
# 字符串反向查找函数(找最后一次出现的字符)
def strrchr(s: str, cr: t.CInt) -> str:
last: str = None
while s[0] != '\0':
if s[0] == t.CChar(cr):
last = s
s += 1
if cr == '\0': return s
return last
# 子串查找函数(在 s 中查找 needle 第一次出现的位置,返回指向该位置的指针,未找到返回 None)
def strstr(s: str, needle: str) -> str:
if needle[0] == 0:
return s
needle_len: t.CSizeT = strlen(needle)
if needle_len == 0:
return s
i: t.CSizeT = 0
s_len: t.CSizeT = strlen(s)
while i + needle_len <= s_len:
if strncmp(s + i, needle, needle_len) == 0:
return s + i
i += 1
return None
# 跳过字符
def strspn(s: str, skip: str = " ") -> int:
si: int = 0
while s[si] != 0:
found: int = 0
sj: int = 0
while skip[sj] != 0:
if s[si] == skip[sj]:
found = 1
break
sj += 1
if found == 0:
break
si += 1
return si
# 内存设置函数
def memset(ptr: t.CVoid | t.CPtr, value: t.CInt, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport:
# 原始实现:
# p: BYTEPTR = BYTEPTR(ptr)
# i: t.CSizeT
# for i in range(num):
# p[i] = t.CUnsignedChar(value)
if num == 0: return ptr
c.Asm(f"""mov rdi, {c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)}
rep stosb""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI])
return ptr
def memset32(ptr: t.CVoid | t.CPtr, value: t.CUInt32T, count: t.CSizeT) -> t.CVoid | t.CPtr:
# 原始实现:
# p: UINT32PTR = UINT32PTR(ptr)
# i: t.CSizeT
# for i in range(count):
# p[i] = value
if count == 0: return ptr
c.Asm(f"""mov rdi, {c.AsmInp(ptr, t.ASM_DESCR.REG_ANY)}
mov eax, {c.AsmInp(value, t.ASM_DESCR.REG_ANY)}
mov rcx, {c.AsmInp(count, t.ASM_DESCR.REG_ANY)}
rep stosd""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDI])
return ptr
# 内存复制函数
def memcpy(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr | t.CExport:
# 原始实现:
# d: BYTEPTR = BYTEPTR(dest)
# s: BYTEPTR = BYTEPTR(src)
# i: t.CSizeT
# for i in range(num):
# d[i] = s[i]
if num == 0: return dest
c.Asm(f"""mov rdi, {c.AsmInp(dest, t.ASM_DESCR.REG_ANY)}
mov rsi, {c.AsmInp(src, t.ASM_DESCR.REG_ANY)}
mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)}
rep movsb""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX,
t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI])
return dest
# 内存移动函数
def memmove(dest: t.CVoid | t.CPtr, src: t.CVoid | t.CPtr, num: t.CSizeT) -> t.CVoid | t.CPtr:
# 原始实现:
# d: BYTEPTR = BYTEPTR(dest)
# s: BYTEPTR = BYTEPTR(src)
# i: t.CSizeT
# if d < s:
# for i in range(num):
# d[i] = s[i]
# elif d > s:
# for i in range(num, 0, -1):
# d[i - 1] = s[i - 1]
if num == 0: return dest
c.Asm(f"""mov rdi, {c.AsmInp(dest, t.ASM_DESCR.REG_ANY)}
mov rsi, {c.AsmInp(src, t.ASM_DESCR.REG_ANY)}
mov rcx, {c.AsmInp(num, t.ASM_DESCR.REG_ANY)}
cmp rdi, rsi
jb 2f
std
add rdi, rcx
dec rdi
add rsi, rcx
dec rsi
rep movsb
cld
jmp 3f
2:
rep movsb
3:""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RCX,
t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI])
return dest
def atoi(src: str) -> t.CInt:
num: t.CInt = 0
sign: t.CInt = 1
s: str = src
if s == None: return 0
# 跳过空白
while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r':
s += 1
# 符号
if s[0] == '-':
sign = -1
s += 1
elif s[0] == '+':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
digit: t.CInt = ch - '0'
num = num * 10 + digit
return num * sign
def atoll(src: str) -> t.CInt64T:
num: t.CInt64T = 0
sign: t.CInt64T = 1
s: str = src
if s == None: return 0
while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r':
s += 1
if s[0] == '-':
sign = -1
s += 1
elif s[0] == '+':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
d: t.CInt = ch - '0'
digit: t.CInt64T = t.CInt64T(d)
num = num * 10 + digit
return num * sign
def atof(src: str) -> t.CDouble:
s: str = src
if s == None: return 0.0
# 跳过空白
while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r':
s += 1
# 符号
sign: t.CDouble = 1.0
if s[0] == '-':
sign = -1.0
s += 1
elif s[0] == '+':
s += 1
# 整数部分
int_part: t.CDouble = 0.0
for ch in s:
if ch < '0' or ch > '9': break
d1: t.CInt = ch - '0'
int_part = int_part * 10.0 + t.CDouble(d1)
s += 1
# 小数部分
frac_part: t.CDouble = 0.0
frac_div: t.CDouble = 1.0
if s[0] == '.':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
d2: t.CInt = ch - '0'
frac_div = frac_div * 10.0
frac_part = frac_part * 10.0 + t.CDouble(d2)
s += 1
# 指数部分
exp: t.CInt = 0
exp_sign: t.CInt = 1
if s[0] == 'e' or s[0] == 'E':
s += 1
if s[0] == '-':
exp_sign = -1
s += 1
elif s[0] == '+':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
d3: t.CInt = ch - '0'
exp = exp * 10 + d3
s += 1
exp = exp * exp_sign
result: t.CDouble = sign * (int_part + frac_part / frac_div)
# 应用指数
if exp > 0:
while exp > 0:
result = result * 10.0
exp -= 1
elif exp < 0:
while exp < 0:
result = result / 10.0
exp += 1
return result
def split(s: str, delim: str, result: t.CArray[str]) -> int:
count: int = 0
start: str = s
if not s or not delim or not result:
return 0
d: t.CChar = delim[0] # 单分隔符
while start[0]:
# 跳过分隔符
while start[0] == d: start += 1
if not start[0]: break
# 记录token起始
result[count] = start
count += 1
# 找到下一个分隔符,截断
while start[0] and start[0] != d: start += 1
if start[0]:
start[0] = '\0'
start += 1
result[count] = None # 结尾标记
return count
+196
View File
@@ -0,0 +1,196 @@
import t, c
from stdint import *
import platmacro
import memhub
import string
# Windows 后端依赖
import w32.win32base
import w32.win32file
import w32.win32process
import w32.win32sync
# POSIX 后端依赖
import posix
# 子进程输出缓冲区大小
OUTPUT_BUF_SIZE: t.CDefine = 65536
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# CompletedProcess 结果类
# =============================================================================
class CompletedProcess:
"""subprocess.run 的返回结果"""
args: str # 原始命令行
returncode: int # 进程退出码(0 表示成功)
stdout: str # 标准输出(capture_output=True 时)
stderr: str # 标准错误(capture_output=True 时)
def __new__(self, args: str, returncode: int, stdout: str, stderr: str) -> t.CPtr:
# 堆分配(避免返回栈地址导致 use-after-return)
return t.CPtr(_mbuddy.alloc(CompletedProcess.__sizeof__()))
def __init__(self, args: str, returncode: int, stdout: str, stderr: str):
self.args = args
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
# =============================================================================
# 入口函数
# =============================================================================
def run(args: str, capture_output: bool = True, text: bool = True) -> CompletedProcess | t.CPtr:
"""同步执行子进程并等待完成。
args 为完整命令行字符串。
capture_output=True 时捕获 stdout/stderr。
text=True 时输出为字符串(当前实现总是返回字符串)。
返回 CompletedProcess 对象。"""
if platmacro.IS_WINDOWS:
return _run_win32(args, capture_output, text)
return _run_posix(args, capture_output, text)
# =============================================================================
# Windows 后端实现
# =============================================================================
def _run_win32(args: str, capture_output: bool, text: bool) -> CompletedProcess | t.CPtr:
"""Windows 平台子进程执行(CreateProcessA + 管道)"""
# 复制命令行(CreateProcessA 需要可修改的 lpCommandLine)
args_len: t.CSizeT = len(args)
cmd_line: bytes = _mbuddy.alloc(args_len + 1)
if cmd_line == None:
return CompletedProcess(args, -1, None, None)
i: t.CSizeT = 0
for ch in args:
cmd_line[i] = ch
i += 1
cmd_line[args_len] = 0
# 安全属性(允许句柄继承)
sa: w32.win32base.SECURITY_ATTRIBUTES = w32.win32base.SECURITY_ATTRIBUTES()
sa.nLength = w32.win32base.SECURITY_ATTRIBUTES.__sizeof__()
sa.lpSecurityDescriptor = t.CPtr(0)
sa.bInheritHandle = 1 # TRUE
# 创建 stdout 管道
stdout_read: w32.win32base.HANDLE = t.CPtr(0)
stdout_write: w32.win32base.HANDLE = t.CPtr(0)
if capture_output:
pipe_result: BOOL = w32.win32file.CreatePipe(
t.CPtr(c.Addr(stdout_read)),
t.CPtr(c.Addr(stdout_write)),
t.CPtr(c.Addr(sa)),
0
)
if pipe_result == 0:
return CompletedProcess(args, -1, None, None)
# 防止读端被子进程继承
w32.win32file.SetHandleInformation(stdout_read, w32.win32file.HANDLE_FLAG_INHERIT, 0)
# 设置启动信息
si: w32.win32process.STARTUPINFOA = w32.win32process.STARTUPINFOA()
si.cb = w32.win32process.STARTUPINFOA.__sizeof__()
if capture_output:
si.dwFlags = w32.win32process.STARTF_USESTDHANDLES
si.hStdOutput = stdout_write
si.hStdError = stdout_write # stderr 合并到 stdout
pi: w32.win32process.PROCESS_INFORMATION = w32.win32process.PROCESS_INFORMATION()
# 创建进程
# capture_output=True 时用 CREATE_NO_WINDOW(输出到管道,不需要控制台)
# capture_output=False 时用 0(继承父进程控制台,让 stdout 直接显示)
create_flags: ULONG = w32.win32process.CREATE_NO_WINDOW if capture_output else 0
create_result: BOOL = w32.win32process.CreateProcessA(
t.CPtr(0), # lpApplicationName (NULL,从命令行解析)
cmd_line, # lpCommandLine (可修改)
t.CPtr(0), # lpProcessAttributes
t.CPtr(0), # lpThreadAttributes
1, # bInheritHandles = TRUE
create_flags, # dwCreationFlags
t.CPtr(0), # lpEnvironment (继承父进程)
t.CPtr(0), # lpCurrentDirectory (继承父进程)
t.CPtr(c.Addr(si)),
t.CPtr(c.Addr(pi))
)
if create_result == 0:
# 创建失败
if capture_output:
w32.win32base.CloseHandle(stdout_read)
w32.win32base.CloseHandle(stdout_write)
return CompletedProcess(args, -1, None, None)
# 关闭父进程的写端(子进程已有写端的继承副本)
if capture_output:
w32.win32base.CloseHandle(stdout_write)
# 读取 stdout + 等待进程结束
# 注意:必须边读边等,否则子进程输出超过管道缓冲区时会死锁
# (子进程阻塞在写 stdout,父进程阻塞在 WaitForSingleObject)
stdout_str: str = None
if capture_output:
buf_size: ULONG = OUTPUT_BUF_SIZE
buf: bytes = _mbuddy.alloc(buf_size)
if buf != None:
total: ULONG = 0
while 1:
bytes_read: ULONG = 0
read_result: BOOL = w32.win32file.ReadFile(
stdout_read,
buf + total,
buf_size - 1 - total,
t.CPtr(c.Addr(bytes_read)),
t.CPtr(0)
)
if read_result == 0 or bytes_read == 0:
break
total += bytes_read
# 缓冲区将满,扩容(翻倍)
if total >= buf_size - 1 - 4096:
new_size: ULONG = buf_size * 2
new_buf: bytes = _mbuddy.alloc(new_size)
if new_buf != None:
string.memcpy(new_buf, buf, total)
buf = new_buf
buf_size = new_size
else:
# 扩容失败,停止读取
break
buf[total] = 0
stdout_str = str(buf)
# 等待进程结束(如果还没退出的话)
w32.win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE)
# 获取退出码
exit_code: ULONG = 0
w32.win32process.GetExitCodeProcess(pi.hProcess, t.CPtr(c.Addr(exit_code)))
# 关闭句柄
w32.win32base.CloseHandle(pi.hProcess)
w32.win32base.CloseHandle(pi.hThread)
if capture_output:
w32.win32base.CloseHandle(stdout_read)
return CompletedProcess(args, exit_code, stdout_str, None)
# =============================================================================
# POSIX 后端实现
# =============================================================================
def _run_posix(args: str, capture_output: bool, text: bool) -> CompletedProcess | t.CPtr:
"""POSIX 平台子进程执行(fork + execvp + pipe + waitpid)
注意:当前为桩函数。POSIX 实现需要 pipe/fork/waitpid,
这些函数在 Windows MinGW 上不可用,待 POSIX 平台测试时再完善。"""
return CompletedProcess(args, -1, None, None)
+200
View File
@@ -0,0 +1,200 @@
import t, c
from stdint import *
import platmacro
import memhub
import string
import stdio
# Windows 后端依赖
import w32.win32base
import w32.win32process
# POSIX 后端依赖
import posix
# 模块级全局 MBuddy 指针(由用户在 main 中赋值初始化)
_mbuddy: memhub.MemBuddy | t.CPtr
# =============================================================================
# C 标准库 IO 声明
# =============================================================================
def fgets(buf: t.CChar | t.CPtr, size: t.CInt, stream: t.CVoid | t.CPtr) -> t.CChar | t.CPtr | t.CExtern | t.CExport: pass
def fflush(stream: t.CVoid | t.CPtr) -> t.CInt | t.CExtern | t.CExport: pass
# C 标准库 exit(刷新缓冲区后终止进程,跨平台)
def exit(status: INT) -> VOID | t.CExtern | t.CExport: pass
# =============================================================================
# 平台信息
# =============================================================================
# 最大整数值(64 位平台 ssize_t 上限)
maxsize: t.CDefine = 9223372036854775807
def platform() -> str:
"""返回平台标识字符串('win32' 或 'linux')"""
if platmacro.IS_WINDOWS:
return "win32"
return "linux"
# =============================================================================
# 进程信息
# =============================================================================
def get_pid() -> int:
"""返回当前进程 ID"""
if platmacro.IS_WINDOWS:
return w32.win32process.GetCurrentProcessId()
return posix.getpid()
# =============================================================================
# 命令行参数(argv)
# =============================================================================
# 全局 argv 状态(首次访问时初始化)
_argc: INT = 0
# _argv 是指针数组(char**),必须用 str | t.CPtr 使索引按 sizeof(char*) 步长
# str 本身是 char*,| t.CPtr 再加一层指针 = char**
# bytes | t.CPtr 也是 char**,可以同样用
_argv: str | t.CPtr
def _init_argv():
"""初始化全局 argv(首次访问时调用一次)"""
global _argc, _argv
if _argc != 0:
return
if platmacro.IS_WINDOWS:
_init_argv_win32()
else:
_init_argv_posix()
def _init_argv_win32():
"""Windows:GetCommandLineA + 手动解析(处理空格/双引号/反斜杠)"""
global _argc, _argv
cmdline: CHARPTR = w32.win32base.GetCommandLineA()
if cmdline == None:
return
cmdlen: t.CSizeT = string.strlen(cmdline)
if cmdlen == 0:
return
# 分配参数字符串缓冲区(最坏情况:整个命令行 + argc 个 \0)
buf: bytes = _mbuddy.alloc(cmdlen + 1)
if buf == None:
return
# 分配指针数组(最坏情况:每个字符都是一个参数)
max_args: t.CSizeT = cmdlen + 1
argv_arr: str | t.CPtr = (str | t.CPtr)(_mbuddy.alloc(max_args * platmacro.SIZEOF_POINTER))
if argv_arr == None:
return
argc: INT = 0
i: t.CSizeT = 0
j: t.CSizeT = 0
in_quote: bool = False
in_arg: bool = False
while i < cmdlen:
ch: t.CInt = cmdline[i]
if ch == 34: # 双引号
in_quote = not in_quote
if not in_arg:
argv_arr[argc] = str(buf + j)
argc += 1
in_arg = True
elif (ch == 32 or ch == 9) and not in_quote:
# 空格或 Tab(引号外):参数分隔符
if in_arg:
buf[j] = 0
j += 1
in_arg = False
else:
if not in_arg:
argv_arr[argc] = str(buf + j)
argc += 1
in_arg = True
buf[j] = ch
j += 1
i += 1
if in_arg:
buf[j] = 0
_argc = argc
_argv = argv_arr
def _init_argv_posix():
"""POSIX:读取 /proc/self/cmdline(参数以 \\0 分隔,末尾双 \\0)"""
global _argc, _argv
fd: INT = posix.open("/proc/self/cmdline", posix.O_RDONLY, 0)
if fd < 0:
return
# 读取 cmdline(4KB 足够大多数情况)
buf: bytes = _mbuddy.alloc(4096)
if buf == None:
posix.close(fd)
return
total: ssize_t = posix.read(fd, buf, 4096)
posix.close(fd)
if total <= 0:
return
# 计算参数个数(\0 分隔)
argc: INT = 0
i: t.CSizeT = 0
total_size: t.CSizeT = t.CSizeT(total)
while i < total_size:
if buf[i] == 0:
argc += 1
i += 1
if argc == 0:
return
# 分配指针数组
argv_arr: str | t.CPtr = (str | t.CPtr)(_mbuddy.alloc(argc * platmacro.SIZEOF_POINTER))
if argv_arr == None:
return
# 填充指针(每个参数的起始地址)
argv_arr[0] = str(buf)
idx: INT = 1
i = 0
while i < total_size and idx < argc:
if buf[i] == 0:
argv_arr[idx] = str(buf + i + 1)
idx += 1
i += 1
_argc = argc
_argv = argv_arr
def argc() -> int:
"""返回命令行参数个数。首次调用时自动初始化。"""
if _argc == 0:
_init_argv()
return _argc
def argv(index: int) -> str:
"""返回第 index 个命令行参数(index 从 0 开始)。
首次调用时自动初始化。索引越界返回 None。"""
if _argc == 0:
_init_argv()
if index < 0 or index >= _argc:
return None
return _argv[index]
+71
View File
@@ -0,0 +1,71 @@
# testcheck - 回归测试格式化输出库
# 提供 PASS/FAIL 计数、分节标题、汇总报告
import t, c
import stdio
from w32.win32console import SetConsoleOutputCP, SetConsoleCP
CP_UTF8: t.CDefine = 65001
_pass_count: t.CInt = 0
_fail_count: t.CInt = 0
_total_pass: t.CInt = 0
_total_fail: t.CInt = 0
def begin(name: str):
"""开始测试套件,打印头部并重置当前套件计数器(累计计数不变)"""
global _pass_count, _fail_count
_pass_count = 0
_fail_count = 0
SetConsoleOutputCP(CP_UTF8)
SetConsoleCP(CP_UTF8)
stdio.printf("=== %s ===\n\n", name)
def section(name: str):
"""打印分节标题"""
stdio.printf("--- %s ---\n", name)
def ok(msg: str):
"""打印 PASS 并计数"""
global _pass_count
_pass_count += 1
stdio.printf("PASS: %s\n", msg)
def fail(msg: str):
"""打印 FAIL 并计数"""
global _fail_count
_fail_count += 1
stdio.printf("FAIL: %s\n", msg)
def check(cond: t.CInt, ok_msg: str, fail_msg: str):
"""条件检查,自动选择 PASS/FAIL"""
if cond:
ok(ok_msg)
else:
fail(fail_msg)
def info(msg: str):
"""打印信息消息(不计入 PASS/FAIL)"""
stdio.printf("%s\n", msg)
def end() -> t.CInt:
"""打印当前套件汇总,累加到总计,返回当前套件失败数"""
global _total_pass, _total_fail
_total_pass += _pass_count
_total_fail += _fail_count
stdio.printf("\n--- Summary ---\n")
stdio.printf("PASS: %d, FAIL: %d\n", _pass_count, _fail_count)
return _fail_count
def summary() -> t.CInt:
"""打印所有套件的总计汇总,返回总失败数"""
stdio.printf("\n=== Total Summary ===\n")
stdio.printf("Total PASS: %d, Total FAIL: %d\n", _total_pass, _total_fail)
return _total_fail
+39
View File
@@ -0,0 +1,39 @@
import stdio, t, c
def this():
s: str = """Ivcre Cevapvcyrf, ol GrezvArkhf
Ornhgl orngf htyvarff.
Rkcyvpvg orngf vzcyvpvg.
Fvzcyr orngf pbzcyrk.
Pbapvfr orngf ireobfr.
Syng orngf qrrc arfgvat.
Fcnpvbhf orngf pyhggrerq.
Ernqnovyvgl vf pehpvny.
Fcrpvny pnfrf qba’g whfgvsl oernxvat gur ehyrf.
Ohg cenpgvpnyvgl orngf cher vqrnyf.
Reebef fubhyq arire or fvyragyl vtaberq.
Hayrff rkcyvpvgyl fgngrq gb or vtaberq.
Jura snprq jvgu nzovthbhf frznagvpf, erfvfg znxvat nffhzcgvbaf.
Hayrff pyrneyl nyybjrq.
Gurer fubhyq or bar — cersrenoyl bayl bar — boivbhf jnl gb qb vg.
Rira vs vg’f uneq gb tenfc ng svefg, hayrff lbh qrrcyl haqrefgnaq gur haqreylvat flfgrz.
Fgnegvat vzzrqvngryl orngf vaqrsvavgr qrynl.
Ohg unfgl npgvba vf bsgra jbefr guna pnershy jnvgvat.
Vs na vzcyrzragngvba vf bofpher naq uneq gb qrfpevor, vg’f n onq fbyhgvba.
Vs na vzcyrzragngvba vf pyrne naq rnfl gb haqrefgnaq, punaprf ner vg’f n tbbq fbyhgvba.
Anzrfcnprf ner vaperqvoyl inyhnoyr — hfr gurz trarebhfyl!"""
# ASCII
m: t.CArray[t.CChar, 256] = [0]
l: t.CArray[int, 2] = [65, 97]
for k in l:
for i in range(26):
m[k + i] = (k + ((i + 13) % 26)) # 隐式类型转换
for ch in s:
_: t.CUInt8T = ch
stdio.printf("%c", m[_] if m[_] else ch)
stdio.printf("\n")
+66
View File
@@ -0,0 +1,66 @@
import t, c
from stdint import *
import memhub
class Vector[T]():
data: t.CVoid | t.CPtr
length: t.CSizeT
capacity: t.CSizeT
elem_size: t.CSizeT
pool: memhub.MemManager | t.CPtr
def __init__(self, pool: memhub.MemManager | t.CPtr, capacity: t.CSizeT, _hint: T):
self.elem_size = T.__sizeof__()
self.capacity = capacity
self.length = 0
self.pool = pool
self.data = pool.alloc(capacity * self.elem_size)
def push(self, value: T):
if self.data == None: return
if self.length >= self.capacity:
self._grow()
if self.length >= self.capacity: return
offset: t.CUInt64T = t.CUInt64T(self.data) + self.length * self.elem_size
dst: t.CVoid | t.CPtr = t.CVoid(offset, t.CPtr)
c.DerefAs(dst, value)
self.length += 1
def _grow(self):
if self.pool == None: return
new_capacity: t.CSizeT = self.capacity * 2
if new_capacity == 0: new_capacity = 4
old_size: t.CSizeT = self.capacity * self.elem_size
new_size: t.CSizeT = new_capacity * self.elem_size
new_data: t.CVoid | t.CPtr = self.pool.realloc(self.data, old_size, new_size)
if new_data == None: return
self.data = new_data
self.capacity = new_capacity
def get(self, index: t.CSizeT) -> T:
if self.data == None: return T(0)
offset: t.CUInt64T = t.CUInt64T(self.data) + index * self.elem_size
typed_ptr = T(offset, t.CPtr)
return c.Deref(typed_ptr)
def set(self, index: t.CSizeT, value: T):
if index >= self.length: return
if self.data == None: return
offset: t.CUInt64T = t.CUInt64T(self.data) + index * self.elem_size
dst: t.CVoid | t.CPtr = t.CVoid(offset, t.CPtr)
c.DerefAs(dst, value)
def len(self) -> t.CSizeT:
return self.length
def clear(self):
self.length = 0
def free(self):
if self.data != None:
if self.pool != None:
self.pool.free(self.data)
self.data = None
self.length = 0
self.capacity = 0
+57
View File
@@ -0,0 +1,57 @@
import t, c
from stdint import *
class Buf:
data: t.CChar | t.CPtr
length: t.CSizeT
capacity: t.CSizeT
owned: bool
def __init__(self, data: t.CChar | t.CPtr, capacity: t.CSizeT, length: t.CSizeT = 0, owned: bool = False):
self.data = data
self.capacity = capacity
self.length = length
self.owned = owned
def clear(self):
self.length = 0
if self.data != None and self.capacity > 0:
self.data[0] = 0
def write(self, src: t.CChar | t.CPtr, count: t.CSizeT) -> t.CSizeT:
if self.data == None: return 0
if src == None: return 0
if count == 0: return 0
avail: t.CSizeT = self.capacity - self.length
if avail <= 0: return 0
n: t.CSizeT = count if count < avail else avail
i: t.CSizeT = 0
while i < n:
self.data[self.length + i] = src[i]
i += 1
self.length += n
self.data[self.length] = 0
return n
def cstr(self) -> t.CChar | t.CPtr:
return self.data
def reset(self):
self.length = 0
if self.data != None and self.capacity > 0:
self.data[0] = 0
def __enter__(self) -> 'Buf' | t.CPtr:
return self
def __exit__(self):
self.reset()
def free(self):
if self.owned and self.data != None:
self.data[0] = 0
self.owned = False
self.data = None
self.length = 0
self.capacity = 0
+1364
View File
File diff suppressed because it is too large. Load diff
+542
View File
@@ -0,0 +1,542 @@
import t, c
U_M_PI: t.CDefine = 3.14159265358979323846
U_M_E: t.CDefine = 2.71828182845904523536
U_M_PI_2: t.CDefine = 1.57079632679489661923
U_M_PI_4: t.CDefine = 0.78539816339744830962
U_M_1_PI: t.CDefine = 0.31830988618379067154
U_M_2_PI: t.CDefine = 0.63661977236758134308
U_M_LN2: t.CDefine = 0.69314718055994530942
U_M_LN10: t.CDefine = 2.30258509299404568402
U_M_2_SQRT_PI: t.CDefine = 1.77245385090551602730
def radians(degrees: t.CDouble) -> t.CDouble:
return degrees * (U_M_PI / t.CDouble(180.0))
def degrees(radians: t.CDouble) -> t.CDouble:
return radians * (t.CDouble(180.0) / U_M_PI)
def sin(x: t.CDouble) -> t.CDouble:
while x > U_M_PI:
x -= t.CDouble(2.0) * U_M_PI
while x < -U_M_PI:
x += t.CDouble(2.0) * U_M_PI
x2: t.CDouble = x * x
result: t.CDouble = x
term: t.CDouble = x
term = term * x2 / t.CDouble(6.0)
result = result - term
term = term * x2 / t.CDouble(20.0)
result = result + term
term = term * x2 / t.CDouble(42.0)
result = result - term
term = term * x2 / t.CDouble(72.0)
result = result + term
term = term * x2 / t.CDouble(110.0)
result = result - term
term = term * x2 / t.CDouble(156.0)
result = result + term
term = term * x2 / t.CDouble(210.0)
result = result - term
term = term * x2 / t.CDouble(272.0)
result = result + term
return result
def cos(x: t.CDouble) -> t.CDouble:
while x > U_M_PI:
x -= t.CDouble(2.0) * U_M_PI
while x < -U_M_PI:
x += t.CDouble(2.0) * U_M_PI
x2: t.CDouble = x * x
result: t.CDouble = t.CDouble(1.0)
term: t.CDouble = t.CDouble(1.0)
term = term * x2 / t.CDouble(2.0)
result = result - term
term = term * x2 / t.CDouble(12.0)
result = result + term
term = term * x2 / t.CDouble(30.0)
result = result - term
term = term * x2 / t.CDouble(56.0)
result = result + term
term = term * x2 / t.CDouble(90.0)
result = result - term
term = term * x2 / t.CDouble(132.0)
result = result + term
term = term * x2 / t.CDouble(182.0)
result = result - term
term = term * x2 / t.CDouble(240.0)
result = result + term
return result
def tan(x: t.CDouble) -> t.CDouble:
return sin(x) / cos(x)
def asin(x: t.CDouble) -> t.CDouble:
if x > t.CDouble(1.0):
x = t.CDouble(1.0)
if x < t.CDouble(-1.0):
x = t.CDouble(-1.0)
x2: t.CDouble = x * x
result: t.CDouble = x
result += x * x2 / t.CDouble(6.0)
result += t.CDouble(3.0) * x * x2 * x2 / t.CDouble(40.0)
result += t.CDouble(5.0) * x * x2 * x2 * x2 / t.CDouble(112.0)
result += t.CDouble(35.0) * x * x2 * x2 * x2 * x2 / t.CDouble(1152.0)
result += t.CDouble(63.0) * x * x2 * x2 * x2 * x2 * x2 / t.CDouble(2816.0)
return result
def acos(x: t.CDouble) -> t.CDouble:
return U_M_PI / t.CDouble(2.0) - asin(x)
def _atan_core(x: t.CDouble) -> t.CDouble:
x2: t.CDouble = x * x
result: t.CDouble = x
term: t.CDouble = x
term = term * x2 / t.CDouble(3.0)
result = result - term
term = term * x2 / t.CDouble(5.0)
result = result + term
term = term * x2 / t.CDouble(7.0)
result = result - term
term = term * x2 / t.CDouble(9.0)
result = result + term
term = term * x2 / t.CDouble(11.0)
result = result - term
term = term * x2 / t.CDouble(13.0)
result = result + term
term = term * x2 / t.CDouble(15.0)
result = result - term
term = term * x2 / t.CDouble(17.0)
result = result + term
term = term * x2 / t.CDouble(19.0)
result = result - term
term = term * x2 / t.CDouble(21.0)
result = result + term
return result
def atan(x: t.CDouble) -> t.CDouble:
ax: t.CDouble = x
if ax < t.CDouble(0.0):
ax = -ax
if ax > t.CDouble(1.0):
return t.CDouble(0.0) - _atan_core(t.CDouble(1.0) / ax) + U_M_PI_2 if x > t.CDouble(0.0) else _atan_core(t.CDouble(1.0) / ax) - U_M_PI_2
return _atan_core(x) if x >= t.CDouble(0.0) else t.CDouble(0.0) - _atan_core(ax)
def atan2(y: t.CDouble, x: t.CDouble) -> t.CDouble:
if x > t.CDouble(0.0):
return atan(y / x)
elif x < t.CDouble(0.0):
if y >= t.CDouble(0.0):
return atan(y / x) + U_M_PI
else:
return atan(y / x) - U_M_PI
else:
if y > t.CDouble(0.0):
return U_M_PI_2
elif y < t.CDouble(0.0):
return t.CDouble(0.0) - U_M_PI_2
else:
return t.CDouble(0.0)
def sinh(x: t.CDouble) -> t.CDouble:
ex: t.CDouble = exp(x)
e_negx: t.CDouble = exp(-x)
return (ex - e_negx) / t.CDouble(2.0)
def cosh(x: t.CDouble) -> t.CDouble:
ex: t.CDouble = exp(x)
e_negx: t.CDouble = exp(-x)
return (ex + e_negx) / t.CDouble(2.0)
def tanh(x: t.CDouble) -> t.CDouble:
ex: t.CDouble = exp(x)
e_negx: t.CDouble = exp(-x)
return (ex - e_negx) / (ex + e_negx)
def exp(x: t.CDouble) -> t.CDouble:
if x > t.CDouble(709.0):
return t.CDouble(1.7976931348623157e308)
if x < t.CDouble(-709.0):
return t.CDouble(0.0)
result: t.CDouble = t.CDouble(1.0)
term: t.CDouble = t.CDouble(1.0)
term = term * x / t.CDouble(1.0)
result = result + term
term = term * x / t.CDouble(2.0)
result = result + term
term = term * x / t.CDouble(3.0)
result = result + term
term = term * x / t.CDouble(4.0)
result = result + term
term = term * x / t.CDouble(5.0)
result = result + term
term = term * x / t.CDouble(6.0)
result = result + term
term = term * x / t.CDouble(7.0)
result = result + term
term = term * x / t.CDouble(8.0)
result = result + term
term = term * x / t.CDouble(9.0)
result = result + term
term = term * x / t.CDouble(10.0)
result = result + term
term = term * x / t.CDouble(11.0)
result = result + term
term = term * x / t.CDouble(12.0)
result = result + term
term = term * x / t.CDouble(13.0)
result = result + term
term = term * x / t.CDouble(14.0)
result = result + term
term = term * x / t.CDouble(15.0)
result = result + term
term = term * x / t.CDouble(16.0)
result = result + term
term = term * x / t.CDouble(17.0)
result = result + term
term = term * x / t.CDouble(18.0)
result = result + term
return result
def log(x: t.CDouble) -> t.CDouble:
if x <= t.CDouble(0.0):
return t.CDouble(-1e308)
exponent: t.CInt = 0
while x >= t.CDouble(2.0):
x /= t.CDouble(2.0)
exponent += 1
while x < t.CDouble(1.0):
x *= t.CDouble(2.0)
exponent -= 1
y: t.CDouble = (x - t.CDouble(1.0)) / (x + t.CDouble(1.0))
y2: t.CDouble = y * y
result: t.CDouble = t.CDouble(2.0) * y
term: t.CDouble = t.CDouble(2.0) * y
term = term * y2
result = result + term / t.CDouble(3.0)
term = term * y2
result = result + term / t.CDouble(5.0)
term = term * y2
result = result + term / t.CDouble(7.0)
term = term * y2
result = result + term / t.CDouble(9.0)
term = term * y2
result = result + term / t.CDouble(11.0)
term = term * y2
result = result + term / t.CDouble(13.0)
term = term * y2
result = result + term / t.CDouble(15.0)
term = term * y2
result = result + term / t.CDouble(17.0)
term = term * y2
result = result + term / t.CDouble(19.0)
term = term * y2
result = result + term / t.CDouble(21.0)
result += t.CDouble(exponent) * U_M_LN2
return result
def sqrt(x: t.CDouble) -> t.CDouble:
if x < t.CDouble(0.0):
return t.CDouble(0.0)
if x == t.CDouble(0.0):
return t.CDouble(0.0)
guess: t.CDouble = x / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
guess = (guess + x / guess) / t.CDouble(2.0)
return guess
def abs(x: t.CInt) -> t.CInt:
return x if x >= 0 else -x
def fabs(x: t.CDouble) -> t.CDouble:
return x if x >= t.CDouble(0.0) else -x
def labs(x: t.CLong) -> t.CLong:
return x if x >= 0 else -x
def factorial(n: t.CInt) -> t.CDouble:
if n < 0: return t.CDouble(0.0)
if n == 0 or n == 1: return t.CDouble(1.0)
result: t.CDouble = t.CDouble(1.0)
for i in range(2, n + 1):
result *= i
return result
def combination(n: t.CInt, k: t.CInt) -> t.CDouble:
if k < 0 or k > n: return t.CDouble(0.0)
if k == 0 or k == n: return t.CDouble(1.0)
k = k if k < n - k else n - k
result: t.CDouble = t.CDouble(1.0)
for i in range(1, k + 1):
result = result * (n - k + i) / i
return result
def permutation(n: t.CInt, k: t.CInt) -> t.CDouble:
if k < 0 or k > n: return t.CDouble(0.0)
result: t.CDouble = t.CDouble(1.0)
for i in range(0, k):
result *= (n - i)
return result
def pow(x: t.CDouble, y: t.CDouble) -> t.CDouble:
if x == t.CDouble(0.0):
if y > t.CDouble(0.0):
return t.CDouble(0.0)
return t.CDouble(1.0)
if x < t.CDouble(0.0):
iy: t.CDouble = y * log(-x)
return exp(iy)
return exp(y * log(x))
def powf(x: t.CDouble, y: t.CDouble) -> t.CDouble:
return pow(x, y)
def cbrt(x: t.CDouble) -> t.CDouble:
return pow(x, t.CDouble(1.0) / t.CDouble(3.0))
def hypot(x: t.CDouble, y: t.CDouble) -> t.CDouble:
return sqrt(x * x + y * y)
def floor(x: t.CDouble) -> t.CDouble:
if x >= t.CDouble(0.0):
return t.CDouble(t.CInt(x))
i: t.CInt = t.CInt(x)
if x < t.CDouble(i):
return t.CDouble(i - 1)
else:
return t.CDouble(i)
def ceil(x: t.CDouble) -> t.CDouble:
if x < t.CDouble(0.0):
return t.CDouble(t.CInt(x))
i: t.CInt = t.CInt(x)
if x > t.CDouble(i):
return t.CDouble(i + 1)
else:
return t.CDouble(i)
def round(x: t.CDouble) -> t.CDouble:
return floor(x + t.CDouble(0.5))
def trunc(x: t.CDouble) -> t.CDouble:
if x >= t.CDouble(0.0):
return floor(x)
else:
return ceil(x)
def fmod(x: t.CDouble, y: t.CDouble) -> t.CDouble:
if y == t.CDouble(0.0):
return t.CDouble(0.0)
result: t.CDouble = x - y * floor(x / y)
if result < t.CDouble(0.0):
result += y
return result
def fmodf(x: float, y: float) -> float:
if y == float(0.0):
return float(0.0)
result: float = x - y * floorf(x / y)
if result < float(0.0):
result += y
return result
def modf(x: t.CDouble, iptr: t.CDouble | t.CPtr) -> t.CDouble:
int_part: t.CDouble = floor(x)
c.Set(c.Deref(iptr), int_part)
return x - int_part
def log10(x: t.CDouble) -> t.CDouble:
return log(x) / U_M_LN10
def log2(x: t.CDouble) -> t.CDouble:
return log(x) / U_M_LN2
def exp2(x: t.CDouble) -> t.CDouble:
return pow(t.CDouble(2.0), x)
def expm1(x: t.CDouble) -> t.CDouble:
return exp(x) - t.CDouble(1.0)
def log1p(x: t.CDouble) -> t.CDouble:
return log(t.CDouble(1.0) + x)
def asinh(x: t.CDouble) -> t.CDouble:
return log(x + sqrt(x * x + t.CDouble(1.0)))
def acosh(x: t.CDouble) -> t.CDouble:
return log(x + sqrt(x * x - t.CDouble(1.0)))
def atanh(x: t.CDouble) -> t.CDouble:
return (log(t.CDouble(1.0) + x) - log(t.CDouble(1.0) - x)) / t.CDouble(2.0)
def gamma(x: t.CDouble) -> t.CDouble:
if x <= t.CDouble(0.0): return t.CDouble(0.0)
if x == t.CDouble(1.0) or x == t.CDouble(2.0): return t.CDouble(1.0)
ln_gamma: t.CDouble = t.CDouble(0.5) * log(t.CDouble(2.0) * U_M_PI / x) + x * log(x / U_M_E)
return exp(ln_gamma)
def erf(x: t.CDouble) -> t.CDouble:
sign: t.CDouble = t.CDouble(1.0) if x >= t.CDouble(0.0) else t.CDouble(-1.0)
abs_x: t.CDouble = fabs(x)
t0: t.CDouble = t.CDouble(4.0) * abs_x * abs_x / U_M_PI
exp_term: t.CDouble = exp(-t0)
return sign * sqrt(t.CDouble(1.0) - exp_term)
def erfc(x: t.CDouble) -> t.CDouble:
return t.CDouble(1.0) - erf(x)
def sqrtf(x: t.CFloat) -> t.CFloat:
if x < t.CFloat(0.0):
return t.CFloat(0.0)
if x == t.CFloat(0.0):
return t.CFloat(0.0)
guess: t.CFloat = x / t.CFloat(2.0)
for i in range(10):
guess = (guess + x / guess) / t.CFloat(2.0)
return guess
def sinf(x: t.CFloat) -> t.CFloat:
while x > t.CFloat(3.14159265):
x -= t.CFloat(6.28318530)
while x < t.CFloat(-3.14159265):
x += t.CFloat(6.28318530)
x2: t.CFloat = x * x
result: t.CFloat = x
term: t.CFloat = x
term = term * x2 / t.CFloat(6.0)
result = result - term
term = term * x2 / t.CFloat(20.0)
result = result + term
term = term * x2 / t.CFloat(42.0)
result = result - term
term = term * x2 / t.CFloat(72.0)
result = result + term
term = term * x2 / t.CFloat(110.0)
result = result - term
term = term * x2 / t.CFloat(156.0)
result = result + term
term = term * x2 / t.CFloat(210.0)
result = result - term
term = term * x2 / t.CFloat(272.0)
result = result + term
return result
def cosf(x: t.CFloat) -> t.CFloat:
while x > t.CFloat(3.14159265):
x -= t.CFloat(6.28318530)
while x < t.CFloat(-3.14159265):
x += t.CFloat(6.28318530)
x2: t.CFloat = x * x
result: t.CFloat = t.CFloat(1.0)
term: t.CFloat = t.CFloat(1.0)
term = term * x2 / t.CFloat(2.0)
result = result - term
term = term * x2 / t.CFloat(12.0)
result = result + term
term = term * x2 / t.CFloat(30.0)
result = result - term
term = term * x2 / t.CFloat(56.0)
result = result + term
term = term * x2 / t.CFloat(90.0)
result = result - term
term = term * x2 / t.CFloat(132.0)
result = result + term
term = term * x2 / t.CFloat(182.0)
result = result - term
term = term * x2 / t.CFloat(240.0)
result = result + term
return result
def tanf(x: t.CFloat) -> t.CFloat:
c: t.CFloat = cosf(x)
if c == t.CFloat(0.0):
return t.CFloat(0.0)
return sinf(x) / c
def fabsf(x: t.CFloat) -> t.CFloat:
return x if x >= t.CFloat(0.0) else -x
def floorf(x: t.CFloat) -> t.CFloat:
if x >= t.CFloat(0.0):
return t.CFloat(t.CInt(x))
i: t.CInt = t.CInt(x)
if x < t.CFloat(i):
return t.CFloat(i - 1)
else:
return t.CFloat(i)
def ceilf(x: t.CFloat) -> t.CFloat:
if x < t.CFloat(0.0):
return t.CFloat(t.CInt(x))
i: t.CInt = t.CInt(x)
if x > t.CFloat(i):
return t.CFloat(i + 1)
else:
return t.CFloat(i)
class _U(t.CUnion):
d: t.CDouble
u: t.CUInt64T
def isnan(x: t.CDouble) -> t.CStatic | t.CInt:
u: t.CUInt64T = t.CUInt64T(x)
exp_part: t.CUInt64T = (u >> 52) & 0x7FF
mantissa_part: t.CUInt64T = u & 0xFFFFFFFFFFFFF
if exp_part == 0x7FF:
if mantissa_part != 0:
return 1
return 0
def isinf(x: t.CDouble) -> t.CStatic | t.CInt:
u: t.CUInt64T = t.CUInt64T(x)
exp_part: t.CUInt64T = (u >> 52) & 0x7FF
mantissa_part: t.CUInt64T = u & 0xFFFFFFFFFFFFF
if exp_part == 0x7FF:
if mantissa_part == 0:
return 1
return 0
+460
View File
@@ -0,0 +1,460 @@
import t, c
# ============================================================
# AVX2 双精度向量运算 (4 x double, 256-bit YMM)
# ============================================================
def simd_add4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] + b[0:4]"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vaddpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_sub4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] - b[0:4]"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vsubpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_mul4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] * b[0:4]"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vmulpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_div4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] / b[0:4]"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vdivpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_sqrt4d(a: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = sqrt(a[0:4])"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vsqrtpd ymm0, ymm0
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0'])
def simd_neg4d(a: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = -a[0:4] (flip sign bit via XOR)"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vpcmpeqd ymm1, ymm1, ymm1
vpsllq ymm1, ymm1, 63
vxorpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_abs4d(a: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = |a[0:4]| (clear sign bit via ANDN)"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vpcmpeqd ymm1, ymm1, ymm1
vpsllq ymm1, ymm1, 63
vandnpd ymm0, ymm1, ymm0
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_max4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = max(a[0:4], b[0:4])"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vmaxpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_min4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = min(a[0:4], b[0:4])"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vminpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_mul_scalar4d(a: t.CPtr, scalar: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] * scalar (broadcast)"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vbroadcastsd ymm1, [{c.AsmInp(scalar, t.ASM_DESCR.REG_ANY)}]
vmulpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_add_scalar4d(a: t.CPtr, scalar: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4] + scalar (broadcast)"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vbroadcastsd ymm1, [{c.AsmInp(scalar, t.ASM_DESCR.REG_ANY)}]
vaddpd ymm0, ymm0, ymm1
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_hsum4d(a: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0] = a[0]+a[1]+a[2]+a[3] (horizontal sum)"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vextractf128 xmm1, ymm0, 1
vaddpd xmm0, xmm0, xmm1
vhaddpd xmm0, xmm0, xmm0
vmovsd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_dot4d(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0] = dot(a[0:4], b[0:4])"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vmulpd ymm0, ymm0, ymm1
vextractf128 xmm1, ymm0, 1
vaddpd xmm0, xmm0, xmm1
vhaddpd xmm0, xmm0, xmm0
vmovsd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1'])
def simd_fma4d(a: t.CPtr, b: t.CPtr, c_val: t.CPtr, out: t.CPtr) -> t.CVoid:
"""AVX2: out[0:4] = a[0:4]*b[0:4] + c[0:4] (fused multiply-add)
Uses vfmadd213pd: ymm0 = ymm1 * ymm0 + ymm2
Load order: b->ymm0, a->ymm1, c->ymm2"""
c.Asm(f"""vmovupd ymm0, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm1, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
vmovupd ymm2, [{c.AsmInp(c_val, t.ASM_DESCR.REG_ANY)}]
vfmadd213pd ymm0, ymm1, ymm2
vmovupd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], ymm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'ymm2'])
# ============================================================
# SSE2 单精度向量运算 (4 x float, 128-bit XMM)
# ============================================================
def simd_add4f(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""SSE2: out[0:4] = a[0:4] + b[0:4] (float)"""
c.Asm(f"""movups xmm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
movups xmm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
addps xmm0, xmm1
movups [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'xmm0', 'xmm1'])
def simd_sub4f(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""SSE2: out[0:4] = a[0:4] - b[0:4] (float)"""
c.Asm(f"""movups xmm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
movups xmm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
subps xmm0, xmm1
movups [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'xmm0', 'xmm1'])
def simd_mul4f(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""SSE2: out[0:4] = a[0:4] * b[0:4] (float)"""
c.Asm(f"""movups xmm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
movups xmm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
mulps xmm0, xmm1
movups [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'xmm0', 'xmm1'])
def simd_div4f(a: t.CPtr, b: t.CPtr, out: t.CPtr) -> t.CVoid:
"""SSE2: out[0:4] = a[0:4] / b[0:4] (float)"""
c.Asm(f"""movups xmm0, [{c.AsmInp(a, t.ASM_DESCR.REG_ANY)}]
movups xmm1, [{c.AsmInp(b, t.ASM_DESCR.REG_ANY)}]
divps xmm0, xmm1
movups [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm0""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'xmm0', 'xmm1'])
# ============================================================
# 批量数组运算 (AVX2 循环, 处理 N 个 double)
# ============================================================
def simd_add_array(a: t.CPtr, b: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = a[i:i+4] + b[i:i+4], i=0,4,8,..."""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r9, {c.AsmInp(b, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
test rcx, rcx
jz .Ladd_end
.Ladd_loop:
vmovupd ymm0, [r8]
vmovupd ymm1, [r9]
vaddpd ymm0, ymm0, ymm1
vmovupd [r10], ymm0
add r8, 32
add r9, 32
add r10, 32
dec rcx
jnz .Ladd_loop
.Ladd_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'rcx', 'r8', 'r9', 'r10'])
def simd_sub_array(a: t.CPtr, b: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = a[i:i+4] - b[i:i+4]"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r9, {c.AsmInp(b, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
test rcx, rcx
jz .Lsub_end
.Lsub_loop:
vmovupd ymm0, [r8]
vmovupd ymm1, [r9]
vsubpd ymm0, ymm0, ymm1
vmovupd [r10], ymm0
add r8, 32
add r9, 32
add r10, 32
dec rcx
jnz .Lsub_loop
.Lsub_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'rcx', 'r8', 'r9', 'r10'])
def simd_mul_array(a: t.CPtr, b: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = a[i:i+4] * b[i:i+4]"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r9, {c.AsmInp(b, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
test rcx, rcx
jz .Lmul_end
.Lmul_loop:
vmovupd ymm0, [r8]
vmovupd ymm1, [r9]
vmulpd ymm0, ymm0, ymm1
vmovupd [r10], ymm0
add r8, 32
add r9, 32
add r10, 32
dec rcx
jnz .Lmul_loop
.Lmul_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'rcx', 'r8', 'r9', 'r10'])
def simd_div_array(a: t.CPtr, b: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = a[i:i+4] / b[i:i+4]"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r9, {c.AsmInp(b, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
test rcx, rcx
jz .Ldiv_end
.Ldiv_loop:
vmovupd ymm0, [r8]
vmovupd ymm1, [r9]
vdivpd ymm0, ymm0, ymm1
vmovupd [r10], ymm0
add r8, 32
add r9, 32
add r10, 32
dec rcx
jnz .Ldiv_loop
.Ldiv_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'rcx', 'r8', 'r9', 'r10'])
def simd_sqrt_array(a: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = sqrt(a[i:i+4])"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
test rcx, rcx
jz .Lsqrt_end
.Lsqrt_loop:
vmovupd ymm0, [r8]
vsqrtpd ymm0, ymm0
vmovupd [r10], ymm0
add r8, 32
add r10, 32
dec rcx
jnz .Lsqrt_loop
.Lsqrt_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'rcx', 'r8', 'r10'])
def simd_abs_array(a: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = |a[i:i+4]|"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
vpcmpeqd ymm2, ymm2, ymm2
vpsllq ymm2, ymm2, 63
test rcx, rcx
jz .Labs_end
.Labs_loop:
vmovupd ymm0, [r8]
vandnpd ymm0, ymm2, ymm0
vmovupd [r10], ymm0
add r8, 32
add r10, 32
dec rcx
jnz .Labs_loop
.Labs_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm2', 'rcx', 'r8', 'r10'])
def simd_neg_array(a: t.CPtr, out: t.CPtr, n: t.CSizeT) -> t.CVoid:
"""AVX2 batch: out[i:i+4] = -a[i:i+4] (flip sign bit via XOR)"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r10, {c.AsmInp(out, t.ASM_DESCR.REG_ANY)}
vpcmpeqd ymm2, ymm2, ymm2
vpsllq ymm2, ymm2, 63
test rcx, rcx
jz .Lneg_end
.Lneg_loop:
vmovupd ymm0, [r8]
vxorpd ymm0, ymm0, ymm2
vmovupd [r10], ymm0
add r8, 32
add r10, 32
dec rcx
jnz .Lneg_loop
.Lneg_end:
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm2', 'rcx', 'r8', 'r10'])
def simd_dot_array(a: t.CPtr, b: t.CPtr, n: t.CSizeT, out: t.CPtr) -> t.CVoid:
"""AVX2 batch: out[0] = dot(a[0:n], b[0:n]) using FMA accumulation"""
c.Asm(f"""mov rcx, {c.AsmInp(n, t.ASM_DESCR.REG_ANY)}
shr rcx, 2
mov r8, {c.AsmInp(a, t.ASM_DESCR.REG_ANY)}
mov r9, {c.AsmInp(b, t.ASM_DESCR.REG_ANY)}
vxorpd ymm2, ymm2, ymm2
test rcx, rcx
jz .Ldot_end
.Ldot_loop:
vmovupd ymm0, [r8]
vmovupd ymm1, [r9]
vfmadd231pd ymm2, ymm0, ymm1
add r8, 32
add r9, 32
dec rcx
jnz .Ldot_loop
.Ldot_end:
vextractf128 xmm1, ymm2, 1
vaddpd xmm2, xmm2, xmm1
vhaddpd xmm2, xmm2, xmm2
vmovsd [{c.AsmInp(out, t.ASM_DESCR.REG_ANY)}], xmm2
vzeroupper""",
op=[t.ASM_DESCR.CLOBBER_MEMORY, 'ymm0', 'ymm1', 'ymm2', 'rcx', 'r8', 'r9'])
# ============================================================
# LLVMIR 精确标量运算 (LLVM 内置函数)
# ============================================================
def simd_sqrt(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: sqrt(x)"""
return c.LLVMIR(f"call double @llvm.sqrt.f64(double {c.LInp(x)})", t.CDouble)
def simd_fabs(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: |x|"""
return c.LLVMIR(f"call double @llvm.fabs.f64(double {c.LInp(x)})", t.CDouble)
def simd_floor(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: floor(x)"""
return c.LLVMIR(f"call double @llvm.floor.f64(double {c.LInp(x)})", t.CDouble)
def simd_ceil(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: ceil(x)"""
return c.LLVMIR(f"call double @llvm.ceil.f64(double {c.LInp(x)})", t.CDouble)
def simd_round(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: round(x)"""
return c.LLVMIR(f"call double @llvm.round.f64(double {c.LInp(x)})", t.CDouble)
def simd_trunc(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: trunc(x)"""
return c.LLVMIR(f"call double @llvm.trunc.f64(double {c.LInp(x)})", t.CDouble)
def simd_fma(a: t.CDouble, b: t.CDouble, c_val: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: a*b + c (single rounding)"""
return c.LLVMIR(f"call double @llvm.fma.f64(double {c.LInp(a)}, double {c.LInp(b)}, double {c.LInp(c_val)})", t.CDouble)
def simd_copysign(mag: t.CDouble, sign: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: copysign(mag, sign)"""
return c.LLVMIR(f"call double @llvm.copysign.f64(double {c.LInp(mag)}, double {c.LInp(sign)})", t.CDouble)
def simd_neg(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: -x (via copysign, correct for negative/-0.0/NaN inputs)
copysign(x, -1.0) is wrong for x < 0 (returns -|x| instead of +|x|).
copysign(x, -x) = |x| * sign(-x) = -x is correct for all IEEE 754 values.
"""
return c.LLVMIR(f"call double @llvm.copysign.f64(double {c.LInp(x)}, double {c.LInp(t.CDouble(0.0) - x)})", t.CDouble)
def simd_minnum(a: t.CDouble, b: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: min(a, b) (NaN-aware)"""
return c.LLVMIR(f"call double @llvm.minnum.f64(double {c.LInp(a)}, double {c.LInp(b)})", t.CDouble)
def simd_maxnum(a: t.CDouble, b: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: max(a, b) (NaN-aware)"""
return c.LLVMIR(f"call double @llvm.maxnum.f64(double {c.LInp(a)}, double {c.LInp(b)})", t.CDouble)
def simd_exp(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: e^x"""
return c.LLVMIR(f"call double @llvm.exp.f64(double {c.LInp(x)})", t.CDouble)
def simd_log(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: ln(x)"""
return c.LLVMIR(f"call double @llvm.log.f64(double {c.LInp(x)})", t.CDouble)
def simd_sin(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: sin(x)"""
return c.LLVMIR(f"call double @llvm.sin.f64(double {c.LInp(x)})", t.CDouble)
def simd_cos(x: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: cos(x)"""
return c.LLVMIR(f"call double @llvm.cos.f64(double {c.LInp(x)})", t.CDouble)
def simd_pow(x: t.CDouble, y: t.CDouble) -> t.CDouble:
"""LLVM intrinsic: x^y"""
return c.LLVMIR(f"call double @llvm.pow.f64(double {c.LInp(x)}, double {c.LInp(y)})", t.CDouble)
+1
View File
@@ -0,0 +1 @@
from .string import *
+379
View File
@@ -0,0 +1,379 @@
# vrandom - 硬件随机数生成库
# 基于 x86 RDRAND / RDSEED 指令,使用内嵌汇编实现
import t, c
import vipermath
# 重试次数限制(RDRAND 通常不需要重试,RDSEED 可能需要)
RDRAND_RETRY_LIMIT: t.CDefine = 10
RDSEED_RETRY_LIMIT: t.CDefine = 100
# ============================================================
# RDRAND - 硬件随机数(伪随机数发生器输出)
# ============================================================
def rdrand16() -> t.CUInt16T:
val: t.CUInt32T = 0
c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return t.CUInt16T(val)
def rdrand32() -> t.CUInt32T:
val: t.CUInt32T = 0
c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return val
def rdrand64() -> t.CUInt64T:
val: t.CUInt64T = 0
c.Asm(f"rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return val
# ============================================================
# RDSEED - 硬件随机种子(熵源直接输出)
# ============================================================
def rdseed16() -> t.CUInt16T:
val: t.CUInt32T = 0
c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return t.CUInt16T(val)
def rdseed32() -> t.CUInt32T:
val: t.CUInt32T = 0
c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return val
def rdseed64() -> t.CUInt64T:
val: t.CUInt64T = 0
c.Asm(f"rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC])
return val
# ============================================================
# Step 版本(带成功标志,匹配 GCC builtin 接口)
# 返回 1 表示成功,0 表示失败;随机值写入 *p
# ============================================================
def rdrand16_step(p: t.CUInt16T | t.CPtr) -> t.CInt:
val: t.CUInt32T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = t.CUInt16T(val)
return t.CInt(ok)
def rdrand32_step(p: t.CUInt32T | t.CPtr) -> t.CInt:
val: t.CUInt32T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = val
return t.CInt(ok)
def rdrand64_step(p: t.CUInt64T | t.CPtr) -> t.CInt:
val: t.CUInt64T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdrand {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = val
return t.CInt(ok)
def rdseed16_step(p: t.CUInt16T | t.CPtr) -> t.CInt:
val: t.CUInt32T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = t.CUInt16T(val)
return t.CInt(ok)
def rdseed32_step(p: t.CUInt32T | t.CPtr) -> t.CInt:
val: t.CUInt32T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = val
return t.CInt(ok)
def rdseed64_step(p: t.CUInt64T | t.CPtr) -> t.CInt:
val: t.CUInt64T = 0
ok: t.CUInt32T = 0
c.Asm(f"""rdseed {c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG)}
setc al
movzx {c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)}, al""",
out=[c.AsmOut(val, t.ASM_DESCR.OUTPUT_REG), c.AsmOut(ok, t.ASM_DESCR.OUTPUT_REG)],
op=[t.ASM_DESCR.CLOBBER_CC, t.ASM_DESCR.CLOBBER_AL])
p[0] = val
return t.CInt(ok)
# ============================================================
# 带重试的便捷接口(自动重试直到成功或达到上限)
# ============================================================
def random_u16() -> t.CUInt16T:
r: t.CUInt16T = 0
i: t.CInt = 0
while i < RDRAND_RETRY_LIMIT:
if rdrand16_step(c.Addr(r)) == 1:
return r
i += 1
return 0
def random_u32() -> t.CUInt32T:
r: t.CUInt32T = 0
i: t.CInt = 0
while i < RDRAND_RETRY_LIMIT:
if rdrand32_step(c.Addr(r)) == 1:
return r
i += 1
return 0
def random_u64() -> t.CUInt64T:
r: t.CUInt64T = 0
i: t.CInt = 0
while i < RDRAND_RETRY_LIMIT:
if rdrand64_step(c.Addr(r)) == 1:
return r
i += 1
return 0
def seed_u16() -> t.CUInt16T:
r: t.CUInt16T = 0
i: t.CInt = 0
while i < RDSEED_RETRY_LIMIT:
if rdseed16_step(c.Addr(r)) == 1:
return r
i += 1
return 0
def seed_u32() -> t.CUInt32T:
r: t.CUInt32T = 0
i: t.CInt = 0
while i < RDSEED_RETRY_LIMIT:
if rdseed32_step(c.Addr(r)) == 1:
return r
i += 1
return 0
def seed_u64() -> t.CUInt64T:
r: t.CUInt64T = 0
i: t.CInt = 0
while i < RDSEED_RETRY_LIMIT:
if rdseed64_step(c.Addr(r)) == 1:
return r
i += 1
return 0
# ============================================================
# Python random 标准库函数实现
# 默认类型:t.CUInt64T (u64), t.CDouble (f64), t.CInt (i32)
# ============================================================
# ---------- 一、随机整数 ----------
def randint(a: t.CInt, b: t.CInt) -> t.CInt:
return t.CInt(a + t.CInt(random_u64() % t.CUInt64T(b - a + 1)))
def randrange(start: t.CInt, stop: t.CInt, step: t.CInt = 1) -> t.CInt:
width: t.CInt = 0
if step > 0:
width = (stop - start + step - 1) // step
else:
width = (start - stop - step - 1) // (-step)
return t.CInt(start + t.CInt(random_u64() % t.CUInt64T(width)) * step)
def getrandbits(k: t.CInt) -> t.CUInt64T:
r: t.CUInt64T = rdrand64()
if k >= 64:
return r
mask: t.CUInt64T = (t.CUInt64T(1) << k) - t.CUInt64T(1)
return r & mask
# ---------- 二、随机浮点数 ----------
def random() -> t.CDouble:
return t.CDouble(rdrand64() >> 11) * (t.CDouble(1.0) / t.CDouble(9007199254740992.0))
def uniform(a: t.CDouble, b: t.CDouble) -> t.CDouble:
return a + (b - a) * random()
def triangular(low: t.CDouble, high: t.CDouble, mode: t.CDouble) -> t.CDouble:
u: t.CDouble = random()
c: t.CDouble = (mode - low) / (high - low)
if u > c:
u = t.CDouble(1.0) - u
c = t.CDouble(1.0) - c
tmp: t.CDouble = low
low = high
high = tmp
return low + (high - low) * vipermath.sqrt(u * c)
def betavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble:
y: t.CDouble = gammavariate(alpha, t.CDouble(1.0))
if y != t.CDouble(0.0):
return y / (y + gammavariate(beta, t.CDouble(1.0)))
return t.CDouble(0.0)
def expovariate(lambd: t.CDouble) -> t.CDouble:
u: t.CDouble = random()
if u < t.CDouble(1e-300):
u = t.CDouble(1e-300)
return -vipermath.log(t.CDouble(1.0) - u) / lambd
def gammavariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble:
u: t.CDouble = t.CDouble(0.0)
d: t.CDouble = t.CDouble(0.0)
c: t.CDouble = t.CDouble(0.0)
x: t.CDouble = t.CDouble(0.0)
v: t.CDouble = t.CDouble(0.0)
if alpha <= t.CDouble(0.0) or beta <= t.CDouble(0.0):
return t.CDouble(0.0)
if alpha < t.CDouble(1.0):
u = random()
if u < t.CDouble(1e-300):
u = t.CDouble(1e-300)
return gammavariate(alpha + t.CDouble(1.0), beta) * vipermath.pow(u, t.CDouble(1.0) / alpha)
d = alpha - t.CDouble(1.0) / t.CDouble(3.0)
c = t.CDouble(1.0) / vipermath.sqrt(t.CDouble(9.0) * d)
while 1:
x = gauss(t.CDouble(0.0), t.CDouble(1.0))
v = t.CDouble(1.0) + c * x
if v > t.CDouble(0.0):
v = v * v * v
u = random()
if u < t.CDouble(1.0) - t.CDouble(0.0331) * x * x * x * x:
return d * v * beta
if vipermath.log(u) < t.CDouble(0.5) * x * x + d * (t.CDouble(1.0) - v + vipermath.log(v)):
return d * v * beta
def gauss(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble:
u1: t.CDouble = random()
u2: t.CDouble = random()
if u1 < t.CDouble(1e-300):
u1 = t.CDouble(1e-300)
z0: t.CDouble = vipermath.sqrt(t.CDouble(-2.0) * vipermath.log(u1)) * vipermath.cos(t.CDouble(2.0) * vipermath.U_M_PI * u2)
return mu + sigma * z0
def normalvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble:
NV_MAGICCONST: t.CDouble = t.CDouble(1.7155277699214135)
u1: t.CDouble = t.CDouble(0.0)
u2: t.CDouble = t.CDouble(0.0)
z: t.CDouble = t.CDouble(0.0)
zz: t.CDouble = t.CDouble(0.0)
while 1:
u1 = random()
u2 = random()
if u2 < t.CDouble(1e-300):
continue
z = NV_MAGICCONST * (u1 - t.CDouble(0.5)) / u2
zz = z * z / t.CDouble(4.0)
if zz <= t.CDouble(0.0) - vipermath.log(u2):
break
return mu + z * sigma
def lognormvariate(mu: t.CDouble, sigma: t.CDouble) -> t.CDouble:
return vipermath.exp(gauss(mu, sigma))
def vonmisesvariate(mu: t.CDouble, kappa: t.CDouble) -> t.CDouble:
if kappa <= t.CDouble(1e-6):
return vipermath.U_M_PI * t.CDouble(2.0) * random()
s: t.CDouble = t.CDouble(0.5) / kappa
r: t.CDouble = s + vipermath.sqrt(t.CDouble(1.0) + s * s)
u1: t.CDouble = t.CDouble(0.0)
u2: t.CDouble = t.CDouble(0.0)
u3: t.CDouble = t.CDouble(0.0)
z: t.CDouble = t.CDouble(0.0)
d: t.CDouble = t.CDouble(0.0)
q: t.CDouble = t.CDouble(0.0)
f: t.CDouble = t.CDouble(0.0)
theta: t.CDouble = t.CDouble(0.0)
two_pi: t.CDouble = vipermath.U_M_PI * t.CDouble(2.0)
while 1:
u1 = random()
z = vipermath.cos(vipermath.U_M_PI * u1)
d = t.CDouble(1.0) / (r + z)
u2 = random()
if u2 < t.CDouble(1.0) - d * d:
break
if u2 < (t.CDouble(1.0) - z) * vipermath.exp(kappa * (z - t.CDouble(1.0)) - d * kappa * r):
break
q = t.CDouble(1.0) / r
f = (q + z) / (t.CDouble(1.0) + q * z)
u3 = random()
if u3 > t.CDouble(0.5):
theta = mu + vipermath.acos(f)
else:
theta = mu - vipermath.acos(f)
while theta < t.CDouble(0.0):
theta += two_pi
while theta >= two_pi:
theta -= two_pi
return theta
def paretovariate(alpha: t.CDouble) -> t.CDouble:
u: t.CDouble = random()
if u < t.CDouble(1e-300):
u = t.CDouble(1e-300)
return t.CDouble(1.0) / vipermath.pow(t.CDouble(1.0) - u, t.CDouble(1.0) / alpha)
def weibullvariate(alpha: t.CDouble, beta: t.CDouble) -> t.CDouble:
u: t.CDouble = random()
if u < t.CDouble(1e-300):
u = t.CDouble(1e-300)
return alpha * vipermath.pow(t.CDouble(-1.0) * vipermath.log(t.CDouble(1.0) - u), t.CDouble(1.0) / beta)
+104
View File
@@ -0,0 +1,104 @@
import t, c
from stdint import *
from w32.win32base import *
from w32.win32process import CreateThread, GetExitCodeThread, GetCurrentThreadId, TlsAlloc, TlsFree, TlsGetValue, TlsSetValue
from w32.win32sync import WaitForSingleObject
# 全部导入锁类,用户也可按需导入
from lock import Lock
from event import Event
from condition import Condition
from rwlock import RWLock
@t.Object
class Thread:
"""线程类,封装 Windows CreateThread。
线程回调签名: def thread_func(arg: t.CPtr) -> t.CPtr
注意: Windows API 限制返回值为 DWORD(32位),64位指针会被截断。
如需返回 64 位结果,请通过 arg 参数结构体传递。
用法:
def worker(arg: t.CPtr) -> t.CPtr:
# 线程逻辑
return NULL
t: Thread = Thread(worker, arg_ptr)
t.start()
t.join()
"""
handle: HANDLE
thread_id: ULONG
target: VOIDPTR
arg: VOIDPTR
started: BOOL
def __init__(self, target: VOIDPTR, arg: VOIDPTR = NULL):
self.handle = NULL
self.thread_id = 0
self.target = target
self.arg = arg
self.started = FALSE
def start(self):
if self.started:
return
self.handle = CreateThread(NULL, 0, self.target, self.arg, 0, c.Addr(self.thread_id))
self.started = TRUE
def join(self, timeout_ms: ULONG = INFINITE) -> BOOL:
if not self.started:
return FALSE
result: ULONG = WaitForSingleObject(self.handle, timeout_ms)
return result == WAIT_OBJECT_0
def is_alive(self) -> BOOL:
if not self.started:
return FALSE
result: ULONG = WaitForSingleObject(self.handle, 0)
return result == WAIT_TIMEOUT
def get_exit_code(self) -> ULONG:
code: ULONG = 0
GetExitCodeThread(self.handle, c.Addr(code))
return code
def close(self):
if self.handle != NULL:
CloseHandle(self.handle)
self.handle = NULL
@t.Object
class local:
"""TLS (Thread Local Storage) 封装。
用法:
tls: local = local()
tls.set(value_ptr)
val: t.CPtr = tls.get()
"""
index: ULONG
def __init__(self):
self.index = TlsAlloc()
def get(self) -> VOIDPTR:
return TlsGetValue(self.index)
def set(self, value: VOIDPTR) -> BOOL:
return TlsSetValue(self.index, value)
def free(self) -> BOOL:
return TlsFree(self.index)
def get_current_thread_id() -> ULONG:
"""获取当前线程 ID"""
return GetCurrentThreadId()
def sleep_ms(ms: ULONG):
"""让当前线程休眠指定毫秒数"""
Sleep(ms)
+394
View File
@@ -0,0 +1,394 @@
import t, c
from stdint import *
import stdio
import w32.win32base
import w32.win32file
class MODE(t.CEnum):
R = 0
W = 1
A = 2
RP = 3
WP = 4
AP = 5
X = 6
XP = 7
class FRESULT(t.CEnum):
OK = 0
ERR = -1
ERR_CLOSED = -2
ERR_PERM = -3
ERR_IO = -4
ERR_NOTFOUND = -5
SEEK_SET: t.CDefine = 0
SEEK_CUR: t.CDefine = 1
SEEK_END: t.CDefine = 2
INVALID_SET_FILE_POINTER: t.CDefine = -1
SHARE_READ: t.CDefine = 0x00000001
SHARE_WRITE: t.CDefine = 0x00000002
SHARE_DELETE: t.CDefine = 0x00000004
class File:
handle: w32.win32base.HANDLE
closed: bool
can_read: bool
can_write: bool
is_append: bool
_share_mode: ULONG
def __init__(self, filename: str, mode: ULONG, share: ULONG = SHARE_READ):
self.closed = True
self.can_read = False
self.can_write = False
self.is_append = False
self._share_mode = share
access: ULONG = 0
disposition: ULONG = w32.win32file.OPEN_EXISTING
if mode == MODE.R:
access = w32.win32file.GENERIC_READ
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
elif mode == MODE.W:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_ALWAYS
self.can_write = True
elif mode == MODE.A:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_ALWAYS
self.can_write = True
self.is_append = True
elif mode == MODE.RP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
self.can_write = True
elif mode == MODE.WP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_ALWAYS
self.can_read = True
self.can_write = True
elif mode == MODE.AP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_ALWAYS
self.can_read = True
self.can_write = True
self.is_append = True
elif mode == MODE.X:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_NEW
self.can_write = True
elif mode == MODE.XP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_NEW
self.can_read = True
self.can_write = True
else:
access = w32.win32file.GENERIC_READ
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
self.handle = w32.win32file.CreateFileA(
filename, access, self._share_mode,
None, disposition, w32.win32file.FILE_ATTRIBUTE_NORMAL, None
)
if self.handle == w32.win32base.INVALID_HANDLE_VALUE:
self.closed = True
return
self.closed = False
if self.is_append:
self.seek(0, SEEK_END)
def __enter__(self) -> 'File' | t.CPtr:
return self
def __exit__(self):
self.close()
def read(self, buf: bytes, count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
bytes_read: ULONG = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf, count, t.CPtr(c.Addr(bytes_read)), None)
if result == 0: return FRESULT.ERR_IO
return LONG(bytes_read)
def write(self, buf: bytes, count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_write: return FRESULT.ERR_PERM
bytes_written: ULONG = 0
result: BOOL = w32.win32file.WriteFile(self.handle, buf, count, t.CPtr(c.Addr(bytes_written)), None)
if result == 0: return FRESULT.ERR_IO
return LONG(bytes_written)
def write_str(self, s: str) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_write: return FRESULT.ERR_PERM
length: ULONG = 0
p: bytes = s
while c.Deref(p) != 0:
length += 1
p += 1
return self.write(s, length)
def seek(self, offset: LONG, origin: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
result: LONG = w32.win32file.SetFilePointer(self.handle, offset, None, origin)
if result == -1: return FRESULT.ERR_IO
return result
def tell(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
return self.seek(0, SEEK_CUR)
def close(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
w32.win32base.CloseHandle(self.handle)
self.closed = True
return FRESULT.OK
def flush(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
w32.win32file.FlushFileBuffers(self.handle)
return FRESULT.OK
def size(self) -> LONGLONG:
if self.closed: return -1
li: w32.win32base.LARGE_INTEGER = w32.win32base.LARGE_INTEGER()
result: BOOL = w32.win32file.GetFileSizeEx(self.handle, t.CPtr(c.Addr(li)))
if result == 0: return -1
return li.QuadPart
def readline(self, buf: bytes, max_count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
if max_count < 2: return FRESULT.ERR
total: ULONG = 0
bytes_read: ULONG = 0
ch: t.CInt = 0
while total < max_count - 1:
bytes_read = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf + total, 1, t.CPtr(c.Addr(bytes_read)), None)
if result == 0 or bytes_read == 0: break
ch = c.Deref(buf + total)
total += 1
if ch == 10: break
if total < max_count:
buf[total] = 0
return LONG(total)
def read_all(self, buf: bytes, max_count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
if max_count < 2: return FRESULT.ERR
# stdio.printf("[DBG read_all] before size()\n")
file_size: LONGLONG = self.size()
# stdio.printf("[DBG read_all] after size(), file_size=%lld\n", file_size)
if file_size < 0: return FRESULT.ERR_IO
to_read: ULONG = 0
if file_size < max_count - 1:
to_read = ULONG(file_size)
else:
to_read = max_count - 1
# stdio.printf("[DBG read_all] to_read=%u, before seek\n", to_read)
self.seek(0, SEEK_SET)
# stdio.printf("[DBG read_all] after seek, before ReadFile\n")
bytes_read: ULONG = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf, to_read, t.CPtr(c.Addr(bytes_read)), None)
# stdio.printf("[DBG read_all] after ReadFile, result=%d, bytes_read=%u\n", result, bytes_read)
if result == 0: return FRESULT.ERR_IO
if bytes_read < max_count:
buf[bytes_read] = 0
return LONG(bytes_read)
class FileW:
handle: w32.win32base.HANDLE
closed: bool
can_read: bool
can_write: bool
is_append: bool
_share_mode: ULONG
def __init__(self, filename: w32.win32base.LPCWSTR, mode: ULONG, share: ULONG = SHARE_READ):
self.closed = True
self.can_read = False
self.can_write = False
self.is_append = False
self._share_mode = share
access: ULONG = 0
disposition: ULONG = w32.win32file.OPEN_EXISTING
if mode == MODE.R:
access = w32.win32file.GENERIC_READ
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
elif mode == MODE.W:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_ALWAYS
self.can_write = True
elif mode == MODE.A:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_ALWAYS
self.can_write = True
self.is_append = True
elif mode == MODE.RP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
self.can_write = True
elif mode == MODE.WP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_ALWAYS
self.can_read = True
self.can_write = True
elif mode == MODE.AP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.OPEN_ALWAYS
self.can_read = True
self.can_write = True
self.is_append = True
elif mode == MODE.X:
access = w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_NEW
self.can_write = True
elif mode == MODE.XP:
access = w32.win32file.GENERIC_READ | w32.win32file.GENERIC_WRITE
disposition = w32.win32file.CREATE_NEW
self.can_read = True
self.can_write = True
else:
access = w32.win32file.GENERIC_READ
disposition = w32.win32file.OPEN_EXISTING
self.can_read = True
self.handle = w32.win32file.CreateFileW(
filename, access, self._share_mode,
None, disposition, w32.win32file.FILE_ATTRIBUTE_NORMAL, None
)
if self.handle == w32.win32base.INVALID_HANDLE_VALUE:
self.closed = True
return
self.closed = False
if self.is_append:
self.seek(0, SEEK_END)
def __enter__(self) -> 'FileW' | t.CPtr:
return self
def __exit__(self):
self.close()
def read(self, buf: bytes, count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
bytes_read: ULONG = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf, count, t.CPtr(c.Addr(bytes_read)), None)
if result == 0: return FRESULT.ERR_IO
return LONG(bytes_read)
def write(self, buf: bytes, count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_write: return FRESULT.ERR_PERM
bytes_written: ULONG = 0
result: BOOL = w32.win32file.WriteFile(self.handle, buf, count, t.CPtr(c.Addr(bytes_written)), None)
if result == 0: return FRESULT.ERR_IO
return LONG(bytes_written)
def write_str(self, s: str) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_write: return FRESULT.ERR_PERM
length: ULONG = 0
p: bytes = s
while c.Deref(p) != 0:
length += 1
p += 1
return self.write(s, length)
def seek(self, offset: LONG, origin: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
result: LONG = w32.win32file.SetFilePointer(self.handle, offset, None, origin)
if result == -1: return FRESULT.ERR_IO
return result
def tell(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
return self.seek(0, SEEK_CUR)
def close(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
w32.win32base.CloseHandle(self.handle)
self.closed = True
return FRESULT.OK
def flush(self) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
w32.win32file.FlushFileBuffers(self.handle)
return FRESULT.OK
def size(self) -> LONGLONG:
if self.closed: return -1
li: w32.win32base.LARGE_INTEGER = w32.win32base.LARGE_INTEGER()
result: BOOL = w32.win32file.GetFileSizeEx(self.handle, t.CPtr(c.Addr(li)))
if result == 0: return -1
return li.QuadPart
def readline(self, buf: bytes, max_count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
if max_count < 2: return FRESULT.ERR
total: ULONG = 0
bytes_read: ULONG = 0
ch: t.CInt = 0
while total < max_count - 1:
bytes_read = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf + total, 1, t.CPtr(c.Addr(bytes_read)), None)
if result == 0 or bytes_read == 0: break
ch = c.Deref(buf + total)
total += 1
if ch == 10: break
if total < max_count:
buf[total] = 0
return LONG(total)
def read_all(self, buf: bytes, max_count: ULONG) -> LONG:
if self.closed: return FRESULT.ERR_CLOSED
if not self.can_read: return FRESULT.ERR_PERM
if max_count < 2: return FRESULT.ERR
file_size: LONGLONG = self.size()
if file_size < 0: return FRESULT.ERR_IO
to_read: ULONG = 0
if file_size < max_count - 1:
to_read = ULONG(file_size)
else:
to_read = max_count - 1
self.seek(0, SEEK_SET)
bytes_read: ULONG = 0
result: BOOL = w32.win32file.ReadFile(self.handle, buf, to_read, t.CPtr(c.Addr(bytes_read)), None)
if result == 0: return FRESULT.ERR_IO
if bytes_read < max_count:
buf[bytes_read] = 0
return LONG(bytes_read)
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:
return FileW(filename, mode, share)
+80
View File
@@ -0,0 +1,80 @@
import t
from stdint import *
HANDLE: t.CTypedef = VOIDPTR
LPCSTR: t.CTypedef = t.CConst | t.CChar | t.CPtr
LPCWSTR: t.CTypedef = t.CConst | t.CUnsignedShort | t.CPtr
INVALID_HANDLE_VALUE: t.CDefine = t.CVoid(-1)
NULL: t.CDefine = 0
TRUE: t.CDefine = 1
FALSE: t.CDefine = 0
INFINITE: t.CDefine = 0xFFFFFFFF
WAIT_FAILED: t.CDefine = 0xFFFFFFFF
WAIT_OBJECT_0: t.CDefine = 0
WAIT_TIMEOUT: t.CDefine = 258
WAIT_ABANDONED: t.CDefine = 0x80
MAX_PATH: t.CDefine = 260
ERROR_SUCCESS: t.CDefine = 0
ERROR_FILE_NOT_FOUND: t.CDefine = 2
ERROR_ACCESS_DENIED: t.CDefine = 5
ERROR_INSUFFICIENT_BUFFER: t.CDefine = 122
class SECURITY_ATTRIBUTES():
nLength: ULONG
lpSecurityDescriptor: VOIDPTR
bInheritHandle: BOOL
class OVERLAPPED():
Internal: ULONGLONG
InternalHigh: ULONGLONG
Offset: ULONG
OffsetHigh: ULONG
hEvent: HANDLE
class FILETIME():
dwLowDateTime: DWORD
dwHighDateTime: DWORD
class SYSTEMTIME():
wYear: WORD
wMonth: WORD
wDayOfWeek: WORD
wDay: WORD
wHour: WORD
wMinute: WORD
wSecond: WORD
wMilliseconds: WORD
class GUID():
Data1: DWORD
Data2: WORD
Data3: WORD
Data4: BYTEPTR
class LARGE_INTEGER():
QuadPart: LONGLONG
class ULARGE_INTEGER():
QuadPart: ULONGLONG
def GetLastError() -> ULONG | t.State: pass
def SetLastError(dwErrCode: ULONG) -> t.State: pass
def CloseHandle(hObject: HANDLE) -> BOOL | t.State: pass
def GetProcAddress(hModule: HANDLE, lpProcName: LPCSTR) -> VOIDPTR | t.State: pass
def GetModuleHandleA(lpModuleName: LPCSTR) -> HANDLE | t.State: pass
def GetModuleHandleW(lpModuleName: LPCWSTR) -> HANDLE | t.State: pass
def LoadLibraryA(lpLibFileName: LPCSTR) -> HANDLE | t.State: pass
def LoadLibraryW(lpLibFileName: LPCWSTR) -> HANDLE | t.State: pass
def FreeLibrary(hLibModule: HANDLE) -> BOOL | t.State: pass
def GetSystemTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass
def GetLocalTime(lpSystemTime: SYSTEMTIME | t.CPtr) -> t.State: pass
def FileTimeToSystemTime(lpFileTime: FILETIME | t.CPtr, lpSystemTime: SYSTEMTIME | t.CPtr) -> BOOL | t.State: pass
def SystemTimeToFileTime(lpSystemTime: SYSTEMTIME | t.CPtr, lpFileTime: FILETIME | t.CPtr) -> BOOL | t.State: pass
def QueryPerformanceCounter(lpPerformanceCount: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass
def QueryPerformanceFrequency(lpFrequency: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass
def Sleep(dwMilliseconds: ULONG) -> t.State: pass
def SleepEx(dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass
def GetTickCount() -> ULONG | t.State: pass
def GetTickCount64() -> ULONGLONG | t.State: pass
def GetCommandLineA() -> CHARPTR | t.State: pass
+111
View File
@@ -0,0 +1,111 @@
import t
from stdint import *
from w32.win32base import *
ENABLE_PROCESSED_INPUT: t.CDefine = 0x0001
ENABLE_LINE_INPUT: t.CDefine = 0x0002
ENABLE_ECHO_INPUT: t.CDefine = 0x0004
ENABLE_WINDOW_INPUT: t.CDefine = 0x0008
ENABLE_MOUSE_INPUT: t.CDefine = 0x0010
ENABLE_INSERT_MODE: t.CDefine = 0x0020
ENABLE_QUICK_EDIT_MODE: t.CDefine = 0x0040
ENABLE_EXTENDED_FLAGS: t.CDefine = 0x0080
ENABLE_PROCESSED_OUTPUT: t.CDefine = 0x0001
ENABLE_WRAP_AT_EOL_OUTPUT: t.CDefine = 0x0002
ENABLE_VIRTUAL_TERMINAL_PROCESSING: t.CDefine = 0x0004
DISABLE_NEWLINE_AUTO_RETURN: t.CDefine = 0x0008
ENABLE_LVB_GRID_WORLDWIDE: t.CDefine = 0x0010
FOREGROUND_BLUE: t.CDefine = 0x0001
FOREGROUND_GREEN: t.CDefine = 0x0002
FOREGROUND_RED: t.CDefine = 0x0004
FOREGROUND_INTENSITY: t.CDefine = 0x0008
BACKGROUND_BLUE: t.CDefine = 0x0010
BACKGROUND_GREEN: t.CDefine = 0x0020
BACKGROUND_RED: t.CDefine = 0x0040
BACKGROUND_INTENSITY: t.CDefine = 0x0080
KEY_EVENT: t.CDefine = 0x0001
MOUSE_EVENT: t.CDefine = 0x0002
WINDOW_BUFFER_SIZE_EVENT: t.CDefine = 0x0004
MENU_EVENT: t.CDefine = 0x0008
FOCUS_EVENT: t.CDefine = 0x0010
class COORD():
X: SHORT
Y: SHORT
class SMALL_RECT():
Left: SHORT
Top: SHORT
Right: SHORT
Bottom: SHORT
class CONSOLE_SCREEN_BUFFER_INFO():
dwSize: COORD
dwCursorPosition: COORD
wAttributes: WORD
srWindow: SMALL_RECT
dwMaximumWindowSize: COORD
class CONSOLE_CURSOR_INFO():
dwSize: ULONG
bVisible: BOOL
class CHAR_INFO():
UnicodeChar: WCHAR
Attributes: WORD
class KEY_EVENT_RECORD():
bKeyDown: BOOL
wRepeatCount: WORD
wVirtualKeyCode: WORD
wVirtualScanCode: WORD
uChar: WCHAR
dwControlKeyState: ULONG
class MOUSE_EVENT_RECORD():
dwMousePosition: COORD
dwButtonState: ULONG
dwControlKeyState: ULONG
dwEventFlags: ULONG
class WINDOW_BUFFER_SIZE_RECORD():
dwSize: COORD
class INPUT_RECORD():
EventType: WORD
Event: KEY_EVENT_RECORD
def SetConsoleOutputCP(codepage: UINT) -> BOOL | t.State: pass
def SetConsoleCP(codepage: UINT) -> BOOL | t.State: pass
def GetConsoleCP() -> UINT | t.State: pass
def GetConsoleOutputCP() -> UINT | t.State: pass
def GetConsoleScreenBufferInfo(hConsoleOutput: HANDLE, lpConsoleScreenBufferInfo: CONSOLE_SCREEN_BUFFER_INFO | t.CPtr) -> BOOL | t.State: pass
def SetConsoleScreenBufferSize(hConsoleOutput: HANDLE, dwSize: COORD) -> BOOL | t.State: pass
def SetConsoleCursorPosition(hConsoleOutput: HANDLE, dwCursorPosition: COORD) -> BOOL | t.State: pass
def GetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass
def SetConsoleCursorInfo(hConsoleOutput: HANDLE, lpConsoleCursorInfo: CONSOLE_CURSOR_INFO | t.CPtr) -> BOOL | t.State: pass
def SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) -> BOOL | t.State: pass
def FillConsoleOutputCharacterA(hConsoleOutput: HANDLE, cCharacter: t.CChar, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass
def FillConsoleOutputCharacterW(hConsoleOutput: HANDLE, cCharacter: WCHAR, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfCharsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass
def FillConsoleOutputAttribute(hConsoleOutput: HANDLE, wAttribute: WORD, nLength: ULONG, dwWriteCoord: COORD, lpNumberOfAttrsWritten: ULONG | t.CPtr) -> BOOL | t.State: pass
def WriteConsoleA(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass
def WriteConsoleW(hConsoleOutput: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfCharsToWrite: ULONG, lpNumberOfCharsWritten: ULONG | t.CPtr, lpReserved: VOIDPTR) -> BOOL | t.State: pass
def ReadConsoleA(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass
def ReadConsoleW(hConsoleInput: HANDLE, lpBuffer: VOIDPTR, nNumberOfCharsToRead: ULONG, lpNumberOfCharsRead: ULONG | t.CPtr, pInputControl: VOIDPTR) -> BOOL | t.State: pass
def GetConsoleMode(hConsoleHandle: HANDLE, lpMode: ULONG | t.CPtr) -> BOOL | t.State: pass
def SetConsoleMode(hConsoleHandle: HANDLE, dwMode: ULONG) -> BOOL | t.State: pass
def ReadConsoleInputA(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass
def ReadConsoleInputW(hConsoleInput: HANDLE, lpBuffer: INPUT_RECORD | t.CPtr, nLength: ULONG, lpNumberOfEventsRead: ULONG | t.CPtr) -> BOOL | t.State: pass
def GetNumberOfConsoleInputEvents(hConsoleInput: HANDLE, lpNumberOfEvents: ULONG | t.CPtr) -> BOOL | t.State: pass
def FlushConsoleInputBuffer(hConsoleInput: HANDLE) -> BOOL | t.State: pass
def SetConsoleTitleA(lpConsoleTitle: LPCSTR) -> BOOL | t.State: pass
def SetConsoleTitleW(lpConsoleTitle: LPCWSTR) -> BOOL | t.State: pass
def GetConsoleTitleA(lpConsoleTitle: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass
def GetConsoleTitleW(lpConsoleTitle: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass
def AllocConsole() -> BOOL | t.State: pass
def FreeConsole() -> BOOL | t.State: pass
def SetConsoleWindowInfo(hConsoleOutput: HANDLE, bAbsolute: BOOL, lpConsoleWindow: SMALL_RECT | t.CPtr) -> BOOL | t.State: pass
def ScrollConsoleScreenBufferA(hConsoleOutput: HANDLE, lpScrollRectangle: SMALL_RECT | t.CPtr, lpClipRectangle: SMALL_RECT | t.CPtr, dwDestinationOrigin: COORD, lpFill: CHAR_INFO | t.CPtr) -> BOOL | t.State: pass
+143
View File
@@ -0,0 +1,143 @@
import t
from stdint import *
from w32.win32base import *
GENERIC_READ: t.CDefine = 0x80000000
GENERIC_WRITE: t.CDefine = 0x40000000
GENERIC_EXECUTE: t.CDefine = 0x20000000
GENERIC_ALL: t.CDefine = 0x10000000
FILE_SHARE_READ: t.CDefine = 0x00000001
FILE_SHARE_WRITE: t.CDefine = 0x00000002
FILE_SHARE_DELETE: t.CDefine = 0x00000004
CREATE_NEW: t.CDefine = 1
CREATE_ALWAYS: t.CDefine = 2
OPEN_EXISTING: t.CDefine = 3
OPEN_ALWAYS: t.CDefine = 4
TRUNCATE_EXISTING: t.CDefine = 5
FILE_ATTRIBUTE_READONLY: t.CDefine = 0x00000001
FILE_ATTRIBUTE_HIDDEN: t.CDefine = 0x00000002
FILE_ATTRIBUTE_SYSTEM: t.CDefine = 0x00000004
FILE_ATTRIBUTE_DIRECTORY: t.CDefine = 0x00000010
FILE_ATTRIBUTE_ARCHIVE: t.CDefine = 0x00000020
FILE_ATTRIBUTE_NORMAL: t.CDefine = 0x00000080
FILE_ATTRIBUTE_TEMPORARY: t.CDefine = 0x00000100
FILE_ATTRIBUTE_COMPRESSED: t.CDefine = 0x00000800
FILE_ATTRIBUTE_OFFLINE: t.CDefine = 0x00001000
FILE_ATTRIBUTE_ENCRYPTED: t.CDefine = 0x00004000
FILE_FLAG_WRITE_THROUGH: t.CDefine = 0x80000000
FILE_FLAG_OVERLAPPED: t.CDefine = 0x40000000
FILE_FLAG_NO_BUFFERING: t.CDefine = 0x20000000
FILE_FLAG_RANDOM_ACCESS: t.CDefine = 0x10000000
FILE_FLAG_SEQUENTIAL_SCAN: t.CDefine = 0x08000000
FILE_FLAG_DELETE_ON_CLOSE: t.CDefine = 0x04000000
FILE_FLAG_BACKUP_SEMANTICS: t.CDefine = 0x02000000
FILE_FLAG_POSIX_SEMANTICS: t.CDefine = 0x01000000
FILE_BEGIN: t.CDefine = 0
FILE_CURRENT: t.CDefine = 1
FILE_END: t.CDefine = 2
STD_INPUT_HANDLE: t.CDefine = t.CUnsignedLong(-10)
STD_OUTPUT_HANDLE: t.CDefine = t.CUnsignedLong(-11)
STD_ERROR_HANDLE: t.CDefine = t.CUnsignedLong(-12)
MOVEFILE_REPLACE_EXISTING: t.CDefine = 0x00000001
MOVEFILE_COPY_ALLOWED: t.CDefine = 0x00000002
MOVEFILE_WRITE_THROUGH: t.CDefine = 0x00000008
class BY_HANDLE_FILE_INFORMATION():
dwFileAttributes: ULONG
ftCreationTime: FILETIME
ftLastAccessTime: FILETIME
ftLastWriteTime: FILETIME
dwVolumeSerialNumber: ULONG
nFileSizeHigh: ULONG
nFileSizeLow: ULONG
nNumberOfLinks: ULONG
nFileIndexHigh: ULONG
nFileIndexLow: ULONG
class WIN32_FIND_DATAA():
dwFileAttributes: ULONG
ftCreationTime: FILETIME
ftLastAccessTime: FILETIME
ftLastWriteTime: FILETIME
nFileSizeHigh: ULONG
nFileSizeLow: ULONG
dwReserved0: ULONG
dwReserved1: ULONG
cFileName: t.CArray[t.CChar, 260]
cAlternateFileName: t.CArray[t.CChar, 14]
class WIN32_FIND_DATAW():
dwFileAttributes: ULONG
ftCreationTime: FILETIME
ftLastAccessTime: FILETIME
ftLastWriteTime: FILETIME
nFileSizeHigh: ULONG
nFileSizeLow: ULONG
dwReserved0: ULONG
dwReserved1: ULONG
cFileName: t.CArray[t.CUInt16T, 260]
cAlternateFileName: t.CArray[t.CUInt16T, 14]
def CreateFileA(lpFileName: LPCSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass
def CreateFileW(lpFileName: LPCWSTR, dwDesiredAccess: ULONG, dwShareMode: ULONG, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwCreationDisposition: ULONG, dwFlagsAndAttributes: ULONG, hTemplateFile: HANDLE) -> HANDLE | t.State: pass
def ReadFile(hFile: HANDLE, lpBuffer: VOIDPTR, nNumberOfBytesToRead: ULONG, lpNumberOfBytesRead: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass
def WriteFile(hFile: HANDLE, lpBuffer: t.CConst | VOIDPTR, nNumberOfBytesToWrite: ULONG, lpNumberOfBytesWritten: ULONG | t.CPtr, lpOverlapped: OVERLAPPED | t.CPtr) -> BOOL | t.State: pass
def SetFilePointer(hFile: HANDLE, lDistanceToMove: LONG, lpDistanceToMoveHigh: LONG | t.CPtr, dwMoveMethod: ULONG) -> LONG | t.State: pass
def SetFilePointerEx(hFile: HANDLE, liDistanceToMove: LARGE_INTEGER | t.CPtr, lpNewFilePointer: LARGE_INTEGER | t.CPtr, dwMoveMethod: ULONG) -> BOOL | t.State: pass
def GetFileSize(hFile: HANDLE, lpFileSizeHigh: ULONG | t.CPtr) -> ULONG | t.State: pass
def GetFileSizeEx(hFile: HANDLE, lpFileSize: LARGE_INTEGER | t.CPtr) -> BOOL | t.State: pass
def SetEndOfFile(hFile: HANDLE) -> BOOL | t.State: pass
def FlushFileBuffers(hFile: HANDLE) -> BOOL | t.State: pass
def GetFileType(hFile: HANDLE) -> ULONG | t.State: pass
def GetFileAttributesA(lpFileName: LPCSTR) -> ULONG | t.State: pass
def GetFileAttributesW(lpFileName: LPCWSTR) -> ULONG | t.State: pass
def SetFileAttributesA(lpFileName: LPCSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass
def SetFileAttributesW(lpFileName: LPCWSTR, dwFileAttributes: ULONG) -> BOOL | t.State: pass
def DeleteFileA(lpFileName: LPCSTR) -> BOOL | t.State: pass
def DeleteFileW(lpFileName: LPCWSTR) -> BOOL | t.State: pass
def MoveFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR) -> BOOL | t.State: pass
def MoveFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR) -> BOOL | t.State: pass
def MoveFileExA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, dwFlags: ULONG) -> BOOL | t.State: pass
def MoveFileExW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, dwFlags: ULONG) -> BOOL | t.State: pass
def CopyFileA(lpExistingFileName: LPCSTR, lpNewFileName: LPCSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass
def CopyFileW(lpExistingFileName: LPCWSTR, lpNewFileName: LPCWSTR, bFailIfExists: BOOL) -> BOOL | t.State: pass
def CreateDirectoryA(lpPathName: LPCSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass
def CreateDirectoryW(lpPathName: LPCWSTR, lpSecurityAttributes: SECURITY_ATTRIBUTES | t.CPtr) -> BOOL | t.State: pass
def RemoveDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass
def RemoveDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass
def FindFirstFileA(lpFileName: LPCSTR, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> HANDLE | t.State: pass
def FindFirstFileW(lpFileName: LPCWSTR, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> HANDLE | t.State: pass
def FindNextFileA(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAA | t.CPtr) -> BOOL | t.State: pass
def FindNextFileW(hFindFile: HANDLE, lpFindFileData: WIN32_FIND_DATAW | t.CPtr) -> BOOL | t.State: pass
def FindClose(hFindFile: HANDLE) -> BOOL | t.State: pass
def GetStdHandle(nStdHandle: ULONG) -> HANDLE | t.State: pass
def SetStdHandle(nStdHandle: ULONG, hHandle: HANDLE) -> BOOL | t.State: pass
def GetFileInformationByHandle(hFile: HANDLE, lpFileInformation: BY_HANDLE_FILE_INFORMATION | t.CPtr) -> BOOL | t.State: pass
def LockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToLockLow: ULONG, nNumberOfBytesToLockHigh: ULONG) -> BOOL | t.State: pass
def UnlockFile(hFile: HANDLE, dwFileOffsetLow: ULONG, dwFileOffsetHigh: ULONG, nNumberOfBytesToUnlockLow: ULONG, nNumberOfBytesToUnlockHigh: ULONG) -> BOOL | t.State: pass
def GetTempPathA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass
def GetTempPathW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass
def GetTempFileNameA(lpPathName: LPCSTR, lpPrefixString: LPCSTR, uUnique: UINT, lpTempFileName: CHARPTR) -> UINT | t.State: pass
def GetTempFileNameW(lpPathName: LPCWSTR, lpPrefixString: LPCWSTR, uUnique: UINT, lpTempFileName: WCHARPTR) -> UINT | t.State: pass
def GetCurrentDirectoryA(nBufferLength: ULONG, lpBuffer: CHARPTR) -> ULONG | t.State: pass
def GetCurrentDirectoryW(nBufferLength: ULONG, lpBuffer: WCHARPTR) -> ULONG | t.State: pass
def SetCurrentDirectoryA(lpPathName: LPCSTR) -> BOOL | t.State: pass
def SetCurrentDirectoryW(lpPathName: LPCWSTR) -> BOOL | t.State: pass
def GetModuleFileNameA(hModule: HANDLE, lpFilename: CHARPTR, nSize: ULONG) -> ULONG | t.State: pass
def GetModuleFileNameW(hModule: HANDLE, lpFilename: WCHARPTR, nSize: ULONG) -> ULONG | t.State: pass
HANDLE_FLAG_INHERIT: t.CDefine = 0x00000001
HANDLE_FLAG_PROTECT_FROM_CLOSE: t.CDefine = 0x00000002
def CreatePipe(hReadPipe: HANDLE | t.CPtr, hWritePipe: HANDLE | t.CPtr, lpPipeAttributes: SECURITY_ATTRIBUTES | t.CPtr, nSize: ULONG) -> BOOL | t.State: pass
def SetHandleInformation(hObject: HANDLE, dwMask: ULONG, dwFlags: ULONG) -> BOOL | t.State: pass
def DuplicateHandle(hSourceProcessHandle: HANDLE, hSourceHandle: HANDLE, hTargetProcessHandle: HANDLE, lpTargetHandle: HANDLE | t.CPtr, dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwOptions: ULONG) -> BOOL | t.State: pass
DUPLICATE_SAME_ACCESS: t.CDefine = 0x00000002
+64
View File
@@ -0,0 +1,64 @@
import t
from stdint import *
from w32.win32base import *
MEM_COMMIT: t.CDefine = 0x00001000
MEM_RESERVE: t.CDefine = 0x00002000
MEM_DECOMMIT: t.CDefine = 0x00004000
MEM_RELEASE: t.CDefine = 0x00008000
MEM_FREE: t.CDefine = 0x00010000
MEM_RESET: t.CDefine = 0x00080000
MEM_TOP_DOWN: t.CDefine = 0x00100000
MEM_WRITE_WATCH: t.CDefine = 0x00200000
MEM_PHYSICAL: t.CDefine = 0x00400000
MEM_LARGE_PAGES: t.CDefine = 0x20000000
PAGE_NOACCESS: t.CDefine = 0x01
PAGE_READONLY: t.CDefine = 0x02
PAGE_READWRITE: t.CDefine = 0x04
PAGE_WRITECOPY: t.CDefine = 0x08
PAGE_EXECUTE: t.CDefine = 0x10
PAGE_EXECUTE_READ: t.CDefine = 0x20
PAGE_EXECUTE_READWRITE: t.CDefine = 0x40
PAGE_EXECUTE_WRITECOPY: t.CDefine = 0x80
PAGE_GUARD: t.CDefine = 0x100
PAGE_NOCACHE: t.CDefine = 0x200
PAGE_WRITECOMBINE: t.CDefine = 0x400
HEAP_NO_SERIALIZE: t.CDefine = 0x00000001
HEAP_GROWABLE: t.CDefine = 0x00000002
HEAP_GENERATE_EXCEPTIONS: t.CDefine = 0x00000004
HEAP_ZERO_MEMORY: t.CDefine = 0x00000008
HEAP_REALLOC_IN_PLACE_ONLY: t.CDefine = 0x00000010
class MEMORY_BASIC_INFORMATION():
BaseAddress: VOIDPTR
AllocationBase: VOIDPTR
AllocationProtect: ULONG
RegionSize: t.CSizeT
State: ULONG
Protect: ULONG
Type: ULONG
def VirtualAlloc(lpAddress: VOIDPTR, dwSize: t.CSizeT, flAllocationType: ULONG, flProtect: ULONG) -> VOIDPTR | t.State: pass
def VirtualFree(lpAddress: VOIDPTR, dwSize: t.CSizeT, dwFreeType: ULONG) -> BOOL | t.State: pass
def VirtualProtect(lpAddress: VOIDPTR, dwSize: t.CSizeT, flNewProtect: ULONG, lpflOldProtect: ULONG | t.CPtr) -> BOOL | t.State: pass
def VirtualQuery(lpAddress: t.CConst | VOIDPTR, lpBuffer: MEMORY_BASIC_INFORMATION | t.CPtr, dwLength: t.CSizeT) -> t.CSizeT | t.State: pass
def VirtualLock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass
def VirtualUnlock(lpAddress: VOIDPTR, dwSize: t.CSizeT) -> BOOL | t.State: pass
def GetProcessHeap() -> HANDLE | t.State: pass
def HeapCreate(flOptions: ULONG, dwInitialSize: t.CSizeT, dwMaximumSize: t.CSizeT) -> HANDLE | t.State: pass
def HeapDestroy(hHeap: HANDLE) -> BOOL | t.State: pass
def HeapAlloc(hHeap: HANDLE, dwFlags: ULONG, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
def HeapReAlloc(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
def HeapFree(hHeap: HANDLE, dwFlags: ULONG, lpMem: VOIDPTR) -> BOOL | t.State: pass
def HeapSize(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> t.CSizeT | t.State: pass
def HeapValidate(hHeap: HANDLE, dwFlags: ULONG, lpMem: t.CConst | VOIDPTR) -> BOOL | t.State: pass
def HeapCompact(hHeap: HANDLE, dwFlags: ULONG) -> t.CSizeT | t.State: pass
def GlobalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
def GlobalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
def GlobalLock(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
def GlobalUnlock(hMem: VOIDPTR) -> BOOL | t.State: pass
def GlobalSize(hMem: VOIDPTR) -> t.CSizeT | t.State: pass
def LocalAlloc(uFlags: UINT, dwBytes: t.CSizeT) -> VOIDPTR | t.State: pass
def LocalFree(hMem: VOIDPTR) -> VOIDPTR | t.State: pass
+112
View File
@@ -0,0 +1,112 @@
import t
from stdint import *
from w32.win32base import *
PROCESS_TERMINATE: t.CDefine = 0x0001
PROCESS_CREATE_THREAD: t.CDefine = 0x0002
PROCESS_VM_OPERATION: t.CDefine = 0x0008
PROCESS_VM_READ: t.CDefine = 0x0010
PROCESS_VM_WRITE: t.CDefine = 0x0020
PROCESS_QUERY_INFORMATION: t.CDefine = 0x0400
PROCESS_ALL_ACCESS: t.CDefine = 0x001FFFFF
THREAD_TERMINATE: t.CDefine = 0x0001
THREAD_SUSPEND_RESUME: t.CDefine = 0x0002
THREAD_GET_CONTEXT: t.CDefine = 0x0008
THREAD_SET_CONTEXT: t.CDefine = 0x0010
THREAD_QUERY_INFORMATION: t.CDefine = 0x0040
THREAD_ALL_ACCESS: t.CDefine = 0x001FFFFF
CREATE_SUSPENDED: t.CDefine = 0x00000004
CREATE_NEW_CONSOLE: t.CDefine = 0x00000010
CREATE_NEW_PROCESS_GROUP: t.CDefine = 0x00000200
CREATE_NO_WINDOW: t.CDefine = 0x08000000
DETACHED_PROCESS: t.CDefine = 0x00000008
STARTF_USESHOWWINDOW: t.CDefine = 0x00000001
STARTF_USESTDHANDLES: t.CDefine = 0x00000100
SW_HIDE: t.CDefine = 0
SW_SHOW: t.CDefine = 5
SW_MINIMIZE: t.CDefine = 6
NORMAL_PRIORITY_CLASS: t.CDefine = 0x00000020
IDLE_PRIORITY_CLASS: t.CDefine = 0x00000040
HIGH_PRIORITY_CLASS: t.CDefine = 0x00000080
REALTIME_PRIORITY_CLASS: t.CDefine = 0x00000100
BELOW_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00004000
ABOVE_NORMAL_PRIORITY_CLASS: t.CDefine = 0x00008000
STILL_ACTIVE: t.CDefine = 259
class STARTUPINFOA():
cb: ULONG
lpReserved: CHARPTR
lpDesktop: CHARPTR
lpTitle: CHARPTR
dwX: ULONG
dwY: ULONG
dwXSize: ULONG
dwYSize: ULONG
dwXCountChars: ULONG
dwYCountChars: ULONG
dwFillAttribute: ULONG
dwFlags: ULONG
wShowWindow: WORD
cbReserved2: WORD
lpReserved2: VOIDPTR
hStdInput: HANDLE
hStdOutput: HANDLE
hStdError: HANDLE
class STARTUPINFOW():
cb: ULONG
lpReserved: WCHARPTR
lpDesktop: WCHARPTR
lpTitle: WCHARPTR
dwX: ULONG
dwY: ULONG
dwXSize: ULONG
dwYSize: ULONG
dwXCountChars: ULONG
dwYCountChars: ULONG
dwFillAttribute: ULONG
dwFlags: ULONG
wShowWindow: WORD
cbReserved2: WORD
lpReserved2: VOIDPTR
hStdInput: HANDLE
hStdOutput: HANDLE
hStdError: HANDLE
class PROCESS_INFORMATION():
hProcess: HANDLE
hThread: HANDLE
dwProcessId: ULONG
dwThreadId: ULONG
def CreateProcessA(lpApplicationName: LPCSTR, lpCommandLine: CHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCSTR, lpStartupInfo: STARTUPINFOA | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass
def CreateProcessW(lpApplicationName: LPCWSTR, lpCommandLine: WCHARPTR, lpProcessAttributes: SECURITY_ATTRIBUTES | t.CPtr, lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInheritHandles: BOOL, dwCreationFlags: ULONG, lpEnvironment: VOIDPTR, lpCurrentDirectory: LPCWSTR, lpStartupInfo: STARTUPINFOW | t.CPtr, lpProcessInformation: PROCESS_INFORMATION | t.CPtr) -> BOOL | t.State: pass
def TerminateProcess(hProcess: HANDLE, uExitCode: UINT) -> BOOL | t.State: pass
def GetExitCodeProcess(hProcess: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass
def GetExitCodeThread(hThread: HANDLE, lpExitCode: ULONG | t.CPtr) -> BOOL | t.State: pass
def OpenProcess(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwProcessId: ULONG) -> HANDLE | t.State: pass
def GetCurrentProcess() -> HANDLE | t.State: pass
def GetCurrentProcessId() -> ULONG | t.State: pass
def CreateThread(lpThreadAttributes: SECURITY_ATTRIBUTES | t.CPtr, dwStackSize: t.CSizeT, lpStartAddress: VOIDPTR, lpParameter: VOIDPTR, dwCreationFlags: ULONG, lpThreadId: ULONG | t.CPtr) -> HANDLE | t.State: pass
def OpenThread(dwDesiredAccess: ULONG, bInheritHandle: BOOL, dwThreadId: ULONG) -> HANDLE | t.State: pass
def SuspendThread(hThread: HANDLE) -> ULONG | t.State: pass
def ResumeThread(hThread: HANDLE) -> ULONG | t.State: pass
def TerminateThread(hThread: HANDLE, dwExitCode: ULONG) -> BOOL | t.State: pass
def GetCurrentThread() -> HANDLE | t.State: pass
def GetCurrentThreadId() -> ULONG | t.State: pass
def GetThreadId(hThread: HANDLE) -> ULONG | t.State: pass
def GetProcessId(hProcess: HANDLE) -> ULONG | t.State: pass
def SetThreadPriority(hThread: HANDLE, nPriority: INT) -> BOOL | t.State: pass
def GetThreadPriority(hThread: HANDLE) -> INT | t.State: pass
def ExitProcess(uExitCode: UINT) -> VOID | t.State: pass
def ExitThread(dwExitCode: ULONG) -> VOID | t.State: pass
def TlsAlloc() -> ULONG | t.State: pass
def TlsFree(dwTlsIndex: ULONG) -> BOOL | t.State: pass
def TlsGetValue(dwTlsIndex: ULONG) -> VOIDPTR | t.State: pass
def TlsSetValue(dwTlsIndex: ULONG, lpTlsValue: VOIDPTR) -> BOOL | t.State: pass
+65
View File
@@ -0,0 +1,65 @@
import t
from stdint import *
from w32.win32base import *
class CRITICAL_SECTION():
DebugInfo: VOIDPTR
LockCount: LONG
RecursionCount: LONG
OwningThread: HANDLE
LockSemaphore: HANDLE
SpinCount: QWORD
def InitializeCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
def EnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
def LeaveCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
def DeleteCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> VOID | t.State: pass
def TryEnterCriticalSection(lpCriticalSection: CRITICAL_SECTION | t.CPtr) -> BOOL | t.State: pass
def SetCriticalSectionSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> ULONG | t.State: pass
def InitializeCriticalSectionAndSpinCount(lpCriticalSection: CRITICAL_SECTION | t.CPtr, dwSpinCount: ULONG) -> BOOL | t.State: pass
def CreateMutexA(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
def CreateMutexW(lpMutexAttributes: SECURITY_ATTRIBUTES | t.CPtr, bInitialOwner: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
def OpenMutexA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
def OpenMutexW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
def ReleaseMutex(hMutex: HANDLE) -> BOOL | t.State: pass
def CreateEventA(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
def CreateEventW(lpEventAttributes: SECURITY_ATTRIBUTES | t.CPtr, bManualReset: BOOL, bInitialState: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
def OpenEventA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
def OpenEventW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
def SetEvent(hEvent: HANDLE) -> BOOL | t.State: pass
def ResetEvent(hEvent: HANDLE) -> BOOL | t.State: pass
def PulseEvent(hEvent: HANDLE) -> BOOL | t.State: pass
def CreateSemaphoreA(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCSTR) -> HANDLE | t.State: pass
def CreateSemaphoreW(lpSemaphoreAttributes: SECURITY_ATTRIBUTES | t.CPtr, lInitialCount: LONG, lMaximumCount: LONG, lpName: LPCWSTR) -> HANDLE | t.State: pass
def OpenSemaphoreA(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCSTR) -> HANDLE | t.State: pass
def OpenSemaphoreW(dwDesiredAccess: ULONG, bInheritHandle: BOOL, lpName: LPCWSTR) -> HANDLE | t.State: pass
def ReleaseSemaphore(hSemaphore: HANDLE, lReleaseCount: LONG, lpPreviousCount: LONG | t.CPtr) -> BOOL | t.State: pass
def WaitForSingleObject(hHandle: HANDLE, dwMilliseconds: ULONG) -> ULONG | t.State: pass
def WaitForSingleObjectEx(hHandle: HANDLE, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass
def WaitForMultipleObjects(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG) -> ULONG | t.State: pass
def WaitForMultipleObjectsEx(nCount: ULONG, lpHandles: VOIDPTR, bWaitAll: BOOL, dwMilliseconds: ULONG, bAlertable: BOOL) -> ULONG | t.State: pass
def InitializeSRWLock(SRWLock: VOIDPTR) -> VOID | t.State: pass
def AcquireSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass
def AcquireSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass
def ReleaseSRWLockExclusive(SRWLock: VOIDPTR) -> VOID | t.State: pass
def ReleaseSRWLockShared(SRWLock: VOIDPTR) -> VOID | t.State: pass
# 条件变量 (Condition Variables) - Vista+
CONDITION_VARIABLE_LOCKMODE_SHARED: t.CDefine = 0x1
def InitializeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
def SleepConditionVariableCS(ConditionVariable: VOIDPTR, CriticalSection: CRITICAL_SECTION | t.CPtr, dwMilliseconds: ULONG) -> BOOL | t.State: pass
def SleepConditionVariableSRW(ConditionVariable: VOIDPTR, SRWLock: VOIDPTR, dwMilliseconds: ULONG, Flags: ULONG) -> BOOL | t.State: pass
def WakeConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
def WakeAllConditionVariable(ConditionVariable: VOIDPTR) -> VOID | t.State: pass
# 一次性初始化 (One-Time Initialization) - Vista+
INIT_ONCE_STATIC_INIT: t.CDefine = 0x00000001
INIT_ONCE_CHECK_ONLY: t.CDefine = 0x00000002
INIT_ONCE_ASYNC: t.CDefine = 0x00000004
INIT_ONCE_INIT_FAILED: t.CDefine = 0x00000008
class INIT_ONCE:
Ptr: t.CPtr
def InitOnceExecuteOnce(InitOnce: INIT_ONCE | t.CPtr, InitFn: VOIDPTR, Parameter: VOIDPTR, Context: VOIDPTR | t.CPtr) -> BOOL | t.State: pass
+104
View File
@@ -0,0 +1,104 @@
import t, c
from stdint import *
from w32.win32base import *
# ============================================================
# w32/winsock2.py — WinSock2 API 声明 (ws2_32.dll)
# ============================================================
# 版本常量
WINSOCK_VERSION: t.CDefine = 0x0202 # 2.2
# 地址族
AF_INET: t.CDefine = 2
AF_INET6: t.CDefine = 23
# 套接字类型
SOCK_STREAM: t.CDefine = 1 # TCP
SOCK_DGRAM: t.CDefine = 2 # UDP
SOCK_RAW: t.CDefine = 3 # 原始套接字
# 协议
IPPROTO_TCP: t.CDefine = 6
IPPROTO_UDP: t.CDefine = 17
# 选项级别
SOL_SOCKET: t.CDefine = 0xFFFF # WinSock2 值
SO_RCVTIMEO: t.CDefine = 0x1006 # WinSock2 值
SO_SNDTIMEO: t.CDefine = 0x1005 # WinSock2 值
SO_REUSEADDR: t.CDefine = 0x0004 # WinSock2 值
# 特殊值
INADDR_ANY: t.CDefine = 0
SOCKET_ERROR: t.CDefine = -1
INVALID_SOCKET: t.CDefine = 0xFFFFFFFF # WinSock2: ~0
# 发送/接收标志
MSG_NOSIGNAL: t.CDefine = 0 # Windows 不支持,设为 0
# 关闭方式
SD_SEND: t.CDefine = 1
SD_RECV: t.CDefine = 0
SD_BOTH: t.CDefine = 2
# ============================================================
# 结构体
# ============================================================
# struct sockaddr_in — 16 字节
class WSASocketAddr:
family: u16 # sin_family
port: u16 # sin_port
addr: u32 # sin_addr.s_addr
zero: u64 # sin_zero
# struct WSADATA — 400 字节
class WSAData:
wVersion: WORD # @ 0
wHighVersion: WORD # @ 2
szDescription: BYTE # @ 4 (257 bytes + padding)
szSystemStatus: BYTE # @ 261 (129 bytes + padding)
iMaxSockets: u16 # @ 390
iMaxUdpDg: u16 # @ 392
lpVendorInfo: CHARPTR # @ 394 (实际上指针是 8 字节对齐)
# struct hostent — 自然对齐: h_name(8) + h_aliases(8) + h_addrtype(2) + h_length(2) + auto-pad(4) + h_addr_list(8) = 32
class WSAHostEnt:
h_name: CHARPTR
h_aliases: CHARPTR
h_addrtype: SHORT
h_length: SHORT
h_addr_list: CHARPTR
# struct timeval
class WinTimeVal:
tv_sec: LONG # 秒
tv_usec: LONG # 微秒
# ============================================================
# WinSock2 API 函数
# ============================================================
def WSAStartup(wVersionRequested: WORD, lpWSAData: WSAData | t.CPtr) -> INT | t.State: pass
def WSACleanup() -> INT | t.State: pass
def WSAGetLastError() -> INT | t.State: pass
def socket(family: INT, type: INT, protocol: INT) -> u64 | t.State: pass
def closesocket(s: u64) -> INT | t.State: pass
def connect(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass
def send(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass
def recv(s: u64, buf: t.CVoid | t.CPtr, len: INT, flags: INT) -> INT | t.State: pass
def bind(s: u64, name: WSASocketAddr | t.CPtr, namelen: INT) -> INT | t.State: pass
def listen(s: u64, backlog: INT) -> INT | t.State: pass
def accept(s: u64, addr: WSASocketAddr | t.CPtr, addrlen: INT | t.CPtr) -> u64 | t.State: pass
def setsockopt(s: u64, level: INT, optname: INT, optval: t.CVoid | t.CPtr, optlen: INT) -> INT | t.State: pass
def shutdown(s: u64, how: INT) -> INT | t.State: pass
def gethostbyname(name: t.CChar | t.CConst | t.CPtr) -> WSAHostEnt | t.CPtr | t.State: pass
def ntohs(netshort: u16) -> u16 | t.State: pass
def htons(hostshort: u16) -> u16 | t.State: pass
def inet_addr(cp: t.CChar | t.CConst | t.CPtr) -> u32 | t.State: pass
+1
View File
@@ -0,0 +1 @@
from .pyzlib import *
+695
View File
@@ -0,0 +1,695 @@
from stdint import *
import zlib.zdeflate as zdeflate
import zlib.zinflate as zinflate
import zlib.zchecksum as zchecksum
import zlib.zdef as zdef
import zlib.zhuff as zhuff
import stdlib
import string
import memhub
import t, c
# ============================================================
# Constants - matching Python zlib module names and values
# ============================================================
# Compression levels
Z_NO_COMPRESSION: t.CDefine = 0
Z_BEST_SPEED: t.CDefine = 1
Z_BEST_COMPRESSION: t.CDefine = 9
Z_DEFAULT_COMPRESSION: t.CDefine = (-1)
# Compression methods
DEFLATED: t.CDefine = 8
# Flush modes
Z_NO_FLUSH: t.CDefine = 0
Z_PARTIAL_FLUSH: t.CDefine = 1
Z_SYNC_FLUSH: t.CDefine = 2
Z_FULL_FLUSH: t.CDefine = 3
Z_FINISH: t.CDefine = 4
Z_BLOCK: t.CDefine = 5
Z_TREES: t.CDefine = 6
# Strategies
Z_DEFAULT_STRATEGY: t.CDefine = 0
Z_FILTERED: t.CDefine = 1
Z_HUFFMAN_ONLY: t.CDefine = 2
Z_RLE: t.CDefine = 3
Z_FIXED: t.CDefine = 4
# Return codes
Z_OK: t.CDefine = 0
Z_STREAM_END: t.CDefine = 1
Z_NEED_DICT: t.CDefine = 2
Z_ERRNO: t.CDefine = (-1)
Z_STREAM_ERROR: t.CDefine = (-2)
Z_DATA_ERROR: t.CDefine = (-3)
Z_MEM_ERROR: t.CDefine = (-4)
Z_BUF_ERROR: t.CDefine = (-5)
Z_VERSION_ERROR: t.CDefine = (-6)
# Window / Buffer constants
MAX_WBITS: t.CDefine = 15
DEF_BUF_SIZE: t.CDefine = 16384
DEF_MEM_LEVEL: t.CDefine = 8
# Version
ZLIB_VERSION: t.CDefine = "1.3.2"
pyzlib_error_msg: t.CArray[t.CChar, 512] = ""
pyzlib_error_code_val: t.CInt = 0
# ============================================================
# Structures
# ============================================================
@t.Object
class Compress:
pool: memhub.MemManager | t.CPtr
stream: VOIDPTR
is_initialized: t.CInt
is_finished: t.CInt
level: t.CInt
method: t.CInt
wbits: t.CInt
memLevel: t.CInt
strategy: t.CInt
zdict: BYTEPTR
zdict_len: t.CSizeT
last_pos: t.CSizeT
input_buf: BYTEPTR
input_buf_len: t.CSizeT
input_buf_cap: t.CSizeT
header_written: t.CInt
def compress(self,
data: BYTEPTR, data_len: t.CSizeT,
out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "compress object not initialized")
return None
if self.is_finished:
set_error(Z_STREAM_ERROR, "compress object already finished")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
if data_len == 0:
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p, 0, 1)
return p
while self.input_buf_len + data_len > self.input_buf_cap:
self.input_buf_cap *= 2
if self.pool == None:
new_buf: BYTEPTR = BYTEPTR(realloc(self.input_buf, self.input_buf_cap))
else:
new_buf: BYTEPTR = BYTEPTR(self.pool.alloc(self.input_buf_cap))
if new_buf:
memcpy(new_buf, self.input_buf, self.input_buf_len)
self.pool.free(self.input_buf)
if not new_buf:
set_error(Z_MEM_ERROR, "out of memory")
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p2: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p2, 0, 1)
return p2
self.input_buf = new_buf
memcpy(self.input_buf + self.input_buf_len, data, data_len)
self.input_buf_len += data_len
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p3: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p3, 0, 1)
return p3
def flush(self, mode: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "compress object not initialized")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换
if mode == Z_FINISH:
if not self.header_written:
self.header_written = 1
input_data: BYTEPTR = self.input_buf
input_len: t.CSizeT = self.input_buf_len
if input_len == 0:
s.writer.write_bits(1, 1)
s.writer.write_bits(1, 2)
lit_tree = zhuff.zhuff_tree()
lit_tree.build_fixed_lit_tree()
lit_tree.encode_symbol(256, c.Addr(s.writer))
else:
s.adler = zchecksum.zchecksum_adler32(input_data, input_len, 1)
s.compress_block(input_data, input_len, 1)
s.is_finished = 1
if s.wbits >= 0:
s.writer.align()
adler: t.CUInt32T = s.adler
s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF
s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF
s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF
s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF
s.writer.byte_pos += 4
self.is_finished = 1
total: t.CSizeT = s.writer.total()
if self.pool == None:
result: BYTEPTR = BYTEPTR(malloc(total))
else:
result: BYTEPTR = BYTEPTR(self.pool.alloc(total))
if result: memcpy(result, s.writer.buf, total)
c.Set(c.Deref(out_len), total)
if self.pool == None:
free(self.input_buf)
else:
self.pool.free(self.input_buf)
self.input_buf = None
self.input_buf_len = 0
self.input_buf_cap = 0
return result
elif mode == Z_SYNC_FLUSH or mode == Z_FULL_FLUSH:
input_data: BYTEPTR = self.input_buf
input_len: t.CSizeT = self.input_buf_len
if input_len > 0:
s.adler = zchecksum.zchecksum_adler32(input_data, input_len, s.adler)
s.compress_block(input_data, input_len, 0)
self.input_buf_len = 0
s.writer.write_bits(0, 1)
s.writer.write_bits(0, 2)
s.writer.align()
prev_pos: t.CSizeT = self.last_pos
total: t.CSizeT = s.writer.total()
delta: t.CSizeT = total - prev_pos
self.last_pos = s.writer.byte_pos
if delta == 0:
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p4: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p4, 0, 1)
return p4
if self.pool == None:
result: BYTEPTR = BYTEPTR(malloc(delta))
else:
result: BYTEPTR = BYTEPTR(self.pool.alloc(delta))
if result: memcpy(result, s.writer.buf + prev_pos, delta)
c.Set(c.Deref(out_len), delta)
return result
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p5: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p5, 0, 1)
return p5
def copy(self) -> Compress | t.CPtr:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "compress object not initialized")
return None
if self.pool == None:
copy_obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__())
else:
copy_obj: Compress | t.CPtr = self.pool.alloc(Compress.__sizeof__())
memset(copy_obj, 0, Compress.__sizeof__())
if not copy_obj:
set_error(Z_MEM_ERROR, "out of memory")
return None
copy_obj.pool = self.pool
s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换
copy_obj.stream = s.copy()
if not copy_obj.stream:
if self.pool == None:
free(copy_obj)
else:
self.pool.free(copy_obj)
set_error(Z_MEM_ERROR, "out of memory")
return None
copy_obj.is_initialized = 1
copy_obj.is_finished = self.is_finished
copy_obj.level = self.level
copy_obj.method = self.method
copy_obj.wbits = self.wbits
copy_obj.memLevel = self.memLevel
copy_obj.strategy = self.strategy
copy_obj.last_pos = self.last_pos
copy_obj.header_written = self.header_written
if self.input_buf and self.input_buf_len > 0:
if self.pool == None:
copy_obj.input_buf = BYTEPTR(calloc(1, self.input_buf_cap))
else:
copy_obj.input_buf = BYTEPTR(self.pool.alloc(self.input_buf_cap))
memset(copy_obj.input_buf, 0, self.input_buf_cap)
if copy_obj.input_buf:
memcpy(copy_obj.input_buf, self.input_buf, self.input_buf_len)
copy_obj.input_buf_cap = self.input_buf_cap
copy_obj.input_buf_len = self.input_buf_len
else:
if self.pool == None:
copy_obj.input_buf = BYTEPTR(calloc(1, 256))
else:
copy_obj.input_buf = BYTEPTR(self.pool.alloc(256))
memset(copy_obj.input_buf, 0, 256)
copy_obj.input_buf_cap = 256
copy_obj.input_buf_len = 0
if self.zdict and self.zdict_len > 0:
copy_obj.zdict = clone_bytes(self.pool, self.zdict, self.zdict_len)
copy_obj.zdict_len = self.zdict_len
return copy_obj
def delete(self):
if self.is_initialized and self.stream:
s: zdeflate.zdeflate_stream | t.CPtr = self.stream # 隐式类型转换
s.destroy()
if self.pool == None:
free(self.zdict)
free(self.input_buf)
free(self)
else:
self.pool.free(self.zdict)
self.pool.free(self.input_buf)
self.pool.free(self)
def __del__(self):
self.delete()
@t.Object
class Decompress:
pool: memhub.MemManager | t.CPtr
stream: VOIDPTR
is_initialized: t.CInt
eof: t.CInt
wbits: t.CInt
zdict: BYTEPTR
zdict_len: t.CSizeT
_unused_data: BYTEPTR
_unused_data_len: t.CSizeT
_unused_data_cap: t.CSizeT
_unconsumed_tail: BYTEPTR
_unconsumed_tail_len: t.CSizeT
_unconsumed_tail_cap: t.CSizeT
input_buf: BYTEPTR
input_buf_len: t.CSizeT
input_buf_cap: t.CSizeT
def decompress(self, data: BYTEPTR, data_len: t.CSizeT,
max_length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "decompress object not initialized")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
if self.eof:
if data and data_len > 0:
append_bytes(self.pool, c.Addr(self._unused_data), c.Addr(self._unused_data_len),
c.Addr(self._unused_data_cap), data, data_len)
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p6: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p6, 0, 1)
return p6
self._unconsumed_tail_len = 0
if data and data_len > 0:
append_bytes(self.pool, c.Addr(self.input_buf), c.Addr(self.input_buf_len),
c.Addr(self.input_buf_cap), data, data_len)
if self.input_buf_len == 0:
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p7: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p7, 0, 1)
return p7
s: zinflate.zinflate_stream | t.CPtr = zinflate.zinflate_create(self.pool, self.wbits)
if not s:
set_error(Z_MEM_ERROR, "out of memory")
return None
if self.zdict and self.zdict_len > 0:
s.set_dictionary(self.zdict, self.zdict_len)
out: t.CUInt8T | t.CPtr = None
err: t.CInt = s.decompress(self.input_buf, self.input_buf_len,
max_length, c.Addr(out), out_len)
if err != 0:
s.destroy()
set_error(Z_DATA_ERROR, "decompression failed")
return None
if s.is_finished:
self.eof = 1
if s.input_pos < s.input_len:
append_bytes(self.pool, c.Addr(self._unused_data), c.Addr(self._unused_data_len),
c.Addr(self._unused_data_cap),
s.input_data + s.input_pos,
s.input_len - s.input_pos)
self.input_buf_len = 0
else:
consumed: t.CSizeT = s.input_pos
if consumed < self.input_buf_len:
remaining: t.CSizeT = self.input_buf_len - consumed
memmove(self.input_buf, self.input_buf + consumed, remaining)
self.input_buf_len = remaining
else:
self.input_buf_len = 0
s.destroy()
return out
def flush(self, length: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "decompress object not initialized")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
c.Set(c.Deref(out_len), 0)
if self.pool == None:
return BYTEPTR(calloc(1, 1))
else:
p8: BYTEPTR = BYTEPTR(self.pool.alloc(1))
memset(p8, 0, 1)
return p8
def copy(self) -> Decompress | t.CPtr:
if not self.is_initialized:
set_error(Z_STREAM_ERROR, "decompress object not initialized")
return None
if self.pool == None:
copy_obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__())
else:
copy_obj: Decompress | t.CPtr = self.pool.alloc(Decompress.__sizeof__())
memset(copy_obj, 0, Decompress.__sizeof__())
if not copy_obj:
set_error(Z_MEM_ERROR, "out of memory")
return None
copy_obj.pool = self.pool
copy_obj.is_initialized = 1
copy_obj.eof = self.eof
copy_obj.wbits = self.wbits
if self.zdict and self.zdict_len > 0:
copy_obj.zdict = clone_bytes(self.pool, self.zdict, self.zdict_len)
copy_obj.zdict_len = self.zdict_len
if self._unused_data and self._unused_data_len > 0:
copy_obj._unused_data = clone_bytes(self.pool, self._unused_data, self._unused_data_len)
copy_obj._unused_data_len = self._unused_data_len
copy_obj._unused_data_cap = self._unused_data_len
if self._unconsumed_tail and self._unconsumed_tail_len > 0:
copy_obj._unconsumed_tail = clone_bytes(self.pool, self._unconsumed_tail, self._unconsumed_tail_len)
copy_obj._unconsumed_tail_len = self._unconsumed_tail_len
copy_obj._unconsumed_tail_cap = self._unconsumed_tail_len
if self.input_buf and self.input_buf_len > 0:
copy_obj.input_buf = clone_bytes(self.pool, self.input_buf, self.input_buf_len)
copy_obj.input_buf_len = self.input_buf_len
copy_obj.input_buf_cap = self.input_buf_cap
else:
if self.pool == None:
copy_obj.input_buf = BYTEPTR(calloc(1, 256))
else:
copy_obj.input_buf = BYTEPTR(self.pool.alloc(256))
memset(copy_obj.input_buf, 0, 256)
copy_obj.input_buf_cap = 256
copy_obj.input_buf_len = 0
return copy_obj
def delete(self):
if self.pool == None:
free(self.zdict)
free(self._unused_data)
free(self._unconsumed_tail)
free(self.input_buf)
free(self)
else:
self.pool.free(self.zdict)
self.pool.free(self._unused_data)
self.pool.free(self._unconsumed_tail)
self.pool.free(self.input_buf)
self.pool.free(self)
def unused_data(self, length: t.CSizeT | t.CPtr) -> BYTEPTR:
#if not self:
# if length:
# c.Set(c.Deref(length), 0)
# return None
if length:
c.Set(c.Deref(length), self._unused_data_len)
return self._unused_data
def unconsumed_tail(self, length: t.CSizeT | t.CPtr) -> BYTEPTR:
#if not self:
# if length:
# c.Set(c.Deref(length), 0)
# return None
if length:
c.Set(c.Deref(length), self._unconsumed_tail_len)
return self._unconsumed_tail
# def eof(self) -> t.CInt:
# # if not obj: return 0
# return self.eof
def set_error(code: int, msg: str):
global pyzlib_error_code_val, pyzlib_error_msg
pyzlib_error_code_val = code
if msg:
strncpy(pyzlib_error_msg, msg, pyzlib_error_msg.__sizeof__() - 1)
pyzlib_error_msg[pyzlib_error_msg.__sizeof__() - 1] = '\0'
else:
pyzlib_error_msg[0] = '\0'
def clone_bytes(pool: memhub.MemManager | t.CPtr, src: BYTEPTR, length: t.CSizeT) -> BYTEPTR:
if not src or length == 0: return None
if pool == None:
dst: BYTEPTR = BYTEPTR(malloc(length))
else:
dst: BYTEPTR = BYTEPTR(pool.alloc(length))
if dst: memcpy(dst, src, length)
return dst
def append_bytes(pool: memhub.MemManager | t.CPtr, buf: BYTE | t.CPtr[t.CPtr], length: t.CSizeT | t.CPtr, cap: t.CSizeT | t.CPtr,
data: BYTEPTR, data_len: t.CSizeT) -> t.CInt:
if not data or data_len == 0: return 0
needed: t.CSizeT = c.Deref(length) + data_len
if needed > c.Deref(cap):
new_cap: t.CSizeT = c.Deref(cap) * 2
if new_cap < needed: new_cap = needed
if pool == None:
new_buf: BYTEPTR = BYTEPTR(realloc(c.Deref(buf), new_cap))
else:
new_buf: BYTEPTR = BYTEPTR(pool.alloc(new_cap))
if new_buf:
memcpy(new_buf, c.Deref(buf), c.Deref(length))
pool.free(c.Deref(buf))
if not new_buf: return -1
c.Set(c.Deref(buf), new_buf)
c.Set(c.Deref(cap), new_cap)
memcpy(c.Deref(buf) + c.Deref(length), data, data_len)
c.Set(c.Deref(length), c.Deref(length) + data_len)
return 0
def shrink_to_fit(pool: memhub.MemManager | t.CPtr, buf: BYTEPTR, length: t.CSizeT) -> BYTEPTR:
if length == 0:
if pool == None:
free(buf)
return BYTEPTR(calloc(1, 1))
else:
pool.free(buf)
p: BYTEPTR = BYTEPTR(pool.alloc(1))
memset(p, 0, 1)
return p
if pool == None:
result: BYTEPTR = BYTEPTR(realloc(buf, length))
return result if result else buf
else:
result: BYTEPTR = BYTEPTR(pool.alloc(length))
if result:
memcpy(result, buf, length)
pool.free(buf)
return result
return buf
def runtime_version() -> str:
return ZLIB_VERSION
def get_error() -> str:
return pyzlib_error_msg
def get_error_code() -> t.CInt:
return pyzlib_error_code_val
def clear_error():
global pyzlib_error_msg, pyzlib_error_code_val
pyzlib_error_msg[0] = '\0'
pyzlib_error_code_val = 0
def compress(pool: memhub.MemManager | t.CPtr, data: BYTEPTR, data_len: t.CSizeT,
level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not data and data_len > 0:
set_error(Z_STREAM_ERROR, "data is None but data_len > 0")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
actual_wbits: t.CInt = wbits
if wbits > MAX_WBITS:
actual_wbits = -MAX_WBITS
raw_result: UINT8PTR = zdeflate.zdeflate_one_shot(pool, data, data_len, level, actual_wbits, out_len)
if not raw_result:
set_error(Z_DATA_ERROR, "compression failed")
return None
if wbits > MAX_WBITS:
gzip_len: t.CSizeT = 10 + c.Deref(out_len) + 8
if pool == None:
gzip_buf: BYTEPTR = BYTEPTR(malloc(gzip_len))
else:
gzip_buf: BYTEPTR = BYTEPTR(pool.alloc(gzip_len))
if not gzip_buf:
if pool == None:
free(raw_result)
else:
pool.free(raw_result)
set_error(Z_MEM_ERROR, "out of memory")
return None
pos: t.CSizeT = 0
gzip_buf[pos + 0] = 0x1F
gzip_buf[pos + 1] = 0x8B
gzip_buf[pos + 2] = 0x08
gzip_buf[pos + 3] = 0x00
gzip_buf[pos + 4] = 0x00
gzip_buf[pos + 5] = 0x00
gzip_buf[pos + 6] = 0x00
gzip_buf[pos + 7] = 0x00
gzip_buf[pos + 8] = 0x00
gzip_buf[pos + 9] = 0xFF
pos += 10
memcpy(gzip_buf + pos, raw_result, c.Deref(out_len))
pos += c.Deref(out_len)
if pool == None:
free(raw_result)
else:
pool.free(raw_result)
crc: t.CUInt32T = zchecksum.zchecksum_crc32(data, data_len, 0)
gzip_buf[pos + 0] = (crc) & 0xFF
gzip_buf[pos + 1] = (crc >> 8) & 0xFF
gzip_buf[pos + 2] = (crc >> 16) & 0xFF
gzip_buf[pos + 3] = (crc >> 24) & 0xFF
gzip_buf[pos + 4] = (data_len) & 0xFF
gzip_buf[pos + 5] = (data_len >> 8) & 0xFF
gzip_buf[pos + 6] = (data_len >> 16) & 0xFF
gzip_buf[pos + 7] = (data_len >> 24) & 0xFF
pos += 8
c.Set(c.Deref(out_len), pos)
return shrink_to_fit(pool, gzip_buf, pos)
return shrink_to_fit(pool, raw_result, c.Deref(out_len))
def decompress(pool: memhub.MemManager | t.CPtr, data: BYTEPTR, data_len: t.CSizeT,
wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> BYTEPTR:
if not data and data_len > 0:
set_error(Z_STREAM_ERROR, "data is None but data_len > 0")
return None
if not out_len:
set_error(Z_STREAM_ERROR, "out_len is None")
return None
result: UINT8PTR = zinflate.zinflate_one_shot(pool, data, data_len, wbits, bufsize, out_len)
if not result:
set_error(Z_DATA_ERROR, "decompression failed")
return None
return shrink_to_fit(pool, result, c.Deref(out_len))
def compressobj(pool: memhub.MemManager | t.CPtr, level: t.CInt, method: t.CInt, wbits: t.CInt,
memLevel: t.CInt, strategy: t.CInt,
zdict: BYTEPTR, zdict_len: t.CSizeT) -> Compress | t.CPtr:
if pool == None:
obj: Compress | t.CPtr = calloc(1, Compress.__sizeof__())
else:
obj: Compress | t.CPtr = pool.alloc(Compress.__sizeof__())
memset(obj, 0, Compress.__sizeof__())
if not obj:
set_error(Z_MEM_ERROR, "out of memory")
return None
obj.pool = pool
actual_wbits: t.CInt = wbits
if wbits > MAX_WBITS: actual_wbits = wbits - 16
s: zdeflate.zdeflate_stream | t.CPtr = zdeflate.zdeflate_create(pool, level, actual_wbits, memLevel, strategy)
if not s:
if pool == None:
free(obj)
else:
pool.free(obj)
set_error(Z_MEM_ERROR, "out of memory")
return None
obj.stream = s
obj.is_initialized = 1
obj.level = level
obj.method = method
obj.wbits = wbits
obj.memLevel = memLevel
obj.strategy = strategy
if pool == None:
obj.input_buf = BYTEPTR(calloc(1, 256))
else:
obj.input_buf = BYTEPTR(pool.alloc(256))
memset(obj.input_buf, 0, 256)
obj.input_buf_cap = 256
obj.input_buf_len = 0
obj.header_written = 0
if zdict and zdict_len > 0:
s.set_dictionary(zdict, zdict_len)
obj.zdict = clone_bytes(pool, zdict, zdict_len)
obj.zdict_len = zdict_len
return obj
def decompressobj(pool: memhub.MemManager | t.CPtr, wbits: t.CInt, zdict: BYTEPTR, zdict_len: t.CSizeT) -> Decompress | t.CPtr:
if pool == None:
obj: Decompress | t.CPtr = calloc(1, Decompress.__sizeof__())
else:
obj: Decompress | t.CPtr = pool.alloc(Decompress.__sizeof__())
memset(obj, 0, Decompress.__sizeof__())
if not obj:
set_error(Z_MEM_ERROR, "out of memory")
return None
obj.pool = pool
actual_wbits: t.CInt = wbits
if wbits > MAX_WBITS: actual_wbits = wbits - 16
obj.stream = None
obj.is_initialized = 1
obj.wbits = actual_wbits
if zdict and zdict_len > 0:
obj.zdict = clone_bytes(pool, zdict, zdict_len)
obj.zdict_len = zdict_len
if pool == None:
obj.input_buf = BYTEPTR(calloc(1, 256))
else:
obj.input_buf = BYTEPTR(pool.alloc(256))
memset(obj.input_buf, 0, 256)
obj.input_buf_cap = 256
obj.input_buf_len = 0
return obj
def zlib_adler32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong:
return zchecksum.zchecksum_adler32(data, length, UINT32(value))
def zlib_crc32(data: BYTEPTR, length: t.CSizeT, value: t.CUnsignedLong) -> t.CUnsignedLong:
return zchecksum.zchecksum_crc32(data, length, UINT32(value))
+89
View File
@@ -0,0 +1,89 @@
from stdint import *
import t, c
def zchecksum_adler32(data: UINT8PTR, length: t.CSizeT, init: UINT32) -> t.CUInt32T:
a: t.CUInt32T = (init >> 0) & 0xFFFF
b: t.CUInt32T = (init >> 16) & 0xFFFF
if not data or length == 0:
return init
i: t.CSizeT
for i in range(length):
a = (a + data[i]) % 65521
b = (b + a) % 65521
return (b << 16) | a
crc32_table: t.CArray[t.CUInt32T, 256] = [
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBBBD6, 0xACBCCB40,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7D49,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDede9EC5, 0x47D7897F, 0x30D0B8E9,
0xBDDA8B1C, 0xCADD8B8A, 0x53D3903A, 0x24D4C2AC,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
]
def zchecksum_crc32(data: UINT8PTR, length: t.CSizeT, init: t.CUInt32T) -> t.CUInt32T:
crc: t.CUInt32T = init ^ 0xFFFFFFFF
if not data or length == 0: return init
i: t.CSizeT
for i in range(length):
crc = crc32_table[(crc ^ data[i]) & 0xFF] ^ (crc >> 8)
return crc ^ 0xFFFFFFFF
+288
View File
@@ -0,0 +1,288 @@
from stdint import *
import stddef
import string
import stdlib
import memhub
import t, c
# ============================================================
# DEFLATE / zlib constants
# ============================================================
ZDEFLATE_WINDOW_BITS: t.CDefine = 15
ZDEFLATE_WINDOW_SIZE: t.CDefine = (1 << ZDEFLATE_WINDOW_BITS)
ZDEFLATE_WINDOW_MASK: t.CDefine = (ZDEFLATE_WINDOW_SIZE - 1)
ZDEFLATE_MIN_MATCH: t.CDefine = 3
ZDEFLATE_MAX_MATCH: t.CDefine = 258
ZDEFLATE_HASH_BITS: t.CDefine = 15
ZDEFLATE_HASH_SIZE: t.CDefine = (1 << ZDEFLATE_HASH_BITS)
ZDEFLATE_HASH_MASK: t.CDefine = (ZDEFLATE_HASH_SIZE - 1)
ZDEFLATE_MAX_CODES: t.CDefine = 288
ZDEFLATE_MAX_DIST_CODES: t.CDefine = 32
ZDEFLATE_MAX_BITS: t.CDefine = 15
ZDEFLATE_MAX_CODELEN_CODES: t.CDefine = 19
ZDEFLATE_LIT_COUNT: t.CDefine = 286
ZDEFLATE_DIST_COUNT: t.CDefine = 30
ZDEFLATE_LEN_SYMBOLS_BASE: t.CDefine = 257
ZDEFLATE_END_OF_BLOCK: t.CDefine = 256
# ============================================================
# Length / Distance extra bits tables (RFC 1951)
# ============================================================
zdeflate_len_extra_bits: t.CArray[t.CInt, 29] = [
0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1,
2, 2, 2, 2,
3, 3, 3, 3,
4, 4, 4, 4,
5, 5, 5, 5,
0
]
zdeflate_len_base: t.CArray[t.CInt, 29] = [
3, 4, 5, 6, 7, 8, 9, 10,
11, 13, 15, 17,
19, 23, 27, 31,
35, 43, 51, 59,
67, 83, 99, 115,
131, 163, 195, 227,
258
]
zdeflate_dist_extra_bits: t.CArray[t.CInt, 30] = [
0, 0, 0, 0,
1, 1,
2, 2,
3, 3,
4, 4,
5, 5,
6, 6,
7, 7,
8, 8,
9, 9,
10, 10,
11, 11,
12, 12,
13, 13
]
zdeflate_dist_base: t.CArray[t.CInt, 30] = [
1, 2, 3, 4,
5, 7,
9, 13,
17, 25,
33, 49,
65, 97,
129, 193,
257, 385,
513, 769,
1025, 1537,
2049, 3073,
4097, 6145,
8193, 12289,
16385, 24577
]
zdeflate_codelen_order: t.CArray[int, 19] = [
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
]
# ============================================================
# Bit writer - writes bits LSB first into a byte buffer
# ============================================================
@t.Object
class zbit_writer:
pool: memhub.MemManager | t.CPtr
buf: BYTE | t.CPtr
cap: t.CSizeT
byte_pos: t.CSizeT
bit_pos: t.CInt
def __init__(self, pool: memhub.MemManager | t.CPtr):
self.pool = pool
self.cap = 4096
if pool == None:
self.buf = BYTEPTR(malloc(self.cap))
else:
self.buf = BYTEPTR(pool.alloc(self.cap))
memset(self.buf, 0, self.cap)
self.byte_pos = 0
self.bit_pos = 0
def ensure(self, need: t.CSizeT):
while self.byte_pos + need + 4 >= self.cap:
new_cap: t.CSizeT = self.cap * 2
if self.pool == None:
new_buf: BYTE | t.CPtr = BYTEPTR(realloc(self.buf, new_cap))
else:
new_buf: BYTE | t.CPtr = BYTEPTR(self.pool.alloc(new_cap))
if new_buf:
memcpy(new_buf, self.buf, self.byte_pos + (self.bit_pos + 7) / 8)
self.pool.free(self.buf)
if not new_buf: return
memset(new_buf + self.cap, 0, new_cap - self.cap)
self.buf = new_buf
self.cap = new_cap
def write_bits(self, value: UINT, nbits: t.CInt):
self.ensure((nbits + 7) / 8 + 1)
for i in range(nbits):
if value & (UINT(1) << i):
self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos)
self.bit_pos += 1
if self.bit_pos == 8:
self.bit_pos = 0
self.byte_pos += 1
def write_bits_rev(self, code: UINT, nbits: t.CInt):
self.ensure((nbits + 7) / 8 + 1)
for i in range(nbits - 1, -1, -1):
if code & (UINT(1) << i):
self.buf[self.byte_pos] |= (UINT(1) << self.bit_pos)
self.bit_pos += 1
if self.bit_pos == 8:
self.bit_pos = 0
self.byte_pos += 1
def stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
self.write_bits(1 if final else 0, 1)
self.write_bits(0, 2)
self.align()
pos: t.CSizeT = 0
while pos < length:
block_length: t.CSizeT = length - pos
if block_length > 65535:
block_length = 65535
n: t.CUInt16T = t.CUInt16T(block_length)
ncomp: t.CUInt16T = ~n
self.write_bits(n, 16)
self.write_bits(ncomp, 16)
self.ensure(block_length)
i: t.CSizeT = 0
for i in range(block_length):
self.buf[self.byte_pos] = data[pos + i]
self.byte_pos += 1
pos += block_length
if pos < length:
self.write_bits(0, 1)
self.write_bits(0, 2)
self.align()
def write_zlib_header(self, wbits: t.CInt, level: t.CInt):
cinfo: t.CInt = wbits - 8
if cinfo < 1: cinfo = 1
if cinfo > 7: cinfo = 7
cmf: t.CUnsignedChar = t.CUnsignedChar((cinfo << 4) | 8)
flevel: t.CInt = 0
if level >= 5: flevel = 3
elif level >= 3: flevel = 1
flg: t.CUnsignedChar = t.CUnsignedChar(flevel << 6)
flg |= t.CUnsignedChar(31 - (cmf * 256 + flg) % 31)
self.buf[self.byte_pos + 0] = cmf
self.buf[self.byte_pos + 1] = flg
self.byte_pos += 2
def write_gzip_header(self):
self.buf[self.byte_pos + 0] = 0x1F
self.buf[self.byte_pos + 1] = 0x8B
self.buf[self.byte_pos + 2] = 0x08
self.buf[self.byte_pos + 3] = 0x00
self.buf[self.byte_pos + 4] = 0x00
self.buf[self.byte_pos + 5] = 0x00
self.buf[self.byte_pos + 6] = 0x00
self.buf[self.byte_pos + 7] = 0x00
self.buf[self.byte_pos + 8] = 0x00
self.buf[self.byte_pos + 9] = 0xFF
self.byte_pos += 10
def align(self):
if self.bit_pos > 0:
self.bit_pos = 0
self.byte_pos += 1
def total(self) -> t.CSizeT:
return self.byte_pos + (1 if (self.bit_pos > 0) else 0)
def free(self):
if self.pool == None:
free(self.buf)
else:
self.pool.free(self.buf)
self.buf = None
self.cap = 0
self.byte_pos = 0
self.bit_pos = 0
def __del__(self):
self.free()
# ============================================================
# Bit reader - reads bits LSB first from a byte buffer
# ============================================================
@t.Object
class zbit_reader:
buf: BYTE | t.CPtr
length: t.CSizeT
byte_pos: t.CSizeT
bit_pos: t.CInt
def init(self, buf: BYTE | t.CPtr, length: t.CSizeT):
self.buf = buf
self.length = length
self.byte_pos = 0
self.bit_pos = 0
def read_bits(self, nbits: t.CInt, out: UINTPTR) -> t.CInt:
val: UINT = 0
for i in range(nbits):
if self.byte_pos >= self.length: return -1
if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos):
val |= (UINT(1) << i)
self.bit_pos += 1
if self.bit_pos == 8:
self.bit_pos = 0
self.byte_pos += 1
c.Set(c.Deref(out), val)
return 0
def read_bits_rev(self, nbits: t.CInt, out: UINTPTR) -> t.CInt:
val: UINT = 0
for i in range(nbits - 1, 0, -1):
if self.byte_pos >= self.length: return -1
if self.buf[self.byte_pos] & (UINT(1) << self.bit_pos):
val |= (UINT(1) << i)
self.bit_pos += 1
if self.bit_pos == 8:
self.bit_pos = 0
self.byte_pos += 1
c.Set(c.Deref(out), val)
return 0
def align(self):
if self.bit_pos > 0:
self.bit_pos = 0
self.byte_pos += 1
# ============================================================
# Memory allocation helper for bare metal
# Can be replaced with custom allocator
# ============================================================
def zdef_alloc(pool: memhub.MemManager | t.CPtr, n: t.CSizeT) -> VOIDPTR:
if pool == None: return malloc(n)
return pool.alloc(n)
def zdef_free(pool: memhub.MemManager | t.CPtr, p: VOIDPTR):
if pool == None:
free(p)
return
pool.free(p)
+434
View File
@@ -0,0 +1,434 @@
from stdint import *
import zlib.zchecksum as zchecksum
import zlib.zhuff as zhuff
import zlib.zdef as zdef
import string
import memhub
import t, c
@t.Object
class zdeflate_stream:
pool: memhub.MemManager | t.CPtr
writer: zdef.zbit_writer
window: BYTE | t.CPtr
window_pos: t.CInt
window_size: t.CInt
hash_head: t.CInt | t.CPtr
hash_prev: t.CInt | t.CPtr
level: t.CInt
strategy: t.CInt
wbits: t.CInt
is_finished: t.CInt
adler: t.CUInt32T
def find_match(self, data: BYTE | t.CPtr, data_len: t.CSizeT,
pos: t.CSizeT, best_dist: t.CInt | t.CPtr) -> t.CInt:
if pos + 2 >= data_len: return 0
h: t.CUnsignedInt = zdeflate_hash(data + pos)
chain: t.CInt = self.hash_head[h]
best_len: t.CInt = zdef.ZDEFLATE_MIN_MATCH - 1
c.Set(c.Deref(best_dist), 0)
max_chain: t.CInt = 128 if (self.level >= 5) else (32 if (self.level >= 2) else 4)
limit: t.CInt = (1 << self.wbits) if (self.wbits > 0) else zdef.ZDEFLATE_WINDOW_SIZE
if limit > zdef.ZDEFLATE_WINDOW_SIZE:
limit = zdef.ZDEFLATE_WINDOW_SIZE
attempts: t.CInt = 0
while chain >= 0 and attempts < max_chain:
dist: t.CInt = t.CInt(pos) - chain
if dist <= 0 or dist > limit: break
match_len: t.CInt = 0
max_len: t.CInt = t.CInt(data_len - pos)
if max_len > zdef.ZDEFLATE_MAX_MATCH:
max_len = zdef.ZDEFLATE_MAX_MATCH
while match_len < max_len and data[pos + match_len] == data[chain + match_len]:
match_len += 1
if match_len > best_len:
best_len = match_len
c.Set(c.Deref(best_dist), dist)
if best_len >= zdef.ZDEFLATE_MAX_MATCH: break
chain = self.hash_prev[chain & zdef.ZDEFLATE_WINDOW_MASK]
if chain <= t.CInt(pos) - limit: break
attempts += 1
return best_len if (best_len >= zdef.ZDEFLATE_MIN_MATCH) else 0
def update_hash(self, data: BYTE | t.CPtr, pos: t.CSizeT):
if pos + 2 < pos: return
h: t.CUnsignedInt = zdeflate_hash(data + pos)
self.hash_prev[pos & zdef.ZDEFLATE_WINDOW_MASK] = self.hash_head[h]
self.hash_head[h] = t.CInt(pos)
def write_fixed_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
lit_tree = zhuff.zhuff_tree()
dist_tree = zhuff.zhuff_tree()
lit_tree.build_fixed_lit_tree()
dist_tree.build_fixed_dist_tree()
self.writer.write_bits(1 if final else 0, 1)
self.writer.write_bits(1, 2)
pos: t.CSizeT = 0
while pos < length:
best_dist: t.CInt = 0
match_len: t.CInt = 0
if self.level > 0 and pos + 2 < length:
match_len = self.find_match(data, length, pos, c.Addr(best_dist))
if match_len >= zdef.ZDEFLATE_MIN_MATCH:
len_sym: t.CInt = zdeflate_len_to_symbol(match_len)
lit_tree.encode_symbol(len_sym, c.Addr(self.writer))
extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257]
if extra > 0:
self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra)
dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist)
dist_tree.encode_symbol(dist_sym, c.Addr(self.writer))
extra = zdef.zdeflate_dist_extra_bits[dist_sym]
if extra > 0:
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
for i in range(match_len):
self.update_hash(data, pos + i)
pos += match_len
else:
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
self.update_hash(data, pos)
pos += 1
lit_tree.encode_symbol(256, c.Addr(self.writer))
def encode_block_data(self, data: UINT8PTR, length: t.CSizeT,
lit_tree: zhuff.zhuff_tree | t.CPtr, dist_tree: zhuff.zhuff_tree | t.CPtr):
pos: t.CSizeT = 0
while pos < length:
best_dist: t.CInt = 0
match_len: t.CInt = 0
if self.level > 0 and pos + 2 < length:
match_len = self.find_match(data, length, pos, c.Addr(best_dist))
if match_len >= zdef.ZDEFLATE_MIN_MATCH:
len_sym: t.CInt = zdeflate_len_to_symbol(match_len)
lit_tree.encode_symbol(len_sym, c.Addr(self.writer))
extra: t.CInt = zdef.zdeflate_len_extra_bits[len_sym - 257]
if extra > 0:
self.writer.write_bits(match_len - zdef.zdeflate_len_base[len_sym - 257], extra)
dist_sym: t.CInt = zdeflate_dist_to_symbol(best_dist)
dist_tree.encode_symbol(dist_sym, c.Addr(self.writer))
extra = zdef.zdeflate_dist_extra_bits[dist_sym]
if extra > 0:
self.writer.write_bits(best_dist - zdef.zdeflate_dist_base[dist_sym], extra)
for j in range(match_len):
self.update_hash(data, pos + j)
pos += match_len
else:
lit_tree.encode_symbol(data[pos], c.Addr(self.writer))
self.update_hash(data, pos)
pos += 1
lit_tree.encode_symbol(256, c.Addr(self.writer))
def write_dynamic_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
lit_freqs: t.CArray[t.CInt, 288]
dist_freqs: t.CArray[t.CInt, 32]
zdeflate_count_freqs(lit_freqs, dist_freqs, self, data, length)
hlit: t.CInt = 286
while hlit > 257 and lit_freqs[hlit - 1] == 0: hlit -= 1
hdist: t.CInt = 30
while hdist > 1 and dist_freqs[hdist - 1] == 0: hdist -= 1
lit_tree = zhuff.zhuff_tree()
dist_tree = zhuff.zhuff_tree()
lit_tree.build_codes(lit_freqs, hlit, zdef.ZDEFLATE_MAX_BITS)
dist_tree.build_codes(dist_freqs, hdist, zdef.ZDEFLATE_MAX_BITS)
all_lengths: t.CArray[t.CInt, 288 + 32]
for i in range(hlit): all_lengths[i] = lit_tree.codes[i].bits
for i in range(hdist): all_lengths[hlit + i] = dist_tree.codes[i].bits
total_lengths: t.CInt = hlit + hdist
cl_freqs: t.CArray[t.CInt, 19]
zdeflate_count_cl_freqs(all_lengths, total_lengths, cl_freqs)
cl_tree = zhuff.zhuff_tree()
cl_tree.build_codes(cl_freqs, 19, 7)
hclen: int = 19
while hclen > 4 and cl_tree.codes[zdef.zdeflate_codelen_order[hclen - 1]].bits == 0: hclen -= 1
self.writer.write_bits(1 if final else 0, 1)
self.writer.write_bits(2, 2)
self.writer.write_bits(hlit - 257, 5)
self.writer.write_bits(hdist - 1, 5)
self.writer.write_bits(hclen - 4, 4)
for j in range(hclen):
self.writer.write_bits(cl_tree.codes[zdef.zdeflate_codelen_order[j]].bits, 3)
zdeflate_write_cl_encoded(all_lengths, total_lengths, c.Addr(self.writer), c.Addr(cl_tree))
self.encode_block_data(data, length, c.Addr(lit_tree), c.Addr(dist_tree))
def compress_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
if self.level == 0:
self.write_stored_block(data, length, final)
elif self.strategy == 4 or length < 128:
self.write_fixed_block(data, length, final)
else:
self.write_dynamic_block(data, length, final)
def write_stored_block(self, data: UINT8PTR, length: t.CSizeT, final: t.CInt):
self.writer.stored_block(data, length, final)
def compress(self, data: UINT8PTR, length: t.CSizeT,
out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
if self.is_finished: return -2
if not data or length == 0:
c.Set(c.Deref(out), None)
c.Set(c.Deref(out_len), 0)
return 0
self.adler = zchecksum.zchecksum_adler32(data, length, self.adler)
memset(self.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())
memset(self.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())
self.compress_block(data, length, 0)
c.Set(c.Deref(out_len), self.writer.total())
c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(self.pool, c.Deref(out_len))))
if not c.Deref(out): return -4
memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len))
return 0
def flush(self, mode: t.CInt, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
if mode == 4:
if not self.is_finished:
if self.level == 0:
self.writer.write_bits(1, 1)
self.writer.write_bits(0, 2)
self.writer.align()
else:
lit_tree = zhuff.zhuff_tree()
lit_tree.build_fixed_lit_tree()
self.writer.write_bits(1, 1)
self.writer.write_bits(1, 2)
lit_tree.encode_symbol(256, c.Addr(self.writer))
self.is_finished = 1
if self.wbits >= 0:
self.writer.align()
adler: t.CUInt32T = self.adler
self.writer.buf[self.writer.byte_pos + 0] = (adler >> 24) & 0xFF
self.writer.buf[self.writer.byte_pos + 1] = (adler >> 16) & 0xFF
self.writer.buf[self.writer.byte_pos + 2] = (adler >> 8) & 0xFF
self.writer.buf[self.writer.byte_pos + 3] = (adler >> 0) & 0xFF
self.writer.byte_pos += 4
elif mode == 2 or mode == 3:
self.writer.write_bits(0, 1)
self.writer.write_bits(0, 2)
self.writer.align()
c.Set(c.Deref(out_len), self.writer.total())
c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(self.pool, c.Deref(out_len))))
if not c.Deref(out): return -4
memcpy(c.Deref(out), self.writer.buf, c.Deref(out_len))
return 0
def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt:
if not dict: return -2
use: t.CSizeT = length
if use > zdef.ZDEFLATE_WINDOW_SIZE:
dict += length - zdef.ZDEFLATE_WINDOW_SIZE
use = zdef.ZDEFLATE_WINDOW_SIZE
memcpy(self.window, dict, use)
self.window_size = t.CInt(use)
self.window_pos = t.CInt(use)
self.adler = zchecksum.zchecksum_adler32(dict, length, self.adler)
return 0
def copy(self) -> zdeflate_stream | t.CPtr:
z: zdeflate_stream | t.CPtr = zdef.zdef_alloc(self.pool, zdeflate_stream.__sizeof__())
if not z: return None
memcpy(z, self, zdeflate_stream.__sizeof__())
z.writer.buf = BYTEPTR(zdef.zdef_alloc(self.pool, self.writer.cap))
if not z.writer.buf:
zdef.zdef_free(self.pool, z)
return None
memcpy(z.writer.buf, self.writer.buf, self.writer.cap)
z.window = BYTEPTR(zdef.zdef_alloc(self.pool, zdef.ZDEFLATE_WINDOW_SIZE))
z.hash_head = INTPTR(zdef.zdef_alloc(self.pool, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()))
z.hash_prev = INTPTR(zdef.zdef_alloc(self.pool, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()))
if not z.window or not z.hash_head or not z.hash_prev:
if z.writer.buf: zdef.zdef_free(self.pool, z.writer.buf)
zdef.zdef_free(self.pool, z)
return None
memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE)
memcpy(z.hash_head, self.hash_head, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())
memcpy(z.hash_prev, self.hash_prev, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())
return z
def destroy(self):
if self.writer.buf: zdef.zdef_free(self.pool, self.writer.buf)
if self.window: zdef.zdef_free(self.pool, self.window)
if self.hash_head: zdef.zdef_free(self.pool, self.hash_head)
if self.hash_prev: zdef.zdef_free(self.pool, self.hash_prev)
zdef.zdef_free(self.pool, self)
def zdeflate_count_freqs(lit_freqs: INTPTR, dist_freqs: INTPTR,
s: zdeflate_stream | t.CPtr, data: UINT8PTR, length: t.CSizeT):
memset(lit_freqs, 0, 288 * int.__sizeof__())
memset(dist_freqs, 0, 32 * int.__sizeof__())
pos: t.CSizeT = 0
while pos < length:
best_dist: t.CInt = 0
match_len: t.CInt = 0
if s.level > 0 and pos + 2 < length:
match_len = zdeflate_stream.find_match(s, data, length, pos, c.Addr(best_dist))
if match_len >= zdef.ZDEFLATE_MIN_MATCH:
len_sym: t.CInt = zdeflate_len_to_symbol(match_len)
lit_freqs[len_sym] += 1
dist_freqs[zdeflate_dist_to_symbol(best_dist)] += 1
for i in range(match_len):
zdeflate_stream.update_hash(s, data, pos + i)
pos += match_len
else:
lit_freqs[data[pos]] += 1
zdeflate_stream.update_hash(s, data, pos)
pos += 1
lit_freqs[256] = 1
def zdeflate_hash(p: BYTE | t.CPtr) -> t.CUnsignedInt:
return (t.CUnsignedInt(p[0]) ^ (t.CUnsignedInt(p[1]) << 5) ^ (t.CUnsignedInt(p[2]) << 10)) & zdef.ZDEFLATE_HASH_MASK
def zdeflate_len_to_symbol(length: t.CInt) -> t.CInt:
for i in range(29):
if length <= zdef.zdeflate_len_base[i] + (1 << zdef.zdeflate_len_extra_bits[i]) - 1:
return 257 + i
return 285
def zdeflate_dist_to_symbol(dist: t.CInt) -> t.CInt:
for i in range(30):
if dist <= zdef.zdeflate_dist_base[i] + (1 << zdef.zdeflate_dist_extra_bits[i]) - 1:
return i
return 29
def zdeflate_count_cl_freqs(all_lengths: INTPTR, total: t.CInt, cl_freqs: INTPTR):
memset(cl_freqs, 0, 19 * int.__sizeof__())
i: t.CInt = 0
while i < total:
if all_lengths[i] == 0:
run: t.CInt = 0
while i + run < total and all_lengths[i + run] == 0: run += 1
while run > 0:
if run >= 11:
count: t.CInt = run
if count > 138: count = 138
cl_freqs[18] += 1
run -= count
elif run >= 3:
count: t.CInt = run
if count > 10: count = 10
cl_freqs[17] += 1
run -= count
else:
cl_freqs[0] += 1
run -= 1
while i < total and all_lengths[i] == 0: i += 1
else:
cl_freqs[all_lengths[i]] += 1
val: t.CInt = all_lengths[i]
i += 1
run: t.CInt = 0
while i + run < total and all_lengths[i + run] == val: run += 1
while run >= 3:
count: t.CInt = run
if count > 6: count = 6
cl_freqs[16] += 1
run -= count
i += run
def zdeflate_write_cl_encoded(all_lengths: INTPTR, total: t.CInt,
w: zdef.zbit_writer | t.CPtr, cl_tree: zhuff.zhuff_tree | t.CPtr):
i: t.CInt = 0
while i < total:
if all_lengths[i] == 0:
run: t.CInt = 0
while i + run < total and all_lengths[i + run] == 0: run += 1
while run > 0:
if run >= 11:
count: t.CInt = run
if count > 138: count = 138
cl_tree.encode_symbol(18, w)
w.write_bits(count - 11, 7)
run -= count
elif run >= 3:
count: t.CInt = run
if count > 10: count = 10
cl_tree.encode_symbol(17, w)
w.write_bits(count - 3, 3)
run -= count
else:
cl_tree.encode_symbol(0, w)
run -= 1
while i < total and all_lengths[i] == 0: i += 1
else:
cl_tree.encode_symbol(all_lengths[i], w)
val: t.CInt = all_lengths[i]
i += 1
run: t.CInt = 0
while i + run < total and all_lengths[i + run] == val: run += 1
while run >= 3:
count: t.CInt = run
if count > 6: count = 6
cl_tree.encode_symbol(16, w)
w.write_bits(count - 3, 2)
run -= count
i += run
def zdeflate_create(pool: memhub.MemManager | t.CPtr, level: t.CInt, wbits: t.CInt, mem_level: t.CInt, strategy: t.CInt) -> zdeflate_stream | t.CPtr:
n: t.CSizeT = zdeflate_stream.__sizeof__()
s: zdeflate_stream | t.CPtr = zdef.zdef_alloc(pool, n)
if not s: return None
memset(s, 0, zdeflate_stream.__sizeof__())
s.pool = pool
s.writer = zdef.zbit_writer(pool)
s.window = BYTEPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_WINDOW_SIZE))
s.hash_head = INTPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__()))
s.hash_prev = INTPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__()))
if not s.window or not s.hash_head or not s.hash_prev:
s.destroy()
return None
memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())
memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())
s.level = level
s.wbits = wbits
s.strategy = strategy
s.is_finished = 0
s.adler = 1
if wbits > 0:
s.writer.write_zlib_header(wbits, level)
elif wbits == 0:
s.writer.write_zlib_header(15, level)
return s
def zdeflate_one_shot(pool: memhub.MemManager | t.CPtr, data: UINT8PTR, length: t.CSizeT,
level: t.CInt, wbits: t.CInt, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr:
s: zdeflate_stream | t.CPtr = zdeflate_create(pool, level, wbits, 8, 0)
if not s: return None
memset(s.hash_head, -1, zdef.ZDEFLATE_HASH_SIZE * int.__sizeof__())
memset(s.hash_prev, -1, zdef.ZDEFLATE_WINDOW_SIZE * int.__sizeof__())
s.adler = zchecksum.zchecksum_adler32(data, length, 1)
if length == 0:
s.writer.write_bits(1, 1)
s.writer.write_bits(1, 2)
lit_tree = zhuff.zhuff_tree()
lit_tree.build_fixed_lit_tree()
lit_tree.encode_symbol(256, c.Addr(s.writer))
else:
s.compress_block(data, length, 1)
s.is_finished = 1
if wbits >= 0:
s.writer.align()
adler: t.CUInt32T = s.adler
s.writer.buf[s.writer.byte_pos + 0] = (adler >> 24) & 0xFF
s.writer.buf[s.writer.byte_pos + 1] = (adler >> 16) & 0xFF
s.writer.buf[s.writer.byte_pos + 2] = (adler >> 8) & 0xFF
s.writer.buf[s.writer.byte_pos + 3] = (adler >> 0) & 0xFF
s.writer.byte_pos += 4
c.Set(c.Deref(out_len), s.writer.total())
result: UINT8PTR = UINT8PTR(zdef.zdef_alloc(pool, c.Deref(out_len)))
if result: memcpy(result, s.writer.buf, c.Deref(out_len))
s.destroy()
return result
+356
View File
@@ -0,0 +1,356 @@
#include <string.h>
from stdint import *
import zlib.zdef as zdef
import memhub
import t, c
ZHUFF_MAX_CODES: t.CDefine = 288
ZHUFF_MAX_BITS: t.CDefine = 15
class zhuff_code:
code: UINT
bits: t.CInt
@t.Object
class zhuff_tree:
pool: memhub.MemManager | t.CPtr
codes: t.CArray[zhuff_code, ZHUFF_MAX_CODES]
count: t.CInt
max_bits: t.CInt
def __init__(self):
self.pool = None
def build_codes(self, freqs: INTPTR, count: t.CInt, max_bits: t.CInt):
lengths: t.CArray[t.CInt, ZHUFF_MAX_CODES]
bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 1]
next_code: t.CArray[UINT, ZHUFF_MAX_BITS + 1]
self.count = count
self.max_bits = max_bits
self.build_code_lengths(lengths, freqs, count, max_bits)
memset(bl_count, 0, bl_count.__sizeof__())
for i in range(count):
if lengths[i] > 0:
bl_count[lengths[i]] += 1
code: t.CUnsignedInt = 0
next_code[0] = 0
for bits in range(1, max_bits + 1):
code = (code + bl_count[bits - 1]) << 1
next_code[bits] = code
for i in range(count):
self.codes[i].bits = lengths[i]
if lengths[i] > 0:
self.codes[i].code = next_code[lengths[i]]
next_code[lengths[i]] += 1
else:
self.codes[i].code = 0
def build_fixed_lit_tree(self):
lengths: t.CArray[t.CInt, 288]
bl_count: t.CArray[t.CInt, 16]
next_code: t.CArray[t.CUnsignedInt, 16]
self.get_fixed_lit_lengths(lengths)
memset(bl_count, 0, bl_count.__sizeof__())
for i in range(288):
if lengths[i] > 0:
bl_count[lengths[i]] += 1
code: t.CUnsignedInt = 0
next_code[0] = 0
for bits in range(1, 9 + 1):
code = (code + bl_count[bits - 1]) << 1
next_code[bits] = code
self.count = 288
self.max_bits = 9
for i in range(288):
self.codes[i].bits = lengths[i]
if lengths[i] > 0:
self.codes[i].code = next_code[lengths[i]]
next_code[lengths[i]] += 1
else:
self.codes[i].code = 0
def build_fixed_dist_tree(self):
lengths: t.CArray[t.CInt, 32]
bl_count: t.CArray[t.CInt, 16]
next_code: t.CArray[t.CUnsignedInt, 16]
self.get_fixed_dist_lengths(lengths)
memset(bl_count, 0, bl_count.__sizeof__())
for i in range(32):
if lengths[i] > 0:
bl_count[lengths[i]] += 1
code: t.CUnsignedInt = 0
next_code[0] = 0
for bits in range(1, 5 + 1):
code = (code + bl_count[bits - 1]) << 1
next_code[bits] = code
self.count = 32
self.max_bits = 5
for i in range(32):
self.codes[i].bits = lengths[i]
if lengths[i] > 0:
self.codes[i].code = next_code[lengths[i]]
next_code[lengths[i]] += 1
else:
self.codes[i].code = 0
def encode_symbol(self, symbol: int, writer: zdef.zbit_writer | t.CPtr):
if symbol < 0 or symbol >= self.count:
return
if self.codes[symbol].bits == 0:
return
writer.write_bits_rev(self.codes[symbol].code, self.codes[symbol].bits)
def build_code_lengths(self, lengths: t.CInt | t.CPtr, freqs: t.CInt | t.CPtr, count: t.CInt, max_bits: t.CInt):
bl_count: t.CArray[t.CInt, ZHUFF_MAX_BITS + 2]
sort_count: t.CInt = 0
memset(bl_count, 0, bl_count.__sizeof__())
memset(lengths, 0, int.__sizeof__() * count)
for i in range(count):
if freqs[i] > 0:
sort_count += 1
if sort_count == 0: return
if sort_count == 1:
for i in range(count):
if freqs[i] > 0:
lengths[i] = 1
return
items: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(self.pool, sort_count * int.__sizeof__()))
item_freqs: t.CInt | t.CPtr = INTPTR(zdef.zdef_alloc(self.pool, sort_count * int.__sizeof__()))
idx: t.CInt = 0
for i in range(count):
if freqs[i] > 0:
items[idx] = i
item_freqs[idx] = freqs[i]
idx += 1
for i in range(sort_count):
key_item: t.CInt = items[i]
key_freq: t.CInt = item_freqs[i]
j: t.CInt = i - 1
while j >= 0 and item_freqs[j] > key_freq:
items[j + 1] = items[j]
item_freqs[j + 1] = item_freqs[j]
j -= 1
items[j + 1] = key_item
item_freqs[j + 1] = key_freq
parent: INTPTR = INTPTR(zdef.zdef_alloc(self.pool, (sort_count * 2) * int.__sizeof__()))
for i in range(sort_count * 2):
parent[i] = -1
heap: INTPTR = INTPTR(zdef.zdef_alloc(self.pool, (sort_count + 1) * int.__sizeof__()))
heap_size: t.CInt = 0
for i in range(sort_count):
heap[heap_size] = i
heap_size += 1
pos: t.CInt = heap_size - 1
while pos > 0:
par: t.CInt = (pos - 1) / 2
if item_freqs[heap[par]] > item_freqs[heap[pos]]:
tmp: t.CInt = heap[par]
heap[par] = heap[pos]
heap[pos] = tmp
pos = par
else: break
combined_freq: INTPTR = INTPTR(zdef.zdef_alloc(self.pool, (sort_count * 2) * int.__sizeof__()))
for i in range(sort_count):
combined_freq[i] = item_freqs[i]
internal: t.CInt = sort_count
while heap_size > 1:
a: t.CInt = heap[0]
heap[0] = heap[heap_size - 1]
heap_size -= 1
pos: t.CInt = 0
while True:
left: t.CInt = 2 * pos + 1
right: t.CInt = 2 * pos + 2
smallest: t.CInt = pos
if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]:
smallest = left
if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]:
smallest = right
if smallest != pos:
tmp: t.CInt = heap[pos]
heap[pos] = heap[smallest]
heap[smallest] = tmp
pos = smallest
else: break
b: t.CInt = heap[0]
heap[0] = heap[heap_size - 1]
heap_size -= 1
pos = 0
while True:
left: t.CInt = 2 * pos + 1
right: t.CInt = 2 * pos + 2
smallest: t.CInt = pos
if left < heap_size and combined_freq[heap[left]] < combined_freq[heap[smallest]]:
smallest = left
if right < heap_size and combined_freq[heap[right]] < combined_freq[heap[smallest]]:
smallest = right
if smallest != pos:
tmp: t.CInt = heap[pos]
heap[pos] = heap[smallest]
heap[smallest] = tmp
pos = smallest
else: break
if internal >= sort_count * 2 - 1: break
combined_freq[internal] = combined_freq[a] + combined_freq[b]
parent[a] = internal
parent[b] = internal
heap[heap_size] = internal
heap_size += 1
pos = heap_size - 1
while pos > 0:
par: t.CInt = (pos - 1) / 2
if combined_freq[heap[par]] > combined_freq[heap[pos]]:
tmp: t.CInt = heap[par]
heap[par] = heap[pos]
heap[pos] = tmp
pos = par
else: break
internal += 1
for i in range(sort_count):
node: t.CInt = i
length: t.CInt = 0
while parent[node] >= 0:
length += 1
node = parent[node]
lengths[items[i]] = length
memset(bl_count, 0, bl_count.__sizeof__())
for i in range(count):
if lengths[i] > 0:
bl_count[lengths[i]] += 1
overflow: t.CInt = 0
for i in range(count):
if lengths[i] > max_bits:
overflow += 1
bl_count[lengths[i]] -= 1
lengths[i] = max_bits
bl_count[max_bits] += 1
while overflow > 0:
bits: t.CInt = max_bits - 1
while bits > 0 and bl_count[bits] == 0:
bits -= 1
if bits == 0: break
bl_count[bits] -= 1
bl_count[bits + 1] += 2
bl_count[max_bits] -= 1
overflow -= 2
sorted_items: INTPTR = INTPTR(zdef.zdef_alloc(self.pool, sort_count * int.__sizeof__()))
si: t.CInt = 0
for i in range(count):
if freqs[i] > 0:
sorted_items[si] = i
si += 1
for i in range(si - 1):
for j in range(i + 1, si):
if lengths[sorted_items[i]] < lengths[sorted_items[j]]:
tmp: t.CInt = sorted_items[i]
sorted_items[i] = sorted_items[j]
sorted_items[j] = tmp
sidx: t.CInt = 0
for bits in range(max_bits, 1, -1):
n: t.CInt = bl_count[bits]
while n > 0 and sidx < si:
lengths[sorted_items[sidx]] = bits
sidx += 1
n -= 1
zdef.zdef_free(self.pool, sorted_items)
zdef.zdef_free(self.pool, heap)
zdef.zdef_free(self.pool, parent)
zdef.zdef_free(self.pool, combined_freq)
zdef.zdef_free(self.pool, item_freqs)
zdef.zdef_free(self.pool, items)
def get_fixed_lit_lengths(self, lengths: INTPTR):
for i in range( 0, 143 + 1): lengths[i] = 8
for i in range(143 + 1, 255 + 1): lengths[i] = 9
for i in range(255 + 1, 279 + 1): lengths[i] = 7
for i in range(279 + 1, 287 + 1): lengths[i] = 8
def get_fixed_dist_lengths(self, lengths: INTPTR):
for i in range(32):
lengths[i] = 5
def build_tree_from_lengths(self, lengths: INTPTR, count: t.CInt, max_bits: t.CInt):
bl_count: t.CArray[t.CInt, 16]
next_code: t.CArray[t.CUnsignedInt, 16]
memset(bl_count, 0, bl_count.__sizeof__())
for i in range(count):
if lengths[i] > 0:
bl_count[lengths[i]] += 1
code: UINT = 0
next_code[0] = 0
for bits in range(1, max_bits + 1):
code = (code + bl_count[bits - 1]) << 1
next_code[bits] = code
self.count = count
self.max_bits = max_bits
for i in range(count):
self.codes[i].bits = lengths[i]
if lengths[i] > 0:
self.codes[i].code = next_code[lengths[i]]
next_code[lengths[i]] += 1
else:
self.codes[i].code = 0
class zhuff_decode_node:
children: t.CArray[t.CInt, 2]
symbol: t.CInt
@t.Object
class zhuff_decode_tree:
pool: memhub.MemManager | t.CPtr
nodes: t.CArray[zhuff_decode_node, 2 * ZHUFF_MAX_CODES]
node_count: t.CInt
root: t.CInt
def __init__(self):
self.pool = None
def build_decode_tree(self, ht: zhuff_tree | t.CPtr):
self.node_count = 1
self.root = 0
self.nodes[0].children[0] = -1
self.nodes[0].children[1] = -1
self.nodes[0].symbol = -1
for i in range(ht.count):
if ht.codes[i].bits == 0: continue
node: int = 0
for bit in range(ht.codes[i].bits - 1, -1, -1):
dir: t.CInt = (ht.codes[i].code >> bit) & 1
if bit > 0:
# Internal node: traverse or create
if self.nodes[node].children[dir] == -1:
new_node: int = self.node_count
self.node_count += 1
self.nodes[new_node].children[0] = -1
self.nodes[new_node].children[1] = -1
self.nodes[new_node].symbol = -1
self.nodes[node].children[dir] = new_node
node = self.nodes[node].children[dir]
else:
# Leaf: bit 0 - set symbol on the child
if self.nodes[node].children[dir] == -1:
leaf: int = self.node_count
self.node_count += 1
self.nodes[leaf].children[0] = -1
self.nodes[leaf].children[1] = -1
self.nodes[leaf].symbol = i
self.nodes[node].children[dir] = leaf
else:
self.nodes[self.nodes[node].children[dir]].symbol = i
def decode_symbol(self, reader: zdef.zbit_reader | t.CPtr) -> t.CInt:
node: int = self.root
while self.nodes[node].symbol == -1:
bit: t.CUnsignedInt
if reader.read_bits(1, c.Addr(bit)) != 0: return -1
dir: t.CInt = t.CInt(bit)
if self.nodes[node].children[dir] == -1: return -1
node = self.nodes[node].children[dir]
return self.nodes[node].symbol
+456
View File
@@ -0,0 +1,456 @@
from stdint import *
import zlib.zchecksum as zchecksum
import zlib.zdef as zdef
import zlib.zhuff as zhuff
import string
import memhub
import t, c
@t.Object
class zinflate_stream:
pool: memhub.MemManager | t.CPtr
reader: zdef.zbit_reader
window: BYTEPTR
window_pos: t.CInt
window_size: t.CInt
wbits: t.CInt
is_finished: t.CInt
is_initialized: t.CInt
header_parsed: t.CInt
is_gzip: t.CInt
adler: t.CUInt32T
crc: t.CUInt32T
output: BYTEPTR
output_len: t.CSizeT
output_cap: t.CSizeT
input_data: t.CConst | BYTEPTR
input_len: t.CSizeT
input_pos: t.CSizeT
max_length: t.CSizeT
def __init__(self):
pass
def output_byte(self, byte: BYTE):
if self.max_length > 0 and self.output_len >= self.max_length: return
if self.output_len >= self.output_cap:
new_cap: t.CSizeT = self.output_cap * 2
if new_cap < 256: new_cap = 256
new_buf: BYTEPTR = BYTEPTR(zdef.zdef_alloc(self.pool, new_cap))
if not new_buf: return
memcpy(new_buf, self.output, self.output_len)
zdef.zdef_free(self.pool, self.output)
self.output = new_buf
self.output_cap = new_cap
self.output[self.output_len] = byte
self.output_len += 1
self.window[self.window_pos & (zdef.ZDEFLATE_WINDOW_SIZE - 1)] = byte
self.window_pos += 1
def parse_header(self) -> t.CInt:
if self.header_parsed: return 0
if self.wbits < 0:
self.header_parsed = 1
self.is_gzip = 0
return 0
if self.input_pos + 2 > self.input_len: return -3
b0: BYTE = self.input_data[self.input_pos]
b1: BYTE = self.input_data[self.input_pos + 1]
if b0 == 0x1F and b1 == 0x8B:
self.is_gzip = 1
if self.input_pos + 10 > self.input_len: return -3
self.input_pos += 10
flg: BYTE = self.input_data[self.input_pos - 6]
if flg & 0x04:
if self.input_pos + 2 > self.input_len: return -3
xlen: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8)
self.input_pos += 2 + xlen
if flg & 0x08:
while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1
self.input_pos += 1
if flg & 0x10:
while self.input_pos < self.input_len and self.input_data[self.input_pos] != 0: self.input_pos += 1
self.input_pos += 1
if flg & 0x02:
self.input_pos += 2
if self.input_pos > self.input_len: return -3
else:
self.is_gzip = 0
if (b0 * 256 + b1) % 31 != 0: return -3
cm: t.CInt = b0 & 0x0F
if cm != 8: return -3
self.input_pos += 2
self.header_parsed = 1
return 0
def read_bits_from_input(self, nbits: t.CInt, out: UINTPTR) -> t.CInt:
val: UINT = 0
for i in range(nbits):
if self.input_pos >= self.input_len: return -3
if self.input_data[self.input_pos] & (UINT(1) << (self.reader.bit_pos)):
val |= (UINT(1) << i)
self.reader.bit_pos += 1
if self.reader.bit_pos == 8:
self.reader.bit_pos = 0
self.input_pos += 1
c.Set(c.Deref(out), val)
return 0
def read_huffman(self, dt: zhuff.zhuff_decode_tree | t.CPtr) -> t.CInt:
node: int = dt.root
while dt.nodes[node].symbol == -1:
bit: UINT
if self.read_bits_from_input(1, c.Addr(bit)) != 0: return -1
dir: int = t.CInt(bit)
if dt.nodes[node].children[dir] == -1: return -3
node = dt.nodes[node].children[dir]
return dt.nodes[node].symbol
def inflate_block_stored(self) -> t.CInt:
if self.reader.bit_pos != 0:
self.reader.bit_pos = 0
self.input_pos += 1
if self.input_pos + 4 > self.input_len: return -3
length: UINT = self.input_data[self.input_pos] | (self.input_data[self.input_pos + 1] << 8)
nlen: UINT = self.input_data[self.input_pos + 2] | (self.input_data[self.input_pos + 3] << 8)
self.input_pos += 4
if (length ^ nlen) != 0xFFFF: return -3
if self.input_pos + length > self.input_len: return -3
i: t.CUnsignedInt
for i in range(length):
self.output_byte(self.input_data[self.input_pos])
self.input_pos += 1
return 0
def inflate_block_fixed(self) -> t.CInt:
lit_tree = zhuff.zhuff_tree()
dist_tree = zhuff.zhuff_tree()
lit_tree.build_fixed_lit_tree()
dist_tree.build_fixed_dist_tree()
lit_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(self.pool, zhuff.zhuff_decode_tree.__sizeof__())
dist_dt: zhuff.zhuff_decode_tree | t.CPtr = zdef.zdef_alloc(self.pool, zhuff.zhuff_decode_tree.__sizeof__())
if not lit_dt or not dist_dt:
if lit_dt: zdef.zdef_free(self.pool, lit_dt)
if dist_dt: zdef.zdef_free(self.pool, dist_dt)
return -4
memset(lit_dt, 0, zhuff.zhuff_decode_tree.__sizeof__())
memset(dist_dt, 0, zhuff.zhuff_decode_tree.__sizeof__())
lit_dt.build_decode_tree(c.Addr(lit_tree))
dist_dt.build_decode_tree(c.Addr(dist_tree))
result: t.CInt = 0
while True:
if self.max_length > 0 and self.output_len >= self.max_length: break
sym: t.CInt = self.read_huffman(lit_dt)
if sym < 0:
result = -3
break
if sym == 256: break
if sym < 256:
self.output_byte(BYTE(sym))
else:
len_idx: t.CInt = sym - 257
if len_idx < 0 or len_idx >= 29:
result = -3
break
length: t.CInt = zdef.zdeflate_len_base[len_idx]
extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx]
if extra > 0:
extra_val: UINT
if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0:
result = -3
break
length += extra_val
dist_sym: t.CInt = self.read_huffman(dist_dt)
if dist_sym < 0 or dist_sym >= 30:
result = -3
break
dist: t.CInt = zdef.zdeflate_dist_base[dist_sym]
extra = zdef.zdeflate_dist_extra_bits[dist_sym]
if extra > 0:
extra_val: UINT
if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0:
result = -3
break
dist += extra_val
for i in range(length):
if self.max_length > 0 and self.output_len >= self.max_length: break
src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1)
byte: BYTE = self.window[src_pos]
self.output_byte(byte)
zdef.zdef_free(self.pool, lit_dt)
zdef.zdef_free(self.pool, dist_dt)
return result
def inflate_block_dynamic(self) -> t.CInt:
hlit_val: UINT
hdist_val: UINT
hclen_val: UINT
if self.read_bits_from_input(5, c.Addr(hlit_val)) != 0: return -3
if self.read_bits_from_input(5, c.Addr(hdist_val)) != 0: return -3
if self.read_bits_from_input(4, c.Addr(hclen_val)) != 0: return -3
hlit: t.CInt = t.CInt(hlit_val) + 257
hdist: t.CInt = t.CInt(hdist_val) + 1
hclen: t.CInt = t.CInt(hclen_val) + 4
cl_lengths: t.CArray[t.CInt, 19]
memset(cl_lengths, 0, cl_lengths.__sizeof__())
for i in range(hclen):
len_val: UINT
if self.read_bits_from_input(3, c.Addr(len_val)) != 0: return -3
cl_lengths[zdef.zdeflate_codelen_order[i]] = t.CInt(len_val)
cl_tree = zhuff.zhuff_tree()
cl_tree.build_tree_from_lengths(cl_lengths, 19, 7)
cl_dt = zhuff.zhuff_decode_tree()
cl_dt.build_decode_tree(c.Addr(cl_tree))
total: t.CInt = hlit + hdist
all_lengths: t.CInt | t.CPtr = zdef.zdef_alloc(self.pool, total * int.__sizeof__())
if not all_lengths: return -4
idx: t.CInt = 0
while idx < total:
sym: t.CInt = self.read_huffman(c.Addr(cl_dt))
if sym < 0 or sym > 18:
zdef.zdef_free(self.pool, all_lengths)
return -3
if sym < 16:
all_lengths[idx] = sym
idx += 1
elif sym == 16:
rep: UINT
if self.read_bits_from_input(2, c.Addr(rep)) != 0:
zdef.zdef_free(self.pool, all_lengths)
return -3
rep += 3
if idx == 0 or idx + rep > total:
zdef.zdef_free(self.pool, all_lengths)
return -3
prev: t.CInt = all_lengths[idx - 1]
i: t.CUnsignedInt
for i in range(rep):
all_lengths[idx] = prev
idx += 1
elif sym == 17:
rep: t.CUnsignedInt
if self.read_bits_from_input(3, c.Addr(rep)) != 0:
zdef.zdef_free(self.pool, all_lengths)
return -3
rep += 3
if idx + rep > total:
zdef.zdef_free(self.pool, all_lengths)
return -3
i: t.CUnsignedInt
for i in range(rep):
all_lengths[idx] = 0
idx += 1
else:
rep: t.CUnsignedInt
if self.read_bits_from_input(7, c.Addr(rep)) != 0:
zdef.zdef_free(self.pool, all_lengths)
return -3
rep += 11
if idx + rep > total:
zdef.zdef_free(self.pool, all_lengths)
return -3
i: t.CUnsignedInt
for i in range(rep):
all_lengths[idx] = 0
idx += 1
lit_tree = zhuff.zhuff_tree()
dist_tree = zhuff.zhuff_tree()
lit_lengths: t.CArray[t.CInt, 288]
memset(lit_lengths, 0, lit_lengths.__sizeof__())
for i in range(hlit):
lit_lengths[i] = all_lengths[i]
lit_tree.build_tree_from_lengths(lit_lengths, hlit, zdef.ZDEFLATE_MAX_BITS)
dist_lengths: t.CArray[t.CInt, 32]
memset(dist_lengths, 0, dist_lengths.__sizeof__())
for i in range(hdist):
dist_lengths[i] = all_lengths[hlit + i]
dist_tree.build_tree_from_lengths(dist_lengths, hdist, zdef.ZDEFLATE_MAX_BITS)
zdef.zdef_free(self.pool, all_lengths)
lit_dt = zhuff.zhuff_decode_tree()
dist_dt = zhuff.zhuff_decode_tree()
lit_dt.build_decode_tree(c.Addr(lit_tree))
dist_dt.build_decode_tree(c.Addr(dist_tree))
while True:
if self.max_length > 0 and self.output_len >= self.max_length: return 0
sym: t.CInt = self.read_huffman(c.Addr(lit_dt))
if sym < 0: return -3
if sym == 256: return 0
if sym < 256:
self.output_byte(BYTE(sym))
else:
len_idx: t.CInt = sym - 257
if len_idx < 0 or len_idx >= 29: return -3
length: t.CInt = zdef.zdeflate_len_base[len_idx]
extra: t.CInt = zdef.zdeflate_len_extra_bits[len_idx]
if extra > 0:
extra_val: UINT
if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3
length += extra_val
dist_sym: t.CInt = self.read_huffman(c.Addr(dist_dt))
if dist_sym < 0 or dist_sym >= 30: return -3
dist: t.CInt = zdef.zdeflate_dist_base[dist_sym]
extra = zdef.zdeflate_dist_extra_bits[dist_sym]
if extra > 0:
extra_val: UINT
if self.read_bits_from_input(extra, c.Addr(extra_val)) != 0: return -3
dist += extra_val
for i in range(length):
if self.max_length > 0 and self.output_len >= self.max_length: return 0
src_pos: t.CInt = (self.window_pos - dist) & (zdef.ZDEFLATE_WINDOW_SIZE - 1)
byte: BYTE = self.window[src_pos]
self.output_byte(byte)
def inflate_stream(self) -> t.CInt:
err: t.CInt = self.parse_header()
if err != 0: return err
while not self.is_finished:
bfinal_val: UINT
btype_val: UINT
if self.read_bits_from_input(1, c.Addr(bfinal_val)) != 0: return -3
if self.read_bits_from_input(2, c.Addr(btype_val)) != 0: return -3
bfinal: t.CInt = t.CInt(bfinal_val)
btype: t.CInt = t.CInt(btype_val)
if btype == 0:
err = self.inflate_block_stored()
elif btype == 1:
err = self.inflate_block_fixed()
elif btype == 2:
err = self.inflate_block_dynamic()
else:
return -3
if err != 0: return err
if bfinal: self.is_finished = 1
if self.max_length > 0 and self.output_len >= self.max_length: return 0
if self.is_gzip:
if self.reader.bit_pos != 0:
self.reader.bit_pos = 0
self.input_pos += 1
if self.input_pos + 8 <= self.input_len:
self.crc = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 0) |
(t.CUInt32T(self.input_data[self.input_pos + 1]) << 8) |
(t.CUInt32T(self.input_data[self.input_pos + 2]) << 16) |
(t.CUInt32T(self.input_data[self.input_pos + 3]) << 24))
self.input_pos += 8
elif self.wbits >= 0:
if self.reader.bit_pos != 0:
self.reader.bit_pos = 0
self.input_pos += 1
if self.input_pos + 4 <= self.input_len:
self.adler = ((t.CUInt32T(self.input_data[self.input_pos + 0]) << 24) |
(t.CUInt32T(self.input_data[self.input_pos + 1]) << 16) |
(t.CUInt32T(self.input_data[self.input_pos + 2]) << 8) |
(t.CUInt32T(self.input_data[self.input_pos + 3]) << 0))
self.input_pos += 4
return 0
def decompress(self, data: UINT8PTR, length: t.CSizeT,
max_length: t.CSizeT, out: t.CUInt8T | t.CPtr[t.CPtr], out_len: t.CSizeT | t.CPtr) -> t.CInt:
if not self.is_initialized: return -2
self.input_data = data
self.input_len = length
self.input_pos = 0
self.reader.bit_pos = 0
self.output_len = 0
self.max_length = max_length
err: t.CInt = self.inflate_stream()
if err != 0: return err
c.Set(c.Deref(out_len), self.output_len)
if self.output_len == 0:
c.Set(c.Deref(out), UINT8PTR(zdef.zdef_alloc(self.pool, 1)))
else:
dst: UINT8PTR = UINT8PTR(zdef.zdef_alloc(self.pool, self.output_len))
c.Set(c.Deref(out), dst)
if dst:
memcpy(dst, self.output, self.output_len)
return 0
def set_dictionary(self, dict: UINT8PTR, length: t.CSizeT) -> t.CInt:
if not dict: return -2
use: t.CSizeT = length
if use > zdef.ZDEFLATE_WINDOW_SIZE:
dict += length - zdef.ZDEFLATE_WINDOW_SIZE
use = zdef.ZDEFLATE_WINDOW_SIZE
memcpy(self.window, dict, use)
self.window_pos = t.CInt(use)
return 0
def copy(self) -> zinflate_stream | t.CPtr:
z: zinflate_stream | t.CPtr = zdef.zdef_alloc(self.pool, zinflate_stream.__sizeof__())
if not z: return None
memcpy(z, self, zinflate_stream.__sizeof__())
z.window = BYTEPTR(zdef.zdef_alloc(self.pool, zdef.ZDEFLATE_WINDOW_SIZE))
z.output = BYTEPTR(zdef.zdef_alloc(self.pool, self.output_cap))
if not z.window or not z.output:
zinflate_stream.destroy(z)
return None
memcpy(z.window, self.window, zdef.ZDEFLATE_WINDOW_SIZE)
memcpy(z.output, self.output, self.output_cap)
return z
def destroy(self):
if not self: return
if self.window: zdef.zdef_free(self.pool, self.window)
if self.output: zdef.zdef_free(self.pool, self.output)
zdef.zdef_free(self.pool, self)
def zinflate_one_shot(pool: memhub.MemManager | t.CPtr, data: UINT8PTR, length: t.CSizeT,
wbits: t.CInt, bufsize: t.CSizeT, out_len: t.CSizeT | t.CPtr) -> t.CUInt8T | t.CPtr:
s: zinflate_stream | t.CPtr = zinflate_create(pool, wbits)
if not s: return None
out: t.CUInt8T | t.CPtr = None
err: t.CInt = s.decompress(data, length, 0, c.Addr(out), out_len)
s.destroy()
if err != 0: return None
return out
def zinflate_create(pool: memhub.MemManager | t.CPtr, wbits: t.CInt) -> zinflate_stream | t.CPtr:
s: zinflate_stream | t.CPtr = zdef.zdef_alloc(pool, zinflate_stream.__sizeof__())
if not s: return None
memset(s, 0, zinflate_stream.__sizeof__())
s.pool = pool
s.wbits = wbits
s.is_initialized = 1
s.adler = 1
s.window = BYTEPTR(zdef.zdef_alloc(pool, zdef.ZDEFLATE_WINDOW_SIZE))
s.output = BYTEPTR(zdef.zdef_alloc(pool, 256))
s.output_cap = 256
s.output_len = 0
s.max_length = 0
if not s.window or not s.output:
s.destroy()
return None
return s