lang: rename signed integer types sN -> iN
Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
This commit is contained in:
@@ -38,11 +38,11 @@ libc :: #library "c";
|
||||
// macOS C-runtime argv/argc accessors (crt_externs.h):
|
||||
// extern char ***_NSGetArgv(void); extern int *_NSGetArgc(void);
|
||||
// Each returns a pointer to the runtime's slot; dereference once for the
|
||||
// `char**` / `int` the process was launched with. Declared as `*s64` /
|
||||
// `*s32` since on 64-bit a `char***` is just a pointer to a pointer-sized
|
||||
// `char**` / `int` the process was launched with. Declared as `*i64` /
|
||||
// `*i32` since on 64-bit a `char***` is just a pointer to a pointer-sized
|
||||
// slot.
|
||||
ns_get_argv :: () -> *s64 #foreign libc "_NSGetArgv";
|
||||
ns_get_argc :: () -> *s32 #foreign libc "_NSGetArgc";
|
||||
ns_get_argv :: () -> *i64 #foreign libc "_NSGetArgv";
|
||||
ns_get_argc :: () -> *i32 #foreign libc "_NSGetArgc";
|
||||
|
||||
// =====================================================================
|
||||
// EXIT-CODE & `--json` CONTRACT (F3.3) — the minimal surface `dist` (and
|
||||
@@ -80,9 +80,9 @@ exit_usage :: () -> noreturn { proc.exit(EX_USAGE); }
|
||||
|
||||
// Number of process arguments (argc). >= 1 for any normally-launched
|
||||
// process, since argv[0] is the executable path.
|
||||
os_argc :: () -> s64 {
|
||||
os_argc :: () -> i64 {
|
||||
inline if OS == {
|
||||
case .macos: { return cast(s64) ns_get_argc().*; }
|
||||
case .macos: { return cast(i64) ns_get_argc().*; }
|
||||
else: {
|
||||
out("std.cli: unsupported platform — only macOS is implemented (needs _NSGetArgv/_NSGetArgc).\n");
|
||||
proc.exit(EX_UNAVAILABLE);
|
||||
@@ -102,8 +102,8 @@ os_argc :: () -> s64 {
|
||||
os_args :: (buf: []string) -> []string {
|
||||
inline if OS == {
|
||||
case .macos: {
|
||||
argc := cast(s64) ns_get_argc().*;
|
||||
argv : [*]s64 = xx ns_get_argv().*;
|
||||
argc := cast(i64) ns_get_argc().*;
|
||||
argv : [*]i64 = xx ns_get_argv().*;
|
||||
n := if argc > buf.len then buf.len else argc;
|
||||
i := 0;
|
||||
while i < n {
|
||||
@@ -216,7 +216,7 @@ FlagValue :: struct {
|
||||
// the failure names a flag rather than an input token (a missing required
|
||||
// flag sets `token` to the flag name).
|
||||
Diag :: struct {
|
||||
index: s64 = -1;
|
||||
index: i64 = -1;
|
||||
token: string = "";
|
||||
}
|
||||
|
||||
@@ -225,7 +225,7 @@ Diag :: struct {
|
||||
Parsed :: struct {
|
||||
group: string;
|
||||
command: string;
|
||||
cmd_index: s64;
|
||||
cmd_index: i64;
|
||||
json: bool; // `--json` mode: true iff `--json` is in argv
|
||||
rest: []string;
|
||||
spec: []FlagSpec; // view of the matched command's flag specs
|
||||
|
||||
@@ -8,27 +8,27 @@ out :: (str: string) -> void #builtin;
|
||||
// sqrt :: (x: $T) -> T #builtin;
|
||||
// sin :: (x: $T) -> T #builtin;
|
||||
// cos :: (x: $T) -> T #builtin;
|
||||
size_of :: ($T: Type) -> s64 #builtin;
|
||||
align_of :: ($T: Type) -> s64 #builtin;
|
||||
size_of :: ($T: Type) -> i64 #builtin;
|
||||
align_of :: ($T: Type) -> i64 #builtin;
|
||||
// Low-level libc bindings, used by allocator implementations to avoid
|
||||
// recursing through `context.allocator`. The bare `malloc`/`free`
|
||||
// spellings are NOT declared: the Allocator protocol + the std/mem.sx
|
||||
// helpers are the allocation surface (`free` is the typed slice helper
|
||||
// there). Raw libc escape hatch: `libc_malloc` / `libc_free`.
|
||||
libc_malloc :: (size: s64) -> *void #foreign libc "malloc";
|
||||
libc_malloc :: (size: i64) -> *void #foreign libc "malloc";
|
||||
libc_free :: (ptr: *void) -> void #foreign libc "free";
|
||||
|
||||
memcpy :: (dst: *void, src: *void, size: s64) -> *void #foreign libc "memcpy";
|
||||
memset :: (dst: *void, val: s64, size: s64) -> void #foreign libc "memset";
|
||||
memcpy :: (dst: *void, src: *void, size: i64) -> *void #foreign libc "memcpy";
|
||||
memset :: (dst: *void, val: i64, size: i64) -> void #foreign libc "memset";
|
||||
type_of :: (val: $T) -> Type #builtin;
|
||||
type_name :: ($T: Type) -> string #builtin;
|
||||
field_count :: ($T: Type) -> s64 #builtin;
|
||||
field_name :: ($T: Type, idx: s64) -> string #builtin;
|
||||
field_value :: (s: $T, idx: s64) -> Any #builtin;
|
||||
field_count :: ($T: Type) -> i64 #builtin;
|
||||
field_name :: ($T: Type, idx: i64) -> string #builtin;
|
||||
field_value :: (s: $T, idx: i64) -> Any #builtin;
|
||||
is_flags :: ($T: Type) -> bool #builtin;
|
||||
type_is_unsigned :: ($T: Type) -> bool #builtin;
|
||||
field_value_int :: ($T: Type, idx: s64) -> s64 #builtin;
|
||||
field_index :: ($T: Type, val: T) -> s64 #builtin;
|
||||
field_value_int :: ($T: Type, idx: i64) -> i64 #builtin;
|
||||
field_index :: ($T: Type, val: T) -> i64 #builtin;
|
||||
error_tag_name :: (e: $T) -> string #builtin;
|
||||
|
||||
// Call-site location, synthesized by the `#caller_location` directive when it
|
||||
@@ -36,8 +36,8 @@ error_tag_name :: (e: $T) -> string #builtin;
|
||||
// to report where they were invoked.
|
||||
Source_Location :: struct {
|
||||
file: string;
|
||||
line: s32;
|
||||
col: s32;
|
||||
line: i32;
|
||||
col: i32;
|
||||
func: string;
|
||||
}
|
||||
string :: []u8 #builtin;
|
||||
@@ -47,7 +47,7 @@ string :: []u8 #builtin;
|
||||
// Bytes-level primitives carry the `_bytes` suffix so the typed
|
||||
// helpers in std/mem.sx own the bare names (`alloc(T, n)`, `free(s)`).
|
||||
Allocator :: protocol #inline {
|
||||
alloc_bytes :: (size: s64) -> *void;
|
||||
alloc_bytes :: (size: i64) -> *void;
|
||||
dealloc_bytes :: (ptr: *void);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
// --- Slice & string allocation ---
|
||||
|
||||
cstring :: (size: s64) -> string {
|
||||
cstring :: (size: i64) -> string {
|
||||
raw := context.allocator.alloc_bytes(size + 1);
|
||||
memset(raw, 0, size + 1);
|
||||
s : string = ---;
|
||||
@@ -15,7 +15,7 @@ cstring :: (size: s64) -> string {
|
||||
s
|
||||
}
|
||||
|
||||
alloc_slice :: ($T: Type, count: s64) -> []T {
|
||||
alloc_slice :: ($T: Type, count: i64) -> []T {
|
||||
raw := context.allocator.alloc_bytes(count * size_of(T));
|
||||
memset(raw, 0, count * size_of(T));
|
||||
s : []T = ---;
|
||||
@@ -24,12 +24,12 @@ alloc_slice :: ($T: Type, count: s64) -> []T {
|
||||
s
|
||||
}
|
||||
|
||||
int_to_string :: (n: s64) -> string {
|
||||
int_to_string :: (n: i64) -> string {
|
||||
if n == 0 { return "0"; }
|
||||
neg := n < 0;
|
||||
// Extract digits straight from `n` without ever negating it: `0 - n`
|
||||
// overflows for s64::MIN (its magnitude is unrepresentable as a
|
||||
// positive s64). sx `%` truncates toward zero, so `n % 10` keeps n's
|
||||
// overflows for i64::MIN (its magnitude is unrepresentable as a
|
||||
// positive i64). sx `%` truncates toward zero, so `n % 10` keeps n's
|
||||
// sign; take each remainder's absolute value for the digit.
|
||||
tmp := cstring(20);
|
||||
i := 19;
|
||||
@@ -47,13 +47,13 @@ int_to_string :: (n: s64) -> string {
|
||||
|
||||
// Unsigned decimal of `n`'s 64 bits — renders the full u64 range
|
||||
// (0 .. 18446744073709551615). Used by `any_to_string` for unsigned
|
||||
// integer values, which an s64-based formatter would misread (e.g. a
|
||||
// integer values, which an i64-based formatter would misread (e.g. a
|
||||
// u64 all-ones value as -1).
|
||||
uint_to_string :: (n: s64) -> string {
|
||||
uint_to_string :: (n: i64) -> string {
|
||||
if n == 0 { return "0"; }
|
||||
// Long division by 10 across the four unsigned 16-bit limbs, most
|
||||
// significant first. Each step folds the running remainder into the
|
||||
// next limb; the per-step accumulator stays well within s64
|
||||
// next limb; the per-step accumulator stays well within i64
|
||||
// (max 9*65536 + 65535), so signed `/` and `%` are exact.
|
||||
g := decompose_u16x4(n);
|
||||
tmp := cstring(20);
|
||||
@@ -80,8 +80,8 @@ bool_to_string :: (b: bool) -> string {
|
||||
float_to_string :: (f: f64) -> string {
|
||||
neg := f < 0.0;
|
||||
v := if neg then 0.0 - f else f;
|
||||
int_part := cast(s64) v;
|
||||
frac := cast(s64) ((v - cast(f64) int_part) * 1000000.0);
|
||||
int_part := cast(i64) v;
|
||||
frac := cast(i64) ((v - cast(f64) int_part) * 1000000.0);
|
||||
if frac < 0 { frac = 0 - frac; }
|
||||
istr := int_to_string(int_part);
|
||||
fstr := int_to_string(frac);
|
||||
@@ -103,7 +103,7 @@ float_to_string :: (f: f64) -> string {
|
||||
buf
|
||||
}
|
||||
|
||||
hex_group :: (buf: string, offset: s64, val: s64) {
|
||||
hex_group :: (buf: string, offset: i64, val: i64) {
|
||||
i := offset + 3;
|
||||
v := val;
|
||||
while i >= offset {
|
||||
@@ -120,7 +120,7 @@ hex_group :: (buf: string, offset: s64, val: s64) {
|
||||
// back into 0..65535 — so callers get correct unsigned arithmetic out
|
||||
// of a signed-only integer type. Shared by the hex and unsigned-decimal
|
||||
// formatters.
|
||||
decompose_u16x4 :: (n: s64) -> [4]s64 {
|
||||
decompose_u16x4 :: (n: i64) -> [4]i64 {
|
||||
g0 := n % 65536;
|
||||
if g0 < 0 { g0 = g0 + 65536; }
|
||||
r1 := (n - g0) / 65536;
|
||||
@@ -132,7 +132,7 @@ decompose_u16x4 :: (n: s64) -> [4]s64 {
|
||||
r3 := (r2 - g2) / 65536;
|
||||
g3 := r3 % 65536;
|
||||
if g3 < 0 { g3 = g3 + 65536; }
|
||||
limbs : [4]s64 = ---;
|
||||
limbs : [4]i64 = ---;
|
||||
limbs[0] = g3;
|
||||
limbs[1] = g2;
|
||||
limbs[2] = g1;
|
||||
@@ -140,7 +140,7 @@ decompose_u16x4 :: (n: s64) -> [4]s64 {
|
||||
limbs
|
||||
}
|
||||
|
||||
int_to_hex_string :: (n: s64) -> string {
|
||||
int_to_hex_string :: (n: i64) -> string {
|
||||
if n == 0 { return "0"; }
|
||||
|
||||
g := decompose_u16x4(n);
|
||||
@@ -168,7 +168,7 @@ concat :: (a: string, b: string) -> string {
|
||||
buf
|
||||
}
|
||||
|
||||
substr :: (s: string, start: s64, len: s64) -> string {
|
||||
substr :: (s: string, start: i64, len: i64) -> string {
|
||||
buf := cstring(len);
|
||||
memcpy(buf.ptr, @s[start], len);
|
||||
buf
|
||||
@@ -251,14 +251,14 @@ slice_to_string :: (items: []$T) -> string {
|
||||
}
|
||||
|
||||
pointer_to_string :: (p: $T) -> string {
|
||||
addr : s64 = xx p;
|
||||
addr : i64 = xx p;
|
||||
if addr == 0 { "null" } else {
|
||||
concat(type_name(T), concat("@0x", int_to_hex_string(addr)))
|
||||
}
|
||||
}
|
||||
|
||||
flags_to_string :: (val: $T) -> string {
|
||||
v := cast(s64) val;
|
||||
v := cast(i64) val;
|
||||
result := "";
|
||||
i := 0;
|
||||
while i < field_count(T) {
|
||||
|
||||
@@ -24,36 +24,36 @@ libc :: #library "c";
|
||||
// API below wraps them. Users should not call these directly.
|
||||
//
|
||||
// macOS `open` is variadic in C (`int open(const char*, int, ...)`);
|
||||
// declared with `..args: []s32` so the mode is passed via the C
|
||||
// declared with `..args: []i32` so the mode is passed via the C
|
||||
// variadic tail. Without that, the mode arg goes to the wrong
|
||||
// register on arm64 and the file ends up with mode 0.
|
||||
|
||||
open :: (path: [:0]u8, flags: s32, ..args: []s32) -> s32 #foreign libc;
|
||||
close :: (fd: s32) -> s32 #foreign libc;
|
||||
read :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
lseek :: (fd: s32, offset: s64, whence: s32) -> s64 #foreign libc;
|
||||
unlink :: (path: [:0]u8) -> s32 #foreign libc;
|
||||
rmdir :: (path: [:0]u8) -> s32 #foreign libc;
|
||||
mkdir :: (path: [:0]u8, mode: u32) -> s32 #foreign libc;
|
||||
access :: (path: [:0]u8, mode: s32) -> s32 #foreign libc;
|
||||
chmod :: (path: [:0]u8, mode: u32) -> s32 #foreign libc;
|
||||
rename :: (oldp: [:0]u8, newp: [:0]u8) -> s32 #foreign libc;
|
||||
open :: (path: [:0]u8, flags: i32, ..args: []i32) -> i32 #foreign libc;
|
||||
close :: (fd: i32) -> i32 #foreign libc;
|
||||
read :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
lseek :: (fd: i32, offset: i64, whence: i32) -> i64 #foreign libc;
|
||||
unlink :: (path: [:0]u8) -> i32 #foreign libc;
|
||||
rmdir :: (path: [:0]u8) -> i32 #foreign libc;
|
||||
mkdir :: (path: [:0]u8, mode: u32) -> i32 #foreign libc;
|
||||
access :: (path: [:0]u8, mode: i32) -> i32 #foreign libc;
|
||||
chmod :: (path: [:0]u8, mode: u32) -> i32 #foreign libc;
|
||||
rename :: (oldp: [:0]u8, newp: [:0]u8) -> i32 #foreign libc;
|
||||
|
||||
// macOS POSIX constants. Linux values differ; split into platform-
|
||||
// conditional includes when we gain a Linux host.
|
||||
O_RDONLY :s32: 0x0000;
|
||||
O_WRONLY :s32: 0x0001;
|
||||
O_RDWR :s32: 0x0002;
|
||||
O_APPEND :s32: 0x0008;
|
||||
O_CREAT :s32: 0x0200;
|
||||
O_TRUNC :s32: 0x0400;
|
||||
O_RDONLY :i32: 0x0000;
|
||||
O_WRONLY :i32: 0x0001;
|
||||
O_RDWR :i32: 0x0002;
|
||||
O_APPEND :i32: 0x0008;
|
||||
O_CREAT :i32: 0x0200;
|
||||
O_TRUNC :i32: 0x0400;
|
||||
|
||||
SEEK_SET :s32: 0;
|
||||
SEEK_CUR :s32: 1;
|
||||
SEEK_END :s32: 2;
|
||||
SEEK_SET :i32: 0;
|
||||
SEEK_CUR :i32: 1;
|
||||
SEEK_END :i32: 2;
|
||||
|
||||
F_OK :s32: 0;
|
||||
F_OK :i32: 0;
|
||||
|
||||
// ── Public types ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -67,7 +67,7 @@ OpenMode :: enum {
|
||||
SeekFrom :: enum { set; current; end; }
|
||||
|
||||
File :: struct {
|
||||
fd: s32 = -1;
|
||||
fd: i32 = -1;
|
||||
|
||||
is_valid :: (self: *File) -> bool { self.fd >= 0 }
|
||||
|
||||
@@ -78,19 +78,19 @@ File :: struct {
|
||||
rc == 0
|
||||
}
|
||||
|
||||
read :: (self: *File, buf: string) -> s64 {
|
||||
read :: (self: *File, buf: string) -> i64 {
|
||||
if self.fd < 0 { return -1; }
|
||||
n := read(self.fd, buf.ptr, xx buf.len);
|
||||
cast(s64) n
|
||||
cast(i64) n
|
||||
}
|
||||
|
||||
write :: (self: *File, data: string) -> s64 {
|
||||
write :: (self: *File, data: string) -> i64 {
|
||||
if self.fd < 0 { return -1; }
|
||||
n := write(self.fd, data.ptr, xx data.len);
|
||||
cast(s64) n
|
||||
cast(i64) n
|
||||
}
|
||||
|
||||
seek :: (self: *File, offset: s64, whence: SeekFrom) -> s64 {
|
||||
seek :: (self: *File, offset: i64, whence: SeekFrom) -> i64 {
|
||||
if self.fd < 0 { return -1; }
|
||||
w := SEEK_SET;
|
||||
if whence == .current { w = SEEK_CUR; }
|
||||
@@ -105,7 +105,7 @@ File :: struct {
|
||||
// idea for `delete_file`/`delete_dir` vs libc's `unlink`/`rmdir`,
|
||||
// `set_mode` vs libc's `chmod`, etc.
|
||||
|
||||
mode_to_flags :: (m: OpenMode) -> s32 {
|
||||
mode_to_flags :: (m: OpenMode) -> i32 {
|
||||
if m == .read { return O_RDONLY; }
|
||||
if m == .write { return O_WRONLY | O_CREAT | O_TRUNC; }
|
||||
if m == .append { return O_WRONLY | O_CREAT | O_APPEND; }
|
||||
@@ -133,7 +133,7 @@ read_file :: (path: [:0]u8) -> ?string {
|
||||
buf := cstring(size);
|
||||
n := read(fd, buf.ptr, xx size);
|
||||
close(fd);
|
||||
if cast(s64) n != size { return null; }
|
||||
if cast(i64) n != size { return null; }
|
||||
buf
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ write_file :: (path: [:0]u8, data: string) -> bool {
|
||||
if fd < 0 { return false; }
|
||||
n := write(fd, data.ptr, xx data.len);
|
||||
close(fd);
|
||||
cast(s64) n == cast(s64) data.len
|
||||
cast(i64) n == cast(i64) data.len
|
||||
}
|
||||
|
||||
append_file :: (path: [:0]u8, data: string) -> bool {
|
||||
@@ -151,7 +151,7 @@ append_file :: (path: [:0]u8, data: string) -> bool {
|
||||
if fd < 0 { return false; }
|
||||
n := write(fd, data.ptr, xx data.len);
|
||||
close(fd);
|
||||
cast(s64) n == cast(s64) data.len
|
||||
cast(i64) n == cast(i64) data.len
|
||||
}
|
||||
|
||||
// ── Single-syscall ops ───────────────────────────────────────────────
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//
|
||||
// Content addressing is security-critical, so the digest is computed
|
||||
// in-process: no shelling out, no platform crypto library. All 32-bit
|
||||
// word arithmetic is done in s64 and masked back to 32 bits with
|
||||
// word arithmetic is done in i64 and masked back to 32 bits with
|
||||
// `& MASK32`, so the result is identical regardless of the host's
|
||||
// native integer width or overflow behaviour.
|
||||
//
|
||||
@@ -39,7 +39,7 @@ MASK32 :: 0xFFFFFFFF;
|
||||
|
||||
// Round constants K[0..63] — the first 32 bits of the fractional parts
|
||||
// of the cube roots of the first 64 primes (FIPS 180-4 §4.2.2).
|
||||
K : [64]s64 = .[
|
||||
K : [64]i64 = .[
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
@@ -51,31 +51,31 @@ K : [64]s64 = .[
|
||||
];
|
||||
|
||||
// 32-bit right rotate. `word` must already be masked to 32 bits.
|
||||
rotr :: (word: s64, n: s64) -> s64 {
|
||||
rotr :: (word: i64, n: i64) -> i64 {
|
||||
((word >> n) | (word << (32 - n))) & MASK32
|
||||
}
|
||||
|
||||
big_sigma0 :: (x: s64) -> s64 { rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22) }
|
||||
big_sigma1 :: (x: s64) -> s64 { rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25) }
|
||||
small_sigma0 :: (x: s64) -> s64 { rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3) }
|
||||
small_sigma1 :: (x: s64) -> s64 { rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10) }
|
||||
big_sigma0 :: (x: i64) -> i64 { rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22) }
|
||||
big_sigma1 :: (x: i64) -> i64 { rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25) }
|
||||
small_sigma0 :: (x: i64) -> i64 { rotr(x, 7) ^ rotr(x, 18) ^ (x >> 3) }
|
||||
small_sigma1 :: (x: i64) -> i64 { rotr(x, 17) ^ rotr(x, 19) ^ (x >> 10) }
|
||||
|
||||
Sha256 :: struct {
|
||||
h: [8]s64; // running hash state (each entry masked to 32 bits)
|
||||
h: [8]i64; // running hash state (each entry masked to 32 bits)
|
||||
buf: [64]u8; // partial-block buffer
|
||||
buf_len: s64; // bytes currently in `buf` (0..63)
|
||||
total_len: s64; // total bytes absorbed so far
|
||||
buf_len: i64; // bytes currently in `buf` (0..63)
|
||||
total_len: i64; // total bytes absorbed so far
|
||||
|
||||
// Crunch the 64-byte block currently in `buf` into the state.
|
||||
process_block :: (self: *Sha256) {
|
||||
w : [64]s64 = ---;
|
||||
w : [64]i64 = ---;
|
||||
t := 0;
|
||||
while t < 16 {
|
||||
base := t * 4;
|
||||
w[t] = ((cast(s64) self.buf[base]) << 24)
|
||||
| ((cast(s64) self.buf[base + 1]) << 16)
|
||||
| ((cast(s64) self.buf[base + 2]) << 8)
|
||||
| (cast(s64) self.buf[base + 3]);
|
||||
w[t] = ((cast(i64) self.buf[base]) << 24)
|
||||
| ((cast(i64) self.buf[base + 1]) << 16)
|
||||
| ((cast(i64) self.buf[base + 2]) << 8)
|
||||
| (cast(i64) self.buf[base + 3]);
|
||||
t += 1;
|
||||
}
|
||||
t = 16;
|
||||
@@ -186,7 +186,7 @@ Sha256 :: struct {
|
||||
}
|
||||
|
||||
// Lowercase-hex ASCII byte for a 0..15 nibble. 48='0', 97='a'.
|
||||
nibble_hex :: (n: s64) -> u8 {
|
||||
nibble_hex :: (n: i64) -> u8 {
|
||||
if n < 10 then xx (n + 48) else xx (n - 10 + 97)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
// This module delivers the JSON VALUE MODEL, the WRITER, and the READER
|
||||
// (parser). The model is built once and shared by both directions.
|
||||
//
|
||||
// NUMBERS ARE INTEGERS ONLY (s64) for this milestone — there is no
|
||||
// NUMBERS ARE INTEGERS ONLY (i64) for this milestone — there is no
|
||||
// fraction or exponent. A JSON value is one of: null, bool, integer,
|
||||
// string, array, object. The reader REJECTS a fraction or exponent
|
||||
// (`error.BadNumber`) rather than silently truncating it.
|
||||
@@ -82,7 +82,7 @@ JsonError :: error { Overflow, Io }
|
||||
Value :: enum {
|
||||
null_;
|
||||
bool_: bool;
|
||||
int_: s64;
|
||||
int_: i64;
|
||||
str: string; // view into caller-owned bytes; not copied
|
||||
array: Array;
|
||||
object: Object;
|
||||
@@ -100,8 +100,8 @@ Member :: struct {
|
||||
// allocator explicitly.
|
||||
Array :: struct {
|
||||
items: [*]Value = null;
|
||||
len: s64 = 0;
|
||||
cap: s64 = 0;
|
||||
len: i64 = 0;
|
||||
cap: i64 = 0;
|
||||
|
||||
// Append `v`, preserving order. Grows the backing store through the
|
||||
// explicit `alloc` when full (doubling), freeing the old buffer.
|
||||
@@ -133,8 +133,8 @@ Array :: struct {
|
||||
// explicit `alloc`.
|
||||
Object :: struct {
|
||||
items: [*]Member = null;
|
||||
len: s64 = 0;
|
||||
cap: s64 = 0;
|
||||
len: i64 = 0;
|
||||
cap: i64 = 0;
|
||||
|
||||
// Append a (key, val) pair at the end. Does not check for or merge a
|
||||
// duplicate key — insertion order is the contract; a repeated key is
|
||||
@@ -177,7 +177,7 @@ Object :: struct {
|
||||
|
||||
Sink :: struct {
|
||||
dst: []u8; // caller-owned destination (buffer mode) or staging (file mode)
|
||||
pos: s64 = 0; // bytes currently in `dst`
|
||||
pos: i64 = 0; // bytes currently in `dst`
|
||||
file: *File = null; // null => buffer mode
|
||||
|
||||
put_byte :: (self: *Sink, b: u8) -> !JsonError {
|
||||
@@ -213,7 +213,7 @@ Sink :: struct {
|
||||
// ── Writer ───────────────────────────────────────────────────────────
|
||||
|
||||
// Lowercase-hex ASCII byte for a 0..15 nibble. 48='0', 97='a'.
|
||||
hex_digit :: (n: s64) -> u8 {
|
||||
hex_digit :: (n: i64) -> u8 {
|
||||
if n < 10 then xx (n + 48) else xx (n - 10 + 97)
|
||||
}
|
||||
|
||||
@@ -224,8 +224,8 @@ write_u_escape :: (c: u8, sink: *Sink) -> !JsonError {
|
||||
try sink.put_byte(117); // 'u'
|
||||
try sink.put_byte(48); // '0'
|
||||
try sink.put_byte(48); // '0'
|
||||
try sink.put_byte(hex_digit((cast(s64) c >> 4) & 0xF));
|
||||
try sink.put_byte(hex_digit(cast(s64) c & 0xF));
|
||||
try sink.put_byte(hex_digit((cast(i64) c >> 4) & 0xF));
|
||||
try sink.put_byte(hex_digit(cast(i64) c & 0xF));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -254,12 +254,12 @@ write_string :: (s: string, sink: *Sink) -> !JsonError {
|
||||
}
|
||||
|
||||
// Emit a signed integer in decimal, no allocation. Digits are formed in a
|
||||
// stack buffer working in NEGATIVE space so s64 MIN
|
||||
// stack buffer working in NEGATIVE space so i64 MIN
|
||||
// (-9223372036854775808) — whose magnitude is not representable as a
|
||||
// positive s64 — serializes correctly.
|
||||
write_int :: (n: s64, sink: *Sink) -> !JsonError {
|
||||
// positive i64 — serializes correctly.
|
||||
write_int :: (n: i64, sink: *Sink) -> !JsonError {
|
||||
if n == 0 { try sink.put_byte(48); return; }
|
||||
tmp : [20]u8 = ---; // 19 digits + sign is the s64 worst case
|
||||
tmp : [20]u8 = ---; // 19 digits + sign is the i64 worst case
|
||||
neg := n < 0;
|
||||
v := n;
|
||||
if !neg { v = 0 - n; } // fold positives into negative space
|
||||
@@ -321,7 +321,7 @@ write_object :: (obj: Object, sink: *Sink) -> !JsonError {
|
||||
// bytes written. Raises `error.Overflow` if `dst` is too small (the
|
||||
// partial contents of `dst` are then undefined — nothing is truncated
|
||||
// silently). No allocation.
|
||||
write_to_buffer :: (v: Value, dst: []u8) -> (s64, !JsonError) {
|
||||
write_to_buffer :: (v: Value, dst: []u8) -> (i64, !JsonError) {
|
||||
sink := Sink.{ dst = dst };
|
||||
try write_value(v, @sink);
|
||||
return sink.pos;
|
||||
@@ -343,7 +343,7 @@ write_to_file :: (v: Value, file: *File, staging: []u8) -> !JsonError {
|
||||
// `parse(src, alloc)` turns a JSON document in `src` into the value model
|
||||
// above. It is the inverse of the writer for the v0 scope: objects (in
|
||||
// INSERTION ORDER), arrays, strings (with full unescaping incl. \uXXXX
|
||||
// and surrogate pairs), s64 integers, bool, null.
|
||||
// and surrogate pairs), i64 integers, bool, null.
|
||||
//
|
||||
// FAILURE SURFACING (hard contract): every malformed input raises on the
|
||||
// error channel (`!JsonParseError`) — never a bogus or default value.
|
||||
@@ -351,7 +351,7 @@ write_to_file :: (v: Value, file: *File, staging: []u8) -> !JsonError {
|
||||
// `pos` (the parser cursor) marks where the failure was detected.
|
||||
//
|
||||
// NOT SUPPORTED (rejected, not silently accepted): a fraction or exponent
|
||||
// in a number (`1.5`, `1e9`) → `BadNumber`; a number outside s64 →
|
||||
// in a number (`1.5`, `1e9`) → `BadNumber`; a number outside i64 →
|
||||
// `BadNumber`; a leading-zero integer (`01`) → `BadNumber`. An UNESCAPED
|
||||
// raw control byte (U+0000..U+001F) inside a string → `BadControlChar`
|
||||
// (RFC 8259 §7 requires those bytes to be escaped); the escaped forms
|
||||
@@ -386,17 +386,17 @@ JsonParseError :: error { UnexpectedToken, UnexpectedEnd, BadEscape, BadNumber,
|
||||
|
||||
// Lowercase/uppercase hex nibble value (0..15) of an ASCII byte; a non-hex
|
||||
// byte in a `\uXXXX` escape is a `BadEscape`.
|
||||
hex_value :: (c: u8) -> (s64, !JsonParseError) {
|
||||
if c >= 48 and c <= 57 { return (cast(s64) c) - 48; } // '0'..'9'
|
||||
if c >= 97 and c <= 102 { return (cast(s64) c) - 97 + 10; } // 'a'..'f'
|
||||
if c >= 65 and c <= 70 { return (cast(s64) c) - 65 + 10; } // 'A'..'F'
|
||||
hex_value :: (c: u8) -> (i64, !JsonParseError) {
|
||||
if c >= 48 and c <= 57 { return (cast(i64) c) - 48; } // '0'..'9'
|
||||
if c >= 97 and c <= 102 { return (cast(i64) c) - 97 + 10; } // 'a'..'f'
|
||||
if c >= 65 and c <= 70 { return (cast(i64) c) - 65 + 10; } // 'A'..'F'
|
||||
raise error.BadEscape;
|
||||
}
|
||||
|
||||
// Encode code point `cp` (already validated 0..0x10FFFF, non-surrogate) as
|
||||
// UTF-8 into `out`, returning the byte count (1..4). No bounds check: the
|
||||
// decode buffer is sized to the raw escaped span, which always dominates.
|
||||
encode_utf8 :: (cp: s64, out: [*]u8) -> s64 {
|
||||
encode_utf8 :: (cp: i64, out: [*]u8) -> i64 {
|
||||
if cp < 0x80 {
|
||||
out[0] = xx cp;
|
||||
return 1;
|
||||
@@ -424,7 +424,7 @@ encode_utf8 :: (cp: s64, out: [*]u8) -> s64 {
|
||||
// EXPLICIT allocator for composites + decoded strings.
|
||||
Parser :: struct {
|
||||
src: string;
|
||||
pos: s64 = 0;
|
||||
pos: i64 = 0;
|
||||
alloc: Allocator;
|
||||
|
||||
// Advance past JSON whitespace (space / tab / LF / CR).
|
||||
@@ -450,7 +450,7 @@ Parser :: struct {
|
||||
|
||||
// Read 4 hex digits at `i` (which must lie within [.., end)); returns
|
||||
// the 16-bit value. Fewer than 4 digits before `end` is a BadEscape.
|
||||
read_hex4 :: (self: *Parser, i: s64, end: s64) -> (s64, !JsonParseError) {
|
||||
read_hex4 :: (self: *Parser, i: i64, end: i64) -> (i64, !JsonParseError) {
|
||||
if i + 4 > end { raise error.BadEscape; }
|
||||
v := 0;
|
||||
k := 0;
|
||||
@@ -464,7 +464,7 @@ Parser :: struct {
|
||||
// Decode the escaped string body in [start, end) into `out`, returning
|
||||
// the decoded byte length. Pass 1 (in parse_string) guarantees there is
|
||||
// no dangling backslash, so the byte after every `\` is in range.
|
||||
decode_into :: (self: *Parser, start: s64, end: s64, out: [*]u8) -> (s64, !JsonParseError) {
|
||||
decode_into :: (self: *Parser, start: i64, end: i64, out: [*]u8) -> (i64, !JsonParseError) {
|
||||
di := 0;
|
||||
i := start;
|
||||
while i < end {
|
||||
@@ -544,15 +544,15 @@ Parser :: struct {
|
||||
return string.{ ptr = out, len = dlen };
|
||||
}
|
||||
|
||||
// Parse an s64 integer (optional '-', then digits). Rejects leading
|
||||
// zeros, a fraction/exponent tail, and any value outside s64 — all
|
||||
// `BadNumber`. Accumulates in NEGATIVE space so s64 MIN parses exactly.
|
||||
parse_number :: (self: *Parser) -> (s64, !JsonParseError) {
|
||||
// s64 bounds, built positionally because |MIN| is not a
|
||||
// representable positive s64 literal. `min_div10` is `MIN / 10`
|
||||
// Parse an i64 integer (optional '-', then digits). Rejects leading
|
||||
// zeros, a fraction/exponent tail, and any value outside i64 — all
|
||||
// `BadNumber`. Accumulates in NEGATIVE space so i64 MIN parses exactly.
|
||||
parse_number :: (self: *Parser) -> (i64, !JsonParseError) {
|
||||
// i64 bounds, built positionally because |MIN| is not a
|
||||
// representable positive i64 literal. `min_div10` is `MIN / 10`
|
||||
// truncated toward zero (remainder -8) — the digit loop's overflow
|
||||
// threshold. Accumulation runs in NEGATIVE space so MIN is exact.
|
||||
s64_min := 0 - 9223372036854775807 - 1;
|
||||
i64_min := 0 - 9223372036854775807 - 1;
|
||||
min_div10 := 0 - 922337203685477580;
|
||||
neg := false;
|
||||
if self.src[self.pos] == 45 { neg = true; self.pos += 1; } // '-'
|
||||
@@ -560,12 +560,12 @@ Parser :: struct {
|
||||
dstart := self.pos;
|
||||
c0 := self.src[self.pos];
|
||||
if c0 < 48 or c0 > 57 { raise error.BadNumber; }
|
||||
val : s64 = 0;
|
||||
val : i64 = 0;
|
||||
digits := 0;
|
||||
while self.pos < self.src.len {
|
||||
c := self.src[self.pos];
|
||||
if c < 48 or c > 57 { break; }
|
||||
d := (cast(s64) c) - 48;
|
||||
d := (cast(i64) c) - 48;
|
||||
if val < min_div10 { raise error.BadNumber; }
|
||||
if val == min_div10 and d > 8 { raise error.BadNumber; }
|
||||
val = val * 10 - d;
|
||||
@@ -578,7 +578,7 @@ Parser :: struct {
|
||||
if nc == 46 or nc == 101 or nc == 69 { raise error.BadNumber; } // '.' / 'e' / 'E' — ints only
|
||||
}
|
||||
if !neg {
|
||||
if val == s64_min { raise error.BadNumber; } // |MIN| not representable as +s64
|
||||
if val == i64_min { raise error.BadNumber; } // |MIN| not representable as +i64
|
||||
val = 0 - val;
|
||||
}
|
||||
return val;
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
List :: struct ($T: Type) {
|
||||
items: [*]T = null;
|
||||
len: s64 = 0;
|
||||
cap: s64 = 0;
|
||||
len: i64 = 0;
|
||||
cap: i64 = 0;
|
||||
|
||||
append :: (list: *List(T), item: T, alloc: Allocator = context.allocator) {
|
||||
if list.len >= list.cap {
|
||||
@@ -22,7 +22,7 @@ List :: struct ($T: Type) {
|
||||
list.len += 1;
|
||||
}
|
||||
|
||||
ensure_capacity :: (list: *List(T), n: s64, alloc: Allocator = context.allocator) {
|
||||
ensure_capacity :: (list: *List(T), n: i64, alloc: Allocator = context.allocator) {
|
||||
if list.cap >= n { return; }
|
||||
new_cap := if list.cap == 0 then 4 else list.cap;
|
||||
while new_cap < n { new_cap = new_cap * 2; }
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
libc :: #library "c";
|
||||
|
||||
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
|
||||
// Prefix the level, append a newline, write the whole line to stderr.
|
||||
log_emit :: (level: string, msg: string) {
|
||||
|
||||
@@ -31,7 +31,7 @@ destroy :: ufcs (a: Allocator, ptr: *$T) {
|
||||
}
|
||||
|
||||
// Allocate a []T of `count` elements. Contents are UNINITIALISED.
|
||||
alloc :: ufcs (a: Allocator, $T: Type, count: s64) -> []T {
|
||||
alloc :: ufcs (a: Allocator, $T: Type, count: i64) -> []T {
|
||||
raw := a.alloc_bytes(count * size_of(T));
|
||||
s : []T = ---;
|
||||
s.ptr = xx raw;
|
||||
@@ -57,7 +57,7 @@ clone :: ufcs (src: []$T, a: Allocator) -> []T {
|
||||
// Reallocate a slice to `new_count` elements: fresh storage, contents
|
||||
// copied up to min(len, new_count), old backing freed. The returned
|
||||
// slice replaces the operand — the old slice is dangling after this.
|
||||
resize :: ufcs (slice: []$T, a: Allocator, new_count: s64) -> []T {
|
||||
resize :: ufcs (slice: []$T, a: Allocator, new_count: i64) -> []T {
|
||||
raw := a.alloc_bytes(new_count * size_of(T));
|
||||
n := if slice.len < new_count then slice.len else new_count;
|
||||
memcpy(raw, xx slice.ptr, n * size_of(T));
|
||||
@@ -72,7 +72,7 @@ resize :: ufcs (slice: []$T, a: Allocator, new_count: s64) -> []T {
|
||||
// dealloc — there is no in-place grow primitive to try yet, and
|
||||
// `align` beyond the heap's natural 8 is not honored until the
|
||||
// protocol carries alignment.
|
||||
mem_realloc :: ufcs (a: Allocator, ptr: *void, old: s64, new: s64, align: s64) -> *void {
|
||||
mem_realloc :: ufcs (a: Allocator, ptr: *void, old: i64, new: i64, align: i64) -> *void {
|
||||
raw := a.alloc_bytes(new);
|
||||
n := if old < new then old else new;
|
||||
memcpy(raw, ptr, n);
|
||||
@@ -91,7 +91,7 @@ mem_realloc :: ufcs (a: Allocator, ptr: *void, old: s64, new: s64, align: s64) -
|
||||
CAllocator :: struct {}
|
||||
|
||||
impl Allocator for CAllocator {
|
||||
alloc_bytes :: (self: *CAllocator, size: s64) -> *void {
|
||||
alloc_bytes :: (self: *CAllocator, size: i64) -> *void {
|
||||
return libc_malloc(size);
|
||||
}
|
||||
dealloc_bytes :: (self: *CAllocator, ptr: *void) {
|
||||
@@ -112,7 +112,7 @@ impl Allocator for CAllocator {
|
||||
// print("alloc count: {}\n", gpa.alloc_count);
|
||||
|
||||
GPA :: struct {
|
||||
alloc_count: s64;
|
||||
alloc_count: i64;
|
||||
|
||||
init :: () -> GPA {
|
||||
GPA.{ alloc_count = 0 }
|
||||
@@ -120,7 +120,7 @@ GPA :: struct {
|
||||
}
|
||||
|
||||
impl Allocator for GPA {
|
||||
alloc_bytes :: (self: *GPA, size: s64) -> *void {
|
||||
alloc_bytes :: (self: *GPA, size: i64) -> *void {
|
||||
self.alloc_count += 1;
|
||||
return libc_malloc(size);
|
||||
}
|
||||
@@ -146,15 +146,15 @@ impl Allocator for GPA {
|
||||
|
||||
ArenaChunk :: struct {
|
||||
next: *ArenaChunk;
|
||||
cap: s64;
|
||||
cap: i64;
|
||||
}
|
||||
|
||||
Arena :: struct {
|
||||
first: *ArenaChunk;
|
||||
end_index: s64;
|
||||
end_index: i64;
|
||||
parent: Allocator;
|
||||
|
||||
add_chunk :: (a: *Arena, min_size: s64) {
|
||||
add_chunk :: (a: *Arena, min_size: i64) {
|
||||
prev_cap := if a.first != null then a.first.cap else 0;
|
||||
needed := min_size + 16 + 16;
|
||||
len := (prev_cap + needed) * 3 / 2;
|
||||
@@ -166,7 +166,7 @@ Arena :: struct {
|
||||
a.end_index = 0;
|
||||
}
|
||||
|
||||
init :: (parent_alloc: Allocator, size: s64) -> Arena {
|
||||
init :: (parent_alloc: Allocator, size: i64) -> Arena {
|
||||
self : Arena = .{ first = null, end_index = 0, parent = parent_alloc };
|
||||
self.add_chunk(size);
|
||||
self
|
||||
@@ -198,7 +198,7 @@ Arena :: struct {
|
||||
}
|
||||
|
||||
impl Allocator for Arena {
|
||||
alloc_bytes :: (self: *Arena, size: s64) -> *void {
|
||||
alloc_bytes :: (self: *Arena, size: i64) -> *void {
|
||||
aligned := (size + 7) & (0 - 8);
|
||||
if self.first != null {
|
||||
usable := self.first.cap - 16;
|
||||
@@ -232,10 +232,10 @@ impl Allocator for Arena {
|
||||
|
||||
BufAlloc :: struct {
|
||||
buf: [*]u8;
|
||||
len: s64;
|
||||
pos: s64;
|
||||
len: i64;
|
||||
pos: i64;
|
||||
|
||||
init :: (buf: [*]u8, len: s64) -> BufAlloc {
|
||||
init :: (buf: [*]u8, len: i64) -> BufAlloc {
|
||||
BufAlloc.{ buf = buf, len = len, pos = 0 }
|
||||
}
|
||||
|
||||
@@ -245,7 +245,7 @@ BufAlloc :: struct {
|
||||
}
|
||||
|
||||
impl Allocator for BufAlloc {
|
||||
alloc_bytes :: (self: *BufAlloc, size: s64) -> *void {
|
||||
alloc_bytes :: (self: *BufAlloc, size: i64) -> *void {
|
||||
aligned := (size + 7) & (0 - 8);
|
||||
if self.pos + aligned > self.len {
|
||||
return null;
|
||||
@@ -282,9 +282,9 @@ impl Allocator for BufAlloc {
|
||||
|
||||
TrackingAllocator :: struct {
|
||||
parent: Allocator;
|
||||
alloc_count: s64;
|
||||
dealloc_count: s64;
|
||||
total_alloc_bytes: s64;
|
||||
alloc_count: i64;
|
||||
dealloc_count: i64;
|
||||
total_alloc_bytes: i64;
|
||||
|
||||
init :: (parent_alloc: Allocator) -> TrackingAllocator {
|
||||
TrackingAllocator.{
|
||||
@@ -295,7 +295,7 @@ TrackingAllocator :: struct {
|
||||
}
|
||||
}
|
||||
|
||||
leak_count :: (t: *TrackingAllocator) -> s64 {
|
||||
leak_count :: (t: *TrackingAllocator) -> i64 {
|
||||
t.alloc_count - t.dealloc_count
|
||||
}
|
||||
|
||||
@@ -306,7 +306,7 @@ TrackingAllocator :: struct {
|
||||
}
|
||||
|
||||
impl Allocator for TrackingAllocator {
|
||||
alloc_bytes :: (self: *TrackingAllocator, size: s64) -> *void {
|
||||
alloc_bytes :: (self: *TrackingAllocator, size: i64) -> *void {
|
||||
ptr := self.parent.alloc_bytes(size);
|
||||
if ptr != null {
|
||||
self.alloc_count += 1;
|
||||
|
||||
@@ -21,12 +21,12 @@ libc :: #library "c";
|
||||
// ── Low-level libc bindings ─────────────────────────────────────────
|
||||
|
||||
popen :: (cmd: [:0]u8, mode: [:0]u8) -> *void #foreign libc;
|
||||
pclose :: (stream: *void) -> s32 #foreign libc;
|
||||
pclose :: (stream: *void) -> i32 #foreign libc;
|
||||
fread :: (ptr: [*]u8, size: usize, nmemb: usize, stream: *void) -> usize #foreign libc;
|
||||
feof :: (stream: *void) -> s32 #foreign libc;
|
||||
feof :: (stream: *void) -> i32 #foreign libc;
|
||||
getenv :: (name: [:0]u8) -> *u8 #foreign libc;
|
||||
strlen :: (s: *u8) -> usize #foreign libc;
|
||||
system :: (cmd: [:0]u8) -> s32 #foreign libc;
|
||||
system :: (cmd: [:0]u8) -> i32 #foreign libc;
|
||||
|
||||
// ── Public types ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -34,7 +34,7 @@ ProcessResult :: struct {
|
||||
/// Exit code as reported by `WEXITSTATUS(status)`. 0 = success.
|
||||
/// Note: doesn't distinguish "killed by signal" from "exited
|
||||
/// non-zero"; phase 1B will return a tagged union.
|
||||
exit_code: s32;
|
||||
exit_code: i32;
|
||||
stdout: string;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ ProcessResult :: struct {
|
||||
// with stdout, append " 2>&1" to the command.
|
||||
run :: (cmd: [:0]u8) -> ?ProcessResult {
|
||||
f := popen(cmd, "r");
|
||||
if cast(s64) f == 0 { return null; }
|
||||
if cast(i64) f == 0 { return null; }
|
||||
|
||||
out := "";
|
||||
buf := cstring(4096);
|
||||
@@ -61,7 +61,7 @@ run :: (cmd: [:0]u8) -> ?ProcessResult {
|
||||
if n > 0 {
|
||||
chunk : string = ---;
|
||||
chunk.ptr = buf.ptr;
|
||||
chunk.len = cast(s64) n;
|
||||
chunk.len = cast(i64) n;
|
||||
out = concat(out, chunk);
|
||||
}
|
||||
}
|
||||
@@ -85,12 +85,12 @@ run :: (cmd: [:0]u8) -> ?ProcessResult {
|
||||
// string if set to "".
|
||||
env :: (name: [:0]u8) -> ?string {
|
||||
p := getenv(name);
|
||||
addr : s64 = xx p;
|
||||
addr : i64 = xx p;
|
||||
if addr == 0 { return null; }
|
||||
n := strlen(p);
|
||||
if n == 0 { return ""; }
|
||||
buf := cstring(cast(s64) n);
|
||||
memcpy(buf.ptr, xx p, cast(s64) n);
|
||||
buf := cstring(cast(i64) n);
|
||||
memcpy(buf.ptr, xx p, cast(i64) n);
|
||||
buf
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ find_executable :: (name: [:0]u8) -> ?string {
|
||||
// via `write(2)`, so skipping the stdio flush loses nothing. Binding the
|
||||
// symbol `"exit"` would also collide with this module's own `exit` function
|
||||
// at the link level.
|
||||
clib_exit :: (code: s32) -> noreturn #foreign libc "_exit";
|
||||
clib_exit :: (code: i32) -> noreturn #foreign libc "_exit";
|
||||
|
||||
// Stop the process immediately with exit code `code`. Does NOT unwind:
|
||||
// no `defer` / `onfail` cleanup runs, no error-trace frames are pushed —
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
libc :: #library "c";
|
||||
|
||||
// POSIX socket API
|
||||
socket :: (domain: s32, kind: s32, protocol: s32) -> s32 #foreign libc;
|
||||
setsockopt :: (fd: s32, level: s32, optname: s32, optval: *s32, optlen: u32) -> s32 #foreign libc;
|
||||
bind :: (fd: s32, addr: *SockAddr, addrlen: u32) -> s32 #foreign libc;
|
||||
listen :: (fd: s32, backlog: s32) -> s32 #foreign libc;
|
||||
accept :: (fd: s32, addr: *SockAddr, addrlen: *u32) -> s32 #foreign libc;
|
||||
read :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
close :: (fd: s32) -> s32 #foreign libc;
|
||||
socket :: (domain: i32, kind: i32, protocol: i32) -> i32 #foreign libc;
|
||||
setsockopt :: (fd: i32, level: i32, optname: i32, optval: *i32, optlen: u32) -> i32 #foreign libc;
|
||||
bind :: (fd: i32, addr: *SockAddr, addrlen: u32) -> i32 #foreign libc;
|
||||
listen :: (fd: i32, backlog: i32) -> i32 #foreign libc;
|
||||
accept :: (fd: i32, addr: *SockAddr, addrlen: *u32) -> i32 #foreign libc;
|
||||
read :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
close :: (fd: i32) -> i32 #foreign libc;
|
||||
|
||||
// Constants (macOS)
|
||||
AF_INET :s32: 2;
|
||||
SOCK_STREAM :s32: 1;
|
||||
SOL_SOCKET :s32: 0xFFFF;
|
||||
SO_REUSEADDR :s32: 0x4;
|
||||
AF_INET :i32: 2;
|
||||
SOCK_STREAM :i32: 1;
|
||||
SOL_SOCKET :i32: 0xFFFF;
|
||||
SO_REUSEADDR :i32: 0x4;
|
||||
|
||||
// macOS sockaddr_in (16 bytes, has sin_len field)
|
||||
SockAddr :: struct {
|
||||
@@ -28,6 +28,6 @@ SockAddr :: struct {
|
||||
sin_zero: u64 = 0;
|
||||
}
|
||||
|
||||
htons :: (port: s64) -> u16 {
|
||||
htons :: (port: i64) -> u16 {
|
||||
cast(u16) (((port & 0xFF) << 8) | ((port >> 8) & 0xFF))
|
||||
}
|
||||
|
||||
@@ -28,16 +28,16 @@ libc :: #library "c";
|
||||
// library/vendors/sx_trace_runtime/sx_trace.c.
|
||||
TraceFrame :: struct {
|
||||
file: string;
|
||||
line: s32;
|
||||
col: s32;
|
||||
line: i32;
|
||||
col: i32;
|
||||
func: string;
|
||||
line_text: string; // the source line, for the snippet + caret
|
||||
}
|
||||
|
||||
// `n` spaces — used to position the `^` caret under a column.
|
||||
spaces :: (n: s32) -> string {
|
||||
spaces :: (n: i32) -> string {
|
||||
s := "";
|
||||
i : s32 = 0;
|
||||
i : i32 = 0;
|
||||
while i < n {
|
||||
s = concat(s, " ");
|
||||
i = i + 1;
|
||||
@@ -54,7 +54,7 @@ sx_trace_len :: () -> u32 #foreign;
|
||||
sx_trace_truncated :: () -> u32 #foreign;
|
||||
sx_trace_frame_at :: (i: u32) -> u64 #foreign;
|
||||
|
||||
write :: (fd: s32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
write :: (fd: i32, buf: [*]u8, count: usize) -> isize #foreign libc;
|
||||
|
||||
// Render the current trace buffer to a string (allocated from
|
||||
// context.allocator). Empty buffer → "" so callers can cheaply skip output.
|
||||
|
||||
Reference in New Issue
Block a user