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