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:
agra
2026-06-12 09:31:53 +03:00
parent 515ecebea7
commit d8076b9333
1054 changed files with 6836 additions and 6839 deletions

View File

@@ -3,7 +3,7 @@ Architecture :: enum { aarch64; x86_64; wasm32; wasm64; unknown; }
OS : OperatingSystem = .unknown;
ARCH : Architecture = .unknown;
POINTER_SIZE : s64 = 8;
POINTER_SIZE : i64 = 8;
BuildOptions :: struct #compiler {
add_link_flag :: (self: BuildOptions, flag: [:0]u8);
@@ -18,9 +18,9 @@ BuildOptions :: struct #compiler {
// zipped under `<dest>/` at the APK root. Idiomatic chess form is
// `opts.add_asset_dir("assets", "assets")`.
add_asset_dir :: (self: BuildOptions, src: [:0]u8, dest: [:0]u8);
asset_dir_count :: (self: BuildOptions) -> s64;
asset_dir_src_at :: (self: BuildOptions, i: s64) -> string;
asset_dir_dest_at :: (self: BuildOptions, i: s64) -> string;
asset_dir_count :: (self: BuildOptions) -> i64;
asset_dir_src_at :: (self: BuildOptions, i: i64) -> string;
asset_dir_dest_at :: (self: BuildOptions, i: i64) -> string;
// Post-link callback. Registers a sx function the compiler will
// invoke after `target.link()` returns. Used by the sx-side
@@ -67,10 +67,10 @@ BuildOptions :: struct #compiler {
// `framework_path_at(0..framework_path_count())` into
// `<bundle>/Frameworks/`. Slice returns aren't natively expressible
// through the compiler-hook bridge yet, hence the indexed form.
framework_count :: (self: BuildOptions) -> s64;
framework_at :: (self: BuildOptions, i: s64) -> string;
framework_path_count :: (self: BuildOptions) -> s64;
framework_path_at :: (self: BuildOptions, i: s64) -> string;
framework_count :: (self: BuildOptions) -> i64;
framework_at :: (self: BuildOptions, i: i64) -> string;
framework_path_count :: (self: BuildOptions) -> i64;
framework_path_at :: (self: BuildOptions, i: i64) -> string;
// Android APK bundling parameters. `manifest_path` overrides the
// bundler's auto-generated AndroidManifest.xml; `keystore_path`
@@ -86,9 +86,9 @@ BuildOptions :: struct #compiler {
// for each entry writes a `.java` file at
// `<stage>/java/<foreign_path>.java`, compiles via javac + d8, and
// bundles the resulting classes.dex into the APK.
jni_main_count :: (self: BuildOptions) -> s64;
jni_main_foreign_path_at :: (self: BuildOptions, i: s64) -> string;
jni_main_java_source_at :: (self: BuildOptions, i: s64) -> string;
jni_main_count :: (self: BuildOptions) -> i64;
jni_main_foreign_path_at :: (self: BuildOptions, i: i64) -> string;
jni_main_java_source_at :: (self: BuildOptions, i: i64) -> string;
}
build_options :: () -> BuildOptions #compiler;

View File

@@ -26,8 +26,8 @@ SEL :: *void;
// Apple's `BOOL` is a signed char (NOT sx's built-in `bool`, which is
// LLVM `i1`). Obj-C method signatures that take or return `BOOL` cross
// the FFI boundary as `s8`.
BOOL :: s8;
// the FFI boundary as `i8`.
BOOL :: i8;
// On macOS libobjc is auto-loaded by libSystem; on iOS it isn't, so we
// link it explicitly. Foundation registers NSString etc. with the runtime,

View File

