mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Fix parameter/field lists and #import #include syntax
This commit is contained in:
+11
-14
@@ -1,13 +1,13 @@
|
|||||||
import "atomic.odin";
|
#import "atomic.odin";
|
||||||
import "fmt.odin";
|
#import "fmt.odin";
|
||||||
import "hash.odin";
|
#import "hash.odin";
|
||||||
import "math.odin";
|
#import "math.odin";
|
||||||
import "mem.odin";
|
#import "mem.odin";
|
||||||
import "opengl.odin";
|
#import "opengl.odin";
|
||||||
import "os.odin";
|
#import "os.odin";
|
||||||
import "sync.odin";
|
#import "sync.odin";
|
||||||
import "utf8.odin";
|
#import "utf8.odin";
|
||||||
import win32 "sys/windows.odin";
|
#import win32 "sys/windows.odin";
|
||||||
|
|
||||||
Thing :: enum f64 {
|
Thing :: enum f64 {
|
||||||
_, // Ignore first value
|
_, // Ignore first value
|
||||||
@@ -15,11 +15,8 @@ Thing :: enum f64 {
|
|||||||
B,
|
B,
|
||||||
C,
|
C,
|
||||||
D,
|
D,
|
||||||
};
|
}
|
||||||
|
|
||||||
main :: proc() {
|
main :: proc() {
|
||||||
fmt.println(Thing.A, Thing.B, Thing.C, Thing.D);
|
fmt.println(Thing.A, Thing.B, Thing.C, Thing.D);
|
||||||
|
|
||||||
x := 123;
|
|
||||||
fmt.println(x);
|
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-88
@@ -1,8 +1,8 @@
|
|||||||
#shared_global_scope;
|
#shared_global_scope;
|
||||||
|
|
||||||
import "os.odin";
|
#import "os.odin";
|
||||||
import "fmt.odin";
|
#import "fmt.odin";
|
||||||
import "mem.odin";
|
#import "mem.odin";
|
||||||
|
|
||||||
// IMPORTANT NOTE(bill): `type_info` & `type_info_val` cannot be used within a
|
// IMPORTANT NOTE(bill): `type_info` & `type_info_val` cannot be used within a
|
||||||
// #shared_global_scope due to the internals of the compiler.
|
// #shared_global_scope due to the internals of the compiler.
|
||||||
@@ -13,71 +13,71 @@ import "mem.odin";
|
|||||||
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
// IMPORTANT NOTE(bill): Do not change the order of any of this data
|
||||||
// The compiler relies upon this _exact_ order
|
// The compiler relies upon this _exact_ order
|
||||||
Type_Info_Member :: struct #ordered {
|
Type_Info_Member :: struct #ordered {
|
||||||
name string; // can be empty if tuple
|
name: string; // can be empty if tuple
|
||||||
type_info ^Type_Info;
|
type_info: ^Type_Info;
|
||||||
offset int; // offsets are not used in tuples
|
offset: int; // offsets are not used in tuples
|
||||||
}
|
}
|
||||||
Type_Info_Record :: struct #ordered {
|
Type_Info_Record :: struct #ordered {
|
||||||
fields []Type_Info_Member;
|
fields: []Type_Info_Member;
|
||||||
size int; // in bytes
|
size: int; // in bytes
|
||||||
align int; // in bytes
|
align: int; // in bytes
|
||||||
packed bool;
|
packed: bool;
|
||||||
ordered bool;
|
ordered: bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type_Info :: union {
|
Type_Info :: union {
|
||||||
Named struct #ordered {
|
Named: struct #ordered {
|
||||||
name string;
|
name: string;
|
||||||
base ^Type_Info; // This will _not_ be a Type_Info.Named
|
base: ^Type_Info; // This will _not_ be a Type_Info.Named
|
||||||
};
|
};
|
||||||
Integer struct #ordered {
|
Integer: struct #ordered {
|
||||||
size int; // in bytes
|
size: int; // in bytes
|
||||||
signed bool;
|
signed: bool;
|
||||||
};
|
};
|
||||||
Float struct #ordered {
|
Float: struct #ordered {
|
||||||
size int; // in bytes
|
size: int; // in bytes
|
||||||
};
|
};
|
||||||
Any struct #ordered {};
|
Any: struct #ordered {};
|
||||||
String struct #ordered {};
|
String: struct #ordered {};
|
||||||
Boolean struct #ordered {};
|
Boolean: struct #ordered {};
|
||||||
Pointer struct #ordered {
|
Pointer: struct #ordered {
|
||||||
elem ^Type_Info; // nil -> rawptr
|
elem: ^Type_Info; // nil -> rawptr
|
||||||
};
|
};
|
||||||
Maybe struct #ordered {
|
Maybe: struct #ordered {
|
||||||
elem ^Type_Info;
|
elem: ^Type_Info;
|
||||||
};
|
};
|
||||||
Procedure struct #ordered {
|
Procedure: struct #ordered {
|
||||||
params ^Type_Info; // Type_Info.Tuple
|
params: ^Type_Info; // Type_Info.Tuple
|
||||||
results ^Type_Info; // Type_Info.Tuple
|
results: ^Type_Info; // Type_Info.Tuple
|
||||||
variadic bool;
|
variadic: bool;
|
||||||
};
|
};
|
||||||
Array struct #ordered {
|
Array: struct #ordered {
|
||||||
elem ^Type_Info;
|
elem: ^Type_Info;
|
||||||
elem_size int;
|
elem_size: int;
|
||||||
count int;
|
count: int;
|
||||||
};
|
};
|
||||||
Slice struct #ordered {
|
Slice: struct #ordered {
|
||||||
elem ^Type_Info;
|
elem: ^Type_Info;
|
||||||
elem_size int;
|
elem_size: int;
|
||||||
};
|
};
|
||||||
Vector struct #ordered {
|
Vector: struct #ordered {
|
||||||
elem ^Type_Info;
|
elem: ^Type_Info;
|
||||||
elem_size int;
|
elem_size: int;
|
||||||
count int;
|
count: int;
|
||||||
align int;
|
align: int;
|
||||||
};
|
};
|
||||||
Tuple Type_Info_Record;
|
Tuple: Type_Info_Record;
|
||||||
Struct Type_Info_Record;
|
Struct: Type_Info_Record;
|
||||||
Union Type_Info_Record;
|
Union: Type_Info_Record;
|
||||||
Raw_Union Type_Info_Record;
|
Raw_Union: Type_Info_Record;
|
||||||
Enum struct #ordered {
|
Enum: struct #ordered {
|
||||||
base ^Type_Info;
|
base: ^Type_Info;
|
||||||
names []string;
|
names: []string;
|
||||||
// TODO(bill): store values some how. Maybe using a raw_union
|
// TODO(bill): store values some how. Maybe using a raw_union
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
type_info_base :: proc(info ^Type_Info) -> ^Type_Info {
|
type_info_base :: proc(info: ^Type_Info) -> ^Type_Info {
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
@@ -91,22 +91,22 @@ type_info_base :: proc(info ^Type_Info) -> ^Type_Info {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
assume :: proc(cond bool) #foreign "llvm.assume"
|
assume :: proc(cond: bool) #foreign "llvm.assume"
|
||||||
|
|
||||||
__debug_trap :: proc() #foreign "llvm.debugtrap"
|
__debug_trap :: proc() #foreign "llvm.debugtrap"
|
||||||
__trap :: proc() #foreign "llvm.trap"
|
__trap :: proc() #foreign "llvm.trap"
|
||||||
read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter"
|
read_cycle_counter :: proc() -> u64 #foreign "llvm.readcyclecounter"
|
||||||
|
|
||||||
bit_reverse16 :: proc(b u16) -> u16 #foreign "llvm.bitreverse.i16"
|
bit_reverse16 :: proc(b: u16) -> u16 #foreign "llvm.bitreverse.i16"
|
||||||
bit_reverse32 :: proc(b u32) -> u32 #foreign "llvm.bitreverse.i32"
|
bit_reverse32 :: proc(b: u32) -> u32 #foreign "llvm.bitreverse.i32"
|
||||||
bit_reverse64 :: proc(b u64) -> u64 #foreign "llvm.bitreverse.i64"
|
bit_reverse64 :: proc(b: u64) -> u64 #foreign "llvm.bitreverse.i64"
|
||||||
|
|
||||||
byte_swap16 :: proc(b u16) -> u16 #foreign "llvm.bswap.i16"
|
byte_swap16 :: proc(b: u16) -> u16 #foreign "llvm.bswap.i16"
|
||||||
byte_swap32 :: proc(b u32) -> u32 #foreign "llvm.bswap.i32"
|
byte_swap32 :: proc(b: u32) -> u32 #foreign "llvm.bswap.i32"
|
||||||
byte_swap64 :: proc(b u64) -> u64 #foreign "llvm.bswap.i64"
|
byte_swap64 :: proc(b: u64) -> u64 #foreign "llvm.bswap.i64"
|
||||||
|
|
||||||
fmuladd32 :: proc(a, b, c f32) -> f32 #foreign "llvm.fmuladd.f32"
|
fmuladd32 :: proc(a, b, c: f32) -> f32 #foreign "llvm.fmuladd.f32"
|
||||||
fmuladd64 :: proc(a, b, c f64) -> f64 #foreign "llvm.fmuladd.f64"
|
fmuladd64 :: proc(a, b, c: f64) -> f64 #foreign "llvm.fmuladd.f64"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -119,21 +119,21 @@ Allocator_Mode :: enum u8 {
|
|||||||
FREE_ALL,
|
FREE_ALL,
|
||||||
RESIZE,
|
RESIZE,
|
||||||
}
|
}
|
||||||
Allocator_Proc :: type proc(allocator_data rawptr, mode Allocator_Mode,
|
Allocator_Proc :: type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment int,
|
size, alignment: int,
|
||||||
old_memory rawptr, old_size int, flags u64) -> rawptr;
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr;
|
||||||
Allocator :: struct #ordered {
|
Allocator :: struct #ordered {
|
||||||
procedure Allocator_Proc;
|
procedure: Allocator_Proc;
|
||||||
data rawptr;
|
data: rawptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context :: struct #ordered {
|
Context :: struct #ordered {
|
||||||
thread_id int;
|
thread_id: int;
|
||||||
|
|
||||||
allocator Allocator;
|
allocator: Allocator;
|
||||||
|
|
||||||
user_data rawptr;
|
user_data: rawptr;
|
||||||
user_index int;
|
user_index: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
#thread_local __context: Context;
|
#thread_local __context: Context;
|
||||||
@@ -153,15 +153,15 @@ __check_context:: proc() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
alloc:: proc(size int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
|
alloc :: proc(size: int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNMENT); }
|
||||||
|
|
||||||
alloc_align:: proc(size, alignment int) -> rawptr #inline {
|
alloc_align :: proc(size, alignment: int) -> rawptr #inline {
|
||||||
__check_context();
|
__check_context();
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
return a.procedure(a.data, Allocator_Mode.ALLOC, size, alignment, nil, 0, 0);
|
return a.procedure(a.data, Allocator_Mode.ALLOC, size, alignment, nil, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
free:: proc(ptr rawptr) #inline {
|
free :: proc(ptr: rawptr) #inline {
|
||||||
__check_context();
|
__check_context();
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
if ptr != nil {
|
if ptr != nil {
|
||||||
@@ -175,8 +175,8 @@ free_all:: proc() #inline {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
resize:: proc (ptr rawptr, old_size, new_size int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
|
resize :: proc(ptr: rawptr, old_size, new_size: int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
|
||||||
resize_align:: proc(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inline {
|
resize_align :: proc(ptr: rawptr, old_size, new_size, alignment: int) -> rawptr #inline {
|
||||||
__check_context();
|
__check_context();
|
||||||
a := context.allocator;
|
a := context.allocator;
|
||||||
return a.procedure(a.data, Allocator_Mode.RESIZE, new_size, alignment, ptr, old_size, 0);
|
return a.procedure(a.data, Allocator_Mode.RESIZE, new_size, alignment, ptr, old_size, 0);
|
||||||
@@ -184,7 +184,7 @@ resize_align:: proc(ptr rawptr, old_size, new_size, alignment int) -> rawptr #in
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
default_resize_align:: proc(old_memory rawptr, old_size, new_size, alignment int) -> rawptr {
|
default_resize_align :: proc(old_memory: rawptr, old_size, new_size, alignment: int) -> rawptr {
|
||||||
if old_memory == nil {
|
if old_memory == nil {
|
||||||
return alloc_align(new_size, alignment);
|
return alloc_align(new_size, alignment);
|
||||||
}
|
}
|
||||||
@@ -209,9 +209,9 @@ default_resize_align:: proc(old_memory rawptr, old_size, new_size, alignment int
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
default_allocator_proc:: proc(allocator_data rawptr, mode Allocator_Mode,
|
default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment int,
|
size, alignment: int,
|
||||||
old_memory rawptr, old_size int, flags u64) -> rawptr {
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||||
using Allocator_Mode;
|
using Allocator_Mode;
|
||||||
|
|
||||||
when false {
|
when false {
|
||||||
@@ -276,7 +276,7 @@ default_allocator:: proc() -> Allocator {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
__string_eq:: proc(a, b string) -> bool {
|
__string_eq :: proc(a, b: string) -> bool {
|
||||||
if a.count != b.count {
|
if a.count != b.count {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -286,24 +286,24 @@ __string_eq:: proc(a, b string) -> bool {
|
|||||||
return mem.compare(a.data, b.data, a.count) == 0;
|
return mem.compare(a.data, b.data, a.count) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
__string_cmp:: proc(a, b string) -> int {
|
__string_cmp :: proc(a, b: string) -> int {
|
||||||
return mem.compare(a.data, b.data, min(a.count, b.count));
|
return mem.compare(a.data, b.data, min(a.count, b.count));
|
||||||
}
|
}
|
||||||
|
|
||||||
__string_ne:: proc(a, b string) -> bool #inline { return !__string_eq(a, b); }
|
__string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b); }
|
||||||
__string_lt:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) < 0; }
|
__string_lt :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) < 0; }
|
||||||
__string_gt:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) > 0; }
|
__string_gt :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) > 0; }
|
||||||
__string_le:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) <= 0; }
|
__string_le :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) <= 0; }
|
||||||
__string_ge:: proc(a, b string) -> bool #inline { return __string_cmp(a, b) >= 0; }
|
__string_ge :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) >= 0; }
|
||||||
|
|
||||||
|
|
||||||
__assert:: proc(file string, line, column int, msg string) #inline {
|
__assert :: proc(file: string, line, column: int, msg: string) #inline {
|
||||||
fmt.fprintf(os.stderr, "%(%:%) Runtime assertion: %\n",
|
fmt.fprintf(os.stderr, "%(%:%) Runtime assertion: %\n",
|
||||||
file, line, column, msg);
|
file, line, column, msg);
|
||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__bounds_check_error:: proc(file string, line, column int, index, count int) {
|
__bounds_check_error :: proc(file: string, line, column: int, index, count: int) {
|
||||||
if 0 <= index && index < count {
|
if 0 <= index && index < count {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -312,7 +312,7 @@ __bounds_check_error:: proc(file string, line, column int, index, count int) {
|
|||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__slice_expr_error:: proc(file string, line, column int, low, high, max int) {
|
__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) {
|
||||||
if 0 <= low && low <= high && high <= max {
|
if 0 <= low && low <= high && high <= max {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ __slice_expr_error:: proc(file string, line, column int, low, high, max int) {
|
|||||||
file, line, column, low, high, max);
|
file, line, column, low, high, max);
|
||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
__substring_expr_error:: proc(file string, line, column int, low, high int) {
|
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
||||||
if 0 <= low && low <= high {
|
if 0 <= low && low <= high {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-21
@@ -1,7 +1,7 @@
|
|||||||
// TODO(bill): Use assembly instead here to implement atomics
|
// TODO(bill): Use assembly instead here to implement atomics
|
||||||
// Inline vs external file?
|
// Inline vs external file?
|
||||||
|
|
||||||
import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||||
_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||||
|
|
||||||
|
|
||||||
@@ -11,30 +11,30 @@ sfence :: proc() { win32.WriteBarrier(); }
|
|||||||
lfence :: proc() { win32.ReadBarrier(); }
|
lfence :: proc() { win32.ReadBarrier(); }
|
||||||
|
|
||||||
|
|
||||||
load32 :: proc(a ^i32) -> i32 {
|
load32 :: proc(a: ^i32) -> i32 {
|
||||||
return a^;
|
return a^;
|
||||||
}
|
}
|
||||||
store32 :: proc(a ^i32, value i32) {
|
store32 :: proc(a: ^i32, value: i32) {
|
||||||
a^ = value;
|
a^ = value;
|
||||||
}
|
}
|
||||||
compare_exchange32 :: proc(a ^i32, expected, desired i32) -> i32 {
|
compare_exchange32 :: proc(a: ^i32, expected, desired: i32) -> i32 {
|
||||||
return win32.InterlockedCompareExchange(a, desired, expected);
|
return win32.InterlockedCompareExchange(a, desired, expected);
|
||||||
}
|
}
|
||||||
exchanged32 :: proc(a ^i32, desired i32) -> i32 {
|
exchanged32 :: proc(a: ^i32, desired: i32) -> i32 {
|
||||||
return win32.InterlockedExchange(a, desired);
|
return win32.InterlockedExchange(a, desired);
|
||||||
}
|
}
|
||||||
fetch_add32 :: proc(a ^i32, operand i32) -> i32 {
|
fetch_add32 :: proc(a: ^i32, operand: i32) -> i32 {
|
||||||
return win32.InterlockedExchangeAdd(a, operand);
|
return win32.InterlockedExchangeAdd(a, operand);
|
||||||
|
|
||||||
}
|
}
|
||||||
fetch_and32 :: proc(a ^i32, operand i32) -> i32 {
|
fetch_and32 :: proc(a: ^i32, operand: i32) -> i32 {
|
||||||
return win32.InterlockedAnd(a, operand);
|
return win32.InterlockedAnd(a, operand);
|
||||||
|
|
||||||
}
|
}
|
||||||
fetch_or32 :: proc(a ^i32, operand i32) -> i32 {
|
fetch_or32 :: proc(a: ^i32, operand: i32) -> i32 {
|
||||||
return win32.InterlockedOr(a, operand);
|
return win32.InterlockedOr(a, operand);
|
||||||
}
|
}
|
||||||
spin_lock32 :: proc(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock32 :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange32(a, 1, 0);
|
old_value := compare_exchange32(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
@@ -45,11 +45,11 @@ spin_lock32 :: proc(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1
|
|||||||
}
|
}
|
||||||
return old_value == 0;
|
return old_value == 0;
|
||||||
}
|
}
|
||||||
spin_unlock32 :: proc(a ^i32) {
|
spin_unlock32 :: proc(a: ^i32) {
|
||||||
store32(a, 0);
|
store32(a, 0);
|
||||||
mfence();
|
mfence();
|
||||||
}
|
}
|
||||||
try_acquire_lock32 :: proc(a ^i32) -> bool {
|
try_acquire_lock32 :: proc(a: ^i32) -> bool {
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value := compare_exchange32(a, 1, 0);
|
old_value := compare_exchange32(a, 1, 0);
|
||||||
mfence();
|
mfence();
|
||||||
@@ -57,28 +57,28 @@ try_acquire_lock32 :: proc(a ^i32) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
load64 :: proc(a ^i64) -> i64 {
|
load64 :: proc(a: ^i64) -> i64 {
|
||||||
return a^;
|
return a^;
|
||||||
}
|
}
|
||||||
store64 :: proc(a ^i64, value i64) {
|
store64 :: proc(a: ^i64, value: i64) {
|
||||||
a^ = value;
|
a^ = value;
|
||||||
}
|
}
|
||||||
compare_exchange64 :: proc(a ^i64, expected, desired i64) -> i64 {
|
compare_exchange64 :: proc(a: ^i64, expected, desired: i64) -> i64 {
|
||||||
return win32.InterlockedCompareExchange64(a, desired, expected);
|
return win32.InterlockedCompareExchange64(a, desired, expected);
|
||||||
}
|
}
|
||||||
exchanged64 :: proc(a ^i64, desired i64) -> i64 {
|
exchanged64 :: proc(a: ^i64, desired: i64) -> i64 {
|
||||||
return win32.InterlockedExchange64(a, desired);
|
return win32.InterlockedExchange64(a, desired);
|
||||||
}
|
}
|
||||||
fetch_add64 :: proc(a ^i64, operand i64) -> i64 {
|
fetch_add64 :: proc(a: ^i64, operand: i64) -> i64 {
|
||||||
return win32.InterlockedExchangeAdd64(a, operand);
|
return win32.InterlockedExchangeAdd64(a, operand);
|
||||||
}
|
}
|
||||||
fetch_and64 :: proc(a ^i64, operand i64) -> i64 {
|
fetch_and64 :: proc(a: ^i64, operand: i64) -> i64 {
|
||||||
return win32.InterlockedAnd64(a, operand);
|
return win32.InterlockedAnd64(a, operand);
|
||||||
}
|
}
|
||||||
fetch_or64 :: proc(a ^i64, operand i64) -> i64 {
|
fetch_or64 :: proc(a: ^i64, operand: i64) -> i64 {
|
||||||
return win32.InterlockedOr64(a, operand);
|
return win32.InterlockedOr64(a, operand);
|
||||||
}
|
}
|
||||||
spin_lock64 :: proc(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock64 :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange64(a, 1, 0);
|
old_value := compare_exchange64(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
@@ -89,11 +89,11 @@ spin_lock64 :: proc(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1
|
|||||||
}
|
}
|
||||||
return old_value == 0;
|
return old_value == 0;
|
||||||
}
|
}
|
||||||
spin_unlock64 :: proc(a ^i64) {
|
spin_unlock64 :: proc(a: ^i64) {
|
||||||
store64(a, 0);
|
store64(a, 0);
|
||||||
mfence();
|
mfence();
|
||||||
}
|
}
|
||||||
try_acquire_lock64 :: proc(a ^i64) -> bool {
|
try_acquire_lock64 :: proc(a: ^i64) -> bool {
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value := compare_exchange64(a, 1, 0);
|
old_value := compare_exchange64(a, 1, 0);
|
||||||
mfence();
|
mfence();
|
||||||
|
|||||||
+36
-38
@@ -1,12 +1,10 @@
|
|||||||
import {
|
#import "os.odin";
|
||||||
"os.odin";
|
#import "mem.odin";
|
||||||
"mem.odin";
|
#import "utf8.odin";
|
||||||
"utf8.odin";
|
|
||||||
}
|
|
||||||
|
|
||||||
PRINT_BUF_SIZE :: 1<<12;
|
PRINT_BUF_SIZE :: 1<<12;
|
||||||
|
|
||||||
fprint :: proc(fd os.Handle, args ..any) -> int {
|
fprint :: proc(fd: os.Handle, args: ..any) -> int {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
buf := data[:0];
|
buf := data[:0];
|
||||||
bprint(^buf, ..args);
|
bprint(^buf, ..args);
|
||||||
@@ -14,14 +12,14 @@ fprint :: proc(fd os.Handle, args ..any) -> int {
|
|||||||
return buf.count;
|
return buf.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintln :: proc(fd os.Handle, args ..any) -> int {
|
fprintln :: proc(fd: os.Handle, args: ..any) -> int {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
buf := data[:0];
|
buf := data[:0];
|
||||||
bprintln(^buf, ..args);
|
bprintln(^buf, ..args);
|
||||||
os.write(fd, buf);
|
os.write(fd, buf);
|
||||||
return buf.count;
|
return buf.count;
|
||||||
}
|
}
|
||||||
fprintf :: proc(fd os.Handle, fmt string, args ..any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
buf := data[:0];
|
buf := data[:0];
|
||||||
bprintf(^buf, fmt, ..args);
|
bprintf(^buf, fmt, ..args);
|
||||||
@@ -30,19 +28,19 @@ fprintf :: proc(fd os.Handle, fmt string, args ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print :: proc(args ..any) -> int {
|
print :: proc(args: ..any) -> int {
|
||||||
return fprint(os.stdout, ..args);
|
return fprint(os.stdout, ..args);
|
||||||
}
|
}
|
||||||
println :: proc(args ..any) -> int {
|
println :: proc(args: ..any) -> int {
|
||||||
return fprintln(os.stdout, ..args);
|
return fprintln(os.stdout, ..args);
|
||||||
}
|
}
|
||||||
printf :: proc(fmt string, args ..any) -> int {
|
printf :: proc(fmt: string, args: ..any) -> int {
|
||||||
return fprintf(os.stdout, fmt, ..args);
|
return fprintf(os.stdout, fmt, ..args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fprint_type :: proc(fd os.Handle, info ^Type_Info) {
|
fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
buf := data[:0];
|
buf := data[:0];
|
||||||
bprint_type(^buf, info);
|
bprint_type(^buf, info);
|
||||||
@@ -51,7 +49,7 @@ fprint_type :: proc(fd os.Handle, info ^Type_Info) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
print_byte_buffer :: proc(buf ^[]byte, b []byte) {
|
print_byte_buffer :: proc(buf: ^[]byte, b: []byte) {
|
||||||
if buf.count < buf.capacity {
|
if buf.count < buf.capacity {
|
||||||
n := min(buf.capacity-buf.count, b.count);
|
n := min(buf.capacity-buf.count, b.count);
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
@@ -61,29 +59,29 @@ print_byte_buffer :: proc(buf ^[]byte, b []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_string :: proc(buf ^[]byte, s string) {
|
bprint_string :: proc(buf: ^[]byte, s: string) {
|
||||||
print_byte_buffer(buf, s as []byte);
|
print_byte_buffer(buf, s as []byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte_reverse :: proc(b []byte) {
|
byte_reverse :: proc(b: []byte) {
|
||||||
n := b.count;
|
n := b.count;
|
||||||
for i := 0; i < n/2; i++ {
|
for i := 0; i < n/2; i++ {
|
||||||
b[i], b[n-1-i] = b[n-1-i], b[i];
|
b[i], b[n-1-i] = b[n-1-i], b[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_rune :: proc(buf ^[]byte, r rune) {
|
bprint_rune :: proc(buf: ^[]byte, r: rune) {
|
||||||
b, n := utf8.encode_rune(r);
|
b, n := utf8.encode_rune(r);
|
||||||
bprint_string(buf, b[:n] as string);
|
bprint_string(buf, b[:n] as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_space :: proc(buf ^[]byte) { bprint_rune(buf, ' '); }
|
bprint_space :: proc(buf: ^[]byte) { bprint_rune(buf, ' '); }
|
||||||
bprint_nl :: proc (buf ^[]byte) { bprint_rune(buf, '\n'); }
|
bprint_nl :: proc (buf: ^[]byte) { bprint_rune(buf, '\n'); }
|
||||||
|
|
||||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
||||||
|
|
||||||
bprint_bool :: proc(buffer ^[]byte, b bool) {
|
bprint_bool :: proc(buffer: ^[]byte, b: bool) {
|
||||||
if b {
|
if b {
|
||||||
bprint_string(buffer, "true");
|
bprint_string(buffer, "true");
|
||||||
} else {
|
} else {
|
||||||
@@ -91,15 +89,15 @@ bprint_bool :: proc(buffer ^[]byte, b bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_pointer :: proc(buffer ^[]byte, p rawptr) #inline {
|
bprint_pointer :: proc(buffer: ^[]byte, p: rawptr) #inline {
|
||||||
bprint_string(buffer, "0x");
|
bprint_string(buffer, "0x");
|
||||||
bprint_u64(buffer, p as uint as u64);
|
bprint_u64(buffer, p as uint as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_f16 :: proc (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 4); }
|
// bprint_f16 :: proc (buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 4); }
|
||||||
bprint_f32 :: proc (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 7); }
|
bprint_f32 :: proc (buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7); }
|
||||||
bprint_f64 :: proc (buffer ^[]byte, f f64) #inline { print__f64(buffer, f as f64, 16); }
|
bprint_f64 :: proc (buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f as f64, 16); }
|
||||||
bprint_u64 :: proc(buffer ^[]byte, value u64) {
|
bprint_u64 :: proc(buffer: ^[]byte, value: u64) {
|
||||||
i := value;
|
i := value;
|
||||||
buf :[20]byte;
|
buf :[20]byte;
|
||||||
len := 0;
|
len := 0;
|
||||||
@@ -115,7 +113,7 @@ bprint_u64 :: proc(buffer ^[]byte, value u64) {
|
|||||||
byte_reverse(buf[:len]);
|
byte_reverse(buf[:len]);
|
||||||
bprint_string(buffer, buf[:len] as string);
|
bprint_string(buffer, buf[:len] as string);
|
||||||
}
|
}
|
||||||
bprint_i64 :: proc(buffer ^[]byte, value i64) {
|
bprint_i64 :: proc(buffer: ^[]byte, value: i64) {
|
||||||
// TODO(bill): Cleanup printing
|
// TODO(bill): Cleanup printing
|
||||||
i := value;
|
i := value;
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
@@ -126,14 +124,14 @@ bprint_i64 :: proc(buffer ^[]byte, value i64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bprint_u128 :: proc(buffer ^[]byte, value u128) {
|
bprint_u128 :: proc(buffer: ^[]byte, value u128) {
|
||||||
a := value transmute [2]u64;
|
a := value transmute [2]u64;
|
||||||
if a[1] != 0 {
|
if a[1] != 0 {
|
||||||
bprint_u64(buffer, a[1]);
|
bprint_u64(buffer, a[1]);
|
||||||
}
|
}
|
||||||
bprint_u64(buffer, a[0]);
|
bprint_u64(buffer, a[0]);
|
||||||
}
|
}
|
||||||
bprint_i128 :: proc(buffer ^[]byte, value i128) {
|
bprint_i128 :: proc(buffer: ^[]byte, value i128) {
|
||||||
i := value;
|
i := value;
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
i = -i;
|
i = -i;
|
||||||
@@ -144,7 +142,7 @@ bprint_i128 :: proc(buffer ^[]byte, value i128) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
print__f64 :: proc(buffer ^[]byte, value f64, decimal_places int) {
|
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
||||||
f := value;
|
f := value;
|
||||||
if f == 0 {
|
if f == 0 {
|
||||||
bprint_rune(buffer, '0');
|
bprint_rune(buffer, '0');
|
||||||
@@ -170,7 +168,7 @@ print__f64 :: proc(buffer ^[]byte, value f64, decimal_places int) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_type :: proc(buf ^[]byte, ti ^Type_Info) {
|
bprint_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
||||||
if ti == nil {
|
if ti == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -302,14 +300,14 @@ bprint_type :: proc(buf ^[]byte, ti ^Type_Info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
make_any :: proc(type_info ^Type_Info, data rawptr) -> any {
|
make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any {
|
||||||
a :any;
|
a :any;
|
||||||
a.type_info = type_info;
|
a.type_info = type_info;
|
||||||
a.data = data;
|
a.data = data;
|
||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_any :: proc(buf ^[]byte, arg any) {
|
bprint_any :: proc(buf: ^[]byte, arg: any) {
|
||||||
if arg.type_info == nil {
|
if arg.type_info == nil {
|
||||||
bprint_string(buf, "<nil>");
|
bprint_string(buf, "<nil>");
|
||||||
return;
|
return;
|
||||||
@@ -423,7 +421,7 @@ bprint_any :: proc(buf ^[]byte, arg any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case Vector:
|
case Vector:
|
||||||
is_bool :: proc(type_info ^Type_Info) -> bool {
|
is_bool :: proc(type_info: ^Type_Info) -> bool {
|
||||||
match type info : type_info {
|
match type info : type_info {
|
||||||
case Named:
|
case Named:
|
||||||
return is_bool(info.base);
|
return is_bool(info.base);
|
||||||
@@ -481,12 +479,12 @@ bprint_any :: proc(buf ^[]byte, arg any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bprintf :: proc(buf ^[]byte, fmt string, args ..any) -> int {
|
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
||||||
is_digit :: proc(r rune) -> bool #inline {
|
is_digit :: proc(r: rune) -> bool #inline {
|
||||||
return '0' <= r && r <= '9';
|
return '0' <= r && r <= '9';
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_int :: proc(s string, offset int) -> (int, int) {
|
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
||||||
result := 0;
|
result := 0;
|
||||||
|
|
||||||
for ; offset < s.count; offset++ {
|
for ; offset < s.count; offset++ {
|
||||||
@@ -546,8 +544,8 @@ bprintf :: proc(buf ^[]byte, fmt string, args ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bprint :: proc(buf ^[]byte, args ..any) -> int {
|
bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
||||||
is_type_string :: proc(info ^Type_Info) -> bool {
|
is_type_string :: proc(info: ^Type_Info) -> bool {
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return false;
|
return false;
|
||||||
@@ -574,7 +572,7 @@ bprint :: proc(buf ^[]byte, args ..any) -> int {
|
|||||||
return buf.count;
|
return buf.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bprintln :: proc(buf ^[]byte, args ..any) -> int {
|
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
|
||||||
for i := 0; i < args.count; i++ {
|
for i := 0; i < args.count; i++ {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
append(buf, ' ');
|
append(buf, ' ');
|
||||||
|
|||||||
+7
-7
@@ -1,4 +1,4 @@
|
|||||||
crc32 :: proc(data rawptr, len int) -> u32 {
|
crc32 :: proc(data: rawptr, len: int) -> u32 {
|
||||||
result := ~(0 as u32);
|
result := ~(0 as u32);
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
@@ -7,7 +7,7 @@ crc32 :: proc(data rawptr, len int) -> u32 {
|
|||||||
}
|
}
|
||||||
return ~result;
|
return ~result;
|
||||||
}
|
}
|
||||||
crc64 :: proc(data rawptr, len int) -> u64 {
|
crc64 :: proc(data: rawptr, len: int) -> u64 {
|
||||||
result := ~(0 as u64);
|
result := ~(0 as u64);
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
for i := 0; i < len; i++ {
|
for i := 0; i < len; i++ {
|
||||||
@@ -17,7 +17,7 @@ crc64 :: proc(data rawptr, len int) -> u64 {
|
|||||||
return ~result;
|
return ~result;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnv32 :: proc(data rawptr, len int) -> u32 {
|
fnv32 :: proc(data: rawptr, len: int) -> u32 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u32 = 0x811c9dc5;
|
h :u32 = 0x811c9dc5;
|
||||||
@@ -27,7 +27,7 @@ fnv32 :: proc(data rawptr, len int) -> u32 {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnv64 :: proc(data rawptr, len int) -> u64 {
|
fnv64 :: proc(data: rawptr, len: int) -> u64 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u64 = 0xcbf29ce484222325;
|
h :u64 = 0xcbf29ce484222325;
|
||||||
@@ -37,7 +37,7 @@ fnv64 :: proc(data rawptr, len int) -> u64 {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnv32a :: proc(data rawptr, len int) -> u32 {
|
fnv32a :: proc(data: rawptr, len: int) -> u32 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u32 = 0x811c9dc5;
|
h :u32 = 0x811c9dc5;
|
||||||
@@ -47,7 +47,7 @@ fnv32a :: proc(data rawptr, len int) -> u32 {
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
fnv64a :: proc(data rawptr, len int) -> u64 {
|
fnv64a :: proc(data: rawptr, len: int) -> u64 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u64 = 0xcbf29ce484222325;
|
h :u64 = 0xcbf29ce484222325;
|
||||||
@@ -58,7 +58,7 @@ fnv64a :: proc(data rawptr, len int) -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
murmur64 :: proc(data_ rawptr, len int) -> u64 {
|
murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
||||||
SEED :: 0x9747b28c;
|
SEED :: 0x9747b28c;
|
||||||
|
|
||||||
when size_of(int) == 8 {
|
when size_of(int) == 8 {
|
||||||
|
|||||||
+44
-44
@@ -24,57 +24,57 @@ Mat2 :: [2]Vec2;
|
|||||||
Mat3 :: [3]Vec3;
|
Mat3 :: [3]Vec3;
|
||||||
Mat4 :: [4]Vec4;
|
Mat4 :: [4]Vec4;
|
||||||
|
|
||||||
sqrt32 :: proc(x f32) -> f32 #foreign "llvm.sqrt.f32"
|
sqrt32 :: proc(x: f32) -> f32 #foreign "llvm.sqrt.f32"
|
||||||
sqrt64 :: proc(x f64) -> f64 #foreign "llvm.sqrt.f64"
|
sqrt64 :: proc(x: f64) -> f64 #foreign "llvm.sqrt.f64"
|
||||||
|
|
||||||
sin32 :: proc(x f32) -> f32 #foreign "llvm.sin.f32"
|
sin32 :: proc(x: f32) -> f32 #foreign "llvm.sin.f32"
|
||||||
sin64 :: proc(x f64) -> f64 #foreign "llvm.sin.f64"
|
sin64 :: proc(x: f64) -> f64 #foreign "llvm.sin.f64"
|
||||||
|
|
||||||
cos32 :: proc(x f32) -> f32 #foreign "llvm.cos.f32"
|
cos32 :: proc(x: f32) -> f32 #foreign "llvm.cos.f32"
|
||||||
cos64 :: proc(x f64) -> f64 #foreign "llvm.cos.f64"
|
cos64 :: proc(x: f64) -> f64 #foreign "llvm.cos.f64"
|
||||||
|
|
||||||
tan32 :: proc(x f32) -> f32 #inline { return sin32(x)/cos32(x); }
|
tan32 :: proc(x: f32) -> f32 #inline { return sin32(x)/cos32(x); }
|
||||||
tan64 :: proc(x f64) -> f64 #inline { return sin64(x)/cos64(x); }
|
tan64 :: proc(x: f64) -> f64 #inline { return sin64(x)/cos64(x); }
|
||||||
|
|
||||||
lerp32 :: proc(a, b, t f32) -> f32 { return a*(1-t) + b*t; }
|
lerp32 :: proc(a, b, t: f32) -> f32 { return a*(1-t) + b*t; }
|
||||||
lerp64 :: proc(a, b, t f64) -> f64 { return a*(1-t) + b*t; }
|
lerp64 :: proc(a, b, t: f64) -> f64 { return a*(1-t) + b*t; }
|
||||||
|
|
||||||
sign32 :: proc(x f32) -> f32 { if x >= 0 { return +1; } return -1; }
|
sign32 :: proc(x: f32) -> f32 { if x >= 0 { return +1; } return -1; }
|
||||||
sign64 :: proc(x f64) -> f64 { if x >= 0 { return +1; } return -1; }
|
sign64 :: proc(x: f64) -> f64 { if x >= 0 { return +1; } return -1; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
copy_sign32 :: proc(x, y f32) -> f32 {
|
copy_sign32 :: proc(x, y: f32) -> f32 {
|
||||||
ix := x transmute u32;
|
ix := x transmute u32;
|
||||||
iy := y transmute u32;
|
iy := y transmute u32;
|
||||||
ix &= 0x7fffffff;
|
ix &= 0x7fffffff;
|
||||||
ix |= iy & 0x80000000;
|
ix |= iy & 0x80000000;
|
||||||
return ix transmute f32;
|
return ix transmute f32;
|
||||||
}
|
}
|
||||||
round32 :: proc(x f32) -> f32 {
|
round32 :: proc(x: f32) -> f32 {
|
||||||
if x >= 0 {
|
if x >= 0 {
|
||||||
return floor32(x + 0.5);
|
return floor32(x + 0.5);
|
||||||
}
|
}
|
||||||
return ceil32(x - 0.5);
|
return ceil32(x - 0.5);
|
||||||
}
|
}
|
||||||
floor32 :: proc(x f32) -> f32 {
|
floor32 :: proc(x: f32) -> f32 {
|
||||||
if x >= 0 {
|
if x >= 0 {
|
||||||
return x as int as f32;
|
return x as int as f32;
|
||||||
}
|
}
|
||||||
return (x-0.5) as int as f32;
|
return (x-0.5) as int as f32;
|
||||||
}
|
}
|
||||||
ceil32 :: proc(x f32) -> f32 {
|
ceil32 :: proc(x: f32) -> f32 {
|
||||||
if x < 0 {
|
if x < 0 {
|
||||||
return x as int as f32;
|
return x as int as f32;
|
||||||
}
|
}
|
||||||
return ((x as int)+1) as f32;
|
return ((x as int)+1) as f32;
|
||||||
}
|
}
|
||||||
|
|
||||||
remainder32 :: proc(x, y f32) -> f32 {
|
remainder32 :: proc(x, y: f32) -> f32 {
|
||||||
return x - round32(x/y) * y;
|
return x - round32(x/y) * y;
|
||||||
}
|
}
|
||||||
|
|
||||||
fmod32 :: proc(x, y f32) -> f32 {
|
fmod32 :: proc(x, y: f32) -> f32 {
|
||||||
y = abs(y);
|
y = abs(y);
|
||||||
result := remainder32(abs(x), y);
|
result := remainder32(abs(x), y);
|
||||||
if sign32(result) < 0 {
|
if sign32(result) < 0 {
|
||||||
@@ -84,32 +84,32 @@ fmod32 :: proc(x, y f32) -> f32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
to_radians :: proc(degrees f32) -> f32 { return degrees * TAU / 360; }
|
to_radians :: proc(degrees: f32) -> f32 { return degrees * TAU / 360; }
|
||||||
to_degrees :: proc(radians f32) -> f32 { return radians * 360 / TAU; }
|
to_degrees :: proc(radians: f32) -> f32 { return radians * 360 / TAU; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dot2 :: proc(a, b Vec2) -> f32 { c := a*b; return c.x + c.y; }
|
dot2 :: proc(a, b: Vec2) -> f32 { c := a*b; return c.x + c.y; }
|
||||||
dot3 :: proc(a, b Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; }
|
dot3 :: proc(a, b: Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; }
|
||||||
dot4 :: proc(a, b Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; }
|
dot4 :: proc(a, b: Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; }
|
||||||
|
|
||||||
cross3 :: proc(x, y Vec3) -> Vec3 {
|
cross3 :: proc(x, y: Vec3) -> Vec3 {
|
||||||
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
||||||
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
||||||
return a - b;
|
return a - b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
vec2_mag :: proc(v Vec2) -> f32 { return sqrt32(dot2(v, v)); }
|
vec2_mag :: proc(v: Vec2) -> f32 { return sqrt32(dot2(v, v)); }
|
||||||
vec3_mag :: proc(v Vec3) -> f32 { return sqrt32(dot3(v, v)); }
|
vec3_mag :: proc(v: Vec3) -> f32 { return sqrt32(dot3(v, v)); }
|
||||||
vec4_mag :: proc(v Vec4) -> f32 { return sqrt32(dot4(v, v)); }
|
vec4_mag :: proc(v: Vec4) -> f32 { return sqrt32(dot4(v, v)); }
|
||||||
|
|
||||||
vec2_norm :: proc(v Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; }
|
vec2_norm :: proc(v: Vec2) -> Vec2 { return v / Vec2{vec2_mag(v)}; }
|
||||||
vec3_norm :: proc(v Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; }
|
vec3_norm :: proc(v: Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; }
|
||||||
vec4_norm :: proc(v Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; }
|
vec4_norm :: proc(v: Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; }
|
||||||
|
|
||||||
vec2_norm0 :: proc(v Vec2) -> Vec2 {
|
vec2_norm0 :: proc(v: Vec2) -> Vec2 {
|
||||||
m := vec2_mag(v);
|
m := vec2_mag(v);
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return Vec2{0};
|
return Vec2{0};
|
||||||
@@ -117,7 +117,7 @@ vec2_norm0 :: proc(v Vec2) -> Vec2 {
|
|||||||
return v / Vec2{m};
|
return v / Vec2{m};
|
||||||
}
|
}
|
||||||
|
|
||||||
vec3_norm0 :: proc(v Vec3) -> Vec3 {
|
vec3_norm0 :: proc(v: Vec3) -> Vec3 {
|
||||||
m := vec3_mag(v);
|
m := vec3_mag(v);
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return Vec3{0};
|
return Vec3{0};
|
||||||
@@ -125,7 +125,7 @@ vec3_norm0 :: proc(v Vec3) -> Vec3 {
|
|||||||
return v / Vec3{m};
|
return v / Vec3{m};
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4_norm0 :: proc(v Vec4) -> Vec4 {
|
vec4_norm0 :: proc(v: Vec4) -> Vec4 {
|
||||||
m := vec4_mag(v);
|
m := vec4_mag(v);
|
||||||
if m == 0 {
|
if m == 0 {
|
||||||
return Vec4{0};
|
return Vec4{0};
|
||||||
@@ -144,7 +144,7 @@ mat4_identity :: proc() -> Mat4 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_transpose :: proc(m Mat4) -> Mat4 {
|
mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
||||||
for j := 0; j < 4; j++ {
|
for j := 0; j < 4; j++ {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
m[i][j], m[j][i] = m[j][i], m[i][j];
|
m[i][j], m[j][i] = m[j][i], m[i][j];
|
||||||
@@ -153,7 +153,7 @@ mat4_transpose :: proc(m Mat4) -> Mat4 {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_mul :: proc(a, b Mat4) -> Mat4 {
|
mat4_mul :: proc(a, b: Mat4) -> Mat4 {
|
||||||
c: Mat4;
|
c: Mat4;
|
||||||
for j := 0; j < 4; j++ {
|
for j := 0; j < 4; j++ {
|
||||||
for i := 0; i < 4; i++ {
|
for i := 0; i < 4; i++ {
|
||||||
@@ -166,7 +166,7 @@ mat4_mul :: proc(a, b Mat4) -> Mat4 {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_mul_vec4 :: proc(m Mat4, v Vec4) -> Vec4 {
|
mat4_mul_vec4 :: proc(m: Mat4, v: Vec4) -> Vec4 {
|
||||||
return Vec4{
|
return Vec4{
|
||||||
m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w,
|
m[0][0]*v.x + m[1][0]*v.y + m[2][0]*v.z + m[3][0]*v.w,
|
||||||
m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w,
|
m[0][1]*v.x + m[1][1]*v.y + m[2][1]*v.z + m[3][1]*v.w,
|
||||||
@@ -175,7 +175,7 @@ mat4_mul_vec4 :: proc(m Mat4, v Vec4) -> Vec4 {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_inverse :: proc(m Mat4) -> Mat4 {
|
mat4_inverse :: proc(m: Mat4) -> Mat4 {
|
||||||
o: Mat4;
|
o: Mat4;
|
||||||
|
|
||||||
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||||
@@ -244,7 +244,7 @@ mat4_inverse :: proc(m Mat4) -> Mat4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mat4_translate :: proc(v Vec3) -> Mat4 {
|
mat4_translate :: proc(v: Vec3) -> Mat4 {
|
||||||
m := mat4_identity();
|
m := mat4_identity();
|
||||||
m[3][0] = v.x;
|
m[3][0] = v.x;
|
||||||
m[3][1] = v.y;
|
m[3][1] = v.y;
|
||||||
@@ -253,7 +253,7 @@ mat4_translate :: proc(v Vec3) -> Mat4 {
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_rotate :: proc(v Vec3, angle_radians f32) -> Mat4 {
|
mat4_rotate :: proc(v: Vec3, angle_radians: f32) -> Mat4 {
|
||||||
c := cos32(angle_radians);
|
c := cos32(angle_radians);
|
||||||
s := sin32(angle_radians);
|
s := sin32(angle_radians);
|
||||||
|
|
||||||
@@ -280,14 +280,14 @@ mat4_rotate :: proc(v Vec3, angle_radians f32) -> Mat4 {
|
|||||||
return rot;
|
return rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_scale :: proc(m Mat4, v Vec3) -> Mat4 {
|
mat4_scale :: proc(m: Mat4, v: Vec3) -> Mat4 {
|
||||||
m[0][0] *= v.x;
|
m[0][0] *= v.x;
|
||||||
m[1][1] *= v.y;
|
m[1][1] *= v.y;
|
||||||
m[2][2] *= v.z;
|
m[2][2] *= v.z;
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat4_scalef :: proc(m Mat4, s f32) -> Mat4 {
|
mat4_scalef :: proc(m: Mat4, s: f32) -> Mat4 {
|
||||||
m[0][0] *= s;
|
m[0][0] *= s;
|
||||||
m[1][1] *= s;
|
m[1][1] *= s;
|
||||||
m[2][2] *= s;
|
m[2][2] *= s;
|
||||||
@@ -295,7 +295,7 @@ mat4_scalef :: proc(m Mat4, s f32) -> Mat4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mat4_look_at :: proc(eye, centre, up Vec3) -> Mat4 {
|
mat4_look_at :: proc(eye, centre, up: Vec3) -> Mat4 {
|
||||||
f := vec3_norm(centre - eye);
|
f := vec3_norm(centre - eye);
|
||||||
s := vec3_norm(cross3(f, up));
|
s := vec3_norm(cross3(f, up));
|
||||||
u := cross3(s, f);
|
u := cross3(s, f);
|
||||||
@@ -309,7 +309,7 @@ mat4_look_at :: proc(eye, centre, up Vec3) -> Mat4 {
|
|||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
mat4_perspective :: proc(fovy, aspect, near, far f32) -> Mat4 {
|
mat4_perspective :: proc(fovy, aspect, near, far: f32) -> Mat4 {
|
||||||
m: Mat4;
|
m: Mat4;
|
||||||
tan_half_fovy := tan32(0.5 * fovy);
|
tan_half_fovy := tan32(0.5 * fovy);
|
||||||
m[0][0] = 1.0 / (aspect*tan_half_fovy);
|
m[0][0] = 1.0 / (aspect*tan_half_fovy);
|
||||||
@@ -321,7 +321,7 @@ mat4_perspective :: proc(fovy, aspect, near, far f32) -> Mat4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mat4_ortho3d :: proc(left, right, bottom, top, near, far f32) -> Mat4 {
|
mat4_ortho3d :: proc(left, right, bottom, top, near, far: f32) -> Mat4 {
|
||||||
m := mat4_identity();
|
m := mat4_identity();
|
||||||
m[0][0] = +2.0 / (right - left);
|
m[0][0] = +2.0 / (right - left);
|
||||||
m[1][1] = +2.0 / (top - bottom);
|
m[1][1] = +2.0 / (top - bottom);
|
||||||
|
|||||||
+38
-40
@@ -1,33 +1,31 @@
|
|||||||
import {
|
#import "fmt.odin";
|
||||||
"fmt.odin";
|
#import "os.odin";
|
||||||
"os.odin";
|
|
||||||
}
|
|
||||||
|
|
||||||
set :: proc(data rawptr, value i32, len int) -> rawptr #link_name "__mem_set" {
|
set :: proc(data: rawptr, value: i32, len: int) -> rawptr #link_name "__mem_set" {
|
||||||
llvm_memset_64bit :: proc(dst rawptr, val byte, len int, align i32, is_volatile bool) #foreign "llvm.memset.p0i8.i64"
|
llvm_memset_64bit :: proc(dst: rawptr, val: byte, len: int, align: i32, is_volatile: bool) #foreign "llvm.memset.p0i8.i64"
|
||||||
llvm_memset_64bit(data, value as byte, len, 1, false);
|
llvm_memset_64bit(data, value as byte, len, 1, false);
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
zero :: proc(data rawptr, len int) -> rawptr #link_name "__mem_zero" {
|
zero :: proc(data: rawptr, len: int) -> rawptr #link_name "__mem_zero" {
|
||||||
return set(data, 0, len);
|
return set(data, 0, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy :: proc(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy" {
|
copy :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy" {
|
||||||
// NOTE(bill): This _must_ implemented like C's memmove
|
// NOTE(bill): This _must_ implemented like C's memmove
|
||||||
llvm_memmove_64bit :: proc(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
|
llvm_memmove_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memmove.p0i8.p0i8.i64"
|
||||||
llvm_memmove_64bit(dst, src, len, 1, false);
|
llvm_memmove_64bit(dst, src, len, 1, false);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
copy_non_overlapping :: proc(dst, src rawptr, len int) -> rawptr #link_name "__mem_copy_non_overlapping" {
|
copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr #link_name "__mem_copy_non_overlapping" {
|
||||||
// NOTE(bill): This _must_ implemented like C's memcpy
|
// NOTE(bill): This _must_ implemented like C's memcpy
|
||||||
llvm_memcpy_64bit :: proc(dst, src rawptr, len int, align i32, is_volatile bool) #foreign "llvm.memcpy.p0i8.p0i8.i64"
|
llvm_memcpy_64bit :: proc(dst, src: rawptr, len: int, align: i32, is_volatile: bool) #foreign "llvm.memcpy.p0i8.p0i8.i64"
|
||||||
llvm_memcpy_64bit(dst, src, len, 1, false);
|
llvm_memcpy_64bit(dst, src, len, 1, false);
|
||||||
return dst;
|
return dst;
|
||||||
}
|
}
|
||||||
|
|
||||||
compare :: proc(dst, src rawptr, n int) -> int #link_name "__mem_compare" {
|
compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
|
||||||
// Translation of http://mgronhol.github.io/fast-strcmp/
|
// Translation of http://mgronhol.github.io/fast-strcmp/
|
||||||
a := slice_ptr(dst as ^byte, n);
|
a := slice_ptr(dst as ^byte, n);
|
||||||
b := slice_ptr(src as ^byte, n);
|
b := slice_ptr(src as ^byte, n);
|
||||||
@@ -64,19 +62,19 @@ compare :: proc(dst, src rawptr, n int) -> int #link_name "__mem_compare" {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
kilobytes :: proc(x int) -> int #inline { return (x) * 1024; }
|
kilobytes :: proc(x: int) -> int #inline { return (x) * 1024; }
|
||||||
megabytes :: proc(x int) -> int #inline { return kilobytes(x) * 1024; }
|
megabytes :: proc(x: int) -> int #inline { return kilobytes(x) * 1024; }
|
||||||
gigabytes :: proc(x int) -> int #inline { return gigabytes(x) * 1024; }
|
gigabytes :: proc(x: int) -> int #inline { return gigabytes(x) * 1024; }
|
||||||
terabytes :: proc(x int) -> int #inline { return terabytes(x) * 1024; }
|
terabytes :: proc(x: int) -> int #inline { return terabytes(x) * 1024; }
|
||||||
|
|
||||||
is_power_of_two :: proc(x int) -> bool {
|
is_power_of_two :: proc(x: int) -> bool {
|
||||||
if x <= 0 {
|
if x <= 0 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (x & (x-1)) == 0;
|
return (x & (x-1)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
align_forward :: proc(ptr rawptr, align int) -> rawptr {
|
align_forward :: proc(ptr: rawptr, align: int) -> rawptr {
|
||||||
assert(is_power_of_two(align));
|
assert(is_power_of_two(align));
|
||||||
|
|
||||||
a := align as uint;
|
a := align as uint;
|
||||||
@@ -91,10 +89,10 @@ align_forward :: proc(ptr rawptr, align int) -> rawptr {
|
|||||||
|
|
||||||
|
|
||||||
Allocation_Header :: struct {
|
Allocation_Header :: struct {
|
||||||
size int;
|
size: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
allocation_header_fill :: proc(header ^Allocation_Header, data rawptr, size int) {
|
allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: int) {
|
||||||
header.size = size;
|
header.size = size;
|
||||||
ptr := (header+1) as ^int;
|
ptr := (header+1) as ^int;
|
||||||
|
|
||||||
@@ -102,7 +100,7 @@ allocation_header_fill :: proc(header ^Allocation_Header, data rawptr, size int)
|
|||||||
(ptr+i)^ = -1;
|
(ptr+i)^ = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allocation_header :: proc(data rawptr) -> ^Allocation_Header {
|
allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
||||||
p := data as ^int;
|
p := data as ^int;
|
||||||
for (p-1)^ == -1 {
|
for (p-1)^ == -1 {
|
||||||
p = (p-1);
|
p = (p-1);
|
||||||
@@ -116,33 +114,33 @@ allocation_header :: proc(data rawptr) -> ^Allocation_Header {
|
|||||||
|
|
||||||
// Custom allocators
|
// Custom allocators
|
||||||
Arena :: struct {
|
Arena :: struct {
|
||||||
backing Allocator;
|
backing: Allocator;
|
||||||
memory []byte;
|
memory: []byte;
|
||||||
temp_count int;
|
temp_count: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
Arena_Temp_Memory :: struct {
|
Arena_Temp_Memory :: struct {
|
||||||
arena ^Arena;
|
arena: ^Arena;
|
||||||
original_count int;
|
original_count: int;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init_arena_from_memory :: proc(using a ^Arena, data []byte) {
|
init_arena_from_memory :: proc(using a: ^Arena, data: []byte) {
|
||||||
backing = Allocator{};
|
backing = Allocator{};
|
||||||
memory = data[:0];
|
memory = data[:0];
|
||||||
temp_count = 0;
|
temp_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_arena_from_context :: proc(using a ^Arena, size int) {
|
init_arena_from_context :: proc(using a: ^Arena, size: int) {
|
||||||
backing = context.allocator;
|
backing = context.allocator;
|
||||||
memory = new_slice(byte, 0, size);
|
memory = new_slice(byte, 0, size);
|
||||||
temp_count = 0;
|
temp_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
free_arena :: proc(using a ^Arena) {
|
free_arena :: proc(using a: ^Arena) {
|
||||||
if backing.procedure != nil {
|
if backing.procedure != nil {
|
||||||
push_allocator backing {
|
push_allocator backing {
|
||||||
free(memory.data);
|
free(memory.data);
|
||||||
@@ -151,16 +149,16 @@ free_arena :: proc(using a ^Arena) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_allocator :: proc(arena ^Arena) -> Allocator {
|
arena_allocator :: proc(arena: ^Arena) -> Allocator {
|
||||||
return Allocator{
|
return Allocator{
|
||||||
procedure = arena_allocator_proc,
|
procedure = arena_allocator_proc,
|
||||||
data = arena,
|
data = arena,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
arena_allocator_proc :: proc(allocator_data rawptr, mode Allocator_Mode,
|
arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
size, alignment int,
|
size, alignment: int,
|
||||||
old_memory rawptr, old_size int, flags u64) -> rawptr {
|
old_memory: rawptr, old_size: int, flags: u64) -> rawptr {
|
||||||
using Allocator_Mode;
|
using Allocator_Mode;
|
||||||
arena := allocator_data as ^Arena;
|
arena := allocator_data as ^Arena;
|
||||||
|
|
||||||
@@ -193,7 +191,7 @@ arena_allocator_proc :: proc(allocator_data rawptr, mode Allocator_Mode,
|
|||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
begin_arena_temp_memory :: proc(a ^Arena) -> Arena_Temp_Memory {
|
begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory {
|
||||||
tmp: Arena_Temp_Memory;
|
tmp: Arena_Temp_Memory;
|
||||||
tmp.arena = a;
|
tmp.arena = a;
|
||||||
tmp.original_count = a.memory.count;
|
tmp.original_count = a.memory.count;
|
||||||
@@ -201,7 +199,7 @@ begin_arena_temp_memory :: proc(a ^Arena) -> Arena_Temp_Memory {
|
|||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
end_arena_temp_memory :: proc(using tmp Arena_Temp_Memory) {
|
end_arena_temp_memory :: proc(using tmp: Arena_Temp_Memory) {
|
||||||
assert(arena.memory.count >= original_count);
|
assert(arena.memory.count >= original_count);
|
||||||
assert(arena.temp_count > 0);
|
assert(arena.temp_count > 0);
|
||||||
arena.memory.count = original_count;
|
arena.memory.count = original_count;
|
||||||
@@ -214,8 +212,8 @@ end_arena_temp_memory :: proc(using tmp Arena_Temp_Memory) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
align_of_type_info :: proc(type_info ^Type_Info) -> int {
|
align_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||||
prev_pow2 :: proc(n i64) -> i64 {
|
prev_pow2 :: proc(n: i64) -> i64 {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -269,12 +267,12 @@ align_of_type_info :: proc(type_info ^Type_Info) -> int {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
align_formula :: proc(size, align int) -> int {
|
align_formula :: proc(size, align: int) -> int {
|
||||||
result := size + align-1;
|
result := size + align-1;
|
||||||
return result - result%align;
|
return result - result%align;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_of_type_info :: proc(type_info ^Type_Info) -> int {
|
size_of_type_info :: proc(type_info: ^Type_Info) -> int {
|
||||||
WORD_SIZE :: size_of(int);
|
WORD_SIZE :: size_of(int);
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
match type info : type_info {
|
match type info : type_info {
|
||||||
@@ -308,7 +306,7 @@ size_of_type_info :: proc(type_info ^Type_Info) -> int {
|
|||||||
case Slice:
|
case Slice:
|
||||||
return 3*WORD_SIZE;
|
return 3*WORD_SIZE;
|
||||||
case Vector:
|
case Vector:
|
||||||
is_bool :: proc(type_info ^Type_Info) -> bool {
|
is_bool :: proc(type_info: ^Type_Info) -> bool {
|
||||||
match type info : type_info {
|
match type info : type_info {
|
||||||
case Named:
|
case Named:
|
||||||
return is_bool(info.base);
|
return is_bool(info.base);
|
||||||
|
|||||||
+67
-67
@@ -1,38 +1,38 @@
|
|||||||
#foreign_system_library "opengl32" when ODIN_OS == "windows";
|
#foreign_system_library "opengl32" when ODIN_OS == "windows";
|
||||||
import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||||
include "opengl_constants.odin";
|
#include "opengl_constants.odin";
|
||||||
|
|
||||||
Clear :: proc(mask u32) #foreign "glClear"
|
Clear :: proc(mask: u32) #foreign "glClear"
|
||||||
ClearColor :: proc(r, g, b, a f32) #foreign "glClearColor"
|
ClearColor :: proc(r, g, b, a: f32) #foreign "glClearColor"
|
||||||
Begin :: proc(mode i32) #foreign "glBegin"
|
Begin :: proc(mode: i32) #foreign "glBegin"
|
||||||
End :: proc() #foreign "glEnd"
|
End :: proc() #foreign "glEnd"
|
||||||
Finish :: proc() #foreign "glFinish"
|
Finish :: proc() #foreign "glFinish"
|
||||||
BlendFunc :: proc(sfactor, dfactor i32) #foreign "glBlendFunc"
|
BlendFunc :: proc(sfactor, dfactor: i32) #foreign "glBlendFunc"
|
||||||
Enable :: proc(cap i32) #foreign "glEnable"
|
Enable :: proc(cap: i32) #foreign "glEnable"
|
||||||
Disable :: proc(cap i32) #foreign "glDisable"
|
Disable :: proc(cap: i32) #foreign "glDisable"
|
||||||
GenTextures :: proc(count i32, result ^u32) #foreign "glGenTextures"
|
GenTextures :: proc(count: i32, result: ^u32) #foreign "glGenTextures"
|
||||||
DeleteTextures:: proc(count i32, result ^u32) #foreign "glDeleteTextures"
|
DeleteTextures:: proc(count: i32, result: ^u32) #foreign "glDeleteTextures"
|
||||||
TexParameteri :: proc(target, pname, param i32) #foreign "glTexParameteri"
|
TexParameteri :: proc(target, pname, param: i32) #foreign "glTexParameteri"
|
||||||
TexParameterf :: proc(target i32, pname i32, param f32) #foreign "glTexParameterf"
|
TexParameterf :: proc(target: i32, pname: i32, param: f32) #foreign "glTexParameterf"
|
||||||
BindTexture :: proc(target i32, texture u32) #foreign "glBindTexture"
|
BindTexture :: proc(target: i32, texture: u32) #foreign "glBindTexture"
|
||||||
LoadIdentity :: proc() #foreign "glLoadIdentity"
|
LoadIdentity :: proc() #foreign "glLoadIdentity"
|
||||||
Viewport :: proc(x, y, width, height i32) #foreign "glViewport"
|
Viewport :: proc(x, y, width, height: i32) #foreign "glViewport"
|
||||||
Ortho :: proc(left, right, bottom, top, near, far f64) #foreign "glOrtho"
|
Ortho :: proc(left, right, bottom, top, near, far: f64) #foreign "glOrtho"
|
||||||
Color3f :: proc(r, g, b f32) #foreign "glColor3f"
|
Color3f :: proc(r, g, b: f32) #foreign "glColor3f"
|
||||||
Vertex3f :: proc(x, y, z f32) #foreign "glVertex3f"
|
Vertex3f :: proc(x, y, z: f32) #foreign "glVertex3f"
|
||||||
TexImage2D :: proc(target, level, internal_format,
|
TexImage2D :: proc(target, level, internal_format,
|
||||||
width, height, border,
|
width, height, border,
|
||||||
format, _type i32, pixels rawptr) #foreign "glTexImage2D"
|
format, _type: i32, pixels: rawptr) #foreign "glTexImage2D"
|
||||||
|
|
||||||
GetError :: proc() -> i32 #foreign "glGetError"
|
GetError :: proc() -> i32 #foreign "glGetError"
|
||||||
GetString :: proc(name i32) -> ^byte #foreign "glGetString"
|
GetString :: proc(name: i32) -> ^byte #foreign "glGetString"
|
||||||
GetIntegerv :: proc(name i32, v ^i32) #foreign "glGetIntegerv"
|
GetIntegerv :: proc(name: i32, v: ^i32) #foreign "glGetIntegerv"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_libgl := win32.LoadLibraryA(("opengl32.dll\x00" as string).data);
|
_libgl := win32.LoadLibraryA(("opengl32.dll\x00" as string).data);
|
||||||
|
|
||||||
GetProcAddress :: proc(name string) -> proc() #cc_c {
|
GetProcAddress :: proc(name: string) -> proc() #cc_c {
|
||||||
assert(name[name.count-1] == 0);
|
assert(name[name.count-1] == 0);
|
||||||
res := win32.wglGetProcAddress(name.data);
|
res := win32.wglGetProcAddress(name.data);
|
||||||
if res == nil {
|
if res == nil {
|
||||||
@@ -41,66 +41,66 @@ GetProcAddress :: proc(name string) -> proc() #cc_c {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenBuffers: proc(count i32, buffers ^u32) #cc_c;
|
GenBuffers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||||
GenVertexArrays: proc(count i32, buffers ^u32) #cc_c;
|
GenVertexArrays: proc(count: i32, buffers: ^u32) #cc_c;
|
||||||
GenSamplers: proc(count i32, buffers ^u32) #cc_c;
|
GenSamplers: proc(count: i32, buffers: ^u32) #cc_c;
|
||||||
BindBuffer: proc(target i32, buffer u32) #cc_c;
|
BindBuffer: proc(target: i32, buffer: u32) #cc_c;
|
||||||
BindVertexArray: proc(buffer u32) #cc_c;
|
BindVertexArray: proc(buffer: u32) #cc_c;
|
||||||
BindSampler: proc(position i32, sampler u32) #cc_c;
|
BindSampler: proc(position: i32, sampler: u32) #cc_c;
|
||||||
BufferData: proc(target i32, size int, data rawptr, usage i32) #cc_c;
|
BufferData: proc(target: i32, size: int, data: rawptr, usage: i32) #cc_c;
|
||||||
BufferSubData: proc(target i32, offset, size int, data rawptr) #cc_c;
|
BufferSubData: proc(target: i32, offset, size: int, data: rawptr) #cc_c;
|
||||||
|
|
||||||
DrawArrays: proc(mode, first i32, count u32) #cc_c;
|
DrawArrays: proc(mode, first: i32, count: u32) #cc_c;
|
||||||
DrawElements: proc(mode i32, count u32, type_ i32, indices rawptr) #cc_c;
|
DrawElements: proc(mode: i32, count: u32, type_: i32, indices: rawptr) #cc_c;
|
||||||
|
|
||||||
MapBuffer: proc(target, access i32) -> rawptr #cc_c;
|
MapBuffer: proc(target, access: i32) -> rawptr #cc_c;
|
||||||
UnmapBuffer: proc(target i32) #cc_c;
|
UnmapBuffer: proc(target: i32) #cc_c;
|
||||||
|
|
||||||
VertexAttribPointer: proc(index u32, size, type_ i32, normalized i32, stride u32, pointer rawptr) #cc_c;
|
VertexAttribPointer: proc(index: u32, size, type_: i32, normalized: i32, stride: u32, pointer: rawptr) #cc_c;
|
||||||
EnableVertexAttribArray: proc(index u32) #cc_c;
|
EnableVertexAttribArray: proc(index: u32) #cc_c;
|
||||||
|
|
||||||
CreateShader: proc(shader_type i32) -> u32 #cc_c;
|
CreateShader: proc(shader_type: i32) -> u32 #cc_c;
|
||||||
ShaderSource: proc(shader u32, count u32, str ^^byte, length ^i32) #cc_c;
|
ShaderSource: proc(shader: u32, count: u32, str: ^^byte, length: ^i32) #cc_c;
|
||||||
CompileShader: proc(shader u32) #cc_c;
|
CompileShader: proc(shader: u32) #cc_c;
|
||||||
CreateProgram: proc() -> u32 #cc_c;
|
CreateProgram: proc() -> u32 #cc_c;
|
||||||
AttachShader: proc(program, shader u32) #cc_c;
|
AttachShader: proc(program, shader: u32) #cc_c;
|
||||||
DetachShader: proc(program, shader u32) #cc_c;
|
DetachShader: proc(program, shader: u32) #cc_c;
|
||||||
DeleteShader: proc(shader u32) #cc_c;
|
DeleteShader: proc(shader: u32) #cc_c;
|
||||||
LinkProgram: proc(program u32) #cc_c;
|
LinkProgram: proc(program: u32) #cc_c;
|
||||||
UseProgram: proc(program u32) #cc_c;
|
UseProgram: proc(program: u32) #cc_c;
|
||||||
DeleteProgram: proc(program u32) #cc_c;
|
DeleteProgram: proc(program: u32) #cc_c;
|
||||||
|
|
||||||
|
|
||||||
GetShaderiv: proc(shader u32, pname i32, params ^i32) #cc_c;
|
GetShaderiv: proc(shader: u32, pname: i32, params: ^i32) #cc_c;
|
||||||
GetProgramiv: proc(program u32, pname i32, params ^i32) #cc_c;
|
GetProgramiv: proc(program: u32, pname: i32, params: ^i32) #cc_c;
|
||||||
GetShaderInfoLog: proc(shader u32, max_length u32, length ^u32, info_long ^byte) #cc_c;
|
GetShaderInfoLog: proc(shader: u32, max_length: u32, length: ^u32, info_long: ^byte) #cc_c;
|
||||||
GetProgramInfoLog: proc(program u32, max_length u32, length ^u32, info_long ^byte) #cc_c;
|
GetProgramInfoLog: proc(program: u32, max_length: u32, length: ^u32, info_long: ^byte) #cc_c;
|
||||||
|
|
||||||
ActiveTexture: proc(texture i32) #cc_c;
|
ActiveTexture: proc(texture: i32) #cc_c;
|
||||||
GenerateMipmap: proc(target i32) #cc_c;
|
GenerateMipmap: proc(target: i32) #cc_c;
|
||||||
|
|
||||||
SamplerParameteri: proc(sampler u32, pname i32, param i32) #cc_c;
|
SamplerParameteri: proc(sampler: u32, pname: i32, param: i32) #cc_c;
|
||||||
SamplerParameterf: proc(sampler u32, pname i32, param f32) #cc_c;
|
SamplerParameterf: proc(sampler: u32, pname: i32, param: f32) #cc_c;
|
||||||
SamplerParameteriv: proc(sampler u32, pname i32, params ^i32) #cc_c;
|
SamplerParameteriv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||||
SamplerParameterfv: proc(sampler u32, pname i32, params ^f32) #cc_c;
|
SamplerParameterfv: proc(sampler: u32, pname: i32, params: ^f32) #cc_c;
|
||||||
SamplerParameterIiv: proc(sampler u32, pname i32, params ^i32) #cc_c;
|
SamplerParameterIiv: proc(sampler: u32, pname: i32, params: ^i32) #cc_c;
|
||||||
SamplerParameterIuiv: proc(sampler u32, pname i32, params ^u32) #cc_c;
|
SamplerParameterIuiv: proc(sampler: u32, pname: i32, params: ^u32) #cc_c;
|
||||||
|
|
||||||
|
|
||||||
Uniform1i: proc(loc i32, v0 i32) #cc_c;
|
Uniform1i: proc(loc: i32, v0: i32) #cc_c;
|
||||||
Uniform2i: proc(loc i32, v0, v1 i32) #cc_c;
|
Uniform2i: proc(loc: i32, v0, v1: i32) #cc_c;
|
||||||
Uniform3i: proc(loc i32, v0, v1, v2 i32) #cc_c;
|
Uniform3i: proc(loc: i32, v0, v1, v2: i32) #cc_c;
|
||||||
Uniform4i: proc(loc i32, v0, v1, v2, v3 i32) #cc_c;
|
Uniform4i: proc(loc: i32, v0, v1, v2, v3: i32) #cc_c;
|
||||||
Uniform1f: proc(loc i32, v0 f32) #cc_c;
|
Uniform1f: proc(loc: i32, v0: f32) #cc_c;
|
||||||
Uniform2f: proc(loc i32, v0, v1 f32) #cc_c;
|
Uniform2f: proc(loc: i32, v0, v1: f32) #cc_c;
|
||||||
Uniform3f: proc(loc i32, v0, v1, v2 f32) #cc_c;
|
Uniform3f: proc(loc: i32, v0, v1, v2: f32) #cc_c;
|
||||||
Uniform4f: proc(loc i32, v0, v1, v2, v3 f32) #cc_c;
|
Uniform4f: proc(loc: i32, v0, v1, v2, v3: f32) #cc_c;
|
||||||
UniformMatrix4fv: proc(loc i32, count u32, transpose i32, value ^f32) #cc_c;
|
UniformMatrix4fv: proc(loc: i32, count: u32, transpose: i32, value: ^f32) #cc_c;
|
||||||
|
|
||||||
GetUniformLocation: proc(program u32, name ^byte) -> i32 #cc_c;
|
GetUniformLocation: proc(program: u32, name: ^byte) -> i32 #cc_c;
|
||||||
|
|
||||||
init :: proc() {
|
init :: proc() {
|
||||||
set_proc_address :: proc(p rawptr, name string) #inline { (p as ^(proc() #cc_c))^ = GetProcAddress(name); }
|
set_proc_address :: proc(p: rawptr, name: string) #inline { (p as ^(proc() #cc_c))^ = GetProcAddress(name); }
|
||||||
|
|
||||||
set_proc_address(^GenBuffers, "glGenBuffers\x00");
|
set_proc_address(^GenBuffers, "glGenBuffers\x00");
|
||||||
set_proc_address(^GenVertexArrays, "glGenVertexArrays\x00");
|
set_proc_address(^GenVertexArrays, "glGenVertexArrays\x00");
|
||||||
|
|||||||
+1
-1
@@ -1,2 +1,2 @@
|
|||||||
include "os_windows.odin" when ODIN_OS == "windows"
|
#include "os_windows.odin" when ODIN_OS == "windows"
|
||||||
|
|
||||||
|
|||||||
+15
-17
@@ -1,7 +1,5 @@
|
|||||||
import {
|
#import win32 "sys/windows.odin";
|
||||||
win32 "sys/windows.odin";
|
#import "fmt.odin";
|
||||||
"fmt.odin";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Handle :: uint;
|
Handle :: uint;
|
||||||
@@ -54,7 +52,7 @@ ERROR_FILE_IS_PIPE : Error : 1<<29 + 0;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
open :: proc(path string, mode int, perm u32) -> (Handle, Error) {
|
open :: proc(path: string, mode: int, perm: u32) -> (Handle, Error) {
|
||||||
using win32;
|
using win32;
|
||||||
if path.count == 0 {
|
if path.count == 0 {
|
||||||
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
||||||
@@ -107,11 +105,11 @@ open :: proc(path string, mode int, perm u32) -> (Handle, Error) {
|
|||||||
return INVALID_HANDLE, err as Error;
|
return INVALID_HANDLE, err as Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
close :: proc(fd Handle) {
|
close :: proc(fd: Handle) {
|
||||||
win32.CloseHandle(fd as win32.HANDLE);
|
win32.CloseHandle(fd as win32.HANDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
write :: proc(fd Handle, data []byte) -> (int, Error) {
|
write :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||||
bytes_written: i32;
|
bytes_written: i32;
|
||||||
e := win32.WriteFile(fd as win32.HANDLE, data.data, data.count as i32, ^bytes_written, nil);
|
e := win32.WriteFile(fd as win32.HANDLE, data.data, data.count as i32, ^bytes_written, nil);
|
||||||
if e != 0 {
|
if e != 0 {
|
||||||
@@ -120,7 +118,7 @@ write :: proc(fd Handle, data []byte) -> (int, Error) {
|
|||||||
return bytes_written as int, ERROR_NONE;
|
return bytes_written as int, ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
read :: proc(fd Handle, data []byte) -> (int, Error) {
|
read :: proc(fd: Handle, data: []byte) -> (int, Error) {
|
||||||
bytes_read: i32;
|
bytes_read: i32;
|
||||||
e := win32.ReadFile(fd as win32.HANDLE, data.data, data.count as u32, ^bytes_read, nil);
|
e := win32.ReadFile(fd as win32.HANDLE, data.data, data.count as u32, ^bytes_read, nil);
|
||||||
if e != win32.FALSE {
|
if e != win32.FALSE {
|
||||||
@@ -130,7 +128,7 @@ read :: proc(fd Handle, data []byte) -> (int, Error) {
|
|||||||
return bytes_read as int, ERROR_NONE;
|
return bytes_read as int, ERROR_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
seek :: proc(fd Handle, offset i64, whence int) -> (i64, Error) {
|
seek :: proc(fd: Handle, offset: i64, whence: int) -> (i64, Error) {
|
||||||
using win32;
|
using win32;
|
||||||
w: u32;
|
w: u32;
|
||||||
match whence {
|
match whence {
|
||||||
@@ -159,7 +157,7 @@ stdout := get_std_handle(win32.STD_OUTPUT_HANDLE);
|
|||||||
stderr := get_std_handle(win32.STD_ERROR_HANDLE);
|
stderr := get_std_handle(win32.STD_ERROR_HANDLE);
|
||||||
|
|
||||||
|
|
||||||
get_std_handle :: proc(h int) -> Handle {
|
get_std_handle :: proc(h: int) -> Handle {
|
||||||
fd := win32.GetStdHandle(h as i32);
|
fd := win32.GetStdHandle(h as i32);
|
||||||
win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0);
|
win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0);
|
||||||
return fd as Handle;
|
return fd as Handle;
|
||||||
@@ -170,7 +168,7 @@ get_std_handle :: proc(h int) -> Handle {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
last_write_time :: proc(fd Handle) -> File_Time {
|
last_write_time :: proc(fd: Handle) -> File_Time {
|
||||||
file_info: win32.BY_HANDLE_FILE_INFORMATION;
|
file_info: win32.BY_HANDLE_FILE_INFORMATION;
|
||||||
win32.GetFileInformationByHandle(fd as win32.HANDLE, ^file_info);
|
win32.GetFileInformationByHandle(fd as win32.HANDLE, ^file_info);
|
||||||
lo := file_info.last_write_time.lo as File_Time;
|
lo := file_info.last_write_time.lo as File_Time;
|
||||||
@@ -178,7 +176,7 @@ last_write_time :: proc(fd Handle) -> File_Time {
|
|||||||
return lo | hi << 32;
|
return lo | hi << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
last_write_time_by_name :: proc(name string) -> File_Time {
|
last_write_time_by_name :: proc(name: string) -> File_Time {
|
||||||
last_write_time: win32.FILETIME;
|
last_write_time: win32.FILETIME;
|
||||||
data: win32.FILE_ATTRIBUTE_DATA;
|
data: win32.FILE_ATTRIBUTE_DATA;
|
||||||
buf: [1024]byte;
|
buf: [1024]byte;
|
||||||
@@ -200,7 +198,7 @@ last_write_time_by_name :: proc(name string) -> File_Time {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
read_entire_file :: proc(name string) -> ([]byte, bool) {
|
read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
||||||
buf: [300]byte;
|
buf: [300]byte;
|
||||||
copy(buf[:], name as []byte);
|
copy(buf[:], name as []byte);
|
||||||
|
|
||||||
@@ -248,18 +246,18 @@ read_entire_file :: proc(name string) -> ([]byte, bool) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
heap_alloc :: proc(size int) -> rawptr {
|
heap_alloc :: proc(size: int) -> rawptr {
|
||||||
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size);
|
return win32.HeapAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, size);
|
||||||
}
|
}
|
||||||
heap_resize :: proc(ptr rawptr, new_size int) -> rawptr {
|
heap_resize :: proc(ptr: rawptr, new_size: int) -> rawptr {
|
||||||
return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
|
return win32.HeapReAlloc(win32.GetProcessHeap(), win32.HEAP_ZERO_MEMORY, ptr, new_size);
|
||||||
}
|
}
|
||||||
heap_free :: proc(ptr rawptr) {
|
heap_free :: proc(ptr: rawptr) {
|
||||||
win32.HeapFree(win32.GetProcessHeap(), 0, ptr);
|
win32.HeapFree(win32.GetProcessHeap(), 0, ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
exit :: proc(code int) {
|
exit :: proc(code: int) {
|
||||||
win32.ExitProcess(code as u32);
|
win32.ExitProcess(code as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+17
-19
@@ -1,52 +1,50 @@
|
|||||||
import {
|
#import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||||
win32 "sys/windows.odin" when ODIN_OS == "windows";
|
#import "atomic.odin";
|
||||||
"atomic.odin";
|
|
||||||
}
|
|
||||||
|
|
||||||
Semaphore :: struct {
|
Semaphore :: struct {
|
||||||
handle win32.HANDLE;
|
handle: win32.HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mutex :: struct {
|
Mutex :: struct {
|
||||||
semaphore Semaphore;
|
semaphore: Semaphore;
|
||||||
counter i32;
|
counter: i32;
|
||||||
owner i32;
|
owner: i32;
|
||||||
recursion i32;
|
recursion: i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
current_thread_id :: proc() -> i32 {
|
current_thread_id :: proc() -> i32 {
|
||||||
return win32.GetCurrentThreadId() as i32;
|
return win32.GetCurrentThreadId() as i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore_init :: proc(s ^Semaphore) {
|
semaphore_init :: proc(s: ^Semaphore) {
|
||||||
s.handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
|
s.handle = win32.CreateSemaphoreA(nil, 0, 1<<31-1, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore_destroy :: proc(s ^Semaphore) {
|
semaphore_destroy :: proc(s: ^Semaphore) {
|
||||||
win32.CloseHandle(s.handle);
|
win32.CloseHandle(s.handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore_post :: proc(s ^Semaphore, count int) {
|
semaphore_post :: proc(s: ^Semaphore, count: int) {
|
||||||
win32.ReleaseSemaphore(s.handle, count as i32, nil);
|
win32.ReleaseSemaphore(s.handle, count as i32, nil);
|
||||||
}
|
}
|
||||||
|
|
||||||
semaphore_release :: proc(s ^Semaphore) #inline { semaphore_post(s, 1); }
|
semaphore_release :: proc(s: ^Semaphore) #inline { semaphore_post(s, 1); }
|
||||||
|
|
||||||
semaphore_wait :: proc(s ^Semaphore) {
|
semaphore_wait :: proc(s: ^Semaphore) {
|
||||||
win32.WaitForSingleObject(s.handle, win32.INFINITE);
|
win32.WaitForSingleObject(s.handle, win32.INFINITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mutex_init :: proc(m ^Mutex) {
|
mutex_init :: proc(m: ^Mutex) {
|
||||||
atomic.store32(^m.counter, 0);
|
atomic.store32(^m.counter, 0);
|
||||||
atomic.store32(^m.owner, current_thread_id());
|
atomic.store32(^m.owner, current_thread_id());
|
||||||
semaphore_init(^m.semaphore);
|
semaphore_init(^m.semaphore);
|
||||||
m.recursion = 0;
|
m.recursion = 0;
|
||||||
}
|
}
|
||||||
mutex_destroy :: proc(m ^Mutex) {
|
mutex_destroy :: proc(m: ^Mutex) {
|
||||||
semaphore_destroy(^m.semaphore);
|
semaphore_destroy(^m.semaphore);
|
||||||
}
|
}
|
||||||
mutex_lock :: proc(m ^Mutex) {
|
mutex_lock :: proc(m: ^Mutex) {
|
||||||
thread_id := current_thread_id();
|
thread_id := current_thread_id();
|
||||||
if atomic.fetch_add32(^m.counter, 1) > 0 {
|
if atomic.fetch_add32(^m.counter, 1) > 0 {
|
||||||
if thread_id != atomic.load32(^m.owner) {
|
if thread_id != atomic.load32(^m.owner) {
|
||||||
@@ -56,7 +54,7 @@ mutex_lock :: proc(m ^Mutex) {
|
|||||||
atomic.store32(^m.owner, thread_id);
|
atomic.store32(^m.owner, thread_id);
|
||||||
m.recursion++;
|
m.recursion++;
|
||||||
}
|
}
|
||||||
mutex_try_lock :: proc(m ^Mutex) -> bool {
|
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||||
thread_id := current_thread_id();
|
thread_id := current_thread_id();
|
||||||
if atomic.load32(^m.owner) == thread_id {
|
if atomic.load32(^m.owner) == thread_id {
|
||||||
atomic.fetch_add32(^m.counter, 1);
|
atomic.fetch_add32(^m.counter, 1);
|
||||||
@@ -73,7 +71,7 @@ mutex_try_lock :: proc(m ^Mutex) -> bool {
|
|||||||
m.recursion++;
|
m.recursion++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
mutex_unlock :: proc(m ^Mutex) {
|
mutex_unlock :: proc(m: ^Mutex) {
|
||||||
recursion: i32;
|
recursion: i32;
|
||||||
thread_id := current_thread_id();
|
thread_id := current_thread_id();
|
||||||
assert(thread_id == atomic.load32(^m.owner));
|
assert(thread_id == atomic.load32(^m.owner));
|
||||||
|
|||||||
+125
-125
@@ -16,7 +16,7 @@ LPARAM :: int;
|
|||||||
LRESULT :: int;
|
LRESULT :: int;
|
||||||
ATOM :: i16;
|
ATOM :: i16;
|
||||||
BOOL :: i32;
|
BOOL :: i32;
|
||||||
WNDPROC :: type proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT;
|
WNDPROC :: type proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT;
|
||||||
|
|
||||||
|
|
||||||
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
|
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
|
||||||
@@ -56,61 +56,61 @@ SW_SHOW :: 5;
|
|||||||
|
|
||||||
|
|
||||||
POINT :: struct #ordered {
|
POINT :: struct #ordered {
|
||||||
x, y i32;
|
x, y: i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
WNDCLASSEXA :: struct #ordered {
|
WNDCLASSEXA :: struct #ordered {
|
||||||
size, style u32;
|
size, style: u32;
|
||||||
wnd_proc WNDPROC;
|
wnd_proc: WNDPROC;
|
||||||
cls_extra, wnd_extra i32;
|
cls_extra, wnd_extra: i32;
|
||||||
instance HINSTANCE;
|
instance: HINSTANCE;
|
||||||
icon HICON;
|
icon: HICON;
|
||||||
cursor HCURSOR;
|
cursor: HCURSOR;
|
||||||
background HBRUSH;
|
background: HBRUSH;
|
||||||
menu_name, class_name ^u8;
|
menu_name, class_name: ^u8;
|
||||||
sm HICON;
|
sm: HICON;
|
||||||
}
|
}
|
||||||
|
|
||||||
MSG :: struct #ordered {
|
MSG :: struct #ordered {
|
||||||
hwnd HWND;
|
hwnd: HWND;
|
||||||
message u32;
|
message: u32;
|
||||||
wparam WPARAM;
|
wparam: WPARAM;
|
||||||
lparam LPARAM;
|
lparam: LPARAM;
|
||||||
time u32;
|
time: u32;
|
||||||
pt POINT;
|
pt: POINT;
|
||||||
}
|
}
|
||||||
|
|
||||||
RECT :: struct #ordered {
|
RECT :: struct #ordered {
|
||||||
left i32;
|
left: i32;
|
||||||
top i32;
|
top: i32;
|
||||||
right i32;
|
right: i32;
|
||||||
bottom i32;
|
bottom: i32;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILETIME :: struct #ordered {
|
FILETIME :: struct #ordered {
|
||||||
lo, hi u32;
|
lo, hi: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
BY_HANDLE_FILE_INFORMATION :: struct #ordered {
|
BY_HANDLE_FILE_INFORMATION :: struct #ordered {
|
||||||
file_attributes u32;
|
file_attributes: u32;
|
||||||
creation_time,
|
creation_time,
|
||||||
last_access_time,
|
last_access_time,
|
||||||
last_write_time FILETIME;
|
last_write_time: FILETIME;
|
||||||
volume_serial_number,
|
volume_serial_number,
|
||||||
file_size_high,
|
file_size_high,
|
||||||
file_size_low,
|
file_size_low,
|
||||||
number_of_links,
|
number_of_links,
|
||||||
file_index_high,
|
file_index_high,
|
||||||
file_index_low u32;
|
file_index_low: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE_ATTRIBUTE_DATA :: struct #ordered {
|
FILE_ATTRIBUTE_DATA :: struct #ordered {
|
||||||
file_attributes u32;
|
file_attributes: u32;
|
||||||
creation_time,
|
creation_time,
|
||||||
last_access_time,
|
last_access_time,
|
||||||
last_write_time FILETIME;
|
last_write_time: FILETIME;
|
||||||
file_size_high,
|
file_size_high,
|
||||||
file_size_low u32;
|
file_size_low: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
GET_FILEEX_INFO_LEVELS :: i32;
|
GET_FILEEX_INFO_LEVELS :: i32;
|
||||||
@@ -119,41 +119,41 @@ GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0;
|
|||||||
GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
|
GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
|
||||||
|
|
||||||
GetLastError :: proc() -> i32 #foreign #dll_import
|
GetLastError :: proc() -> i32 #foreign #dll_import
|
||||||
ExitProcess :: proc(exit_code u32) #foreign #dll_import
|
ExitProcess :: proc(exit_code: u32) #foreign #dll_import
|
||||||
GetDesktopWindow :: proc() -> HWND #foreign #dll_import
|
GetDesktopWindow :: proc() -> HWND #foreign #dll_import
|
||||||
GetCursorPos :: proc(p ^POINT) -> i32 #foreign #dll_import
|
GetCursorPos :: proc(p: ^POINT) -> i32 #foreign #dll_import
|
||||||
ScreenToClient :: proc(h HWND, p ^POINT) -> i32 #foreign #dll_import
|
ScreenToClient :: proc(h: HWND, p: ^POINT) -> i32 #foreign #dll_import
|
||||||
GetModuleHandleA :: proc(module_name ^u8) -> HINSTANCE #foreign #dll_import
|
GetModuleHandleA :: proc(module_name: ^u8) -> HINSTANCE #foreign #dll_import
|
||||||
GetStockObject :: proc(fn_object i32) -> HGDIOBJ #foreign #dll_import
|
GetStockObject :: proc(fn_object: i32) -> HGDIOBJ #foreign #dll_import
|
||||||
PostQuitMessage :: proc(exit_code i32) #foreign #dll_import
|
PostQuitMessage :: proc(exit_code: i32) #foreign #dll_import
|
||||||
SetWindowTextA :: proc(hwnd HWND, c_string ^u8) -> BOOL #foreign #dll_import
|
SetWindowTextA :: proc(hwnd: HWND, c_string: ^u8) -> BOOL #foreign #dll_import
|
||||||
|
|
||||||
QueryPerformanceFrequency :: proc(result ^i64) -> i32 #foreign #dll_import
|
QueryPerformanceFrequency :: proc(result: ^i64) -> i32 #foreign #dll_import
|
||||||
QueryPerformanceCounter :: proc(result ^i64) -> i32 #foreign #dll_import
|
QueryPerformanceCounter :: proc(result: ^i64) -> i32 #foreign #dll_import
|
||||||
|
|
||||||
Sleep :: proc(ms i32) -> i32 #foreign #dll_import
|
Sleep :: proc(ms: i32) -> i32 #foreign #dll_import
|
||||||
|
|
||||||
OutputDebugStringA :: proc(c_str ^u8) #foreign #dll_import
|
OutputDebugStringA :: proc(c_str: ^u8) #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
RegisterClassExA :: proc(wc ^WNDCLASSEXA) -> ATOM #foreign #dll_import
|
RegisterClassExA :: proc(wc: ^WNDCLASSEXA) -> ATOM #foreign #dll_import
|
||||||
CreateWindowExA :: proc(ex_style u32,
|
CreateWindowExA :: proc(ex_style: u32,
|
||||||
class_name, title ^u8,
|
class_name, title: ^u8,
|
||||||
style u32,
|
style: u32,
|
||||||
x, y, w, h i32,
|
x, y, w, h: i32,
|
||||||
parent HWND, menu HMENU, instance HINSTANCE,
|
parent: HWND, menu: HMENU, instance: HINSTANCE,
|
||||||
param rawptr) -> HWND #foreign #dll_import
|
param: rawptr) -> HWND #foreign #dll_import
|
||||||
|
|
||||||
ShowWindow :: proc(hwnd HWND, cmd_show i32) -> BOOL #foreign #dll_import
|
ShowWindow :: proc(hwnd: HWND, cmd_show: i32) -> BOOL #foreign #dll_import
|
||||||
TranslateMessage :: proc(msg ^MSG) -> BOOL #foreign #dll_import
|
TranslateMessage :: proc(msg: ^MSG) -> BOOL #foreign #dll_import
|
||||||
DispatchMessageA :: proc(msg ^MSG) -> LRESULT #foreign #dll_import
|
DispatchMessageA :: proc(msg: ^MSG) -> LRESULT #foreign #dll_import
|
||||||
UpdateWindow :: proc(hwnd HWND) -> BOOL #foreign #dll_import
|
UpdateWindow :: proc(hwnd: HWND) -> BOOL #foreign #dll_import
|
||||||
PeekMessageA :: proc(msg ^MSG, hwnd HWND,
|
PeekMessageA :: proc(msg: ^MSG, hwnd: HWND,
|
||||||
msg_filter_min, msg_filter_max, remove_msg u32) -> BOOL #foreign #dll_import
|
msg_filter_min, msg_filter_max, remove_msg: u32) -> BOOL #foreign #dll_import
|
||||||
|
|
||||||
DefWindowProcA :: proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT #foreign #dll_import
|
DefWindowProcA :: proc(hwnd: HWND, msg: u32, wparam: WPARAM, lparam: LPARAM) -> LRESULT #foreign #dll_import
|
||||||
|
|
||||||
AdjustWindowRect :: proc(rect ^RECT, style u32, menu BOOL) -> BOOL #foreign #dll_import
|
AdjustWindowRect :: proc(rect: ^RECT, style: u32, menu: BOOL) -> BOOL #foreign #dll_import
|
||||||
GetActiveWindow :: proc() -> HWND #foreign #dll_import
|
GetActiveWindow :: proc() -> HWND #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
@@ -164,27 +164,27 @@ GetQueryPerformanceFrequency :: proc() -> i64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
GetCommandLineA :: proc() -> ^u8 #foreign #dll_import
|
GetCommandLineA :: proc() -> ^u8 #foreign #dll_import
|
||||||
GetSystemMetrics :: proc(index i32) -> i32 #foreign #dll_import
|
GetSystemMetrics :: proc(index: i32) -> i32 #foreign #dll_import
|
||||||
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
|
GetCurrentThreadId :: proc() -> u32 #foreign #dll_import
|
||||||
|
|
||||||
// File Stuff
|
// File Stuff
|
||||||
|
|
||||||
CloseHandle :: proc(h HANDLE) -> i32 #foreign #dll_import
|
CloseHandle :: proc(h: HANDLE) -> i32 #foreign #dll_import
|
||||||
GetStdHandle :: proc(h i32) -> HANDLE #foreign #dll_import
|
GetStdHandle :: proc(h: i32) -> HANDLE #foreign #dll_import
|
||||||
CreateFileA :: proc(filename ^u8, desired_access, share_mode u32,
|
CreateFileA :: proc(filename: ^u8, desired_access, share_mode: u32,
|
||||||
security rawptr,
|
security: rawptr,
|
||||||
creation, flags_and_attribs u32, template_file HANDLE) -> HANDLE #foreign #dll_import
|
creation, flags_and_attribs: u32, template_file: HANDLE) -> HANDLE #foreign #dll_import
|
||||||
ReadFile :: proc(h HANDLE, buf rawptr, to_read u32, bytes_read ^i32, overlapped rawptr) -> BOOL #foreign #dll_import
|
ReadFile :: proc(h: HANDLE, buf: rawptr, to_read: u32, bytes_read: ^i32, overlapped: rawptr) -> BOOL #foreign #dll_import
|
||||||
WriteFile :: proc(h HANDLE, buf rawptr, len i32, written_result ^i32, overlapped rawptr) -> i32 #foreign #dll_import
|
WriteFile :: proc(h: HANDLE, buf: rawptr, len: i32, written_result: ^i32, overlapped: rawptr) -> i32 #foreign #dll_import
|
||||||
|
|
||||||
GetFileSizeEx :: proc(file_handle HANDLE, file_size ^i64) -> BOOL #foreign #dll_import
|
GetFileSizeEx :: proc(file_handle: HANDLE, file_size: ^i64) -> BOOL #foreign #dll_import
|
||||||
GetFileAttributesExA :: proc(filename ^u8, info_level_id GET_FILEEX_INFO_LEVELS, file_info rawptr) -> BOOL #foreign #dll_import
|
GetFileAttributesExA :: proc(filename: ^u8, info_level_id: GET_FILEEX_INFO_LEVELS, file_info: rawptr) -> BOOL #foreign #dll_import
|
||||||
GetFileInformationByHandle :: proc(file_handle HANDLE, file_info ^BY_HANDLE_FILE_INFORMATION) -> BOOL #foreign #dll_import
|
GetFileInformationByHandle :: proc(file_handle: HANDLE, file_info: ^BY_HANDLE_FILE_INFORMATION) -> BOOL #foreign #dll_import
|
||||||
|
|
||||||
GetFileType :: proc(file_handle HANDLE) -> u32 #foreign #dll_import
|
GetFileType :: proc(file_handle: HANDLE) -> u32 #foreign #dll_import
|
||||||
SetFilePointer :: proc(file_handle HANDLE, distance_to_move i32, distance_to_move_high ^i32, move_method u32) -> u32 #foreign #dll_import
|
SetFilePointer :: proc(file_handle: HANDLE, distance_to_move: i32, distance_to_move_high: ^i32, move_method: u32) -> u32 #foreign #dll_import
|
||||||
|
|
||||||
SetHandleInformation :: proc(obj HANDLE, mask, flags u32) -> BOOL #foreign #dll_import
|
SetHandleInformation :: proc(obj: HANDLE, mask, flags: u32) -> BOOL #foreign #dll_import
|
||||||
|
|
||||||
HANDLE_FLAG_INHERIT :: 1;
|
HANDLE_FLAG_INHERIT :: 1;
|
||||||
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2;
|
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2;
|
||||||
@@ -238,9 +238,9 @@ INVALID_SET_FILE_POINTER :: ~(0 as u32);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
HeapAlloc :: proc (h HANDLE, flags u32, bytes int) -> rawptr #foreign #dll_import
|
HeapAlloc :: proc (h: HANDLE, flags: u32, bytes: int) -> rawptr #foreign #dll_import
|
||||||
HeapReAlloc :: proc (h HANDLE, flags u32, memory rawptr, bytes int) -> rawptr #foreign #dll_import
|
HeapReAlloc :: proc (h: HANDLE, flags: u32, memory: rawptr, bytes: int) -> rawptr #foreign #dll_import
|
||||||
HeapFree :: proc (h HANDLE, flags u32, memory rawptr) -> BOOL #foreign #dll_import
|
HeapFree :: proc (h: HANDLE, flags: u32, memory: rawptr) -> BOOL #foreign #dll_import
|
||||||
GetProcessHeap :: proc () -> HANDLE #foreign #dll_import
|
GetProcessHeap :: proc () -> HANDLE #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
@@ -249,29 +249,29 @@ HEAP_ZERO_MEMORY :: 0x00000008;
|
|||||||
// Synchronization
|
// Synchronization
|
||||||
|
|
||||||
SECURITY_ATTRIBUTES :: struct #ordered {
|
SECURITY_ATTRIBUTES :: struct #ordered {
|
||||||
length u32;
|
length: u32;
|
||||||
security_descriptor rawptr;
|
security_descriptor: rawptr;
|
||||||
inherit_handle BOOL;
|
inherit_handle: BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
INFINITE :: 0xffffffff;
|
INFINITE :: 0xffffffff;
|
||||||
|
|
||||||
CreateSemaphoreA :: proc(attributes ^SECURITY_ATTRIBUTES, initial_count, maximum_count i32, name ^byte) -> HANDLE #foreign #dll_import
|
CreateSemaphoreA :: proc(attributes: ^SECURITY_ATTRIBUTES, initial_count, maximum_count: i32, name: ^byte) -> HANDLE #foreign #dll_import
|
||||||
ReleaseSemaphore :: proc(semaphore HANDLE, release_count i32, previous_count ^i32) -> BOOL #foreign #dll_import
|
ReleaseSemaphore :: proc(semaphore: HANDLE, release_count: i32, previous_count: ^i32) -> BOOL #foreign #dll_import
|
||||||
WaitForSingleObject :: proc(handle HANDLE, milliseconds u32) -> u32 #foreign #dll_import
|
WaitForSingleObject :: proc(handle: HANDLE, milliseconds: u32) -> u32 #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
InterlockedCompareExchange :: proc(dst ^i32, exchange, comparand i32) -> i32 #foreign
|
InterlockedCompareExchange :: proc(dst: ^i32, exchange, comparand: i32) -> i32 #foreign
|
||||||
InterlockedExchange :: proc(dst ^i32, desired i32) -> i32 #foreign
|
InterlockedExchange :: proc(dst: ^i32, desired: i32) -> i32 #foreign
|
||||||
InterlockedExchangeAdd :: proc(dst ^i32, desired i32) -> i32 #foreign
|
InterlockedExchangeAdd :: proc(dst: ^i32, desired: i32) -> i32 #foreign
|
||||||
InterlockedAnd :: proc(dst ^i32, desired i32) -> i32 #foreign
|
InterlockedAnd :: proc(dst: ^i32, desired: i32) -> i32 #foreign
|
||||||
InterlockedOr :: proc(dst ^i32, desired i32) -> i32 #foreign
|
InterlockedOr :: proc(dst: ^i32, desired: i32) -> i32 #foreign
|
||||||
|
|
||||||
InterlockedCompareExchange64 :: proc(dst ^i64, exchange, comparand i64) -> i64 #foreign
|
InterlockedCompareExchange64 :: proc(dst: ^i64, exchange, comparand: i64) -> i64 #foreign
|
||||||
InterlockedExchange64 :: proc(dst ^i64, desired i64) -> i64 #foreign
|
InterlockedExchange64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign
|
||||||
InterlockedExchangeAdd64 :: proc(dst ^i64, desired i64) -> i64 #foreign
|
InterlockedExchangeAdd64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign
|
||||||
InterlockedAnd64 :: proc(dst ^i64, desired i64) -> i64 #foreign
|
InterlockedAnd64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign
|
||||||
InterlockedOr64 :: proc(dst ^i64, desired i64) -> i64 #foreign
|
InterlockedOr64 :: proc(dst: ^i64, desired: i64) -> i64 #foreign
|
||||||
|
|
||||||
_mm_pause :: proc() #foreign
|
_mm_pause :: proc() #foreign
|
||||||
ReadWriteBarrier :: proc() #foreign
|
ReadWriteBarrier :: proc() #foreign
|
||||||
@@ -281,24 +281,24 @@ ReadBarrier :: proc() #foreign
|
|||||||
|
|
||||||
// GDI
|
// GDI
|
||||||
BITMAPINFOHEADER :: struct #ordered {
|
BITMAPINFOHEADER :: struct #ordered {
|
||||||
size u32;
|
size: u32;
|
||||||
width, height i32;
|
width, height: i32;
|
||||||
planes, bit_count i16;
|
planes, bit_count: i16;
|
||||||
compression u32;
|
compression: u32;
|
||||||
size_image u32;
|
size_image: u32;
|
||||||
x_pels_per_meter i32;
|
x_pels_per_meter: i32;
|
||||||
y_pels_per_meter i32;
|
y_pels_per_meter: i32;
|
||||||
clr_used u32;
|
clr_used: u32;
|
||||||
clr_important u32;
|
clr_important: u32;
|
||||||
}
|
}
|
||||||
BITMAPINFO :: struct #ordered {
|
BITMAPINFO :: struct #ordered {
|
||||||
using header BITMAPINFOHEADER;
|
using header: BITMAPINFOHEADER;
|
||||||
colors [1]RGBQUAD;
|
colors: [1]RGBQUAD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RGBQUAD :: struct #ordered {
|
RGBQUAD :: struct #ordered {
|
||||||
blue, green, red, reserved byte;
|
blue, green, red, reserved: byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
BI_RGB :: 0;
|
BI_RGB :: 0;
|
||||||
@@ -306,20 +306,20 @@ DIB_RGB_COLORS :: 0x00;
|
|||||||
SRCCOPY: u32 : 0x00cc0020;
|
SRCCOPY: u32 : 0x00cc0020;
|
||||||
|
|
||||||
|
|
||||||
StretchDIBits :: proc (hdc HDC,
|
StretchDIBits :: proc (hdc: HDC,
|
||||||
x_dst, y_dst, width_dst, height_dst i32,
|
x_dst, y_dst, width_dst, height_dst: i32,
|
||||||
x_src, y_src, width_src, header_src i32,
|
x_src, y_src, width_src, header_src: i32,
|
||||||
bits rawptr, bits_info ^BITMAPINFO,
|
bits: rawptr, bits_info: ^BITMAPINFO,
|
||||||
usage u32,
|
usage: u32,
|
||||||
rop u32) -> i32 #foreign #dll_import
|
rop: u32) -> i32 #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
LoadLibraryA :: proc (c_str ^u8) -> HMODULE #foreign
|
LoadLibraryA :: proc (c_str: ^u8) -> HMODULE #foreign
|
||||||
FreeLibrary :: proc (h HMODULE) #foreign
|
FreeLibrary :: proc (h: HMODULE) #foreign
|
||||||
GetProcAddress :: proc (h HMODULE, c_str ^u8) -> PROC #foreign
|
GetProcAddress :: proc (h: HMODULE, c_str: ^u8) -> PROC #foreign
|
||||||
|
|
||||||
GetClientRect :: proc(hwnd HWND, rect ^RECT) -> BOOL #foreign
|
GetClientRect :: proc(hwnd: HWND, rect: ^RECT) -> BOOL #foreign
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -348,13 +348,13 @@ PFD_STEREO_DONTCARE :: 0x80000000;
|
|||||||
|
|
||||||
HGLRC :: HANDLE;
|
HGLRC :: HANDLE;
|
||||||
PROC :: type proc() #cc_c;
|
PROC :: type proc() #cc_c;
|
||||||
wglCreateContextAttribsARBType :: proc(hdc HDC, hshareContext rawptr, attribList ^i32) -> HGLRC;
|
wglCreateContextAttribsARBType :: proc(hdc: HDC, hshareContext: rawptr, attribList: ^i32) -> HGLRC;
|
||||||
|
|
||||||
|
|
||||||
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
PIXELFORMATDESCRIPTOR :: struct #ordered {
|
||||||
size,
|
size,
|
||||||
version,
|
version,
|
||||||
flags u32;
|
flags: u32;
|
||||||
|
|
||||||
pixel_type,
|
pixel_type,
|
||||||
color_bits,
|
color_bits,
|
||||||
@@ -375,18 +375,18 @@ PIXELFORMATDESCRIPTOR :: struct #ordered {
|
|||||||
stencil_bits,
|
stencil_bits,
|
||||||
aux_buffers,
|
aux_buffers,
|
||||||
layer_type,
|
layer_type,
|
||||||
reserved byte;
|
reserved: byte;
|
||||||
|
|
||||||
layer_mask,
|
layer_mask,
|
||||||
visible_mask,
|
visible_mask,
|
||||||
damage_mask u32;
|
damage_mask: u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
GetDC :: proc(h HANDLE) -> HDC #foreign
|
GetDC :: proc(h: HANDLE) -> HDC #foreign
|
||||||
SetPixelFormat :: proc(hdc HDC, pixel_format i32, pfd ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import
|
SetPixelFormat :: proc(hdc: HDC, pixel_format: i32, pfd: ^PIXELFORMATDESCRIPTOR ) -> BOOL #foreign #dll_import
|
||||||
ChoosePixelFormat :: proc(hdc HDC, pfd ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import
|
ChoosePixelFormat :: proc(hdc: HDC, pfd: ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll_import
|
||||||
SwapBuffers :: proc(hdc HDC) -> BOOL #foreign #dll_import
|
SwapBuffers :: proc(hdc: HDC) -> BOOL #foreign #dll_import
|
||||||
ReleaseDC :: proc(wnd HWND, hdc HDC) -> i32 #foreign #dll_import
|
ReleaseDC :: proc(wnd: HWND, hdc: HDC) -> i32 #foreign #dll_import
|
||||||
|
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
|
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092;
|
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092;
|
||||||
@@ -394,17 +394,17 @@ WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126;
|
|||||||
WGL_CONTEXT_CORE_PROFILE_BIT_ARB :: 0x0001;
|
WGL_CONTEXT_CORE_PROFILE_BIT_ARB :: 0x0001;
|
||||||
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002;
|
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002;
|
||||||
|
|
||||||
wglCreateContext :: proc(hdc HDC) -> HGLRC #foreign #dll_import
|
wglCreateContext :: proc(hdc: HDC) -> HGLRC #foreign #dll_import
|
||||||
wglMakeCurrent :: proc(hdc HDC, hglrc HGLRC) -> BOOL #foreign #dll_import
|
wglMakeCurrent :: proc(hdc: HDC, hglrc: HGLRC) -> BOOL #foreign #dll_import
|
||||||
wglGetProcAddress :: proc(c_str ^u8) -> PROC #foreign #dll_import
|
wglGetProcAddress :: proc(c_str: ^u8) -> PROC #foreign #dll_import
|
||||||
wglDeleteContext :: proc(hglrc HGLRC) -> BOOL #foreign #dll_import
|
wglDeleteContext :: proc(hglrc: HGLRC) -> BOOL #foreign #dll_import
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
GetKeyState :: proc(v_key i32) -> i16 #foreign #dll_import
|
GetKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
||||||
GetAsyncKeyState :: proc(v_key i32) -> i16 #foreign #dll_import
|
GetAsyncKeyState :: proc(v_key: i32) -> i16 #foreign #dll_import
|
||||||
|
|
||||||
is_key_down :: proc(key Key_Code) -> bool #inline { return GetAsyncKeyState(key as i32) < 0; }
|
is_key_down :: proc(key: Key_Code) -> bool #inline { return GetAsyncKeyState(key as i32) < 0; }
|
||||||
|
|
||||||
Key_Code :: enum i32 {
|
Key_Code :: enum i32 {
|
||||||
LBUTTON = 0x01,
|
LBUTTON = 0x01,
|
||||||
|
|||||||
+7
-7
@@ -9,7 +9,7 @@ SURROGATE_MIN :: 0xd800;
|
|||||||
SURROGATE_MAX :: 0xdfff;
|
SURROGATE_MAX :: 0xdfff;
|
||||||
|
|
||||||
Accept_Range :: struct {
|
Accept_Range :: struct {
|
||||||
lo, hi u8;
|
lo, hi: u8;
|
||||||
}
|
}
|
||||||
|
|
||||||
accept_ranges := [5]Accept_Range{
|
accept_ranges := [5]Accept_Range{
|
||||||
@@ -40,7 +40,7 @@ accept_sizes := [256]byte{
|
|||||||
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
|
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
|
||||||
};
|
};
|
||||||
|
|
||||||
encode_rune :: proc(r rune) -> ([4]byte, int) {
|
encode_rune :: proc(r: rune) -> ([4]byte, int) {
|
||||||
buf: [4]byte;
|
buf: [4]byte;
|
||||||
i := r as u32;
|
i := r as u32;
|
||||||
mask: byte : 0x3f;
|
mask: byte : 0x3f;
|
||||||
@@ -74,7 +74,7 @@ encode_rune :: proc(r rune) -> ([4]byte, int) {
|
|||||||
return buf, 4;
|
return buf, 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
decode_rune :: proc(s string) -> (rune, int) {
|
decode_rune :: proc(s: string) -> (rune, int) {
|
||||||
n := s.count;
|
n := s.count;
|
||||||
if n < 1 {
|
if n < 1 {
|
||||||
return RUNE_ERROR, 0;
|
return RUNE_ERROR, 0;
|
||||||
@@ -119,7 +119,7 @@ decode_rune :: proc(s string) -> (rune, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
valid_rune :: proc(r rune) -> bool {
|
valid_rune :: proc(r: rune) -> bool {
|
||||||
if r < 0 {
|
if r < 0 {
|
||||||
return false;
|
return false;
|
||||||
} else if SURROGATE_MIN <= r && r <= SURROGATE_MAX {
|
} else if SURROGATE_MIN <= r && r <= SURROGATE_MAX {
|
||||||
@@ -130,7 +130,7 @@ valid_rune :: proc(r rune) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
valid_string :: proc(s string) -> bool {
|
valid_string :: proc(s: string) -> bool {
|
||||||
n := s.count;
|
n := s.count;
|
||||||
for i := 0; i < n; {
|
for i := 0; i < n; {
|
||||||
si := s[i];
|
si := s[i];
|
||||||
@@ -163,7 +163,7 @@ valid_string :: proc(s string) -> bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
rune_count :: proc(s string) -> int {
|
rune_count :: proc(s: string) -> int {
|
||||||
count := 0;
|
count := 0;
|
||||||
n := s.count;
|
n := s.count;
|
||||||
for i := 0; i < n; count++ {
|
for i := 0; i < n; count++ {
|
||||||
@@ -200,7 +200,7 @@ rune_count :: proc(s string) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rune_size :: proc(r rune) -> int {
|
rune_size :: proc(r: rune) -> int {
|
||||||
match {
|
match {
|
||||||
case r < 0: return -1;
|
case r < 0: return -1;
|
||||||
case r <= 1<<7 - 1: return 1;
|
case r <= 1<<7 - 1: return 1;
|
||||||
|
|||||||
+5
-22
@@ -1235,32 +1235,15 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(gd, GenericDecl, decl);
|
case_ast_node(id, ImportDecl, decl);
|
||||||
if (!parent_scope->is_file) {
|
|
||||||
// NOTE(bill): Within a procedure, variables must be in order
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for_array(iota, gd->specs) {
|
|
||||||
AstNode *spec = gd->specs.e[iota];
|
|
||||||
switch (spec->kind) {
|
|
||||||
case AstNode_BadDecl:
|
|
||||||
break;
|
|
||||||
case_ast_node(is, ImportSpec, spec);
|
|
||||||
if (!parent_scope->is_file) {
|
if (!parent_scope->is_file) {
|
||||||
// NOTE(bill): _Should_ be caught by the parser
|
// NOTE(bill): _Should_ be caught by the parser
|
||||||
// TODO(bill): Better error handling if it isn't
|
// TODO(bill): Better error handling if it isn't
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DelayedDecl di = {parent_scope, spec};
|
DelayedDecl di = {parent_scope, decl};
|
||||||
array_add(&c->delayed_imports, di);
|
array_add(&c->delayed_imports, di);
|
||||||
case_end;
|
case_end;
|
||||||
default:
|
|
||||||
error(ast_node_token(spec), "Invalid specification in declaration: `%.*s`", LIT(ast_node_strings[spec->kind]));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case_end;
|
|
||||||
case_ast_node(fl, ForeignLibrary, decl);
|
case_ast_node(fl, ForeignLibrary, decl);
|
||||||
if (!parent_scope->is_file) {
|
if (!parent_scope->is_file) {
|
||||||
// NOTE(bill): _Should_ be caught by the parser
|
// NOTE(bill): _Should_ be caught by the parser
|
||||||
@@ -1283,8 +1266,8 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
|||||||
void check_import_entities(Checker *c, MapScope *file_scopes) {
|
void check_import_entities(Checker *c, MapScope *file_scopes) {
|
||||||
for_array(i, c->delayed_imports) {
|
for_array(i, c->delayed_imports) {
|
||||||
Scope *parent_scope = c->delayed_imports.e[i].parent;
|
Scope *parent_scope = c->delayed_imports.e[i].parent;
|
||||||
AstNode *spec = c->delayed_imports.e[i].decl;
|
AstNode *decl = c->delayed_imports.e[i].decl;
|
||||||
ast_node(id, ImportSpec, spec);
|
ast_node(id, ImportDecl, decl);
|
||||||
Token token = id->relpath;
|
Token token = id->relpath;
|
||||||
|
|
||||||
HashKey key = hash_string(id->fullpath);
|
HashKey key = hash_string(id->fullpath);
|
||||||
@@ -1342,7 +1325,7 @@ void check_import_entities(Checker *c, MapScope *file_scopes) {
|
|||||||
}
|
}
|
||||||
// NOTE(bill): Do not add other imported entities
|
// NOTE(bill): Do not add other imported entities
|
||||||
add_entity(c, parent_scope, NULL, e);
|
add_entity(c, parent_scope, NULL, e);
|
||||||
if (id->keyword == Token_import) { // `#import`ed entities don't get exported
|
if (id->is_import) { // `#import`ed entities don't get exported
|
||||||
HashKey key = hash_string(e->token.string);
|
HashKey key = hash_string(e->token.string);
|
||||||
map_entity_set(&parent_scope->implicit, key, e);
|
map_entity_set(&parent_scope->implicit, key, e);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -283,7 +283,7 @@ void check_const_decl(Checker *c, Entity *e, AstNode *type_expr, AstNode *init,
|
|||||||
check_init_constant(c, e, &operand);
|
check_init_constant(c, e, &operand);
|
||||||
c->context.iota = (ExactValue){0};
|
c->context.iota = (ExactValue){0};
|
||||||
|
|
||||||
if (e->type == t_invalid) {
|
if (operand.mode == Addressing_Invalid) {
|
||||||
error(e->token, "Illegal cyclic declaration");
|
error(e->token, "Illegal cyclic declaration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+88
-224
@@ -250,21 +250,6 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
|||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
||||||
AST_NODE_KIND(_StmtEnd, "", i32) \
|
AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||||
AST_NODE_KIND(_SpecBegin, "", i32) \
|
|
||||||
AST_NODE_KIND(TypeSpec, "type specification", struct { \
|
|
||||||
AstNode *name; \
|
|
||||||
AstNode *type; \
|
|
||||||
AstNode *note; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(ImportSpec, "import specification", struct { \
|
|
||||||
TokenKind keyword; \
|
|
||||||
Token relpath; \
|
|
||||||
String fullpath; \
|
|
||||||
Token import_name; \
|
|
||||||
AstNode *cond; \
|
|
||||||
AstNode *note; \
|
|
||||||
}) \
|
|
||||||
AST_NODE_KIND(_SpecEnd, "", i32) \
|
|
||||||
AST_NODE_KIND(_DeclBegin, "", i32) \
|
AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||||
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
AST_NODE_KIND(BadDecl, "bad declaration", struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(GenericDecl, "declaration", struct { \
|
AST_NODE_KIND(GenericDecl, "declaration", struct { \
|
||||||
@@ -281,6 +266,15 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
|||||||
AstNodeArray values; \
|
AstNodeArray values; \
|
||||||
u64 tags; \
|
u64 tags; \
|
||||||
}) \
|
}) \
|
||||||
|
AST_NODE_KIND(ImportDecl, "import declaration", struct { \
|
||||||
|
Token token; \
|
||||||
|
bool is_import; \
|
||||||
|
Token relpath; \
|
||||||
|
String fullpath; \
|
||||||
|
Token import_name; \
|
||||||
|
AstNode *cond; \
|
||||||
|
AstNode *note; \
|
||||||
|
}) \
|
||||||
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
AST_NODE_KIND(ForeignLibrary, "foreign library", struct { \
|
||||||
Token token, filepath; \
|
Token token, filepath; \
|
||||||
String base_dir; \
|
String base_dir; \
|
||||||
@@ -496,14 +490,11 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->GenericDecl.token;
|
return node->GenericDecl.token;
|
||||||
case AstNode_ValueDecl:
|
case AstNode_ValueDecl:
|
||||||
return ast_node_token(node->ValueDecl.names.e[0]);
|
return ast_node_token(node->ValueDecl.names.e[0]);
|
||||||
|
case AstNode_ImportDecl:
|
||||||
|
return node->ImportDecl.token;
|
||||||
case AstNode_ForeignLibrary:
|
case AstNode_ForeignLibrary:
|
||||||
return node->ForeignLibrary.token;
|
return node->ForeignLibrary.token;
|
||||||
|
|
||||||
case AstNode_TypeSpec:
|
|
||||||
return ast_node_token(node->TypeSpec.name);
|
|
||||||
case AstNode_ImportSpec:
|
|
||||||
return node->ImportSpec.relpath;
|
|
||||||
|
|
||||||
case AstNode_Field: {
|
case AstNode_Field: {
|
||||||
if (node->Field.names.count > 0) {
|
if (node->Field.names.count > 0) {
|
||||||
@@ -1081,20 +1072,14 @@ AstNode *make_value_decl(AstFile *f, bool is_var, AstNodeArray names, AstNode *t
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *make_type_spec(AstFile *f, AstNode *name, AstNode *type) {
|
|
||||||
AstNode *result = make_node(f, AstNode_TypeSpec);
|
|
||||||
result->TypeSpec.name = name;
|
|
||||||
result->TypeSpec.type = type;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
AstNode *make_import_decl(AstFile *f, Token token, bool is_import, Token relpath, Token import_name, AstNode *cond) {
|
||||||
AstNode *make_import_spec(AstFile *f, TokenKind keyword, Token relpath, Token import_name, AstNode *cond) {
|
AstNode *result = make_node(f, AstNode_ImportDecl);
|
||||||
AstNode *result = make_node(f, AstNode_ImportSpec);
|
result->ImportDecl.token = token;
|
||||||
result->ImportSpec.keyword = keyword;
|
result->ImportDecl.is_import = is_import;
|
||||||
result->ImportSpec.relpath = relpath;
|
result->ImportDecl.relpath = relpath;
|
||||||
result->ImportSpec.import_name = import_name;
|
result->ImportDecl.import_name = import_name;
|
||||||
result->ImportSpec.cond = cond;
|
result->ImportDecl.cond = cond;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1206,13 +1191,6 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
|||||||
case Token_Semicolon:
|
case Token_Semicolon:
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// case Token_var:
|
|
||||||
// case Token_const:
|
|
||||||
case Token_type:
|
|
||||||
case Token_proc:
|
|
||||||
case Token_import:
|
|
||||||
case Token_include:
|
|
||||||
|
|
||||||
case Token_if:
|
case Token_if:
|
||||||
case Token_when:
|
case Token_when:
|
||||||
case Token_return:
|
case Token_return:
|
||||||
@@ -1294,12 +1272,6 @@ bool is_semicolon_optional_for_node(AstFile *f, AstNode *s) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AstNode_TypeSpec:
|
|
||||||
if (f->prev_token.kind == Token_CloseBrace) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1787,8 +1759,8 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
if ((tags & ProcTag_foreign) != 0) {
|
if ((tags & ProcTag_foreign) != 0) {
|
||||||
return make_proc_lit(f, type, NULL, tags, foreign_name, link_name);
|
return make_proc_lit(f, type, NULL, tags, foreign_name, link_name);
|
||||||
}
|
}
|
||||||
if ((tags & ProcTag_link_name) != 0) {
|
if (tags != 0) {
|
||||||
syntax_error(token, "A procedure typed cannot be tagged with `#link_name`");
|
syntax_error(token, "A procedure type cannot have tags");
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
@@ -1802,8 +1774,8 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
if (type != NULL) {
|
if (type != NULL) {
|
||||||
// TODO(bill): Is this correct???
|
// TODO(bill): Is this correct???
|
||||||
// NOTE(bill): Sanity check as identifiers should be handled already
|
// NOTE(bill): Sanity check as identifiers should be handled already
|
||||||
// TokenPos pos = ast_node_token(type).pos;
|
TokenPos pos = ast_node_token(type).pos;
|
||||||
// GB_ASSERT_MSG(type->kind != AstNode_Ident, "Type Cannot be identifier %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column);
|
GB_ASSERT_MSG(type->kind != AstNode_Ident, "Type cannot be identifier %.*s(%td:%td)", LIT(pos.file), pos.line, pos.column);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2138,153 +2110,6 @@ AstNode *parse_type(AstFile *f) {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define PARSE_SPEC_PROC(name) AstNode *(name)(AstFile *f, TokenKind keyword, isize index)
|
|
||||||
typedef PARSE_SPEC_PROC(*ParserSpecProc);
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_generic_decl(AstFile *f, TokenKind keyword, ParserSpecProc spec_proc) {
|
|
||||||
Token token = expect_token(f, keyword);
|
|
||||||
Token open = {0}, close = {0};
|
|
||||||
AstNodeArray specs = {0};
|
|
||||||
if (f->curr_token.kind == Token_OpenBrace) {
|
|
||||||
open = expect_token(f, Token_OpenBrace);
|
|
||||||
array_init(&specs, heap_allocator());
|
|
||||||
|
|
||||||
|
|
||||||
for (isize index = 0;
|
|
||||||
f->curr_token.kind != Token_CloseBrace &&
|
|
||||||
f->curr_token.kind != Token_EOF;
|
|
||||||
index++) {
|
|
||||||
AstNode *spec = spec_proc(f, keyword, index);
|
|
||||||
array_add(&specs, spec);
|
|
||||||
expect_semicolon(f, spec);
|
|
||||||
}
|
|
||||||
|
|
||||||
close = expect_token(f, Token_CloseBrace);
|
|
||||||
} else {
|
|
||||||
array_init_reserve(&specs, heap_allocator(), 1);
|
|
||||||
array_add(&specs, spec_proc(f, keyword, 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
return make_generic_decl(f, token, open, close, specs, 0, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// PARSE_SPEC_PROC(parse_value_spec) {
|
|
||||||
// AstNodeArray names = parse_identfier_list(f);
|
|
||||||
// parse_check_name_list_for_reserves(f, names);
|
|
||||||
// AstNode *type = parse_type_attempt(f);
|
|
||||||
// AstNodeArray values = {0};
|
|
||||||
|
|
||||||
// if (allow_token(f, Token_Eq)) {
|
|
||||||
// values = parse_rhs_expr_list(f);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (values.count > names.count) {
|
|
||||||
// syntax_error(f->curr_token, "Too many values on the right hand side of the declaration");
|
|
||||||
// }
|
|
||||||
|
|
||||||
// switch (keyword) {
|
|
||||||
// case Token_var:
|
|
||||||
// if (type == NULL && values.count == 0 && names.count > 0) {
|
|
||||||
// syntax_error(f->curr_token, "Missing type or initialization");
|
|
||||||
// return make_bad_decl(f, f->curr_token, f->curr_token);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// case Token_const:
|
|
||||||
// if (values.count == 0 && (index == 0 || type != NULL)) {
|
|
||||||
// syntax_error(f->curr_token, "Missing constant value");
|
|
||||||
// return make_bad_decl(f, f->curr_token, f->curr_token);
|
|
||||||
// }
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // TODO(bill): Fix this so it does not require it
|
|
||||||
// if (values.e == NULL) {
|
|
||||||
// values = make_ast_node_array(f);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return make_value_spec(f, keyword, names, type, values);
|
|
||||||
// }
|
|
||||||
PARSE_SPEC_PROC(parse_type_spec) {
|
|
||||||
AstNode *name = parse_identifier(f);
|
|
||||||
AstNode *type = parse_type(f);
|
|
||||||
return make_type_spec(f, name, type);
|
|
||||||
}
|
|
||||||
PARSE_SPEC_PROC(parse_import_spec) {
|
|
||||||
AstNode *cond = NULL;
|
|
||||||
Token import_name = {0};
|
|
||||||
|
|
||||||
switch (f->curr_token.kind) {
|
|
||||||
case Token_Period:
|
|
||||||
import_name = f->curr_token;
|
|
||||||
import_name.kind = Token_Ident;
|
|
||||||
next_token(f);
|
|
||||||
break;
|
|
||||||
case Token_Ident:
|
|
||||||
import_name = f->curr_token;
|
|
||||||
next_token(f);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
import_name.pos = f->curr_token.pos;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_eq(import_name.string, str_lit("_"))) {
|
|
||||||
syntax_error(import_name, "Illegal import name: `_`");
|
|
||||||
}
|
|
||||||
|
|
||||||
Token file_path = expect_token_after(f, Token_String, "import");
|
|
||||||
if (allow_token(f, Token_when)) {
|
|
||||||
cond = parse_expr(f, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *spec = NULL;
|
|
||||||
if (f->curr_proc != NULL) {
|
|
||||||
syntax_error(import_name, "You cannot use `import` within a procedure. This must be done at the file scope");
|
|
||||||
spec = make_bad_decl(f, import_name, file_path);
|
|
||||||
} else {
|
|
||||||
spec = make_import_spec(f, Token_import, file_path, import_name, cond);
|
|
||||||
}
|
|
||||||
return spec;
|
|
||||||
}
|
|
||||||
PARSE_SPEC_PROC(parse_include_spec) {
|
|
||||||
AstNode *cond = NULL;
|
|
||||||
Token file_path = expect_token_after(f, Token_String, "include");
|
|
||||||
Token import_name = file_path;
|
|
||||||
import_name.string = str_lit(".");
|
|
||||||
|
|
||||||
if (allow_token(f, Token_when)) {
|
|
||||||
cond = parse_expr(f, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *spec = NULL;
|
|
||||||
if (f->curr_proc != NULL) {
|
|
||||||
syntax_error(import_name, "You cannot use `include` within a procedure. This must be done at the file scope");
|
|
||||||
spec = make_bad_decl(f, import_name, file_path);
|
|
||||||
} else {
|
|
||||||
spec = make_import_spec(f, Token_include, file_path, import_name, cond);
|
|
||||||
}
|
|
||||||
return spec;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *parse_decl(AstFile *f) {
|
|
||||||
switch (f->curr_token.kind) {
|
|
||||||
case Token_import:
|
|
||||||
return parse_generic_decl(f, f->curr_token.kind, parse_import_spec);
|
|
||||||
case Token_include:
|
|
||||||
return parse_generic_decl(f, f->curr_token.kind, parse_include_spec);
|
|
||||||
|
|
||||||
default: {
|
|
||||||
Token token = f->curr_token;
|
|
||||||
syntax_error(token, "Expected a declaration");
|
|
||||||
fix_advance_to_next_stmt(f);
|
|
||||||
return make_bad_decl(f, token, f->curr_token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_simple_stmt(AstFile *f) {
|
AstNode *parse_simple_stmt(AstFile *f) {
|
||||||
Token start_token = f->curr_token;
|
Token start_token = f->curr_token;
|
||||||
AstNodeArray lhs = parse_lhs_expr_list(f);
|
AstNodeArray lhs = parse_lhs_expr_list(f);
|
||||||
@@ -2458,7 +2283,7 @@ AstNodeArray parse_field_list(AstFile *f, isize *name_count_, bool allow_using,
|
|||||||
|
|
||||||
name_count += names.count;
|
name_count += names.count;
|
||||||
|
|
||||||
// expect_token_after(f, Token_Colon, "parameter list");
|
expect_token_after(f, Token_Colon, "parameter list");
|
||||||
|
|
||||||
AstNode *type = NULL;
|
AstNode *type = NULL;
|
||||||
if (ellipsis_ok && f->curr_token.kind == Token_Ellipsis) {
|
if (ellipsis_ok && f->curr_token.kind == Token_Ellipsis) {
|
||||||
@@ -3101,16 +2926,6 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
expect_semicolon(f, s);
|
expect_semicolon(f, s);
|
||||||
return s;
|
return s;
|
||||||
|
|
||||||
// case Token_var:
|
|
||||||
// case Token_const:
|
|
||||||
case Token_proc:
|
|
||||||
case Token_type:
|
|
||||||
case Token_import:
|
|
||||||
case Token_include:
|
|
||||||
s = parse_decl(f);
|
|
||||||
expect_semicolon(f, s);
|
|
||||||
return s;
|
|
||||||
|
|
||||||
case Token_if: return parse_if_stmt(f);
|
case Token_if: return parse_if_stmt(f);
|
||||||
case Token_when: return parse_when_stmt(f);
|
case Token_when: return parse_when_stmt(f);
|
||||||
case Token_for: return parse_for_stmt(f);
|
case Token_for: return parse_for_stmt(f);
|
||||||
@@ -3183,7 +2998,63 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
Token hash_token = expect_token(f, Token_Hash);
|
Token hash_token = expect_token(f, Token_Hash);
|
||||||
Token name = expect_token(f, Token_Ident);
|
Token name = expect_token(f, Token_Ident);
|
||||||
String tag = name.string;
|
String tag = name.string;
|
||||||
if (str_eq(tag, str_lit("shared_global_scope"))) {
|
if (str_eq(tag, str_lit("import"))) {
|
||||||
|
AstNode *cond = NULL;
|
||||||
|
Token import_name = {0};
|
||||||
|
|
||||||
|
switch (f->curr_token.kind) {
|
||||||
|
case Token_Period:
|
||||||
|
import_name = f->curr_token;
|
||||||
|
import_name.kind = Token_Ident;
|
||||||
|
next_token(f);
|
||||||
|
break;
|
||||||
|
case Token_Ident:
|
||||||
|
import_name = f->curr_token;
|
||||||
|
next_token(f);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
import_name.pos = f->curr_token.pos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_eq(import_name.string, str_lit("_"))) {
|
||||||
|
syntax_error(import_name, "Illegal #import name: `_`");
|
||||||
|
}
|
||||||
|
|
||||||
|
Token file_path = expect_token_after(f, Token_String, "#import");
|
||||||
|
if (allow_token(f, Token_when)) {
|
||||||
|
cond = parse_expr(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *decl = NULL;
|
||||||
|
if (f->curr_proc != NULL) {
|
||||||
|
syntax_error(import_name, "You cannot use `#import` within a procedure. This must be done at the file scope");
|
||||||
|
decl = make_bad_decl(f, import_name, file_path);
|
||||||
|
} else {
|
||||||
|
decl = make_import_decl(f, hash_token, true, file_path, import_name, cond);
|
||||||
|
}
|
||||||
|
expect_semicolon(f, decl);
|
||||||
|
return decl;
|
||||||
|
} else if (str_eq(tag, str_lit("include"))) {
|
||||||
|
AstNode *cond = NULL;
|
||||||
|
Token file_path = expect_token_after(f, Token_String, "#include");
|
||||||
|
Token import_name = file_path;
|
||||||
|
import_name.string = str_lit(".");
|
||||||
|
|
||||||
|
if (allow_token(f, Token_when)) {
|
||||||
|
cond = parse_expr(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AstNode *decl = NULL;
|
||||||
|
if (f->curr_proc != NULL) {
|
||||||
|
syntax_error(import_name, "You cannot use `#include` within a procedure. This must be done at the file scope");
|
||||||
|
decl = make_bad_decl(f, import_name, file_path);
|
||||||
|
} else {
|
||||||
|
decl = make_import_decl(f, hash_token, false, file_path, import_name, cond);
|
||||||
|
}
|
||||||
|
expect_semicolon(f, decl);
|
||||||
|
return decl;
|
||||||
|
} else if (str_eq(tag, str_lit("shared_global_scope"))) {
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
f->is_global_scope = true;
|
f->is_global_scope = true;
|
||||||
s = make_empty_stmt(f, f->curr_token);
|
s = make_empty_stmt(f, f->curr_token);
|
||||||
@@ -3461,22 +3332,18 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
|
|||||||
node->kind != AstNode_EmptyStmt) {
|
node->kind != AstNode_EmptyStmt) {
|
||||||
// NOTE(bill): Sanity check
|
// NOTE(bill): Sanity check
|
||||||
syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
|
syntax_error_node(node, "Only declarations are allowed at file scope %.*s", LIT(ast_node_strings[node->kind]));
|
||||||
} else if (node->kind == AstNode_GenericDecl) {
|
} else if (node->kind == AstNode_ImportDecl) {
|
||||||
AstNodeGenericDecl *gd = &node->GenericDecl;
|
ast_node(id, ImportDecl, node);
|
||||||
for_array(spec_index, gd->specs) {
|
String file_str = id->relpath.string;
|
||||||
AstNode *spec = gd->specs.e[spec_index];
|
|
||||||
switch (spec->kind) {
|
|
||||||
case_ast_node(is, ImportSpec, spec);
|
|
||||||
String file_str = is->relpath.string;
|
|
||||||
|
|
||||||
if (!is_import_path_valid(file_str)) {
|
if (!is_import_path_valid(file_str)) {
|
||||||
if (is->keyword == Token_include) {
|
if (id->is_import) {
|
||||||
syntax_error_node(node, "Invalid #include path: `%.*s`", LIT(file_str));
|
syntax_error_node(node, "Invalid import path: `%.*s`", LIT(file_str));
|
||||||
} else {
|
} else {
|
||||||
syntax_error_node(node, "Invalid #import path: `%.*s`", LIT(file_str));
|
syntax_error_node(node, "Invalid include path: `%.*s`", LIT(file_str));
|
||||||
}
|
}
|
||||||
// NOTE(bill): It's a naughty name
|
// NOTE(bill): It's a naughty name
|
||||||
gd->specs.e[spec_index] = make_bad_decl(f, is->relpath, is->relpath);
|
decls.e[i] = make_bad_decl(f, id->relpath, id->relpath);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3491,11 +3358,8 @@ void parse_setup_file_decls(Parser *p, AstFile *f, String base_dir, AstNodeArray
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is->fullpath = import_file;
|
id->fullpath = import_file;
|
||||||
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
try_add_import_path(p, import_file, file_str, ast_node_token(node).pos);
|
||||||
case_end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (node->kind == AstNode_ForeignLibrary) {
|
} else if (node->kind == AstNode_ForeignLibrary) {
|
||||||
AstNodeForeignLibrary *fl = &node->ForeignLibrary;
|
AstNodeForeignLibrary *fl = &node->ForeignLibrary;
|
||||||
String file_str = fl->filepath.string;
|
String file_str = fl->filepath.string;
|
||||||
|
|||||||
+2
-3
@@ -86,8 +86,8 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
|||||||
TOKEN_KIND(Token_proc, "proc"), \
|
TOKEN_KIND(Token_proc, "proc"), \
|
||||||
/* TOKEN_KIND(Token_var, "var"), */\
|
/* TOKEN_KIND(Token_var, "var"), */\
|
||||||
/* TOKEN_KIND(Token_const, "const"), */\
|
/* TOKEN_KIND(Token_const, "const"), */\
|
||||||
TOKEN_KIND(Token_import, "import"), \
|
/* TOKEN_KIND(Token_import, "import"), */\
|
||||||
TOKEN_KIND(Token_include, "include"), \
|
/* TOKEN_KIND(Token_include, "include"), */\
|
||||||
TOKEN_KIND(Token_macro, "macro"), \
|
TOKEN_KIND(Token_macro, "macro"), \
|
||||||
TOKEN_KIND(Token_match, "match"), \
|
TOKEN_KIND(Token_match, "match"), \
|
||||||
TOKEN_KIND(Token_break, "break"), \
|
TOKEN_KIND(Token_break, "break"), \
|
||||||
@@ -824,7 +824,6 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
break;
|
break;
|
||||||
case ';':
|
case ';':
|
||||||
token.kind = Token_Semicolon;
|
token.kind = Token_Semicolon;
|
||||||
token.string = str_lit(";");
|
|
||||||
break;
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
token.kind = Token_Comma;
|
token.kind = Token_Comma;
|
||||||
|
|||||||
Reference in New Issue
Block a user