Files
Viper_VRTE/string.vp
T
TermiNexus e71daeea0e docs(includes): R11 注释英文化——75 个文件的中文注释改写为英文短注释
按规范「注释只讲解作用,不掺杂历史原因,尽量英文」:把 includes 下 75 个 .vp 的中文 # 注释与三引号 docstring 改写为英文,每个注释块压到 2 行以内。

保留要点:作用、约束、危险警告(不得/必须/注意)、ABI 与类型约定(如 BYTEPTR | t.CPtr = i8** 的跨模块坍缩坑)、位宽/长度约定、fail-fast 要求、内存与句柄所有权。

未动:文件头注释(规范豁免,仍是中文)、运行时中文字符串常量(printf / fatal_error / MlirFail 等用户可见消息,属代码字面量)。

验证:独立脚本比对 HEAD 与工作区的代码骨架(剥离 # 注释与三引号 docstring 后的非空行)——75 个文件逐字节一致;行尾 CRLF/LF 未被改动;全文剩余中文仅 547 行头注释、0 条行尾注释。bootstrap 三重重编 SUCCESS;全量 77/77 顺序回归通过。
2026-10-05 16:18:44 +08:00

609 lines
19 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from stdint import *
import t, c
import stdio
# String copy function
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
# String concatenate function
def strcat(dest: str, src: str) -> str:
if dest == None or src == None: return dest
original_dest: str = dest
# Find end of dest
while dest[0] != '\0':
dest += 1
# Copy src
for s in src:
dest[0] = s
dest += 1
dest[0] = 0
return original_dest
# String copy function with limited length
def strncpy(dest: str, src: str, n: sizet) -> str:
if dest == None or src == None or n == 0: return dest
original_dest: str = dest
i: sizet = 0
for s in src:
if i >= n: break
dest[0] = s
dest += 1
i += 1
# Fill remaining space with '\0'
while i < n:
dest[0] = 0
dest += 1
i += 1
return original_dest
# String concatenate function with limited length
def strncat(dest: str, src: str, n: sizet) -> str:
if dest == None or src == None or n == 0: return dest
original_dest: str = dest
# Find end of dest
while dest[0] != '\0':
dest += 1
# Copy up to n chars from src
i: sizet = 0
for s in src:
if i >= n: break
dest[0] = s
dest += 1
i += 1
dest[0] = 0
return original_dest
# String length function
export def strlen(src: str) -> sizet:
length: sizet = 0
for _ in src:
length += 1
return length
# String comparison function
# Note: str1[0] - str2[0] is an i8 subtraction that wraps (0xFF means -1), so both operands
# must be promoted to i32 before subtracting (as in memcmp below); otherwise strcmp("abc","abd") returns 255 instead of -1.
def strcmp(str1: str, str2: str) -> int:
# Pointer-equality short-circuit: identical pointers guarantee identical contents, so return 0 directly and skip the full byte loop.
# Semantics strictly unchanged (same pointer => same content => strcmp result is 0); different pointers fall through to the loop below.
if str1 == str2:
return 0
while str1[0] != '\0' and str2[0] != '\0':
if str1[0] != str2[0]:
return int(str1[0]) - int(str2[0])
str1 += 1
str2 += 1
return int(str1[0]) - int(str2[0])
def samestr(str1: str, str2: str) -> bool:
return strcmp(str1, str2) == 0
# String compare function with limited length
def strncmp(str1: str, str2: str, n: sizet) -> int:
# Pointer-equality short-circuit (same as strcmp): identical pointers compare equal for any n, so return 0.
# Semantics strictly unchanged.
if str1 == str2:
return 0
i: sizet = 0
while str1[0] != '\0' and str2[0] != '\0' and i < n:
if str1[0] != str2[0]:
return int(str1[0]) - int(str2[0])
str1 += 1
str2 += 1
i += 1
if i < n:
return int(str1[0]) - int(str2[0])
return 0
# Memory compare function
def memcmp(ptr1: t.CPtr, ptr2: t.CPtr, n: sizet) -> int:
p1: BYTEPTR = BYTEPTR(ptr1)
p2: BYTEPTR = BYTEPTR(ptr2)
for i in range(n):
if p1[i] != p2[i]:
return int(p1[i]) - int(p2[i])
return 0
# String find function
def strchr(s: str, cr: int) -> str:
while s[0] != '\0':
if s[0] == char(cr):
return str(s)
s += 1
if cr == '\0':
return str(s)
return None
# String reverse find function (find last occurrence of character)
def strrchr(s: str, cr: int) -> str:
last: str = None
while s[0] != '\0':
if s[0] == char(cr):
last = s
s += 1
if cr == '\0': return s
return last
# Substring search function (find first occurrence of needle in s, return pointer to that position, or None if not found)
# Hot-path optimization: use strchr to jump to first-char candidates instead of calling strncmp at every byte, and drop the upfront strlen(s) (strncmp stops at '\0').
# Semantics unchanged: an empty needle returns s; not found returns None.
def strstr(s: str, needle: str) -> str:
if needle[0] == 0:
return s
needle_len: sizet = strlen(needle)
if needle_len == 0:
return s
first_ch: int = int(needle[0])
cur: str = s
while True:
hit: str = strchr(cur, first_ch)
if hit is None:
return None
if strncmp(hit, needle, needle_len) == 0:
return hit
cur = hit + 1
# String skip function
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
# Memory set function
export def memset(ptr: t.CPtr, value: int, num: sizet) -> t.CPtr:
# Original implementation:
# p: BYTEPTR = BYTEPTR(ptr)
# i: sizet
# 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=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDI])
return ptr
def memset32(ptr: t.CPtr, value: uint32, count: sizet) -> t.CPtr:
# Original implementation:
# p: UINT32PTR = UINT32PTR(ptr)
# i: sizet
# 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=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDI])
return ptr
# Memory copy function
export def memcpy(dest: t.CPtr, src: t.CPtr, num: sizet) -> t.CPtr:
# Original implementation:
# d: BYTEPTR = BYTEPTR(dest)
# s: BYTEPTR = BYTEPTR(src)
# i: sizet
# 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=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RCX,
ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_RSI])
return dest
# Memory move function
def memmove(dest: t.CPtr, src: t.CPtr, num: sizet) -> t.CPtr:
# Original implementation:
# d: BYTEPTR = BYTEPTR(dest)
# s: BYTEPTR = BYTEPTR(src)
# i: sizet
# 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=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RCX,
ASM_DESCR.CLOBBER_RDI, ASM_DESCR.CLOBBER_RSI])
return dest
def atoi(src: str) -> int:
num: int = 0
sign: int = 1
s: str = src
if s == None: return 0
# Skip whitespace
while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r':
s += 1
# Sign
if s[0] == '-':
sign = -1
s += 1
elif s[0] == '+':
s += 1
for ch in s:
if ch < '0' or ch > '9': break
digit: int = ch - '0'
num = num * 10 + digit
return num * sign
def atoll(src: str) -> int64:
num: int64 = 0
sign: int64 = 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
# Hex prefix 0x / 0X
is_hex: int = 0
if s[0] == '0' and (s[1] == 'x' or s[1] == 'X'):
is_hex = 1
s += 2
if is_hex:
for ch in s:
d: int = 0
if ch >= '0' and ch <= '9':
d = ch - '0'
elif ch >= 'a' and ch <= 'f':
d = ch - 'a' + 10
elif ch >= 'A' and ch <= 'F':
d = ch - 'A' + 10
else:
break
digit: int64 = int64(d)
num = num * 16 + digit
else:
for ch in s:
if ch < '0' or ch > '9': break
d: int = ch - '0'
digit: int64 = int64(d)
num = num * 10 + digit
return num * sign
# ============================================================
# Correctly-rounded decimal literal -> double conversion (N4): mantissa in u64 (<=19 digits, 20th digit rounds once),
# scaled once by an exact power of ten in double-double (hi+lo, ~106 bits) then rounded a single final time.
# Convention: no global table (10^0..10^22 built by repeated multiplication of 10, each step exact).
# For p<0 compute 10^p*2^600 in the normal range and scale back exactly, avoiding subnormal loss in the double-double low part below ~1e-292.
# ============================================================
# _dd_split_hi - upper half of the Dekker split (hi = top 26 bits).
# Magnitude rescaling: multiply by 2^-28 when |a| > 6.7e292 and by 2^28 when |a| < 1e-292 (powers of two, lossless for normals); caller gets the lower half via lo = a - hi.
def _dd_split_hi(a: double) -> double:
aa: double = a
big: int = 0
small: int = 0
if a > 6.7e292 or a < -6.7e292:
aa = a * 3.725290298461914e-09
big = 1
elif (a > 0.0 and a < 1.0e-292) or (a < 0.0 and a > -1.0e-292):
aa = a * 268435456.0
small = 1
tt: double = aa * 134217729.0
hi: double = tt - (tt - aa)
if big != 0:
return hi * 268435456.0
if small != 0:
return hi * 3.725290298461914e-09
return hi
# _dd_mul - double-double multiply: out = a × b (out[0]=hi, out[1]=lo)
def _dd_mul(ah: double, al: double, bh: double, bl: double,
out: t.CArray[double, 2]):
p: double = ah * bh
a_hi: double = _dd_split_hi(ah)
a_lo: double = ah - a_hi
b_hi: double = _dd_split_hi(bh)
b_lo: double = bh - b_hi
e: double = ((a_hi * b_hi - p) + a_hi * b_lo + a_lo * b_hi) + a_lo * b_lo
e = e + (ah * bl + al * bh)
s: double = p + e
out[0] = s
out[1] = e - (s - p)
# _dd_add - double-double add: out = a + b
def _dd_add(ah: double, al: double, bh: double, bl: double,
out: t.CArray[double, 2]):
s: double = ah + bh
bb: double = s - ah
e: double = (ah - (s - bb)) + (bh - bb)
e = e + (al + bl)
r0: double = s + e
out[0] = r0
out[1] = e - (r0 - s)
# _dd_div - double-double divide: out = a / b (q0 plus one residual correction step)
def _dd_div(ah: double, al: double, bh: double, bl: double,
out: t.CArray[double, 2], tmp: t.CArray[double, 2]):
q0: double = ah / bh
_dd_mul(bh, bl, q0, 0.0, tmp)
_dd_add(ah, al, -tmp[0], -tmp[1], tmp)
q1: double = tmp[0] / bh
_dd_add(q0, 0.0, q1, 0.0, out)
# _dd_from_u64 - u64 -> double-double (exact: hi is the rounded value, lo the exact residual)
def _dd_from_u64(m: uint64, out: t.CArray[double, 2]):
hi: double = double(m)
lo: double = 0.0
if m >= uint64(9007199254740992):
lo = double(m - uint64(hi))
s: double = hi + lo
bb: double = s - hi
out[0] = s
out[1] = (hi - (s - bb)) + (lo - bb)
# _dd_pow10 - double-double 10^e (e >= 0; chunked by <=22 so each chunk is exact)
def _dd_pow10(e: int, out: t.CArray[double, 2], tmp: t.CArray[double, 2]):
out[0] = 1.0
out[1] = 0.0
k: int = e
while k > 0:
step: int = 22
if k < 22:
step = k
p10: double = 1.0
for i in range(step):
p10 = p10 * 10.0
_dd_mul(out[0], out[1], p10, 0.0, tmp)
out[0] = tmp[0]
out[1] = tmp[1]
k -= step
# _pow2 - 2^n (|n| <= 1000): repeated multiply by 2/0.5, exact at every step
def _pow2(n: int) -> double:
r: double = 1.0
i: int = n
if i >= 0:
while i > 0:
r = r * 2.0
i -= 1
else:
while i < 0:
r = r * 0.5
i += 1
return r
# _atof_scale_stepwise - stepwise ×/÷10 scaling (fallback for subnormal/overflow cases)
def _atof_scale_stepwise(x: double, p: int) -> double:
r: double = x
e: int = p
while e > 0:
r = r * 10.0
e -= 1
while e < 0:
r = r / 10.0
e += 1
return r
def atof(src: str) -> double:
s: str = src
if s == None: return 0.0
# Skip whitespace
while s[0] == ' ' or s[0] == '\t' or s[0] == '\n' or s[0] == '\r':
s += 1
# Sign
sign: double = 1.0
if s[0] == '-':
sign = -1.0
s += 1
elif s[0] == '+':
s += 1
# Mantissa: significant digits packed into u64 (<=19 digits), tracking the decimal exponent
mant: uint64 = 0
nd: int = 0
dexp: int = 0
seen_dot: int = 0
started: int = 0
rounded: int = 0
while s[0] != '\0':
ch: char = s[0]
if ch >= '0' and ch <= '9':
d: int = ch - '0'
if started == 0:
# Leading zeros are not stored in the mantissa; leading zeros in the fraction still advance the decimal exponent
if d != 0:
started = 1
mant = uint64(d)
nd = 1
if seen_dot != 0:
dexp -= 1
elif seen_dot != 0:
dexp -= 1
elif nd < 19:
mant = mant * uint64(10) + uint64(d)
nd += 1
if seen_dot != 0:
dexp -= 1
else:
# From the 20th digit on: dropped integer digits bump the exponent; dropped fraction digits do not.
# Only the 20th digit is used for one rounding (dropped amount <= 1e-19 relative error).
if seen_dot == 0:
dexp += 1
elif rounded == 0:
if d >= 5:
mant += uint64(1)
rounded = 1
elif ch == '.':
seen_dot = 1
else:
break
s += 1
if started == 0:
return sign * 0.0
# Carry: rounding may turn 19 digits into 20
if mant >= uint64(10000000000000000000):
mant = mant // uint64(10)
dexp += 1
# Exponent part
exp: int = 0
if s[0] == 'e' or s[0] == 'E':
s += 1
exp_sign: int = 1
if s[0] == '-':
exp_sign = -1
s += 1
elif s[0] == '+':
s += 1
while s[0] >= '0' and s[0] <= '9':
exp = exp * 10 + (s[0] - '0')
s += 1
exp = exp * exp_sign
p: int = dexp + exp
if p == 0:
return sign * double(mant)
# Double-double scaling: mant × 10^p, single final rounding
ta: t.CArray[double, 2]
tb: t.CArray[double, 2]
tc: t.CArray[double, 2]
tr: t.CArray[double, 2]
_dd_from_u64(mant, ta)
v: double = 0.0
if p > 0:
_dd_pow10(p, tb, tr)
_dd_mul(ta[0], ta[1], tb[0], tb[1], tr)
v = tr[0] + tr[1]
else:
# p < 0: compute 2^600 / 10^(-p) (= 10^p * 2^600) in the normal range, then scale back exactly.
# Direct 10^p loses effective bits to subnormals for large |p|; divide the denominator in chunks of <=308 (10^313 overflows to inf and yields NaN).
tb[0] = _pow2(600)
tb[1] = 0.0
q: int = -p
while q > 0:
step2: int = 308
if q < 308:
step2 = q
_dd_pow10(step2, tc, tr)
_dd_div(tb[0], tb[1], tc[0], tc[1], tr, tc)
tb[0] = tr[0]
tb[1] = tr[1]
q -= step2
_dd_mul(ta[0], ta[1], tb[0], tb[1], tr)
v = (tr[0] + tr[1]) * _pow2(-600)
# Normal range (not NaN / not inf / not subnormal) -> the correctly rounded result
if v == v and v <= 1.7976931348623157e308 and v >= -1.7976931348623157e308 \
and (v == 0.0 or v >= 2.2250738585072014e-308 or v <= -2.2250738585072014e-308):
return sign * v
# Overflow / subnormal / NaN -> fall back to stepwise scaling
return sign * _atof_scale_stepwise(double(mant), p)
def atof_out(src: str, out: double*) -> int:
"""Write the atof result to out[0] (out-parameter form, avoiding the cross-module double return bug).
The return value only signals success (1) or failure (0); the value is passed via the out pointer."""
if out is None:
return 0
v: double = atof(src)
out[0] = v
return 1
def split(s: str, delim: str, result: t.CArray[str], cap: int) -> int:
"""Split s by a single-character delimiter, writing token pointers to result[0..] and a None sentinel at the end.
cap is the declared capacity (element count); token count is limited to <= cap-1, leaving one slot for the sentinel."""
count: int = 0
start: str = s
if not s or not delim or not result:
return 0
if cap <= 0:
return 0
d: char = delim[0] # single delimiter
while start[0]:
# Skip delimiters
while start[0] == d: start += 1
if not start[0]: break
# Capacity guard: keep the last slot for the end sentinel
if count >= cap - 1:
break
# Record token start
result[count] = start
count += 1
# Find the next delimiter and truncate
while start[0] and start[0] != d: start += 1
if start[0]:
start[0] = '\0'
start += 1
result[count] = None # end marker
return count
ascii_lowercase: str = "abcdefghijklmnopqrstuvwxyz"
ascii_uppercase: str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
ascii_letters: str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
digits: str = "0123456789"
hexdigits: str = "0123456789abcdefABCDEF"
octdigits: str = "01234567"
punctuation: str = "!\"#$%&'()*+,-./:;<=>?@[]^_`{|}~"
whitespace: str = " \t\n\r\f\v"
printable: str = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\f\v"