@@ -32,8 +32,8 @@
// it wraps. Total = 48 bytes.
Block :: struct {
isa: *void;
flags: s32;
reserved: s32;
flags: i32;
reserved: i32;
invoke: *void;
descriptor: *void;
sx_env: *void;
@@ -95,7 +95,7 @@ impl Into(Block) for Closure(..$args) -> $R {
build_block_convert :: (args: []Type, $ret: Type) -> string {
ret_name := type_name(ret);
code := "__invoke :: (block_self: *Block";
i : s64 = 0;
i : i64 = 0;
while i < args.len {
code = concat(code, ", arg");
code = concat(code, int_to_string(i));

View File

@@ -2,8 +2,8 @@
// No #library needed — caller provides a loader (e.g. SDL_GL_GetProcAddress)
// Constants
GL_FALSE :s32: 0;
GL_TRUE :s32: 1;
GL_FALSE :i32: 0;
GL_TRUE :i32: 1;
GL_DEPTH_TEST :u32: 0x0B71;
GL_CULL_FACE :u32: 0x0B44;
GL_BLEND :u32: 0x0BE2;
@@ -29,35 +29,35 @@ glClearColor : (f32, f32, f32, f32) -> void callconv(.c) = ---;
glClear : (u32) -> void callconv(.c) = ---;
glEnable : (u32) -> void callconv(.c) = ---;
glDisable : (u32) -> void callconv(.c) = ---;
glViewport : (s32, s32, s32, s32) -> void callconv(.c) = ---;
glViewport : (i32, i32, i32, i32) -> void callconv(.c) = ---;
glFlush : () -> void callconv(.c) = ---;
glDrawArrays : (u32, s32, s32) -> void callconv(.c) = ---;
glDrawArrays : (u32, i32, i32) -> void callconv(.c) = ---;
glPolygonMode : (u32, u32) -> void callconv(.c) = ---;
glLineWidth : (f32) -> void callconv(.c) = ---;
glCreateShader : (u32) -> u32 callconv(.c) = ---;
glShaderSource : (u32, s32, *[:0]u8, *s32) -> void callconv(.c) = ---;
glShaderSource : (u32, i32, *[:0]u8, *i32) -> void callconv(.c) = ---;
glCompileShader : (u32) -> void callconv(.c) = ---;
glGetShaderiv : (u32, u32, *s32) -> void callconv(.c) = ---;
glGetShaderInfoLog : (u32, s32, *s32, [*]u8) -> void callconv(.c) = ---;
glGetShaderiv : (u32, u32, *i32) -> void callconv(.c) = ---;
glGetShaderInfoLog : (u32, i32, *i32, [*]u8) -> void callconv(.c) = ---;
glCreateProgram : () -> u32 callconv(.c) = ---;
glAttachShader : (u32, u32) -> void callconv(.c) = ---;
glLinkProgram : (u32) -> void callconv(.c) = ---;
glGetProgramiv : (u32, u32, *s32) -> void callconv(.c) = ---;
glGetProgramInfoLog : (u32, s32, *s32, [*]u8) -> void callconv(.c) = ---;
glGetProgramiv : (u32, u32, *i32) -> void callconv(.c) = ---;
glGetProgramInfoLog : (u32, i32, *i32, [*]u8) -> void callconv(.c) = ---;
glUseProgram : (u32) -> void callconv(.c) = ---;
glDeleteShader : (u32) -> void callconv(.c) = ---;
glGenVertexArrays : (s32, *u32) -> void callconv(.c) = ---;
glGenBuffers : (s32, *u32) -> void callconv(.c) = ---;
glGenVertexArrays : (i32, *u32) -> void callconv(.c) = ---;
glGenBuffers : (i32, *u32) -> void callconv(.c) = ---;
glBindVertexArray : (u32) -> void callconv(.c) = ---;
glBindBuffer : (u32, u32) -> void callconv(.c) = ---;
glBufferData : (u32, isize, *void, u32) -> void callconv(.c) = ---;
glVertexAttribPointer : (u32, s32, u32, u8, s32, *void) -> void callconv(.c) = ---;
glVertexAttribPointer : (u32, i32, u32, u8, i32, *void) -> void callconv(.c) = ---;
glEnableVertexAttribArray : (u32) -> void callconv(.c) = ---;
glGetUniformLocation : (u32, [*]u8) -> s32 callconv(.c) = ---;
glUniformMatrix4fv : (s32, s32, u8, [*]f32) -> void callconv(.c) = ---;
glUniform3f : (s32, f32, f32, f32) -> void callconv(.c) = ---;
glGetUniformLocation : (u32, [*]u8) -> i32 callconv(.c) = ---;
glUniformMatrix4fv : (i32, i32, u8, [*]f32) -> void callconv(.c) = ---;
glUniform3f : (i32, f32, f32, f32) -> void callconv(.c) = ---;
glDepthFunc : (u32) -> void callconv(.c) = ---;
glUniform1f : (s32, f32) -> void callconv(.c) = ---;
glUniform1f : (i32, f32) -> void callconv(.c) = ---;
GL_LESS :u32: 0x0201;
GL_LEQUAL :u32: 0x0203;
GL_SCISSOR_TEST :u32: 0x0C11;
@@ -76,26 +76,26 @@ GL_RED :u32: 0x1903;
GL_R8 :u32: 0x8229;
GL_UNPACK_ALIGNMENT :u32: 0x0CF5;
glScissor : (s32, s32, s32, s32) -> void callconv(.c) = ---;
glScissor : (i32, i32, i32, i32) -> void callconv(.c) = ---;
glBufferSubData : (u32, isize, isize, *void) -> void callconv(.c) = ---;
glGenTextures : (s32, *u32) -> void callconv(.c) = ---;
glGenTextures : (i32, *u32) -> void callconv(.c) = ---;
glBindTexture : (u32, u32) -> void callconv(.c) = ---;
glTexImage2D : (u32, s32, s32, s32, s32, s32, u32, u32, *void) -> void callconv(.c) = ---;
glTexParameteri : (u32, u32, s32) -> void callconv(.c) = ---;
glTexImage2D : (u32, i32, i32, i32, i32, i32, u32, u32, *void) -> void callconv(.c) = ---;
glTexParameteri : (u32, u32, i32) -> void callconv(.c) = ---;
glBlendFunc : (u32, u32) -> void callconv(.c) = ---;
glReadPixels : (s32, s32, s32, s32, u32, u32, *void) -> void callconv(.c) = ---;
glReadPixels : (i32, i32, i32, i32, u32, u32, *void) -> void callconv(.c) = ---;
glActiveTexture : (u32) -> void callconv(.c) = ---;
glUniform1i : (s32, s32) -> void callconv(.c) = ---;
glPixelStorei : (u32, s32) -> void callconv(.c) = ---;
glTexSubImage2D : (u32, s32, s32, s32, s32, s32, u32, u32, *void) -> void callconv(.c) = ---;
glDeleteTextures : (s32, *u32) -> void callconv(.c) = ---;
glUniform1i : (i32, i32) -> void callconv(.c) = ---;
glPixelStorei : (u32, i32) -> void callconv(.c) = ---;
glTexSubImage2D : (u32, i32, i32, i32, i32, i32, u32, u32, *void) -> void callconv(.c) = ---;
glDeleteTextures : (i32, *u32) -> void callconv(.c) = ---;
glGenFramebuffers : (s32, *u32) -> void callconv(.c) = ---;
glGenRenderbuffers : (s32, *u32) -> void callconv(.c) = ---;
glGenFramebuffers : (i32, *u32) -> void callconv(.c) = ---;
glGenRenderbuffers : (i32, *u32) -> void callconv(.c) = ---;
glBindFramebuffer : (u32, u32) -> void callconv(.c) = ---;
glBindRenderbuffer : (u32, u32) -> void callconv(.c) = ---;
glFramebufferRenderbuffer : (u32, u32, u32, u32) -> void callconv(.c) = ---;
glGetRenderbufferParameteriv : (u32, u32, *s32) -> void callconv(.c) = ---;
glGetRenderbufferParameteriv : (u32, u32, *i32) -> void callconv(.c) = ---;
glCheckFramebufferStatus : (u32) -> u32 callconv(.c) = ---;
GL_TEXTURE_WRAP_S :u32: 0x2802;
@@ -173,7 +173,7 @@ create_program :: (vert_src: [:0]u8, frag_src: [:0]u8) -> u32 {
glAttachShader(prog, fs);
glLinkProgram(prog);
status : s32 = 0;
status : i32 = 0;
glGetProgramiv(prog, GL_LINK_STATUS, @status);
if status == GL_FALSE {
log_buf: [512]u8 = ---;
@@ -190,7 +190,7 @@ compile_shader :: (shader_type : u32, source: [:0]u8) -> u32 {
glShaderSource(shader, 1, source, null);
glCompileShader(shader);
status : s32 = 0;
status : i32 = 0;
glGetShaderiv(shader, GL_COMPILE_STATUS, @status);
if status == GL_FALSE {
log_buf : [512]u8 = ---;

View File

@@ -8,7 +8,7 @@ Vector2 :: struct {
x, y: f32;
}
InitWindow :: (width: s32, height: s32, title: [:0]u8) -> void #foreign raylib;
InitWindow :: (width: i32, height: i32, title: [:0]u8) -> void #foreign raylib;
CloseWindow :: () -> void #foreign raylib;
WindowShouldClose :: () -> bool #foreign raylib;
BeginDrawing :: () -> void #foreign raylib;

View File

@@ -9,19 +9,19 @@ SDL_WINDOW_RESIZABLE :u64: 0x20;
SDL_WINDOW_HIGH_PIXEL_DENSITY :u64: 0x2000;
// SDL_GLAttr (enum starting at 0)
SDL_GL_DOUBLEBUFFER :s32: 5;
SDL_GL_DEPTH_SIZE :s32: 6;
SDL_GL_CONTEXT_MAJOR_VERSION :s32: 17;
SDL_GL_CONTEXT_MINOR_VERSION :s32: 18;
SDL_GL_CONTEXT_FLAGS :s32: 19;
SDL_GL_CONTEXT_PROFILE_MASK :s32: 20;
SDL_GL_DOUBLEBUFFER :i32: 5;
SDL_GL_DEPTH_SIZE :i32: 6;
SDL_GL_CONTEXT_MAJOR_VERSION :i32: 17;
SDL_GL_CONTEXT_MINOR_VERSION :i32: 18;
SDL_GL_CONTEXT_FLAGS :i32: 19;
SDL_GL_CONTEXT_PROFILE_MASK :i32: 20;
// SDL_GLProfile
SDL_GL_CONTEXT_PROFILE_CORE :s32: 0x1;
SDL_GL_CONTEXT_PROFILE_ES :s32: 0x4;
SDL_GL_CONTEXT_PROFILE_CORE :i32: 0x1;
SDL_GL_CONTEXT_PROFILE_ES :i32: 0x4;
// SDL_GLContextFlag
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG :s32: 0x2;
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG :i32: 0x2;
// SDL_Keycode — virtual key codes (layout-dependent)
SDL_Keycode :: enum u32 {
@@ -220,8 +220,8 @@ SDL_Keycode :: enum u32 {
SDL_WindowData :: struct {
timestamp: u64; // event time in nanoseconds
window_id: u32;
data1: s32; // event-dependent: x position for moved, width for resized
data2: s32; // event-dependent: y position for moved, height for resized
data1: i32; // event-dependent: x position for moved, width for resized
data2: i32; // event-dependent: y position for moved, height for resized
}
SDL_Keymod :: enum flags u16 {
@@ -322,14 +322,14 @@ SDL_Event :: enum struct { tag: u32; _: u32; payload: [30]u32; } {
// Functions
SDL_Init :: (flags: u32) -> bool #foreign;
SDL_Quit :: () -> void #foreign;
SDL_CreateWindow :: (title: [:0]u8, w: s32, h: s32, flags: u64) -> *void #foreign;
SDL_CreateWindow :: (title: [:0]u8, w: i32, h: i32, flags: u64) -> *void #foreign;
SDL_DestroyWindow :: (window: *void) -> void #foreign;
SDL_GL_SetAttribute :: (attr: s32, value: s32) -> bool #foreign;
SDL_GL_SetAttribute :: (attr: i32, value: i32) -> bool #foreign;
SDL_GL_CreateContext :: (window: *void) -> *void #foreign;
SDL_GL_DestroyContext :: (context: *void) -> bool #foreign;
SDL_GL_MakeCurrent :: (window: *void, context: *void) -> bool #foreign;
SDL_GL_SwapWindow :: (window: *void) -> bool #foreign;
SDL_GL_SetSwapInterval :: (interval: s32) -> bool #foreign;
SDL_GL_SetSwapInterval :: (interval: i32) -> bool #foreign;
SDL_GL_GetProcAddress :: (proc: [:0]u8) -> *void #foreign;
SDL_PollEvent :: (event: *SDL_Event) -> bool #foreign;
SDL_AddEventWatch :: (filter: *void, userdata: *void) -> bool #foreign;
@@ -338,15 +338,15 @@ SDL_GetPerformanceCounter :: () -> u64 #foreign;
SDL_GetPerformanceFrequency :: () -> u64 #foreign;
SDL_Delay :: (ms: u32) -> void #foreign;
SDL_GetWindowDisplayScale :: (window: *void) -> f32 #foreign;
SDL_GetWindowSize :: (window: *void, w: *s32, h: *s32) -> bool #foreign;
SDL_SetWindowSize :: (window: *void, w: s32, h: s32) -> bool #foreign;
SDL_GetWindowSizeInPixels :: (window: *void, w: *s32, h: *s32) -> bool #foreign;
SDL_GetWindowSize :: (window: *void, w: *i32, h: *i32) -> bool #foreign;
SDL_SetWindowSize :: (window: *void, w: i32, h: i32) -> bool #foreign;
SDL_GetWindowSizeInPixels :: (window: *void, w: *i32, h: *i32) -> bool #foreign;
SDL_Rect :: struct {
x: s32;
y: s32;
w: s32;
h: s32;
x: i32;
y: i32;
w: i32;
h: i32;
}
SDL_GetPrimaryDisplay :: () -> u32 #foreign;

View File

@@ -1,4 +1,4 @@
libc :: #library "c";
emscripten_set_main_loop :: (func: *void, fps: s32, sim_infinite: s32) #foreign libc;
emscripten_run_script_int :: (script: [:0]u8) -> s32 #foreign libc;
emscripten_set_main_loop :: (func: *void, fps: i32, sim_infinite: i32) #foreign libc;
emscripten_run_script_int :: (script: [:0]u8) -> i32 #foreign libc;

View File

@@ -11,10 +11,10 @@ GPU :: protocol {
// Bind the GPU to a backend-specific render target (e.g. a
// CAMetalLayer on iOS). pixel_w/pixel_h are the drawable's pixel
// dimensions; call resize when they change.
init :: (target: *void, pixel_w: s32, pixel_h: s32) -> bool;
init :: (target: *void, pixel_w: i32, pixel_h: i32) -> bool;
shutdown :: ();
resize :: (pixel_w: s32, pixel_h: s32);
resize :: (pixel_w: i32, pixel_h: i32);
begin_frame :: (clear: ClearColor) -> bool;
@@ -26,17 +26,17 @@ GPU :: protocol {
end_frame :: (target_time: f64);
create_shader :: (vsrc: string, fsrc: string) -> ShaderHandle;
create_buffer :: (size_bytes: s64) -> BufferHandle;
update_buffer :: (buf: BufferHandle, data: *void, size_bytes: s64);
create_buffer :: (size_bytes: i64) -> BufferHandle;
update_buffer :: (buf: BufferHandle, data: *void, size_bytes: i64);
// Sub-buffer write at a byte offset. Required for Metal where re-using
// the same buffer slice across multiple draws in a single command
// encoder is a race: the GPU executes draws asynchronously and reads
// shared-storage buffer contents at execution time, so the LAST writer
// wins if every flush targets offset 0. Renderers that issue more than
// one draw per frame must advance their write offset between flushes.
update_buffer_at :: (buf: BufferHandle, data: *void, size_bytes: s64, byte_offset: s64);
create_texture :: (w: s32, h: s32, format: TextureFormat, pixels: *void) -> TextureHandle;
update_texture_region :: (tex: TextureHandle, x: s32, y: s32, w: s32, h: s32, pixels: *void);
update_buffer_at :: (buf: BufferHandle, data: *void, size_bytes: i64, byte_offset: i64);
create_texture :: (w: i32, h: i32, format: TextureFormat, pixels: *void) -> TextureHandle;
update_texture_region :: (tex: TextureHandle, x: i32, y: i32, w: i32, h: i32, pixels: *void);
// Release a GPU resource. Implementations release the backing object and
// null the slot so the handle becomes inert. Calling with handle 0 or
@@ -49,9 +49,9 @@ GPU :: protocol {
set_shader :: (sh: ShaderHandle);
set_vertex_buffer :: (buf: BufferHandle);
set_texture :: (slot: u32, tex: TextureHandle);
set_vertex_constants :: (slot: u32, data: *void, size_bytes: s64);
set_scissor :: (x: s32, y: s32, w: s32, h: s32);
set_vertex_constants :: (slot: u32, data: *void, size_bytes: i64);
set_scissor :: (x: i32, y: i32, w: i32, h: i32);
disable_scissor :: ();
draw_triangles :: (vertex_offset: s32, vertex_count: s32);
draw_triangles :: (vertex_offset: i32, vertex_count: i32);
}

View File

@@ -48,13 +48,13 @@ Gles3TextureSlot :: struct {
Gles3ShaderSlot :: struct {
program: u32 = 0;
proj_loc: s32 = 0 - 1;
tex_loc: s32 = 0 - 1;
proj_loc: i32 = 0 - 1;
tex_loc: i32 = 0 - 1;
}
Gles3Gpu :: struct {
pixel_w: s32 = 0;
pixel_h: s32 = 0;
pixel_w: i32 = 0;
pixel_h: i32 = 0;
// The renderer's vertex layout is fixed (see file header). One VAO,
// reused across every set_vertex_buffer.
@@ -82,7 +82,7 @@ impl GPU for Gles3Gpu {
// single shared VAO. Must be called once the EGL context is
// current (AndroidPlatform.run_frame_loop ensures this before
// invoking the user's per-frame closure). `target` is unused.
init :: (self: *Gles3Gpu, target: *void, pixel_w: s32, pixel_h: s32) -> bool {
init :: (self: *Gles3Gpu, target: *void, pixel_w: i32, pixel_h: i32) -> bool {
inline if OS != .android { return false; }
self.pixel_w = pixel_w;
self.pixel_h = pixel_h;
@@ -110,7 +110,7 @@ impl GPU for Gles3Gpu {
// happens when the NativeActivity tears down).
}
resize :: (self: *Gles3Gpu, pixel_w: s32, pixel_h: s32) {
resize :: (self: *Gles3Gpu, pixel_w: i32, pixel_h: i32) {
self.pixel_w = pixel_w;
self.pixel_h = pixel_h;
}
@@ -145,7 +145,7 @@ impl GPU for Gles3Gpu {
xx self.shaders.len
}
create_buffer :: (self: *Gles3Gpu, size_bytes: s64) -> BufferHandle {
create_buffer :: (self: *Gles3Gpu, size_bytes: i64) -> BufferHandle {
inline if OS != .android { return 0; }
if size_bytes <= 0 { return 0; }
b : u32 = 0;
@@ -156,7 +156,7 @@ impl GPU for Gles3Gpu {
xx self.buffers.len
}
update_buffer :: (self: *Gles3Gpu, handle: BufferHandle, data: *void, size_bytes: s64) {
update_buffer :: (self: *Gles3Gpu, handle: BufferHandle, data: *void, size_bytes: i64) {
inline if OS != .android { return; }
buf := gles3_lookup_buffer(self, handle);
if buf == 0 { return; }
@@ -166,7 +166,7 @@ impl GPU for Gles3Gpu {
glBufferSubData(GL_ARRAY_BUFFER, 0, xx size_bytes, data);
}
update_buffer_at :: (self: *Gles3Gpu, handle: BufferHandle, data: *void, size_bytes: s64, byte_offset: s64) {
update_buffer_at :: (self: *Gles3Gpu, handle: BufferHandle, data: *void, size_bytes: i64, byte_offset: i64) {
inline if OS != .android { return; }
buf := gles3_lookup_buffer(self, handle);
if buf == 0 { return; }
@@ -177,12 +177,12 @@ impl GPU for Gles3Gpu {
glBufferSubData(GL_ARRAY_BUFFER, xx byte_offset, xx size_bytes, data);
}
create_texture :: (self: *Gles3Gpu, w: s32, h: s32, format: TextureFormat, pixels: *void) -> TextureHandle {
create_texture :: (self: *Gles3Gpu, w: i32, h: i32, format: TextureFormat, pixels: *void) -> TextureHandle {
inline if OS != .android { return 0; }
if w <= 0 { return 0; }
if h <= 0 { return 0; }
internal_fmt : s32 = 0;
internal_fmt : i32 = 0;
ext_fmt : u32 = 0;
bpp : u32 = 0;
if format == .rgba8 {
@@ -210,10 +210,10 @@ impl GPU for Gles3Gpu {
xx self.textures.len
}
update_texture_region :: (self: *Gles3Gpu, handle: TextureHandle, x: s32, y: s32, w: s32, h: s32, pixels: *void) {
update_texture_region :: (self: *Gles3Gpu, handle: TextureHandle, x: i32, y: i32, w: i32, h: i32, pixels: *void) {
inline if OS != .android { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.textures.len { return; }
slot := self.textures.items[handle - 1];
if slot.tex == 0 { return; }
@@ -235,7 +235,7 @@ impl GPU for Gles3Gpu {
destroy_texture :: (self: *Gles3Gpu, tex: TextureHandle) {
inline if OS != .android { return; }
if tex == 0 { return; }
h64 : s64 = xx tex;
h64 : i64 = xx tex;
if h64 > self.textures.len { return; }
t := self.textures.items[tex - 1].tex;
if t == 0 { return; }
@@ -248,7 +248,7 @@ impl GPU for Gles3Gpu {
set_shader :: (self: *Gles3Gpu, handle: ShaderHandle) {
inline if OS != .android { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.shaders.len { return; }
prog := self.shaders.items[handle - 1].program;
if prog == 0 { return; }
@@ -280,14 +280,14 @@ impl GPU for Gles3Gpu {
inline if OS != .android { return; }
if slot != 0 { return; } // renderer only uses unit 0
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.textures.len { return; }
t := self.textures.items[handle - 1].tex;
if t == 0 { return; }
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, t);
if self.current_shader != 0 {
cs64 : s64 = xx self.current_shader;
cs64 : i64 = xx self.current_shader;
if cs64 <= self.shaders.len {
loc := self.shaders.items[self.current_shader - 1].tex_loc;
if loc >= 0 { glUniform1i(loc, 0); }
@@ -298,19 +298,19 @@ impl GPU for Gles3Gpu {
// For slot 1 + 64 bytes the renderer is uploading the 4x4 projection
// matrix into `uniform mat4 uProj`. Look up via the current shader's
// cached uniform location.
set_vertex_constants :: (self: *Gles3Gpu, slot: u32, data: *void, size_bytes: s64) {
set_vertex_constants :: (self: *Gles3Gpu, slot: u32, data: *void, size_bytes: i64) {
inline if OS != .android { return; }
if slot != 1 { return; }
if size_bytes != 64 { return; }
if self.current_shader == 0 { return; }
cs64 : s64 = xx self.current_shader;
cs64 : i64 = xx self.current_shader;
if cs64 > self.shaders.len { return; }
loc := self.shaders.items[self.current_shader - 1].proj_loc;
if loc < 0 { return; }
glUniformMatrix4fv(loc, 1, 0, xx data);
}
set_scissor :: (self: *Gles3Gpu, x: s32, y: s32, w: s32, h: s32) {
set_scissor :: (self: *Gles3Gpu, x: i32, y: i32, w: i32, h: i32) {
inline if OS != .android { return; }
glEnable(GL_SCISSOR_TEST);
glScissor(x, self.pixel_h - (y + h), w, h);
@@ -321,7 +321,7 @@ impl GPU for Gles3Gpu {
glDisable(GL_SCISSOR_TEST);
}
draw_triangles :: (self: *Gles3Gpu, vertex_offset: s32, vertex_count: s32) {
draw_triangles :: (self: *Gles3Gpu, vertex_offset: i32, vertex_count: i32) {
inline if OS != .android { return; }
if vertex_count <= 0 { return; }
glDrawArrays(GL_TRIANGLES, vertex_offset, vertex_count);
@@ -331,7 +331,7 @@ impl GPU for Gles3Gpu {
gles3_lookup_buffer :: (self: *Gles3Gpu, handle: u32) -> u32 {
inline if OS != .android { return 0; }
if handle == 0 { return 0; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.buffers.len { return 0; }
self.buffers.items[handle - 1]
}

View File

@@ -75,8 +75,8 @@ MetalGPU :: struct {
device: *void = null; // id<MTLDevice>
queue: *void = null; // id<MTLCommandQueue>
layer: *void = null; // CAMetalLayer*
pixel_w: s32 = 0;
pixel_h: s32 = 0;
pixel_w: i32 = 0;
pixel_h: i32 = 0;
// Per-frame transients. Live only between begin_frame and end_frame.
drawable: *void = null; // id<CAMetalDrawable>
@@ -100,7 +100,7 @@ impl GPU for MetalGPU {
// UIKit hands us a layer), then re-call `init(layer, w, h)` once the
// CAMetalLayer is available. The second call only updates the layer
// ref + dims; device/queue are preserved.
init :: (self: *MetalGPU, target: *void, pixel_w: s32, pixel_h: s32) -> bool {
init :: (self: *MetalGPU, target: *void, pixel_w: i32, pixel_h: i32) -> bool {
inline if OS != .ios { return false; }
if target != null {
self.layer = target;
@@ -116,7 +116,7 @@ impl GPU for MetalGPU {
// would send `release` to queue + device.
}
resize :: (self: *MetalGPU, pixel_w: s32, pixel_h: s32) {
resize :: (self: *MetalGPU, pixel_w: i32, pixel_h: i32) {
self.pixel_w = pixel_w;
self.pixel_h = pixel_h;
inline if OS == .ios {
@@ -145,29 +145,29 @@ impl GPU for MetalGPU {
metal_create_shader_ios(self, vsrc)
}
create_buffer :: (self: *MetalGPU, size_bytes: s64) -> BufferHandle {
create_buffer :: (self: *MetalGPU, size_bytes: i64) -> BufferHandle {
inline if OS != .ios { return 0; }
metal_create_buffer_ios(self, size_bytes)
}
update_buffer :: (self: *MetalGPU, buf: BufferHandle, data: *void, size_bytes: s64) {
update_buffer :: (self: *MetalGPU, buf: BufferHandle, data: *void, size_bytes: i64) {
inline if OS == .ios {
metal_update_buffer_ios(self, buf, data, size_bytes);
}
}
update_buffer_at :: (self: *MetalGPU, buf: BufferHandle, data: *void, size_bytes: s64, byte_offset: s64) {
update_buffer_at :: (self: *MetalGPU, buf: BufferHandle, data: *void, size_bytes: i64, byte_offset: i64) {
inline if OS == .ios {
metal_update_buffer_at_ios(self, buf, data, size_bytes, byte_offset);
}
}
create_texture :: (self: *MetalGPU, w: s32, h: s32, format: TextureFormat, pixels: *void) -> TextureHandle {
create_texture :: (self: *MetalGPU, w: i32, h: i32, format: TextureFormat, pixels: *void) -> TextureHandle {
inline if OS != .ios { return 0; }
metal_create_texture_ios(self, w, h, format, pixels)
}
update_texture_region :: (self: *MetalGPU, tex: TextureHandle, x: s32, y: s32, w: s32, h: s32, pixels: *void) {
update_texture_region :: (self: *MetalGPU, tex: TextureHandle, x: i32, y: i32, w: i32, h: i32, pixels: *void) {
inline if OS == .ios {
metal_update_texture_region_ios(self, tex, x, y, w, h, pixels);
}
@@ -213,13 +213,13 @@ impl GPU for MetalGPU {
}
}
set_vertex_constants :: (self: *MetalGPU, slot: u32, data: *void, size_bytes: s64) {
set_vertex_constants :: (self: *MetalGPU, slot: u32, data: *void, size_bytes: i64) {
inline if OS == .ios {
metal_set_vertex_constants_ios(self, slot, data, size_bytes);
}
}
set_scissor :: (self: *MetalGPU, x: s32, y: s32, w: s32, h: s32) {
set_scissor :: (self: *MetalGPU, x: i32, y: i32, w: i32, h: i32) {
inline if OS == .ios {
metal_set_scissor_ios(self, x, y, w, h);
}
@@ -231,7 +231,7 @@ impl GPU for MetalGPU {
}
}
draw_triangles :: (self: *MetalGPU, vertex_offset: s32, vertex_count: s32) {
draw_triangles :: (self: *MetalGPU, vertex_offset: i32, vertex_count: i32) {
inline if OS == .ios {
metal_draw_triangles_ios(self, vertex_offset, vertex_count);
}
@@ -446,7 +446,7 @@ metal_create_shader_ios :: (self: *MetalGPU, src: string) -> u32 {
// Shared-memory MTLBuffer (CPU + GPU visible on UMA hardware). `contents`
// returns the mapped pointer for memcpy uploads.
metal_create_buffer_ios :: (self: *MetalGPU, size_bytes: s64) -> u32 {
metal_create_buffer_ios :: (self: *MetalGPU, size_bytes: i64) -> u32 {
inline if OS != .ios { return 0; }
if self.device == null { return 0; }
if size_bytes <= 0 { return 0; }
@@ -462,7 +462,7 @@ metal_create_buffer_ios :: (self: *MetalGPU, size_bytes: s64) -> u32 {
xx self.buffers.len
}
metal_update_buffer_ios :: (self: *MetalGPU, handle: u32, data: *void, size_bytes: s64) {
metal_update_buffer_ios :: (self: *MetalGPU, handle: u32, data: *void, size_bytes: i64) {
inline if OS != .ios { return; }
buf := metal_lookup_buffer(self, handle);
if buf == null { return; }
@@ -475,7 +475,7 @@ metal_update_buffer_ios :: (self: *MetalGPU, handle: u32, data: *void, size_byte
memcpy(dst, data, size_bytes);
}
metal_update_buffer_at_ios :: (self: *MetalGPU, handle: u32, data: *void, size_bytes: s64, byte_offset: s64) {
metal_update_buffer_at_ios :: (self: *MetalGPU, handle: u32, data: *void, size_bytes: i64, byte_offset: i64) {
inline if OS != .ios { return; }
buf := metal_lookup_buffer(self, handle);
if buf == null { return; }
@@ -489,7 +489,7 @@ metal_update_buffer_at_ios :: (self: *MetalGPU, handle: u32, data: *void, size_b
// Add byte_offset via integer arithmetic — `@dst[i]` on `[*]u8`
// already does this, but we keep this form explicit so a future
// pointer-arithmetic regression here can't hide.
base_i : s64 = xx base;
base_i : i64 = xx base;
dst_at : *void = xx (base_i + byte_offset);
memcpy(dst_at, data, size_bytes);
}
@@ -497,7 +497,7 @@ metal_update_buffer_at_ios :: (self: *MetalGPU, handle: u32, data: *void, size_b
metal_lookup_buffer :: (self: *MetalGPU, handle: u32) -> *void {
inline if OS != .ios { return null; }
if handle == 0 { return null; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.buffers.len { return null; }
self.buffers.items[handle - 1]
}
@@ -505,14 +505,14 @@ metal_lookup_buffer :: (self: *MetalGPU, handle: u32) -> *void {
metal_lookup_shader :: (self: *MetalGPU, handle: u32) -> *void {
inline if OS != .ios { return null; }
if handle == 0 { return null; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.shaders.len { return null; }
self.shaders.items[handle - 1]
}
// ── Textures ─────────────────────────────────────────────────────────────
metal_create_texture_ios :: (self: *MetalGPU, w: s32, h: s32, format: TextureFormat, pixels: *void) -> u32 {
metal_create_texture_ios :: (self: *MetalGPU, w: i32, h: i32, format: TextureFormat, pixels: *void) -> u32 {
inline if OS != .ios { return 0; }
if self.device == null { return 0; }
if w <= 0 { return 0; }
@@ -557,10 +557,10 @@ metal_create_texture_ios :: (self: *MetalGPU, w: s32, h: s32, format: TextureFor
xx self.textures.len
}
metal_update_texture_region_ios :: (self: *MetalGPU, handle: u32, x: s32, y: s32, w: s32, h: s32, pixels: *void) {
metal_update_texture_region_ios :: (self: *MetalGPU, handle: u32, x: i32, y: i32, w: i32, h: i32, pixels: *void) {
inline if OS != .ios { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.textures.len { return; }
slot := self.textures.items[handle - 1];
if slot.tex == null { return; }
@@ -592,7 +592,7 @@ metal_update_texture_region_ios :: (self: *MetalGPU, handle: u32, x: s32, y: s32
metal_destroy_shader_ios :: (self: *MetalGPU, handle: u32) {
inline if OS != .ios { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.shaders.len { return; }
obj := self.shaders.items[handle - 1];
if obj == null { return; }
@@ -604,7 +604,7 @@ metal_destroy_shader_ios :: (self: *MetalGPU, handle: u32) {
metal_destroy_buffer_ios :: (self: *MetalGPU, handle: u32) {
inline if OS != .ios { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.buffers.len { return; }
obj := self.buffers.items[handle - 1];
if obj == null { return; }
@@ -616,7 +616,7 @@ metal_destroy_buffer_ios :: (self: *MetalGPU, handle: u32) {
metal_destroy_texture_ios :: (self: *MetalGPU, handle: u32) {
inline if OS != .ios { return; }
if handle == 0 { return; }
h64 : s64 = xx handle;
h64 : i64 = xx handle;
if h64 > self.textures.len { return; }
obj := self.textures.items[handle - 1].tex;
if obj == null { return; }
@@ -651,7 +651,7 @@ metal_set_texture_ios :: (self: *MetalGPU, slot: u32, h: u32) {
inline if OS != .ios { return; }
if self.encoder == null { return; }
if h == 0 { return; }
h64 : s64 = xx h;
h64 : i64 = xx h;
if h64 > self.textures.len { return; }
tex := self.textures.items[h - 1].tex;
if tex == null { return; }
@@ -660,7 +660,7 @@ metal_set_texture_ios :: (self: *MetalGPU, slot: u32, h: u32) {
msg(self.encoder, sel_registerName("setFragmentTexture:atIndex:".ptr), tex, xx slot);
}
metal_set_vertex_constants_ios :: (self: *MetalGPU, slot: u32, data: *void, size_bytes: s64) {
metal_set_vertex_constants_ios :: (self: *MetalGPU, slot: u32, data: *void, size_bytes: i64) {
inline if OS != .ios { return; }
if self.encoder == null { return; }
if data == null { return; }
@@ -671,7 +671,7 @@ metal_set_vertex_constants_ios :: (self: *MetalGPU, slot: u32, data: *void, size
data, xx size_bytes, xx slot);
}
metal_set_scissor_ios :: (self: *MetalGPU, x: s32, y: s32, w: s32, h: s32) {
metal_set_scissor_ios :: (self: *MetalGPU, x: i32, y: i32, w: i32, h: i32) {
inline if OS != .ios { return; }
if self.encoder == null { return; }
rect : MTLScissorRect = .{ x = xx x, y = xx y, width = xx w, height = xx h };
@@ -690,7 +690,7 @@ metal_disable_scissor_ios :: (self: *MetalGPU) {
msg(self.encoder, sel_registerName("setScissorRect:".ptr), rect);
}
metal_draw_triangles_ios :: (self: *MetalGPU, vertex_offset: s32, vertex_count: s32) {
metal_draw_triangles_ios :: (self: *MetalGPU, vertex_offset: i32, vertex_count: i32) {
inline if OS != .ios { return; }
if self.encoder == null { return; }
if vertex_count <= 0 { return; }

View File

@@ -56,7 +56,7 @@ SurfaceView :: #foreign #jni_class("android/view/SurfaceView") {
SurfaceHolderCallback :: #foreign #jni_class("android/view/SurfaceHolder$Callback") { }
MotionEvent :: #foreign #jni_class("android/view/MotionEvent") {
getAction :: (self: *Self) -> s32;
getAction :: (self: *Self) -> i32;
getX :: (self: *Self) -> f32;
getY :: (self: *Self) -> f32;
}
@@ -72,23 +72,23 @@ ActivityClass :: #foreign #jni_class("android/app/Activity") {
// can route through `AAssetManager_open` when running on Android.
sx_android_set_asset_manager :: (mgr: *void) #foreign;
__android_log_print :: (prio: s32, tag: *u8, fmt: *u8) -> s32 #foreign;
usleep :: (us: u32) -> s32 #foreign;
__android_log_print :: (prio: i32, tag: *u8, fmt: *u8) -> i32 #foreign;
usleep :: (us: u32) -> i32 #foreign;
// libandroid
ANativeWindow_fromSurface :: (env: *void, surface: *void) -> *void #foreign;
ANativeWindow_release :: (window: *void) #foreign;
ANativeWindow_getWidth :: (window: *void) -> s32 #foreign;
ANativeWindow_getHeight :: (window: *void) -> s32 #foreign;
ANativeWindow_setBuffersGeometry :: (w: *void, width: s32, height: s32, fmt: s32) -> s32 #foreign;
ANativeWindow_getWidth :: (window: *void) -> i32 #foreign;
ANativeWindow_getHeight :: (window: *void) -> i32 #foreign;
ANativeWindow_setBuffersGeometry :: (w: *void, width: i32, height: i32, fmt: i32) -> i32 #foreign;
AAssetManager_fromJava :: (env: *void, mgr: *void) -> *void #foreign;
// pthread (link libpthread is built into bionic).
pthread_create :: (thread: *u64, attr: *void, start: (*void) -> *void callconv(.c), arg: *void) -> s32 #foreign;
pthread_mutex_init :: (m: *void, attr: *void) -> s32 #foreign;
pthread_mutex_lock :: (m: *void) -> s32 #foreign;
pthread_mutex_unlock :: (m: *void) -> s32 #foreign;
pthread_create :: (thread: *u64, attr: *void, start: (*void) -> *void callconv(.c), arg: *void) -> i32 #foreign;
pthread_mutex_init :: (m: *void, attr: *void) -> i32 #foreign;
pthread_mutex_lock :: (m: *void) -> i32 #foreign;
pthread_mutex_unlock :: (m: *void) -> i32 #foreign;
// EGL. Constants from <EGL/egl.h>. We bring up an ES3 context with a
// 24-bit RGB framebuffer + 24-bit depth (same shape chess used under
@@ -99,25 +99,25 @@ EGL_NO_CONTEXT :*void: null;
EGL_NO_SURFACE :*void: null;
EGL_TRUE :u32: 1;
EGL_FALSE :u32: 0;
EGL_NONE :s32: 0x3038;
EGL_RED_SIZE :s32: 0x3024;
EGL_GREEN_SIZE :s32: 0x3023;
EGL_BLUE_SIZE :s32: 0x3022;
EGL_ALPHA_SIZE :s32: 0x3021;
EGL_DEPTH_SIZE :s32: 0x3025;
EGL_RENDERABLE_TYPE :s32: 0x3040;
EGL_SURFACE_TYPE :s32: 0x3033;
EGL_OPENGL_ES3_BIT :s32: 0x00000040;
EGL_WINDOW_BIT :s32: 0x0004;
EGL_NATIVE_VISUAL_ID :s32: 0x302E;
EGL_CONTEXT_CLIENT_VERSION :s32: 0x3098;
EGL_NONE :i32: 0x3038;
EGL_RED_SIZE :i32: 0x3024;
EGL_GREEN_SIZE :i32: 0x3023;
EGL_BLUE_SIZE :i32: 0x3022;
EGL_ALPHA_SIZE :i32: 0x3021;
EGL_DEPTH_SIZE :i32: 0x3025;
EGL_RENDERABLE_TYPE :i32: 0x3040;
EGL_SURFACE_TYPE :i32: 0x3033;
EGL_OPENGL_ES3_BIT :i32: 0x00000040;
EGL_WINDOW_BIT :i32: 0x0004;
EGL_NATIVE_VISUAL_ID :i32: 0x302E;
EGL_CONTEXT_CLIENT_VERSION :i32: 0x3098;
eglGetDisplay :: (id: u64) -> *void #foreign;
eglInitialize :: (d: *void, major: *s32, minor: *s32) -> u32 #foreign;
eglChooseConfig :: (d: *void, attrs: *s32, configs: **void, sz: s32, num: *s32) -> u32 #foreign;
eglGetConfigAttrib :: (d: *void, cfg: *void, attr: s32, value: *s32) -> u32 #foreign;
eglCreateContext :: (d: *void, cfg: *void, share: *void, attrs: *s32) -> *void #foreign;
eglCreateWindowSurface :: (d: *void, cfg: *void, window: *void, attrs: *s32) -> *void #foreign;
eglInitialize :: (d: *void, major: *i32, minor: *i32) -> u32 #foreign;
eglChooseConfig :: (d: *void, attrs: *i32, configs: **void, sz: i32, num: *i32) -> u32 #foreign;
eglGetConfigAttrib :: (d: *void, cfg: *void, attr: i32, value: *i32) -> u32 #foreign;
eglCreateContext :: (d: *void, cfg: *void, share: *void, attrs: *i32) -> *void #foreign;
eglCreateWindowSurface :: (d: *void, cfg: *void, window: *void, attrs: *i32) -> *void #foreign;
eglMakeCurrent :: (d: *void, draw: *void, read: *void, ctx: *void) -> u32 #foreign;
eglSwapBuffers :: (d: *void, surface: *void) -> u32 #foreign;
eglDestroyContext :: (d: *void, ctx: *void) -> u32 #foreign;
@@ -127,7 +127,7 @@ eglTerminate :: (d: *void) -> u32 #foreign;
// ── Touch ring ──────────────────────────────────────────────────────────
TouchEvent :: struct {
action: s32;
action: i32;
x: f32;
y: f32;
}
@@ -136,10 +136,10 @@ TouchEvent :: struct {
//
// Every per-instance piece of state — EGL handles, ANativeWindow, render
// thread, touch ring + mutex, frame closure, user main fn — lives here.
// No module-level globals: a previous shape had `g_viewport_w : s32` at
// No module-level globals: a previous shape had `g_viewport_w : i32` at
// module scope, which silently shadowed chess's own
// `g_viewport_w : f32` on `#import` and caused the renderer to receive
// a logical width cast to s32 instead of the physical pixel width.
// a logical width cast to i32 instead of the physical pixel width.
//
// `logical_w` is the consumer's design width in points (e.g. chess sets
// 414 to match an iPhone 12 layout). `begin_frame` derives `dpi_scale`
@@ -149,8 +149,8 @@ TouchEvent :: struct {
AndroidPlatform :: struct {
title: [:0]u8 = "";
width: s32 = 0;
height: s32 = 0;
width: i32 = 0;
height: i32 = 0;
// Set by consumer code BEFORE `init` if a fixed design width is
// wanted (chess uses 414). When 0, the platform reports
@@ -168,8 +168,8 @@ AndroidPlatform :: struct {
// Pixel-size from ANativeWindow_get{Width,Height}; derived dpi_scale
// (pixel_w / logical_w when logical_w > 0, else 1.0).
pixel_w: s32 = 0;
pixel_h: s32 = 0;
pixel_w: i32 = 0;
pixel_h: i32 = 0;
dpi_scale: f32 = 1.0;
// Render thread lifecycle. `user_main_fn` is the consumer's `main`
@@ -238,7 +238,7 @@ sx_android_detach_window :: (plat: *AndroidPlatform) {
}
}
sx_android_set_viewport :: (plat: *AndroidPlatform, w: s32, h: s32) {
sx_android_set_viewport :: (plat: *AndroidPlatform, w: i32, h: i32) {
plat.pixel_w = w;
plat.pixel_h = h;
sx_android_recompute_scale(plat);
@@ -280,11 +280,11 @@ sx_android_egl_init :: (plat: *AndroidPlatform) -> bool {
plat.egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if plat.egl_display == EGL_NO_DISPLAY { return false; }
major : s32 = 0;
minor : s32 = 0;
major : i32 = 0;
minor : i32 = 0;
if eglInitialize(plat.egl_display, @major, @minor) == EGL_FALSE { return false; }
cfg_attrs : [13]s32 = .{
cfg_attrs : [13]i32 = .{
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
@@ -293,15 +293,15 @@ sx_android_egl_init :: (plat: *AndroidPlatform) -> bool {
EGL_DEPTH_SIZE, 24,
EGL_NONE,
};
num_cfg : s32 = 0;
num_cfg : i32 = 0;
if eglChooseConfig(plat.egl_display, @cfg_attrs[0], @plat.egl_config, 1, @num_cfg) == EGL_FALSE { return false; }
if num_cfg < 1 { return false; }
visual_id : s32 = 0;
visual_id : i32 = 0;
eglGetConfigAttrib(plat.egl_display, plat.egl_config, EGL_NATIVE_VISUAL_ID, @visual_id);
ANativeWindow_setBuffersGeometry(plat.app_window, 0, 0, visual_id);
ctx_attrs : [3]s32 = .{ EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
ctx_attrs : [3]i32 = .{ EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
plat.egl_context = eglCreateContext(plat.egl_display, plat.egl_config, EGL_NO_CONTEXT, @ctx_attrs[0]);
if plat.egl_context == EGL_NO_CONTEXT { return false; }
@@ -329,7 +329,7 @@ sx_android_recompute_scale :: (plat: *AndroidPlatform) {
// ── Touch event queue ───────────────────────────────────────────────────
sx_android_push_touch :: (plat: *AndroidPlatform, action: s32, x: f32, y: f32) {
sx_android_push_touch :: (plat: *AndroidPlatform, action: i32, x: f32, y: f32) {
sx_android_ensure_touch_mutex(plat);
pthread_mutex_lock(xx @plat.touch_mutex_storage[0]);
next := (plat.touch_tail + 1) % 64;
@@ -373,7 +373,7 @@ sx_android_ensure_touch_mutex :: (plat: *AndroidPlatform) {
// ── Platform impl ───────────────────────────────────────────────────────
impl Platform for AndroidPlatform {
init :: (self: *AndroidPlatform, title: [:0]u8, w: s32, h: s32) -> bool {
init :: (self: *AndroidPlatform, title: [:0]u8, w: i32, h: i32) -> bool {
self.title = title;
self.width = w;
self.height = h;

View File

@@ -12,10 +12,10 @@
// against the bare name within the namespace.
WindowInsets :: #foreign #jni_class("android/view/WindowInsets") {
getSystemWindowInsetTop :: (self: *Self) -> s32;
getSystemWindowInsetLeft :: (self: *Self) -> s32;
getSystemWindowInsetBottom :: (self: *Self) -> s32;
getSystemWindowInsetRight :: (self: *Self) -> s32;
getSystemWindowInsetTop :: (self: *Self) -> i32;
getSystemWindowInsetLeft :: (self: *Self) -> i32;
getSystemWindowInsetBottom :: (self: *Self) -> i32;
getSystemWindowInsetRight :: (self: *Self) -> i32;
}
View :: #foreign #jni_class("android/view/View") {

View File

@@ -4,7 +4,7 @@
#import "modules/platform/types.sx";
Platform :: protocol {
init :: (title: [:0]u8, w: s32, h: s32) -> bool;
init :: (title: [:0]u8, w: i32, h: i32) -> bool;
run_frame_loop :: (frame_fn: Closure());

View File

@@ -130,7 +130,7 @@ bundle_main :: () -> bool {
// Android (Week 7) will zip them into the APK at the same relative path.
// Recursive copy shells out to `cp -R` until fs.sx grows `list_dir`.
asset_count := opts.asset_dir_count();
j : s64 = 0;
j : i64 = 0;
while j < asset_count {
src := opts.asset_dir_src_at(j);
dest := opts.asset_dir_dest_at(j);
@@ -156,7 +156,7 @@ bundle_main :: () -> bool {
out("error: bundle: cannot create Frameworks dir\n");
return false;
}
i : s64 = 0;
i : i64 = 0;
while i < fw_count {
fw_name := opts.framework_at(i);
if !embed_framework(opts, fw_name, fw_dir) {
@@ -369,7 +369,7 @@ copy_asset_dir :: (src: string, dest: string, bundle: string) -> bool {
embed_framework :: (opts: BuildOptions, name: string, dest_dir: string) -> bool {
subdir := concat(name, ".framework");
path_count := opts.framework_path_count();
i : s64 = 0;
i : i64 = 0;
while i < path_count {
base := opts.framework_path_at(i);
candidate := concat(base, "/");
@@ -701,7 +701,7 @@ android_bundle_main :: (opts: BuildOptions, binary: string, apk_path: string, bu
// path used a hardcoded `assets/` walk; the sx form respects every
// `add_asset_dir(src, dest)` pair the user registered.
asset_count := opts.asset_dir_count();
j : s64 = 0;
j : i64 = 0;
while j < asset_count {
src := opts.asset_dir_src_at(j);
dest := opts.asset_dir_dest_at(j);
@@ -988,7 +988,7 @@ compile_jni_main_sources :: (opts: BuildOptions, stage: string, android_jar: str
javac_files := "";
d8_files := "";
count := opts.jni_main_count();
i : s64 = 0;
i : i64 = 0;
while i < count {
foreign := opts.jni_main_foreign_path_at(i);
java_source := opts.jni_main_java_source_at(i);

View File

@@ -11,7 +11,7 @@
g_sdl_plat : *SdlPlatform = null;
chdir :: (path: [*]u8) -> s32 #foreign;
chdir :: (path: [*]u8) -> i32 #foreign;
SDL_GetBasePath :: () -> [*]u8 #foreign;
// A macOS `.app` launched via Finder / `open` starts with CWD=`/`, so a
@@ -26,7 +26,7 @@ sdl_chdir_to_bundle :: () {
bp := SDL_GetBasePath();
if bp == null { return; }
// Reorient only when the base path lives inside a `.app` bundle.
i : s64 = 0;
i : i64 = 0;
found := false;
while bp[i] != 0 {
if bp[i] == 46 and bp[i + 1] == 97 and bp[i + 2] == 112 and bp[i + 3] == 112 {
@@ -43,10 +43,10 @@ SdlPlatform :: struct {
gl_ctx: *void = null;
running: bool = true;
width: s32 = 0;
height: s32 = 0;
pixel_w: s32 = 0;
pixel_h: s32 = 0;
width: i32 = 0;
height: i32 = 0;
pixel_w: i32 = 0;
pixel_h: i32 = 0;
dpi_scale: f32 = 1.0;
delta_time: f32 = 0.008;
@@ -59,7 +59,7 @@ SdlPlatform :: struct {
}
impl Platform for SdlPlatform {
init :: (self: *SdlPlatform, title: [:0]u8, w: s32, h: s32) -> bool {
init :: (self: *SdlPlatform, title: [:0]u8, w: i32, h: i32) -> bool {
self.running = true;
self.has_frame_closure = false;
self.delta_time = 0.008;
@@ -178,8 +178,8 @@ impl Platform for SdlPlatform {
self.last_perf = current;
inline if OS == .wasm {
new_w : s32 = 0;
new_h : s32 = 0;
new_w : i32 = 0;
new_h : i32 = 0;
SDL_GetWindowSize(self.window, @new_w, @new_h);
if new_w != self.width or new_h != self.height {
self.width = new_w;

View File

@@ -5,8 +5,8 @@
FrameContext :: struct {
viewport_w: f32;
viewport_h: f32;
pixel_w: s32;
pixel_h: s32;
pixel_w: i32;
pixel_h: i32;
dpi_scale: f32;
delta_time: f32;
// The host clock time at which the next vsync will present the frame

View File

@@ -15,9 +15,9 @@
#import "modules/platform/types.sx";
#import "modules/platform/api.sx";
UIApplicationMain :: (argc: s32, argv: *void, principal_class: *NSString, delegate_class: *NSString) -> s32 #foreign;
UIApplicationMain :: (argc: i32, argv: *void, principal_class: *NSString, delegate_class: *NSString) -> i32 #foreign;
dlsym :: (handle: *void, name: [*]u8) -> *void #foreign;
chdir :: (path: [*]u8) -> s32 #foreign;
chdir :: (path: [*]u8) -> i32 #foreign;
// QuartzCore's wall-clock helper used by CoreAnimation. Seconds since boot,
// monotonic. We use it as the timebase for keyboard-inset lockstep so the
@@ -67,7 +67,7 @@ NSValue :: #foreign #objc_class("NSValue") {
NSNumber :: #foreign #objc_class("NSNumber") {
#extends NSObject;
// Class method (no `self: *Self` first param → static dispatch).
numberWithBool :: (b: s8) -> *NSNumber;
numberWithBool :: (b: i8) -> *NSNumber;
// Instance value extractors.
doubleValue :: (self: *Self) -> f64;
unsignedLongValue :: (self: *Self) -> u64;
@@ -128,7 +128,7 @@ CADisplayLink :: #foreign #objc_class("CADisplayLink") {
CALayer :: #foreign #objc_class("CALayer") {
#extends NSObject;
setOpaque :: (self: *Self, opaque: s8);
setOpaque :: (self: *Self, opaque: i8);
}
CAEAGLLayer :: #foreign #objc_class("CAEAGLLayer") {
@@ -145,10 +145,10 @@ CAMetalLayer :: #foreign #objc_class("CAMetalLayer") {
EAGLContext :: #foreign #objc_class("EAGLContext") {
#extends NSObject;
alloc :: () -> *EAGLContext;
initWithAPI :: (self: *Self, api: s32) -> *EAGLContext;
initWithAPI :: (self: *Self, api: i32) -> *EAGLContext;
setCurrentContext :: (ctx: *EAGLContext);
renderbufferStorage_fromDrawable :: (self: *Self, target: u32, drawable: *void) -> s8;
presentRenderbuffer :: (self: *Self, target: u32) -> s8;
renderbufferStorage_fromDrawable :: (self: *Self, target: u32, drawable: *void) -> i8;
presentRenderbuffer :: (self: *Self, target: u32) -> i8;
}
// ── UIKit chrome (Phase 3.2 C4) ────────────────────────────────────────
@@ -166,8 +166,8 @@ UIScreen :: #foreign #objc_class("UIScreen") {
// extend it so the runtime picks up the responder-chain behavior.
UIResponder :: #foreign #objc_class("UIResponder") {
#extends NSObject;
becomeFirstResponder :: (self: *Self) -> s8;
resignFirstResponder :: (self: *Self) -> s8;
becomeFirstResponder :: (self: *Self) -> i8;
resignFirstResponder :: (self: *Self) -> i8;
}
UIView :: #foreign #objc_class("UIView") {
@@ -292,8 +292,8 @@ UIKitPlatform :: struct {
viewport_w: f32 = 0.0;
viewport_h: f32 = 0.0;
pixel_w: s32 = 0;
pixel_h: s32 = 0;
pixel_w: i32 = 0;
pixel_h: i32 = 0;
dpi_scale: f32 = 1.0;
delta_time: f32 = 0.016;
@@ -334,7 +334,7 @@ UIKitPlatform :: struct {
}
impl Platform for UIKitPlatform {
init :: (self: *UIKitPlatform, title: [:0]u8, w: s32, h: s32) -> bool {
init :: (self: *UIKitPlatform, title: [:0]u8, w: i32, h: i32) -> bool {
self.dpi_scale = 1.0;
self.delta_time = 0.016;
self.has_frame_closure = false;
@@ -501,8 +501,8 @@ impl Platform for UIKitPlatform {
glBindFramebuffer(GL_FRAMEBUFFER, self.framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, self.color_renderbuffer);
pw : s32 = 0;
ph : s32 = 0;
pw : i32 = 0;
ph : i32 = 0;
GL_RENDERBUFFER_WIDTH :u32: 0x8D42;
GL_RENDERBUFFER_HEIGHT :u32: 0x8D43;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, @pw);

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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 ───────────────────────────────────────────────

View File

@@ -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)
}

View File

@@ -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;

View File

@@ -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; }

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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 —

View File

@@ -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))
}

View File

@@ -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.

View File

@@ -93,12 +93,12 @@ DOCK_ANIM_DURATION :f32: 0.19; // 190ms
DockInteraction :: struct {
// Drag state
dragging_child: s64; // -1 = none
dragging_child: i64; // -1 = none
drag_start_pos: Point;
drag_offset: Point;
click_fraction_x: f32;
click_fraction_y: f32;
hovered_zone: s64; // -1 = none, else DockZone ordinal
hovered_zone: i64; // -1 = none, else DockZone ordinal
// Per-child state
natural_sizes: List(Size);
@@ -111,7 +111,7 @@ DockInteraction :: struct {
anim_sizes: List(Animated(Size));
header_pressed: List(bool);
child_count: s64;
child_count: i64;
parent_allocator: Allocator; // GPA — used for persistent list growth
init :: (self: *DockInteraction) {
@@ -135,7 +135,7 @@ DockInteraction :: struct {
self.header_pressed = List(bool).{};
}
ensure_capacity :: (self: *DockInteraction, count: s64) {
ensure_capacity :: (self: *DockInteraction, count: i64) {
if self.child_count >= count { return; }
while self.child_count < count {
self.natural_sizes.append(Size.zero(), self.parent_allocator);
@@ -151,7 +151,7 @@ DockInteraction :: struct {
}
}
set_target_size :: (self: *DockInteraction, index: s64, target: Size) {
set_target_size :: (self: *DockInteraction, index: i64, target: Size) {
if index >= self.child_count { return; }
anim := @self.anim_sizes.items[index];
cur := anim.to;
@@ -168,7 +168,7 @@ DockInteraction :: struct {
}
}
get_animated_size :: (self: *DockInteraction, index: s64) -> Size {
get_animated_size :: (self: *DockInteraction, index: i64) -> Size {
if index >= self.child_count { return Size.zero(); }
(@self.anim_sizes.items[index]).current
}
@@ -197,7 +197,7 @@ DockInteraction :: struct {
}
}
start_dragging :: (interaction: *DockInteraction, child_index: s64, pos: Point, panel_frame: Frame) {
start_dragging :: (interaction: *DockInteraction, child_index: i64, pos: Point, panel_frame: Frame) {
interaction.dragging_child = child_index;
interaction.drag_start_pos = pos;
interaction.drag_offset = Point.zero();
@@ -218,7 +218,7 @@ start_dragging :: (interaction: *DockInteraction, child_index: s64, pos: Point,
// Helper functions
// =============================================================================
zone_by_index :: (i: s64) -> DockZone {
zone_by_index :: (i: i64) -> DockZone {
if i == {
case 0: .fill;
case 1: .center;
@@ -234,8 +234,8 @@ zone_by_index :: (i: s64) -> DockZone {
}
find_hovered_zone :: (bounds: Frame, pos: Point, hint_size: f32, enable_corners: bool) -> ?DockZone {
count : s64 = if enable_corners then 10 else 6;
i : s64 = 0;
count : i64 = if enable_corners then 10 else 6;
i : i64 = 0;
while i < count {
zone := zone_by_index(i);
hint := dock_zone_get_hint_frame(zone, bounds, hint_size);
@@ -365,7 +365,7 @@ DockPanel :: struct {
corner_radius: f32;
header_height: f32;
dock_interaction: *DockInteraction;
panel_index: s64;
panel_index: i64;
DEFAULT_BG :Color: Color.rgba(26, 26, 31, 242);
DEFAULT_HEADER_BG :Color: Color.rgba(38, 38, 46, 255);
@@ -469,7 +469,7 @@ Dock :: struct {
hint_active_color: Color;
preview_color: Color;
enable_corners: bool;
on_dock: ?Closure(s64, DockZone);
on_dock: ?Closure(i64, DockZone);
make :: (interaction: *DockInteraction, delta_time: *f32) -> Dock {
d : Dock = ---;
@@ -519,7 +519,7 @@ impl View for Dock {
dt : f32 = self.delta_time.*;
interaction.tick_animations(dt);
i : s64 = 0;
i : i64 = 0;
while i < self.children.len {
child := @self.children.items[i];
@@ -603,7 +603,7 @@ impl View for Dock {
}
// Draw children
i : s64 = 0;
i : i64 = 0;
while i < self.children.len {
child := @self.children.items[i];
child.view.render(ctx, child.computed_frame);
@@ -619,8 +619,8 @@ impl View for Dock {
}
// Zone hint indicators
count : s64 = if self.enable_corners then 10 else 6;
j : s64 = 0;
count : i64 = if self.enable_corners then 10 else 6;
j : i64 = 0;
while j < count {
zone := zone_by_index(j);
hint_frame := dock_zone_get_hint_frame(zone, frame, self.hint_size);

View File

@@ -16,14 +16,14 @@ GesturePhase :: enum {
TapValue :: struct {
location: Point;
count: s32;
count: i32;
}
TapGesture :: struct {
count: s32;
count: i32;
on_tap: ?Closure();
phase: GesturePhase;
tap_count: s32;
tap_count: i32;
start_position: Point;
TAP_THRESHOLD :f32: 10.0;

View File

@@ -50,7 +50,7 @@ ShapedGlyph :: struct {
}
is_ascii :: (text: string) -> bool {
i : s64 = 0;
i : i64 = 0;
while i < text.len {
if text[i] >= 128 { return false; }
i += 1;
@@ -69,9 +69,9 @@ KBTS_USER_ID_GENERATION_MODE_CODEPOINT_INDEX :u32: 0;
KbtsGlyphIterator :: struct {
glyph_storage: *void;
current_glyph: *void;
last_advance_x: s32;
x: s32;
y: s32;
last_advance_x: i32;
x: i32;
y: i32;
}
KbtsRun :: struct {
@@ -89,15 +89,15 @@ KbtsGlyph :: struct {
codepoint: u32;
id: u16;
uid: u16;
user_id_or_codepoint_index: s32;
offset_x: s32;
offset_y: s32;
advance_x: s32;
advance_y: s32;
user_id_or_codepoint_index: i32;
offset_x: i32;
offset_y: i32;
advance_x: i32;
advance_y: i32;
}
// kbts_font_info2 base (simplified — we only need the Size field for dispatch)
KBTS_FONT_INFO_STRING_ID_COUNT :s32: 7;
KBTS_FONT_INFO_STRING_ID_COUNT :i32: 7;
KbtsFontInfo2 :: struct {
size: u32;
@@ -111,21 +111,21 @@ KbtsFontInfo2 :: struct {
KbtsFontInfo2_1 :: struct {
base: KbtsFontInfo2;
units_per_em: u16;
x_min: s16;
y_min: s16;
x_max: s16;
y_max: s16;
ascent: s16;
descent: s16;
line_gap: s16;
x_min: i16;
y_min: i16;
x_max: i16;
y_max: i16;
ascent: i16;
descent: i16;
line_gap: i16;
}
GLYPH_ATLAS_W :s32: 1024;
GLYPH_ATLAS_H :s32: 1024;
FONTINFO_SIZE :s64: 256;
GLYPH_ATLAS_W :i32: 1024;
GLYPH_ATLAS_H :i32: 1024;
FONTINFO_SIZE :i64: 256;
PackResult :: struct {
x, y: s32;
x, y: i32;
}
// Dynamic glyph cache with on-demand rasterization and texture atlas packing.
@@ -136,25 +136,25 @@ GlyphCache :: struct {
// Atlas texture (GPU)
texture_id: u32;
atlas_width: s32;
atlas_height: s32;
atlas_width: i32;
atlas_height: i32;
// Atlas bitmap (CPU-side for updates)
bitmap: [*]u8;
// Shelf packer state
shelf_y: s32;
shelf_height: s32;
cursor_x: s32;
padding: s32;
shelf_y: i32;
shelf_height: i32;
cursor_x: i32;
padding: i32;
// Glyph lookup cache
entries: List(GlyphEntry);
// Hash table for O(1) glyph lookup (open addressing, linear probing)
hash_keys: [*]u32; // key per slot (0 = empty sentinel)
hash_vals: [*]s32; // index into entries list
hash_cap: s64; // table capacity (power of 2)
hash_vals: [*]i32; // index into entries list
hash_cap: i64; // table capacity (power of 2)
// Dirty tracking for texture upload
dirty: bool;
@@ -172,12 +172,12 @@ GlyphCache :: struct {
shape_ctx: *void;
shape_font: *void;
units_per_em: u16;
font_data_size: s32;
font_data_size: i32;
shaped_buf: List(ShapedGlyph);
// Shape cache: skip reshaping if same text + size as last call
last_shape_ptr: [*]u8;
last_shape_len: s64;
last_shape_len: i64;
last_shape_size_q: u16;
// Allocator that owns every dynamically-grown buffer on this cache —
@@ -199,7 +199,7 @@ GlyphCache :: struct {
self.parent_allocator = context.allocator;
// Load font file
file_size : s32 = 0;
file_size : i32 = 0;
font_data := read_file_bytes(path, @file_size);
if font_data == null {
out("Failed to load font: ");
@@ -216,9 +216,9 @@ GlyphCache :: struct {
stbtt_InitFont(self.font_info, font_data, 0);
// Get font vertical metrics (in unscaled font units)
ascent_i : s32 = 0;
descent_i : s32 = 0;
linegap_i : s32 = 0;
ascent_i : i32 = 0;
descent_i : i32 = 0;
linegap_i : i32 = 0;
stbtt_GetFontVMetrics(self.font_info, @ascent_i, @descent_i, @linegap_i);
// Store unscaled metrics — we'll scale per font_size in measure_text
@@ -241,7 +241,7 @@ GlyphCache :: struct {
// Allocate atlas bitmap
self.atlas_width = GLYPH_ATLAS_W;
self.atlas_height = GLYPH_ATLAS_H;
bitmap_size : s64 = xx self.atlas_width * xx self.atlas_height;
bitmap_size : i64 = xx self.atlas_width * xx self.atlas_height;
self.bitmap = xx self.parent_allocator.alloc_bytes(bitmap_size);
memset(self.bitmap, 0, bitmap_size);
@@ -257,10 +257,10 @@ GlyphCache :: struct {
// Init hash table (256 slots)
self.hash_cap = 256;
hash_bytes : s64 = self.hash_cap * 4; // u32 per slot
hash_bytes : i64 = self.hash_cap * 4; // u32 per slot
self.hash_keys = xx self.parent_allocator.alloc_bytes(hash_bytes);
memset(self.hash_keys, 0, hash_bytes);
val_bytes : s64 = self.hash_cap * 8; // s64 per slot (s32 would suffice but alignment)
val_bytes : i64 = self.hash_cap * 8; // i64 per slot (i32 would suffice but alignment)
self.hash_vals = xx self.parent_allocator.alloc_bytes(val_bytes);
// Create the atlas texture. In GPU-protocol mode we create empty and
@@ -296,7 +296,7 @@ GlyphCache :: struct {
// Hash table lookup (open addressing, linear probing)
mask := self.hash_cap - 1;
slot : s64 = xx ((key * 2654435761) >> 24) & xx mask;
slot : i64 = xx ((key * 2654435761) >> 24) & xx mask;
while self.hash_keys[slot] != 0 {
if self.hash_keys[slot] == key {
return @self.entries.items[self.hash_vals[slot]].glyph;
@@ -309,18 +309,18 @@ GlyphCache :: struct {
scale := stbtt_ScaleForPixelHeight(self.font_info, actual_size);
// Get glyph bounding box
x0 : s32 = 0;
y0 : s32 = 0;
x1 : s32 = 0;
y1 : s32 = 0;
x0 : i32 = 0;
y0 : i32 = 0;
x1 : i32 = 0;
y1 : i32 = 0;
stbtt_GetGlyphBitmapBox(self.font_info, xx glyph_index, scale, scale, @x0, @y0, @x1, @y1);
glyph_w := if x1 > x0 then x1 - x0 else 0;
glyph_h := if y1 > y0 then y1 - y0 else 0;
// Get horizontal metrics
advance_i : s32 = 0;
lsb_i : s32 = 0;
advance_i : i32 = 0;
lsb_i : i32 = 0;
stbtt_GetGlyphHMetrics(self.font_info, xx glyph_index, @advance_i, @lsb_i);
advance : f32 = xx advance_i * scale;
@@ -349,7 +349,7 @@ GlyphCache :: struct {
}
// Rasterize directly into atlas bitmap
dest_offset : s64 = xx pack.y * xx self.atlas_width + xx pack.x;
dest_offset : i64 = xx pack.y * xx self.atlas_width + xx pack.x;
stbtt_MakeGlyphBitmap(
self.font_info,
@self.bitmap[dest_offset],
@@ -384,13 +384,13 @@ GlyphCache :: struct {
}
// Insert a key→index mapping into the hash table, growing if needed
hash_insert :: (self: *GlyphCache, key: u32, index: s64) {
hash_insert :: (self: *GlyphCache, key: u32, index: i64) {
// Grow if load factor > 70%
if self.entries.len * 10 > self.hash_cap * 7 {
self.hash_grow();
}
mask := self.hash_cap - 1;
slot : s64 = xx ((key * 2654435761) >> 24) & xx mask;
slot : i64 = xx ((key * 2654435761) >> 24) & xx mask;
while self.hash_keys[slot] != 0 {
slot = (slot + 1) & mask;
}
@@ -405,19 +405,19 @@ GlyphCache :: struct {
old_vals := self.hash_vals;
self.hash_cap = old_cap * 2;
hash_bytes : s64 = self.hash_cap * 4;
hash_bytes : i64 = self.hash_cap * 4;
self.hash_keys = xx self.parent_allocator.alloc_bytes(hash_bytes);
memset(self.hash_keys, 0, hash_bytes);
val_bytes : s64 = self.hash_cap * 8;
val_bytes : i64 = self.hash_cap * 8;
self.hash_vals = xx self.parent_allocator.alloc_bytes(val_bytes);
// Rehash
mask := self.hash_cap - 1;
i : s64 = 0;
i : i64 = 0;
while i < old_cap {
k := old_keys[i];
if k != 0 {
slot : s64 = xx ((k * 2654435761) >> 24) & xx mask;
slot : i64 = xx ((k * 2654435761) >> 24) & xx mask;
while self.hash_keys[slot] != 0 {
slot = (slot + 1) & mask;
}
@@ -456,7 +456,7 @@ GlyphCache :: struct {
// Shelf-based rectangle packer.
// Returns PackResult with x >= 0 on success, x = -1 if no space.
try_pack :: (self: *GlyphCache, w: s32, h: s32) -> PackResult {
try_pack :: (self: *GlyphCache, w: i32, h: i32) -> PackResult {
padded_w := w + self.padding;
padded_h := h + self.padding;
@@ -488,15 +488,15 @@ GlyphCache :: struct {
grow :: (self: *GlyphCache) {
new_w := self.atlas_width * 2;
new_h := self.atlas_height * 2;
new_size : s64 = xx new_w * xx new_h;
new_size : i64 = xx new_w * xx new_h;
new_bitmap : [*]u8 = xx self.parent_allocator.alloc_bytes(new_size);
memset(new_bitmap, 0, new_size);
// Copy old rows into new bitmap
y : s32 = 0;
y : i32 = 0;
while y < self.atlas_height {
old_off : s64 = xx y * xx self.atlas_width;
new_off : s64 = xx y * xx new_w;
old_off : i64 = xx y * xx self.atlas_width;
new_off : i64 = xx y * xx new_w;
memcpy(@new_bitmap[new_off], @self.bitmap[old_off], xx self.atlas_width);
y += 1;
}
@@ -525,7 +525,7 @@ GlyphCache :: struct {
// Recompute UV coordinates for all cached glyphs
atlas_wf : f32 = xx new_w;
atlas_hf : f32 = xx new_h;
i : s64 = 0;
i : i64 = 0;
while i < self.entries.len {
g := @self.entries.items[i].glyph;
if g.width > 0.0 {
@@ -591,13 +591,13 @@ GlyphCache :: struct {
shape_ascii :: (self: *GlyphCache, text: string, font_size: f32) {
scale := stbtt_ScaleForPixelHeight(self.font_info, font_size);
total : f32 = 0.0;
i : s64 = 0;
i : i64 = 0;
while i < text.len {
ch : s32 = xx text[i];
ch : i32 = xx text[i];
glyph_index : u16 = xx stbtt_FindGlyphIndex(self.font_info, ch);
advance_i : s32 = 0;
lsb_i : s32 = 0;
advance_i : i32 = 0;
lsb_i : i32 = 0;
stbtt_GetGlyphHMetrics(self.font_info, xx glyph_index, @advance_i, @lsb_i);
adv : f32 = xx advance_i * scale;
@@ -650,7 +650,7 @@ GlyphCache :: struct {
measure_text :: (self: *GlyphCache, text: string, font_size: f32) -> Size {
self.shape_text(text, font_size);
width : f32 = 0.0;
i : s64 = 0;
i : i64 = 0;
while i < self.shaped_buf.len {
width += self.shaped_buf.items[i].advance;
i += 1;

View File

@@ -27,7 +27,7 @@ UIPipeline :: struct {
// `push Context` site.
arena_a: Arena;
arena_b: Arena;
frame_index: s64;
frame_index: i64;
body: Closure() -> View;
has_body: bool;
parent_allocator: Allocator;

View File

@@ -35,12 +35,12 @@ RenderNode :: struct {
// Opacity
opacity: f32;
depth: s64;
depth: i64;
}
RenderTree :: struct {
nodes: List(RenderNode);
generation: s64;
generation: i64;
init :: () -> RenderTree {
RenderTree.{ generation = 0 }
@@ -51,7 +51,7 @@ RenderTree :: struct {
self.generation += 1;
}
add :: (self: *RenderTree, node: RenderNode) -> s64 {
add :: (self: *RenderTree, node: RenderNode) -> i64 {
idx := self.nodes.len;
self.nodes.append(node);
idx
@@ -62,9 +62,9 @@ RenderTree :: struct {
RenderContext :: struct {
tree: *RenderTree;
clip_depth: s64;
clip_depth: i64;
opacity: f32;
depth: s64;
depth: i64;
init :: (tree: *RenderTree) -> RenderContext {
RenderContext.{

View File

@@ -10,27 +10,27 @@
#import "modules/ui/font.sx";
// Vertex: pos(2) + uv(2) + color(4) + params(4) = 12 floats
UI_VERTEX_FLOATS :s64: 12;
UI_VERTEX_BYTES :s64: 48;
MAX_UI_VERTICES :s64: 16384;
UI_VERTEX_FLOATS :i64: 12;
UI_VERTEX_BYTES :i64: 48;
MAX_UI_VERTICES :i64: 16384;
UIRenderer :: struct {
// GL-side handles. Used when `gpu == null` (every non-iOS target today).
vao: u32;
vbo: u32;
shader: u32;
proj_loc: s32;
tex_loc: s32;
proj_loc: i32;
tex_loc: i32;
// CPU-side vertex scratch buffer — same for both backends.
vertices: [*]f32;
vertex_count: s64;
vertex_count: i64;
screen_width: f32;
screen_height: f32;
dpi_scale: f32;
white_texture: u32; // GL name OR TextureHandle (both are u32-shaped)
current_texture: u32;
draw_calls: s64;
draw_calls: i64;
// GPU protocol backend. When set, the renderer routes shader / buffer /
// texture / draw calls through `gpu` instead of raw GL. The chess game
@@ -44,8 +44,8 @@ UIRenderer :: struct {
// time, not at draw-call submission, so re-using offset 0 across flushes
// would let the last writer win and earlier batches would render as
// whatever was uploaded last. Reset to 0 in `begin()`.
mtl_buf_offset: s64 = 0;
mtl_buf_capacity: s64 = 0;
mtl_buf_offset: i64 = 0;
mtl_buf_capacity: i64 = 0;
init :: (self: *UIRenderer) {
// Allocate vertex scratch (CPU side) — same for both backends.
@@ -295,7 +295,7 @@ UIRenderer :: struct {
flush :: (self: *UIRenderer) {
if self.vertex_count == 0 { return; }
upload_size : s64 = self.vertex_count * UI_VERTEX_BYTES;
upload_size : i64 = self.vertex_count * UI_VERTEX_BYTES;
if self.gpu != null {
// Mirror the GL path: bind current texture before drawing.
@@ -315,7 +315,7 @@ UIRenderer :: struct {
}
byte_off := self.mtl_buf_offset;
self.gpu.update_buffer_at(self.mtl_vbuf, xx self.vertices, upload_size, byte_off);
vertex_off : s32 = xx (byte_off / UI_VERTEX_BYTES);
vertex_off : i32 = xx (byte_off / UI_VERTEX_BYTES);
self.gpu.draw_triangles(vertex_off, xx self.vertex_count);
// Each batch starts on a vertex boundary so `vertex_off =
// byte_off / UI_VERTEX_BYTES` lands on a whole vertex (otherwise
@@ -364,7 +364,7 @@ UIRenderer :: struct {
raster_size := node.font_size * font.dpi_scale;
inv_dpi := font.inv_dpi;
i : s64 = 0;
i : i64 = 0;
while i < font.shaped_buf.len {
shaped := font.shaped_buf.items[i];
cached := font.get_or_rasterize(shaped.glyph_index, raster_size);

View File

@@ -14,17 +14,17 @@ State :: struct ($T: Type) {
// --- StateEntry — type-erased storage ---
StateEntry :: struct {
id: s64;
id: i64;
data: [*]u8;
size: s64;
generation: s64;
size: i64;
generation: i64;
}
// --- StateStore — manages persistent state ---
StateStore :: struct {
entries: List(StateEntry);
current_generation: s64;
current_generation: i64;
parent_allocator: Allocator;
init :: (self: *StateStore) {
@@ -33,9 +33,9 @@ StateStore :: struct {
self.parent_allocator = context.allocator;
}
get_or_create :: (self: *StateStore, id: s64, $T: Type, default: T) -> State(T) {
get_or_create :: (self: *StateStore, id: i64, $T: Type, default: T) -> State(T) {
// Search for existing entry
i : s64 = 0;
i : i64 = 0;
while i < self.entries.len {
if self.entries.items[i].id == id {
self.entries.items[i].generation = self.current_generation;

View File

@@ -45,7 +45,7 @@ impl View for StatsPanel {
// FPS value
dt := self.delta_time.*;
fps : s64 = if dt > 0.0 then xx (1.0 / dt) else 0;
fps : i64 = if dt > 0.0 then xx (1.0 / dt) else 0;
fps_text := format("FPS: {}", fps);
fps_size := measure_text(fps_text, StatsPanel.VALUE_SIZE);
fps_frame := Frame.make(