ui pipeline
This commit is contained in:
@@ -1,155 +0,0 @@
|
||||
#import "std.sx";
|
||||
|
||||
// --- Allocator protocol ---
|
||||
|
||||
Allocator :: struct {
|
||||
ctx: *void;
|
||||
alloc_fn: (*void, s64) -> *void;
|
||||
free_fn: (*void, *void) -> void;
|
||||
}
|
||||
|
||||
allocator_alloc :: (a: Allocator, size: s64) -> *void {
|
||||
a.alloc_fn(a.ctx, size);
|
||||
}
|
||||
|
||||
allocator_dealloc :: (a: Allocator, ptr: *void) {
|
||||
a.free_fn(a.ctx, ptr);
|
||||
}
|
||||
|
||||
alloc :: ufcs allocator_alloc;
|
||||
dealloc :: ufcs allocator_dealloc;
|
||||
|
||||
// --- GPA: general purpose allocator (malloc/free wrapper) ---
|
||||
|
||||
GPA :: struct {
|
||||
alloc_count: s64;
|
||||
}
|
||||
|
||||
gpa_alloc :: (ctx: *void, size: s64) -> *void {
|
||||
gpa : *GPA = xx ctx;
|
||||
gpa.alloc_count += 1;
|
||||
malloc(size);
|
||||
}
|
||||
|
||||
gpa_free :: (ctx: *void, ptr: *void) {
|
||||
gpa : *GPA = xx ctx;
|
||||
gpa.alloc_count -= 1;
|
||||
free(ptr);
|
||||
}
|
||||
|
||||
gpa_create :: (gpa: *GPA) -> Allocator {
|
||||
Allocator.{ ctx = gpa, alloc_fn = gpa_alloc, free_fn = gpa_free };
|
||||
}
|
||||
|
||||
// --- Arena: multi-chunk bump allocator (Zig-inspired) ---
|
||||
|
||||
ArenaChunk :: struct {
|
||||
next: *ArenaChunk;
|
||||
cap: s64;
|
||||
}
|
||||
|
||||
Arena :: struct {
|
||||
first: *ArenaChunk;
|
||||
end_index: s64;
|
||||
parent: Allocator;
|
||||
}
|
||||
|
||||
arena_add_chunk :: (a: *Arena, min_size: s64) {
|
||||
prev_cap := if a.first != null then a.first.cap else 0;
|
||||
needed := min_size + 16 + 16;
|
||||
len := (prev_cap + needed) * 3 / 2;
|
||||
raw := a.parent.alloc(len);
|
||||
chunk : *ArenaChunk = xx raw;
|
||||
chunk.next = a.first;
|
||||
chunk.cap = len;
|
||||
a.first = chunk;
|
||||
a.end_index = 0;
|
||||
}
|
||||
|
||||
arena_alloc :: (ctx: *void, size: s64) -> *void {
|
||||
a : *Arena = xx ctx;
|
||||
aligned := (size + 7) & (0 - 8);
|
||||
if a.first != null {
|
||||
usable := a.first.cap - 16;
|
||||
if a.end_index + aligned <= usable {
|
||||
buf : [*]u8 = xx a.first;
|
||||
ptr := @buf[16 + a.end_index];
|
||||
a.end_index = a.end_index + aligned;
|
||||
return ptr;
|
||||
}
|
||||
}
|
||||
arena_add_chunk(a, aligned);
|
||||
buf : [*]u8 = xx a.first;
|
||||
ptr := @buf[16 + a.end_index];
|
||||
a.end_index = a.end_index + aligned;
|
||||
ptr;
|
||||
}
|
||||
|
||||
arena_free :: (ctx: *void, ptr: *void) {
|
||||
}
|
||||
|
||||
arena_create :: (a: *Arena, parent: Allocator, size: s64) -> Allocator {
|
||||
a.first = null;
|
||||
a.end_index = 0;
|
||||
a.parent = parent;
|
||||
arena_add_chunk(a, size);
|
||||
Allocator.{ ctx = a, alloc_fn = arena_alloc, free_fn = arena_free };
|
||||
}
|
||||
|
||||
arena_reset :: (a: *Arena) {
|
||||
// Keep first chunk (newest/largest), free the rest
|
||||
if a.first != null {
|
||||
it := a.first.next;
|
||||
while it != null {
|
||||
next := it.next;
|
||||
a.parent.dealloc(it);
|
||||
it = next;
|
||||
}
|
||||
a.first.next = null;
|
||||
}
|
||||
a.end_index = 0;
|
||||
}
|
||||
|
||||
arena_deinit :: (a: *Arena) {
|
||||
it := a.first;
|
||||
while it != null {
|
||||
next := it.next;
|
||||
a.parent.dealloc(it);
|
||||
it = next;
|
||||
}
|
||||
a.first = null;
|
||||
a.end_index = 0;
|
||||
}
|
||||
|
||||
// --- BufAlloc: bump allocator backed by a user-provided slice ---
|
||||
|
||||
BufAlloc :: struct {
|
||||
buf: [*]u8;
|
||||
len: s64;
|
||||
pos: s64;
|
||||
}
|
||||
|
||||
buf_alloc :: (ctx: *void, size: s64) -> *void {
|
||||
b : *BufAlloc = xx ctx;
|
||||
aligned := (size + 7) & (0 - 8);
|
||||
if b.pos + aligned > b.len {
|
||||
return null;
|
||||
}
|
||||
ptr := @b.buf[b.pos];
|
||||
b.pos = b.pos + aligned;
|
||||
ptr;
|
||||
}
|
||||
|
||||
buf_free :: (ctx: *void, ptr: *void) {
|
||||
}
|
||||
|
||||
buf_create :: (b: *BufAlloc, buf: [*]u8, len: s64) -> Allocator {
|
||||
b.buf = buf;
|
||||
b.len = len;
|
||||
b.pos = 0;
|
||||
Allocator.{ ctx = b, alloc_fn = buf_alloc, free_fn = buf_free };
|
||||
}
|
||||
|
||||
buf_reset :: (b: *BufAlloc) {
|
||||
b.pos = 0;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
PI :f32: 3.14159265;
|
||||
|
||||
sqrt :: (x: $T) -> T #builtin;
|
||||
sin :: (x: $T) -> T #builtin;
|
||||
cos :: (x: $T) -> T #builtin;
|
||||
@@ -1,59 +0,0 @@
|
||||
#import "math.sx";
|
||||
|
||||
Matrix44 :: union {
|
||||
data: [16]f32;
|
||||
struct { c0, c1, c2, c3: Vector(4, f32); };
|
||||
}
|
||||
|
||||
mat4_perspective :: (fov: f32, aspect: f32, near: f32, far: f32) -> Matrix44 {
|
||||
half := fov / 2.0;
|
||||
f := cos(half) / sin(half);
|
||||
m : Matrix44 = ---;
|
||||
m.c0 = .[f / aspect, 0.0, 0.0, 0.0];
|
||||
m.c1 = .[0.0, f, 0.0, 0.0];
|
||||
m.c2 = .[0.0, 0.0, (far + near) / (near - far), -1.0];
|
||||
m.c3 = .[0.0, 0.0, (2.0 * far * near) / (near - far), 0.0];
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_translate :: (tx: f32, ty: f32, tz: f32) -> Matrix44 {
|
||||
m : Matrix44 = ---;
|
||||
m.c0 = .[1.0, 0.0, 0.0, 0.0];
|
||||
m.c1 = .[0.0, 1.0, 0.0, 0.0];
|
||||
m.c2 = .[0.0, 0.0, 1.0, 0.0];
|
||||
m.c3 = .[tx, ty, tz, 1.0];
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_rotate_y :: (angle: f32) -> Matrix44 {
|
||||
c := cos(angle);
|
||||
s := sin(angle);
|
||||
m : Matrix44 = ---;
|
||||
m.c0 = .[c, 0.0, 0.0 - s, 0.0];
|
||||
m.c1 = .[0.0, 1.0, 0.0, 0.0];
|
||||
m.c2 = .[s, 0.0, c, 0.0];
|
||||
m.c3 = .[0.0, 0.0, 0.0, 1.0];
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4_rotate_x :: (angle: f32) -> Matrix44 {
|
||||
c := cos(angle);
|
||||
s := sin(angle);
|
||||
m : Matrix44 = ---;
|
||||
m.c0 = .[1.0, 0.0, 0.0, 0.0];
|
||||
m.c1 = .[0.0, c, s, 0.0];
|
||||
m.c2 = .[0.0, 0.0 - s, c, 0.0];
|
||||
m.c3 = .[0.0, 0.0, 0.0, 1.0];
|
||||
m;
|
||||
}
|
||||
|
||||
|
||||
mat4_multiply :: (a: *Matrix44, b: *Matrix44) -> Matrix44 {
|
||||
out: Matrix44 = ---;
|
||||
out.c0 = a.c0 * b.c0.x + a.c1 * b.c0.y + a.c2 * b.c0.z + a.c3 * b.c0.w;
|
||||
out.c1 = a.c0 * b.c1.x + a.c1 * b.c1.y + a.c2 * b.c1.z + a.c3 * b.c1.w;
|
||||
out.c2 = a.c0 * b.c2.x + a.c1 * b.c2.y + a.c2 * b.c2.z + a.c3 * b.c2.w;
|
||||
out.c3 = a.c0 * b.c3.x + a.c1 * b.c3.y + a.c2 * b.c3.z + a.c3 * b.c3.w;
|
||||
return out;
|
||||
}
|
||||
multiply :: ufcs mat4_multiply;
|
||||
@@ -1,22 +0,0 @@
|
||||
#import "math.sx";
|
||||
|
||||
vec3_dot :: (a: Vector(3,f32), b: Vector(3,f32)) -> f32 {
|
||||
return a.x*b.x + a.y*b.y + a.z*b.z;
|
||||
}
|
||||
dot :: ufcs vec3_dot;
|
||||
|
||||
vec3_cross :: (a: Vector(3,f32), b: Vector(3,f32)) -> Vector(3,f32) {
|
||||
.[a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x];
|
||||
}
|
||||
cross :: ufcs vec3_cross;
|
||||
|
||||
vec3_length :: (v: Vector(3,f32)) -> f32 {
|
||||
return sqrt(dot(v, v));
|
||||
}
|
||||
length :: ufcs vec3_length;
|
||||
|
||||
|
||||
vec3_normal :: (v: Vector(3,f32)) -> Vector(3,f32) {
|
||||
return v / length(v);
|
||||
}
|
||||
normal :: ufcs vec3_normal;
|
||||
@@ -1,98 +0,0 @@
|
||||
// OpenGL 3.3 Core — runtime-loaded function pointers
|
||||
// No #library needed — caller provides a loader (e.g. SDL_GL_GetProcAddress)
|
||||
|
||||
// Constants
|
||||
GL_FALSE :s32: 0;
|
||||
GL_TRUE :s32: 1;
|
||||
GL_DEPTH_TEST :u32: 0x0B71;
|
||||
GL_CULL_FACE :u32: 0x0B44;
|
||||
GL_BLEND :u32: 0x0BE2;
|
||||
GL_TRIANGLES :u32: 4;
|
||||
GL_LINES :u32: 1;
|
||||
GL_FLOAT :u32: 0x1406;
|
||||
GL_UNSIGNED_INT :u32: 0x1405;
|
||||
GL_VERTEX_SHADER :u32: 0x8B31;
|
||||
GL_FRAGMENT_SHADER :u32: 0x8B30;
|
||||
GL_COMPILE_STATUS :u32: 0x8B81;
|
||||
GL_LINK_STATUS :u32: 0x8B82;
|
||||
GL_ARRAY_BUFFER :u32: 0x8892;
|
||||
GL_ELEMENT_ARRAY_BUFFER :u32: 0x8893;
|
||||
GL_STATIC_DRAW :u32: 0x88E4;
|
||||
GL_COLOR_BUFFER_BIT :u32: 0x4000;
|
||||
GL_DEPTH_BUFFER_BIT :u32: 0x0100;
|
||||
GL_FRONT_AND_BACK :u32: 0x0408;
|
||||
GL_LINE :u32: 0x1B01;
|
||||
GL_FILL :u32: 0x1B02;
|
||||
|
||||
// Function pointer variables (mutable, loaded at runtime)
|
||||
glClearColor : (f32, f32, f32, f32) -> void = ---;
|
||||
glClear : (u32) -> void = ---;
|
||||
glEnable : (u32) -> void = ---;
|
||||
glDisable : (u32) -> void = ---;
|
||||
glViewport : (s32, s32, s32, s32) -> void = ---;
|
||||
glDrawArrays : (u32, s32, s32) -> void = ---;
|
||||
glPolygonMode : (u32, u32) -> void = ---;
|
||||
glLineWidth : (f32) -> void = ---;
|
||||
glCreateShader : (u32) -> u32 = ---;
|
||||
glShaderSource : (u32, s32, *[:0]u8, *s32) -> void = ---;
|
||||
glCompileShader : (u32) -> void = ---;
|
||||
glGetShaderiv : (u32, u32, *s32) -> void = ---;
|
||||
glGetShaderInfoLog : (u32, s32, *s32, [*]u8) -> void = ---;
|
||||
glCreateProgram : () -> u32 = ---;
|
||||
glAttachShader : (u32, u32) -> void = ---;
|
||||
glLinkProgram : (u32) -> void = ---;
|
||||
glGetProgramiv : (u32, u32, *s32) -> void = ---;
|
||||
glGetProgramInfoLog : (u32, s32, *s32, [*]u8) -> void = ---;
|
||||
glUseProgram : (u32) -> void = ---;
|
||||
glDeleteShader : (u32) -> void = ---;
|
||||
glGenVertexArrays : (s32, *u32) -> void = ---;
|
||||
glGenBuffers : (s32, *u32) -> void = ---;
|
||||
glBindVertexArray : (u32) -> void = ---;
|
||||
glBindBuffer : (u32, u32) -> void = ---;
|
||||
glBufferData : (u32, s64, *void, u32) -> void = ---;
|
||||
glVertexAttribPointer : (u32, s32, u32, u8, s32, *void) -> void = ---;
|
||||
glEnableVertexAttribArray : (u32) -> void = ---;
|
||||
glGetUniformLocation : (u32, [:0]u8) -> s32 = ---;
|
||||
glUniformMatrix4fv : (s32, s32, u8, [16]f32) -> void = ---;
|
||||
glUniform3f : (s32, f32, f32, f32) -> void = ---;
|
||||
glDepthFunc : (u32) -> void = ---;
|
||||
glUniform1f : (s32, f32) -> void = ---;
|
||||
GL_LESS :u32: 0x0201;
|
||||
GL_LEQUAL :u32: 0x0203;
|
||||
|
||||
// Loader: call once after creating GL context
|
||||
// Pass in a proc loader (e.g. SDL_GL_GetProcAddress)
|
||||
load_gl :: (get_proc: ([:0]u8) -> *void) {
|
||||
glClearColor = xx get_proc("glClearColor");
|
||||
glClear = xx get_proc("glClear");
|
||||
glEnable = xx get_proc("glEnable");
|
||||
glDisable = xx get_proc("glDisable");
|
||||
glViewport = xx get_proc("glViewport");
|
||||
glDrawArrays = xx get_proc("glDrawArrays");
|
||||
glPolygonMode = xx get_proc("glPolygonMode");
|
||||
glLineWidth = xx get_proc("glLineWidth");
|
||||
glCreateShader = xx get_proc("glCreateShader");
|
||||
glShaderSource = xx get_proc("glShaderSource");
|
||||
glCompileShader = xx get_proc("glCompileShader");
|
||||
glGetShaderiv = xx get_proc("glGetShaderiv");
|
||||
glGetShaderInfoLog = xx get_proc("glGetShaderInfoLog");
|
||||
glCreateProgram = xx get_proc("glCreateProgram");
|
||||
glAttachShader = xx get_proc("glAttachShader");
|
||||
glLinkProgram = xx get_proc("glLinkProgram");
|
||||
glGetProgramiv = xx get_proc("glGetProgramiv");
|
||||
glGetProgramInfoLog = xx get_proc("glGetProgramInfoLog");
|
||||
glUseProgram = xx get_proc("glUseProgram");
|
||||
glDeleteShader = xx get_proc("glDeleteShader");
|
||||
glGenVertexArrays = xx get_proc("glGenVertexArrays");
|
||||
glGenBuffers = xx get_proc("glGenBuffers");
|
||||
glBindVertexArray = xx get_proc("glBindVertexArray");
|
||||
glBindBuffer = xx get_proc("glBindBuffer");
|
||||
glBufferData = xx get_proc("glBufferData");
|
||||
glVertexAttribPointer = xx get_proc("glVertexAttribPointer");
|
||||
glEnableVertexAttribArray = xx get_proc("glEnableVertexAttribArray");
|
||||
glGetUniformLocation = xx get_proc("glGetUniformLocation");
|
||||
glUniformMatrix4fv = xx get_proc("glUniformMatrix4fv");
|
||||
glUniform3f = xx get_proc("glUniform3f");
|
||||
glDepthFunc = xx get_proc("glDepthFunc");
|
||||
glUniform1f = xx get_proc("glUniform1f");
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
raylib :: #library "raylib";
|
||||
|
||||
Color :: struct {
|
||||
r, g, b, a: u8;
|
||||
}
|
||||
|
||||
Vector2 :: struct {
|
||||
x, y: f32;
|
||||
}
|
||||
|
||||
InitWindow :: (width: s32, height: s32, title: [:0]u8) -> void #foreign raylib;
|
||||
CloseWindow :: () -> void #foreign raylib;
|
||||
WindowShouldClose :: () -> bool #foreign raylib;
|
||||
BeginDrawing :: () -> void #foreign raylib;
|
||||
EndDrawing :: () -> void #foreign raylib;
|
||||
ClearBackground :: (color: Color) -> void #foreign raylib;
|
||||
DrawTriangle :: (v1: Vector2, v2: Vector2, v3: Vector2, color: Color) -> void #foreign raylib;
|
||||
334
modules/sdl3.sx
334
modules/sdl3.sx
@@ -1,334 +0,0 @@
|
||||
sdl3 :: #library "SDL3";
|
||||
|
||||
// SDL_InitFlags
|
||||
SDL_INIT_VIDEO :u32: 0x20;
|
||||
|
||||
// SDL_WindowFlags
|
||||
SDL_WINDOW_OPENGL :u64: 0x2;
|
||||
|
||||
// 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_GLProfile
|
||||
SDL_GL_CONTEXT_PROFILE_CORE :s32: 0x1;
|
||||
|
||||
// SDL_GLContextFlag
|
||||
SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG :s32: 0x2;
|
||||
|
||||
// SDL_Keycode — virtual key codes (layout-dependent)
|
||||
SDL_Keycode :: enum u32 {
|
||||
// Common
|
||||
unknown :: 0x00;
|
||||
return_key :: 0x0D;
|
||||
escape :: 0x1B;
|
||||
backspace :: 0x08;
|
||||
tab :: 0x09;
|
||||
space :: 0x20;
|
||||
delete_key :: 0x7F;
|
||||
|
||||
// Punctuation
|
||||
exclaim :: 0x21;
|
||||
double_quote :: 0x22;
|
||||
hash :: 0x23;
|
||||
dollar :: 0x24;
|
||||
percent :: 0x25;
|
||||
ampersand :: 0x26;
|
||||
apostrophe :: 0x27;
|
||||
leftparen :: 0x28;
|
||||
rightparen :: 0x29;
|
||||
asterisk :: 0x2A;
|
||||
plus :: 0x2B;
|
||||
comma :: 0x2C;
|
||||
minus :: 0x2D;
|
||||
period :: 0x2E;
|
||||
slash :: 0x2F;
|
||||
colon :: 0x3A;
|
||||
semicolon :: 0x3B;
|
||||
less :: 0x3C;
|
||||
equals :: 0x3D;
|
||||
greater :: 0x3E;
|
||||
question :: 0x3F;
|
||||
at :: 0x40;
|
||||
leftbracket :: 0x5B;
|
||||
backslash :: 0x5C;
|
||||
rightbracket :: 0x5D;
|
||||
caret :: 0x5E;
|
||||
underscore :: 0x5F;
|
||||
grave :: 0x60;
|
||||
leftbrace :: 0x7B;
|
||||
pipe :: 0x7C;
|
||||
rightbrace :: 0x7D;
|
||||
tilde :: 0x7E;
|
||||
plusminus :: 0xB1;
|
||||
|
||||
// Numbers
|
||||
key_0 :: 0x30;
|
||||
key_1 :: 0x31;
|
||||
key_2 :: 0x32;
|
||||
key_3 :: 0x33;
|
||||
key_4 :: 0x34;
|
||||
key_5 :: 0x35;
|
||||
key_6 :: 0x36;
|
||||
key_7 :: 0x37;
|
||||
key_8 :: 0x38;
|
||||
key_9 :: 0x39;
|
||||
|
||||
// Letters
|
||||
a :: 0x61;
|
||||
b :: 0x62;
|
||||
c :: 0x63;
|
||||
d :: 0x64;
|
||||
e :: 0x65;
|
||||
f :: 0x66;
|
||||
g :: 0x67;
|
||||
h :: 0x68;
|
||||
i :: 0x69;
|
||||
j :: 0x6A;
|
||||
k :: 0x6B;
|
||||
l :: 0x6C;
|
||||
m :: 0x6D;
|
||||
n :: 0x6E;
|
||||
o :: 0x6F;
|
||||
p :: 0x70;
|
||||
q :: 0x71;
|
||||
r :: 0x72;
|
||||
s :: 0x73;
|
||||
t :: 0x74;
|
||||
u :: 0x75;
|
||||
v :: 0x76;
|
||||
w :: 0x77;
|
||||
x :: 0x78;
|
||||
y :: 0x79;
|
||||
z :: 0x7A;
|
||||
|
||||
// Function keys
|
||||
f1 :: 0x4000003A;
|
||||
f2 :: 0x4000003B;
|
||||
f3 :: 0x4000003C;
|
||||
f4 :: 0x4000003D;
|
||||
f5 :: 0x4000003E;
|
||||
f6 :: 0x4000003F;
|
||||
f7 :: 0x40000040;
|
||||
f8 :: 0x40000041;
|
||||
f9 :: 0x40000042;
|
||||
f10 :: 0x40000043;
|
||||
f11 :: 0x40000044;
|
||||
f12 :: 0x40000045;
|
||||
f13 :: 0x40000068;
|
||||
f14 :: 0x40000069;
|
||||
f15 :: 0x4000006A;
|
||||
f16 :: 0x4000006B;
|
||||
f17 :: 0x4000006C;
|
||||
f18 :: 0x4000006D;
|
||||
f19 :: 0x4000006E;
|
||||
f20 :: 0x4000006F;
|
||||
f21 :: 0x40000070;
|
||||
f22 :: 0x40000071;
|
||||
f23 :: 0x40000072;
|
||||
f24 :: 0x40000073;
|
||||
|
||||
// Navigation
|
||||
capslock :: 0x40000039;
|
||||
printscreen :: 0x40000046;
|
||||
scrolllock :: 0x40000047;
|
||||
pause :: 0x40000048;
|
||||
insert :: 0x40000049;
|
||||
home :: 0x4000004A;
|
||||
pageup :: 0x4000004B;
|
||||
end :: 0x4000004D;
|
||||
pagedown :: 0x4000004E;
|
||||
right :: 0x4000004F;
|
||||
left :: 0x40000050;
|
||||
down :: 0x40000051;
|
||||
up :: 0x40000052;
|
||||
|
||||
// Keypad
|
||||
numlock :: 0x40000053;
|
||||
kp_divide :: 0x40000054;
|
||||
kp_multiply :: 0x40000055;
|
||||
kp_minus :: 0x40000056;
|
||||
kp_plus :: 0x40000057;
|
||||
kp_enter :: 0x40000058;
|
||||
kp_1 :: 0x40000059;
|
||||
kp_2 :: 0x4000005A;
|
||||
kp_3 :: 0x4000005B;
|
||||
kp_4 :: 0x4000005C;
|
||||
kp_5 :: 0x4000005D;
|
||||
kp_6 :: 0x4000005E;
|
||||
kp_7 :: 0x4000005F;
|
||||
kp_8 :: 0x40000060;
|
||||
kp_9 :: 0x40000061;
|
||||
kp_0 :: 0x40000062;
|
||||
kp_period :: 0x40000063;
|
||||
kp_equals :: 0x40000067;
|
||||
kp_comma :: 0x40000085;
|
||||
|
||||
// Modifiers
|
||||
lctrl :: 0x400000E0;
|
||||
lshift :: 0x400000E1;
|
||||
lalt :: 0x400000E2;
|
||||
lgui :: 0x400000E3;
|
||||
rctrl :: 0x400000E4;
|
||||
rshift :: 0x400000E5;
|
||||
ralt :: 0x400000E6;
|
||||
rgui :: 0x400000E7;
|
||||
mode :: 0x40000101;
|
||||
|
||||
// Editing
|
||||
undo :: 0x4000007A;
|
||||
cut :: 0x4000007B;
|
||||
copy :: 0x4000007C;
|
||||
paste :: 0x4000007D;
|
||||
find :: 0x4000007E;
|
||||
|
||||
// Media
|
||||
mute :: 0x4000007F;
|
||||
volumeup :: 0x40000080;
|
||||
volumedown :: 0x40000081;
|
||||
media_play :: 0x40000106;
|
||||
media_pause :: 0x40000107;
|
||||
media_fast_forward :: 0x40000109;
|
||||
media_rewind :: 0x4000010A;
|
||||
media_next_track :: 0x4000010B;
|
||||
media_previous_track :: 0x4000010C;
|
||||
media_stop :: 0x4000010D;
|
||||
media_eject :: 0x4000010E;
|
||||
media_play_pause :: 0x4000010F;
|
||||
|
||||
// System
|
||||
application :: 0x40000065;
|
||||
power :: 0x40000066;
|
||||
execute :: 0x40000074;
|
||||
help :: 0x40000075;
|
||||
menu :: 0x40000076;
|
||||
select :: 0x40000077;
|
||||
sleep :: 0x40000102;
|
||||
wake :: 0x40000103;
|
||||
}
|
||||
|
||||
// Event payload structs — match SDL3 layout from byte 4 onward (after the u32 type tag)
|
||||
// Common header: reserved (u32), timestamp (u64)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
SDL_Keymod :: enum flags u16 {
|
||||
lshift :: 0b0000_0000_0000_0001; // left Shift
|
||||
rshift :: 0b0000_0000_0000_0010; // right Shift
|
||||
level5 :: 0b0000_0000_0000_0100; // Level 5 Shift
|
||||
lctrl :: 0b0000_0000_0100_0000; // left Ctrl
|
||||
rctrl :: 0b0000_0000_1000_0000; // right Ctrl
|
||||
lalt :: 0b0000_0001_0000_0000; // left Alt
|
||||
ralt :: 0b0000_0010_0000_0000; // right Alt
|
||||
lgui :: 0b0000_0100_0000_0000; // left GUI (Windows/Cmd key)
|
||||
rgui :: 0b0000_1000_0000_0000; // right GUI (Windows/Cmd key)
|
||||
num :: 0b0001_0000_0000_0000; // Num Lock
|
||||
caps :: 0b0010_0000_0000_0000; // Caps Lock
|
||||
mode :: 0b0100_0000_0000_0000; // AltGr
|
||||
scroll :: 0b1000_0000_0000_0000; // Scroll Lock
|
||||
}
|
||||
|
||||
SDL_KeyData :: struct {
|
||||
timestamp: u64; // event time in nanoseconds
|
||||
window_id: u32; // window with keyboard focus
|
||||
which: u32; // keyboard instance id, 0 if unknown or virtual
|
||||
scancode: u32; // physical key code (layout-independent)
|
||||
key: SDL_Keycode; // virtual key code (layout-dependent)
|
||||
mod: SDL_Keymod; // active modifier keys
|
||||
raw: u16; // platform-specific scancode
|
||||
down: u8; // 1 if pressed, 0 if released
|
||||
repeat: u8; // 1 if this is a key repeat
|
||||
}
|
||||
|
||||
SDL_MouseMotionData :: struct {
|
||||
timestamp: u64; // event time in nanoseconds
|
||||
window_id: u32; // window with mouse focus
|
||||
which: u32; // mouse instance id, 0 for touch events
|
||||
state: u32; // button state bitmask (bit 0 = left, 1 = middle, 2 = right)
|
||||
x: f32; // x position relative to window
|
||||
y: f32; // y position relative to window
|
||||
xrel: f32; // relative motion in x
|
||||
yrel: f32; // relative motion in y
|
||||
}
|
||||
|
||||
SDL_MouseButtonData :: struct {
|
||||
timestamp: u64; // event time in nanoseconds
|
||||
window_id: u32; // window with mouse focus
|
||||
which: u32; // mouse instance id, 0 for touch events
|
||||
button: u8; // button index (1 = left, 2 = middle, 3 = right)
|
||||
down: u8; // 1 if pressed, 0 if released
|
||||
clicks: u8; // 1 for single-click, 2 for double-click, etc.
|
||||
_: u8;
|
||||
x: f32; // x position relative to window
|
||||
y: f32; // y position relative to window
|
||||
}
|
||||
|
||||
SDL_MouseWheelData :: struct {
|
||||
timestamp: u64; // event time in nanoseconds
|
||||
window_id: u32; // window with mouse focus
|
||||
which: u32; // mouse instance id
|
||||
x: f32; // horizontal scroll (positive = right)
|
||||
y: f32; // vertical scroll (positive = away from user)
|
||||
direction: u32; // 0 = normal, 1 = flipped (multiply by -1 to normalize)
|
||||
mouse_x: f32; // mouse x position relative to window
|
||||
mouse_y: f32; // mouse y position relative to window
|
||||
}
|
||||
|
||||
SDL_Event :: enum struct { tag: u32; _: u32; payload: [30]u32; } {
|
||||
none :: 0;
|
||||
|
||||
// Application
|
||||
quit :: 0x100;
|
||||
|
||||
// Window
|
||||
window_shown :: 0x202: SDL_WindowData;
|
||||
window_hidden :: 0x203: SDL_WindowData;
|
||||
window_exposed :: 0x204: SDL_WindowData;
|
||||
window_moved :: 0x205: SDL_WindowData;
|
||||
window_resized :: 0x206: SDL_WindowData;
|
||||
window_minimized :: 0x209: SDL_WindowData;
|
||||
window_maximized :: 0x20A: SDL_WindowData;
|
||||
window_restored :: 0x20B: SDL_WindowData;
|
||||
window_mouse_enter :: 0x20C: SDL_WindowData;
|
||||
window_mouse_leave :: 0x20D: SDL_WindowData;
|
||||
window_focus_gained :: 0x20E: SDL_WindowData;
|
||||
window_focus_lost :: 0x20F: SDL_WindowData;
|
||||
window_close_requested :: 0x210: SDL_WindowData;
|
||||
window_destroyed :: 0x219: SDL_WindowData;
|
||||
|
||||
// Keyboard
|
||||
key_down :: 0x300: SDL_KeyData;
|
||||
key_up :: 0x301: SDL_KeyData;
|
||||
|
||||
// Mouse
|
||||
mouse_motion :: 0x400: SDL_MouseMotionData;
|
||||
mouse_button_down :: 0x401: SDL_MouseButtonData;
|
||||
mouse_button_up :: 0x402: SDL_MouseButtonData;
|
||||
mouse_wheel :: 0x403: SDL_MouseWheelData;
|
||||
}
|
||||
|
||||
// Functions
|
||||
SDL_Init :: (flags: u32) -> bool #foreign sdl3;
|
||||
SDL_Quit :: () -> void #foreign sdl3;
|
||||
SDL_CreateWindow :: (title: [:0]u8, w: s32, h: s32, flags: u64) -> *void #foreign sdl3;
|
||||
SDL_DestroyWindow :: (window: *void) -> void #foreign sdl3;
|
||||
SDL_GL_SetAttribute :: (attr: s32, value: s32) -> bool #foreign sdl3;
|
||||
SDL_GL_CreateContext :: (window: *void) -> *void #foreign sdl3;
|
||||
SDL_GL_DestroyContext :: (context: *void) -> bool #foreign sdl3;
|
||||
SDL_GL_MakeCurrent :: (window: *void, context: *void) -> bool #foreign sdl3;
|
||||
SDL_GL_SwapWindow :: (window: *void) -> bool #foreign sdl3;
|
||||
SDL_GL_SetSwapInterval :: (interval: s32) -> bool #foreign sdl3;
|
||||
SDL_GL_GetProcAddress :: (proc: [:0]u8) -> *void #foreign sdl3;
|
||||
SDL_PollEvent :: (event: *SDL_Event) -> bool #foreign sdl3;
|
||||
SDL_GetTicks :: () -> u64 #foreign sdl3;
|
||||
SDL_Delay :: (ms: u32) -> void #foreign sdl3;
|
||||
SDL_GetError :: () -> [*]u8 #foreign sdl3;
|
||||
@@ -1,33 +0,0 @@
|
||||
// POSIX socket module (macOS only)
|
||||
// sockaddr_in layout and constants are platform-specific.
|
||||
|
||||
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: s64) -> s64 #foreign libc;
|
||||
write :: (fd: s32, buf: [*]u8, count: s64) -> s64 #foreign libc;
|
||||
close :: (fd: s32) -> s32 #foreign libc;
|
||||
|
||||
// Constants (macOS)
|
||||
AF_INET :s32: 2;
|
||||
SOCK_STREAM :s32: 1;
|
||||
SOL_SOCKET :s32: 0xFFFF;
|
||||
SO_REUSEADDR :s32: 0x4;
|
||||
|
||||
// macOS sockaddr_in (16 bytes, has sin_len field)
|
||||
SockAddr :: struct {
|
||||
sin_len: u8;
|
||||
sin_family: u8;
|
||||
sin_port: u16;
|
||||
sin_addr: u32 = 0;
|
||||
sin_zero: u64 = 0;
|
||||
}
|
||||
|
||||
htons :: (port: s64) -> u16 {
|
||||
cast(u16) (((port & 0xFF) << 8) | ((port >> 8) & 0xFF));
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
#import c {
|
||||
#include "vendors/stb_image/stb_image.h";
|
||||
#include "vendors/stb_image/stb_image_write.h";
|
||||
#source "vendors/stb_image/stb_image_impl.c";
|
||||
#source "vendors/stb_image/stb_image_write_impl.c";
|
||||
};
|
||||
352
modules/std.sx
352
modules/std.sx
@@ -1,352 +0,0 @@
|
||||
Vector :: ($N: int, $T: Type) -> Type #builtin;
|
||||
out :: (str: string) -> void #builtin;
|
||||
size_of :: ($T: Type) -> s64 #builtin;
|
||||
malloc :: (size: s64) -> *void #builtin;
|
||||
memcpy :: (dst: *void, src: *void, size: s64) -> *void #builtin;
|
||||
memset :: (dst: *void, val: s64, size: s64) -> void #builtin;
|
||||
free :: (ptr: *void) -> void #builtin;
|
||||
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;
|
||||
is_flags :: ($T: Type) -> bool #builtin;
|
||||
field_value_int :: ($T: Type, idx: s64) -> s64 #builtin;
|
||||
field_index :: ($T: Type, val: T) -> s64 #builtin;
|
||||
string :: []u8 #builtin;
|
||||
|
||||
#import "allocators.sx";
|
||||
|
||||
// --- Context ---
|
||||
|
||||
Context :: struct {
|
||||
allocator: Allocator;
|
||||
data: *void;
|
||||
}
|
||||
|
||||
context : Context = ---;
|
||||
|
||||
// --- Slice & string allocation ---
|
||||
|
||||
context_alloc :: (size: s64) -> *void {
|
||||
if context.allocator.ctx != null then context.allocator.alloc(size) else malloc(size);
|
||||
}
|
||||
|
||||
cstring :: (size: s64) -> string {
|
||||
raw := context_alloc(size + 1);
|
||||
memset(raw, 0, size + 1);
|
||||
s : string = ---;
|
||||
s.ptr = xx raw;
|
||||
s.len = size;
|
||||
s;
|
||||
}
|
||||
|
||||
alloc_slice :: ($T: Type, count: s64) -> []T {
|
||||
raw := context_alloc(count * size_of(T));
|
||||
memset(raw, 0, count * size_of(T));
|
||||
s : []T = ---;
|
||||
s.ptr = xx raw;
|
||||
s.len = count;
|
||||
s;
|
||||
}
|
||||
|
||||
int_to_string :: (n: s64) -> string {
|
||||
if n == 0 { return "0"; }
|
||||
neg := n < 0;
|
||||
v := if neg then 0 - n else n;
|
||||
// Single pass: fill digits backwards into temp string, then substr
|
||||
tmp := cstring(20);
|
||||
i := 19;
|
||||
while v > 0 {
|
||||
tmp[i] = (v % 10) + 48;
|
||||
v = v / 10;
|
||||
i -= 1;
|
||||
}
|
||||
if neg { tmp[i] = 45; i -= 1; }
|
||||
substr(tmp, i + 1, 20 - i - 1);
|
||||
}
|
||||
|
||||
bool_to_string :: (b: bool) -> string {
|
||||
if b then "true" else "false";
|
||||
}
|
||||
|
||||
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);
|
||||
if frac < 0 { frac = 0 - frac; }
|
||||
istr := int_to_string(int_part);
|
||||
fstr := int_to_string(frac);
|
||||
il := istr.len;
|
||||
fl := fstr.len;
|
||||
prefix := if neg then 1 else 0;
|
||||
total := prefix + il + 1 + 6;
|
||||
buf := cstring(total);
|
||||
pos := 0;
|
||||
if neg { buf[0] = 45; pos = 1; }
|
||||
memcpy(@buf[pos], istr.ptr, il);
|
||||
pos = pos + il;
|
||||
buf[pos] = 46;
|
||||
pos += 1;
|
||||
pad := 6 - fl;
|
||||
memset(@buf[pos], 48, pad);
|
||||
pos = pos + pad;
|
||||
memcpy(@buf[pos], fstr.ptr, fl);
|
||||
buf;
|
||||
}
|
||||
|
||||
hex_group :: (buf: string, offset: s64, val: s64) {
|
||||
i := offset + 3;
|
||||
v := val;
|
||||
while i >= offset {
|
||||
d := v % 16;
|
||||
buf[i] = if d < 10 then d + 48 else d - 10 + 97;
|
||||
v = v / 16;
|
||||
i -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
int_to_hex_string :: (n: s64) -> string {
|
||||
if n == 0 { return "0"; }
|
||||
|
||||
// Split into four 16-bit groups for correct unsigned treatment
|
||||
g0 := n % 65536;
|
||||
if g0 < 0 { g0 = g0 + 65536; }
|
||||
r1 := (n - g0) / 65536;
|
||||
g1 := r1 % 65536;
|
||||
if g1 < 0 { g1 = g1 + 65536; }
|
||||
r2 := (r1 - g1) / 65536;
|
||||
g2 := r2 % 65536;
|
||||
if g2 < 0 { g2 = g2 + 65536; }
|
||||
r3 := (r2 - g2) / 65536;
|
||||
g3 := r3 % 65536;
|
||||
if g3 < 0 { g3 = g3 + 65536; }
|
||||
|
||||
buf := cstring(16);
|
||||
hex_group(buf, 0, g3);
|
||||
hex_group(buf, 4, g2);
|
||||
hex_group(buf, 8, g1);
|
||||
hex_group(buf, 12, g0);
|
||||
|
||||
// Skip leading zeros (keep at least 1 digit)
|
||||
start := 0;
|
||||
while start < 15 {
|
||||
if buf[start] != 48 { break; }
|
||||
start += 1;
|
||||
}
|
||||
substr(buf, start, 16 - start);
|
||||
}
|
||||
|
||||
concat :: (a: string, b: string) -> string {
|
||||
al := a.len;
|
||||
bl := b.len;
|
||||
buf := cstring(al + bl);
|
||||
memcpy(buf.ptr, a.ptr, al);
|
||||
memcpy(@buf[al], b.ptr, bl);
|
||||
buf;
|
||||
}
|
||||
|
||||
substr :: (s: string, start: s64, len: s64) -> string {
|
||||
buf := cstring(len);
|
||||
memcpy(buf.ptr, @s[start], len);
|
||||
buf;
|
||||
}
|
||||
|
||||
struct_to_string :: (s: $T) -> string {
|
||||
result := concat(type_name(T), "{");
|
||||
i := 0;
|
||||
while i < field_count(T) {
|
||||
if i > 0 { result = concat(result, ", "); }
|
||||
result = concat(result, field_name(T, i));
|
||||
result = concat(result, ": ");
|
||||
result = concat(result, any_to_string(field_value(s, i)));
|
||||
i += 1;
|
||||
}
|
||||
concat(result, "}");
|
||||
}
|
||||
|
||||
vector_to_string :: (v: $T) -> string {
|
||||
result := "[";
|
||||
i := 0;
|
||||
while i < field_count(T) {
|
||||
if i > 0 { result = concat(result, ", "); }
|
||||
result = concat(result, any_to_string(field_value(v, i)));
|
||||
i += 1;
|
||||
}
|
||||
concat(result, "]");
|
||||
}
|
||||
|
||||
array_to_string :: (a: $T) -> string {
|
||||
result := "[";
|
||||
i := 0;
|
||||
while i < field_count(T) {
|
||||
if i > 0 { result = concat(result, ", "); }
|
||||
result = concat(result, any_to_string(field_value(a, i)));
|
||||
i += 1;
|
||||
}
|
||||
concat(result, "]");
|
||||
}
|
||||
|
||||
slice_to_string :: (items: []$T) -> string {
|
||||
result := "[";
|
||||
i := 0;
|
||||
while i < items.len {
|
||||
if i > 0 { result = concat(result, ", "); }
|
||||
result = concat(result, any_to_string(field_value(items, i)));
|
||||
i += 1;
|
||||
}
|
||||
concat(result, "]");
|
||||
}
|
||||
|
||||
pointer_to_string :: (p: $T) -> string {
|
||||
addr : s64 = 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;
|
||||
result := "";
|
||||
i := 0;
|
||||
while i < field_count(T) {
|
||||
fv := field_value_int(T, i);
|
||||
if v & fv {
|
||||
if result.len > 0 { result = concat(result, " | "); }
|
||||
result = concat(result, concat(".", field_name(T, i)));
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
if result.len == 0 { result = "0"; }
|
||||
result;
|
||||
}
|
||||
|
||||
enum_to_string :: (u: $T) -> string {
|
||||
if is_flags(T) { return flags_to_string(u); }
|
||||
idx := field_index(T, u);
|
||||
result := concat(".", field_name(T, idx));
|
||||
payload := field_value(u, idx);
|
||||
pstr := any_to_string(payload);
|
||||
if pstr.len > 0 {
|
||||
result = concat(result, concat("(", concat(pstr, ")")));
|
||||
}
|
||||
result;
|
||||
}
|
||||
|
||||
any_to_string :: (val: Any) -> string {
|
||||
result := "<?>";
|
||||
type := type_of(val);
|
||||
if type == {
|
||||
case void: result = "";
|
||||
case int: result = int_to_string(xx val);
|
||||
case string: { s : string = xx val; result = s; }
|
||||
case bool: result = bool_to_string(xx val);
|
||||
case float: result = float_to_string(xx val);
|
||||
case struct: result = struct_to_string(cast(type) val);
|
||||
case enum: result = enum_to_string(cast(type) val);
|
||||
case vector: result = vector_to_string(cast(type) val);
|
||||
case array: result = array_to_string(cast(type) val);
|
||||
case slice: result = slice_to_string(cast(type) val);
|
||||
case pointer: result = pointer_to_string(cast(type) val);
|
||||
case type: { s : string = xx val; result = s; }
|
||||
}
|
||||
result;
|
||||
}
|
||||
|
||||
build_format :: (fmt: string) -> string {
|
||||
code := "result := \"\"; ";
|
||||
seg_start := 0;
|
||||
i := 0;
|
||||
arg_idx := 0;
|
||||
while i < fmt.len {
|
||||
if fmt[i] == 123 {
|
||||
if i + 1 < fmt.len {
|
||||
if fmt[i + 1] == 125 {
|
||||
if i > seg_start {
|
||||
code = concat(code, "result = concat(result, substr(fmt, ");
|
||||
code = concat(code, int_to_string(seg_start));
|
||||
code = concat(code, ", ");
|
||||
code = concat(code, int_to_string(i - seg_start));
|
||||
code = concat(code, ")); ");
|
||||
}
|
||||
code = concat(code, "result = concat(result, any_to_string(args[");
|
||||
code = concat(code, int_to_string(arg_idx));
|
||||
code = concat(code, "])); ");
|
||||
arg_idx += 1;
|
||||
i += 2;
|
||||
seg_start = i;
|
||||
} else if fmt[i + 1] == 123 {
|
||||
code = concat(code, "result = concat(result, substr(fmt, ");
|
||||
code = concat(code, int_to_string(seg_start));
|
||||
code = concat(code, ", ");
|
||||
code = concat(code, int_to_string(i - seg_start + 1));
|
||||
code = concat(code, ")); ");
|
||||
i += 2;
|
||||
seg_start = i;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
} else if fmt[i] == 125 {
|
||||
if i + 1 < fmt.len {
|
||||
if fmt[i + 1] == 125 {
|
||||
code = concat(code, "result = concat(result, substr(fmt, ");
|
||||
code = concat(code, int_to_string(seg_start));
|
||||
code = concat(code, ", ");
|
||||
code = concat(code, int_to_string(i - seg_start + 1));
|
||||
code = concat(code, ")); ");
|
||||
i += 2;
|
||||
seg_start = i;
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
} else {
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
if seg_start < fmt.len {
|
||||
code = concat(code, "result = concat(result, substr(fmt, ");
|
||||
code = concat(code, int_to_string(seg_start));
|
||||
code = concat(code, ", ");
|
||||
code = concat(code, int_to_string(fmt.len - seg_start));
|
||||
code = concat(code, ")); ");
|
||||
}
|
||||
code;
|
||||
}
|
||||
|
||||
format :: ($fmt: string, args: ..Any) -> string {
|
||||
#insert build_format(fmt);
|
||||
#insert "result;";
|
||||
}
|
||||
|
||||
print :: ($fmt: string, args: ..Any) {
|
||||
#insert build_format(fmt);
|
||||
#insert "out(result);";
|
||||
}
|
||||
|
||||
List :: struct ($T: Type) {
|
||||
items: [*]T = null;
|
||||
len: s64 = 0;
|
||||
cap: s64 = 0;
|
||||
}
|
||||
|
||||
append ::(list: *List($T), item: T) {
|
||||
if list.len >= list.cap {
|
||||
new_cap := if list.cap == 0 then 4 else list.cap * 2;
|
||||
new_items : [*]T = xx malloc(new_cap * size_of(T));
|
||||
if list.len > 0 {
|
||||
memcpy(new_items, list.items, list.len * size_of(T));
|
||||
free(list.items);
|
||||
}
|
||||
list.items = new_items;
|
||||
list.cap = new_cap;
|
||||
}
|
||||
list.items[list.len] = item;
|
||||
list.len += 1;
|
||||
}
|
||||
Reference in New Issue
Block a user