mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-17 00:11:25 -07:00
Begin transition to Jai-like syntax
This commit is contained in:
+5
-2
@@ -11,7 +11,7 @@ import {
|
||||
win32 "sys/windows.odin";
|
||||
}
|
||||
|
||||
const Thing = enum f64 {
|
||||
Thing :: enum f64 {
|
||||
_, // Ignore first value
|
||||
A = 1<<(10*iota),
|
||||
B,
|
||||
@@ -19,6 +19,9 @@ const Thing = enum f64 {
|
||||
D,
|
||||
};
|
||||
|
||||
const main = proc() {
|
||||
main :: proc() {
|
||||
fmt.println(Thing.A, Thing.B, Thing.C, Thing.D);
|
||||
|
||||
x := 123;
|
||||
fmt.println(x);
|
||||
}
|
||||
|
||||
+15
-15
@@ -83,7 +83,7 @@ proc type_info_base(info ^Type_Info) -> ^Type_Info {
|
||||
if info == nil {
|
||||
return nil;
|
||||
}
|
||||
var base = info;
|
||||
base := info;
|
||||
match type i : base {
|
||||
case Type_Info.Named:
|
||||
base = i.base;
|
||||
@@ -140,14 +140,14 @@ type {
|
||||
}
|
||||
}
|
||||
|
||||
#thread_local var __context Context;
|
||||
#thread_local __context: Context;
|
||||
|
||||
|
||||
const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
|
||||
DEFAULT_ALIGNMENT :: align_of([vector 4]f32);
|
||||
|
||||
|
||||
proc __check_context() {
|
||||
var c = ^__context;
|
||||
c := ^__context;
|
||||
|
||||
if c.allocator.procedure == nil {
|
||||
c.allocator = default_allocator();
|
||||
@@ -161,20 +161,20 @@ proc alloc(size int) -> rawptr #inline { return alloc_align(size, DEFAULT_ALIGNM
|
||||
|
||||
proc alloc_align(size, alignment int) -> rawptr #inline {
|
||||
__check_context();
|
||||
var a = context.allocator;
|
||||
a := context.allocator;
|
||||
return a.procedure(a.data, Allocator_Mode.ALLOC, size, alignment, nil, 0, 0);
|
||||
}
|
||||
|
||||
proc free(ptr rawptr) #inline {
|
||||
__check_context();
|
||||
var a = context.allocator;
|
||||
a := context.allocator;
|
||||
if ptr != nil {
|
||||
a.procedure(a.data, Allocator_Mode.FREE, 0, 0, ptr, 0, 0);
|
||||
}
|
||||
}
|
||||
proc free_all() #inline {
|
||||
__check_context();
|
||||
var a = context.allocator;
|
||||
a := context.allocator;
|
||||
a.procedure(a.data, Allocator_Mode.FREE_ALL, 0, 0, nil, 0, 0);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ proc free_all() #inline {
|
||||
proc resize (ptr rawptr, old_size, new_size int) -> rawptr #inline { return resize_align(ptr, old_size, new_size, DEFAULT_ALIGNMENT); }
|
||||
proc resize_align(ptr rawptr, old_size, new_size, alignment int) -> rawptr #inline {
|
||||
__check_context();
|
||||
var a = context.allocator;
|
||||
a := context.allocator;
|
||||
return a.procedure(a.data, Allocator_Mode.RESIZE, new_size, alignment, ptr, old_size, 0);
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ proc default_resize_align(old_memory rawptr, old_size, new_size, alignment int)
|
||||
return old_memory;
|
||||
}
|
||||
|
||||
var new_memory = alloc_align(new_size, alignment);
|
||||
new_memory := alloc_align(new_size, alignment);
|
||||
if new_memory == nil {
|
||||
return nil;
|
||||
}
|
||||
@@ -221,9 +221,9 @@ proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
|
||||
when false {
|
||||
match mode {
|
||||
case ALLOC:
|
||||
var total_size = size + alignment + size_of(mem.AllocationHeader);
|
||||
var ptr = os.heap_alloc(total_size);
|
||||
var header = ptr as ^mem.AllocationHeader;
|
||||
total_size := size + alignment + size_of(mem.AllocationHeader);
|
||||
ptr := os.heap_alloc(total_size);
|
||||
header := ptr as ^mem.AllocationHeader;
|
||||
ptr = mem.align_forward(header+1, alignment);
|
||||
mem.allocation_header_fill(header, ptr, size);
|
||||
return mem.zero(ptr, size);
|
||||
@@ -236,9 +236,9 @@ proc default_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
|
||||
// NOTE(bill): Does nothing
|
||||
|
||||
case RESIZE:
|
||||
var total_size = size + alignment + size_of(mem.AllocationHeader);
|
||||
var ptr = os.heap_resize(mem.allocation_header(old_memory), total_size);
|
||||
var header = ptr as ^mem.AllocationHeader;
|
||||
total_size := size + alignment + size_of(mem.AllocationHeader);
|
||||
ptr := os.heap_resize(mem.allocation_header(old_memory), total_size);
|
||||
header := ptr as ^mem.AllocationHeader;
|
||||
ptr = mem.align_forward(header+1, alignment);
|
||||
mem.allocation_header_fill(header, ptr, size);
|
||||
return mem.zero(ptr, size);
|
||||
|
||||
+7
-7
@@ -2,7 +2,7 @@
|
||||
// Inline vs external file?
|
||||
|
||||
import win32 "sys/windows.odin" when ODIN_OS == "windows";
|
||||
var _ = compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||
_ := compile_assert(ODIN_ARCH == "amd64"); // TODO(bill): x86 version
|
||||
|
||||
|
||||
proc yield_thread() { win32._mm_pause(); }
|
||||
@@ -35,8 +35,8 @@ proc fetch_or32(a ^i32, operand i32) -> i32 {
|
||||
return win32.InterlockedOr(a, operand);
|
||||
}
|
||||
proc spin_lock32(a ^i32, time_out int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
var old_value = compare_exchange32(a, 1, 0);
|
||||
var counter = 0;
|
||||
old_value := compare_exchange32(a, 1, 0);
|
||||
counter := 0;
|
||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||
counter++;
|
||||
yield_thread();
|
||||
@@ -51,7 +51,7 @@ proc spin_unlock32(a ^i32) {
|
||||
}
|
||||
proc try_acquire_lock32(a ^i32) -> bool {
|
||||
yield_thread();
|
||||
var old_value = compare_exchange32(a, 1, 0);
|
||||
old_value := compare_exchange32(a, 1, 0);
|
||||
mfence();
|
||||
return old_value == 0;
|
||||
}
|
||||
@@ -79,8 +79,8 @@ proc fetch_or64(a ^i64, operand i64) -> i64 {
|
||||
return win32.InterlockedOr64(a, operand);
|
||||
}
|
||||
proc spin_lock64(a ^i64, time_out int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||
var old_value = compare_exchange64(a, 1, 0);
|
||||
var counter = 0;
|
||||
old_value := compare_exchange64(a, 1, 0);
|
||||
counter := 0;
|
||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||
counter++;
|
||||
yield_thread();
|
||||
@@ -95,7 +95,7 @@ proc spin_unlock64(a ^i64) {
|
||||
}
|
||||
proc try_acquire_lock64(a ^i64) -> bool {
|
||||
yield_thread();
|
||||
var old_value = compare_exchange64(a, 1, 0);
|
||||
old_value := compare_exchange64(a, 1, 0);
|
||||
mfence();
|
||||
return old_value == 0;
|
||||
}
|
||||
|
||||
+60
-60
@@ -4,26 +4,26 @@ import {
|
||||
"utf8.odin";
|
||||
}
|
||||
|
||||
const PRINT_BUF_SIZE = 1<<12;
|
||||
PRINT_BUF_SIZE :: 1<<12;
|
||||
|
||||
proc fprint(fd os.Handle, args ..any) -> int {
|
||||
var data [PRINT_BUF_SIZE]byte;
|
||||
var buf = data[:0];
|
||||
data :[PRINT_BUF_SIZE]byte;
|
||||
buf := data[:0];
|
||||
bprint(^buf, ..args);
|
||||
os.write(fd, buf);
|
||||
return buf.count;
|
||||
}
|
||||
|
||||
proc fprintln(fd os.Handle, args ..any) -> int {
|
||||
var data [PRINT_BUF_SIZE]byte;
|
||||
var buf = data[:0];
|
||||
data :[PRINT_BUF_SIZE]byte;
|
||||
buf := data[:0];
|
||||
bprintln(^buf, ..args);
|
||||
os.write(fd, buf);
|
||||
return buf.count;
|
||||
}
|
||||
proc fprintf(fd os.Handle, fmt string, args ..any) -> int {
|
||||
var data [PRINT_BUF_SIZE]byte;
|
||||
var buf = data[:0];
|
||||
data :[PRINT_BUF_SIZE]byte;
|
||||
buf := data[:0];
|
||||
bprintf(^buf, fmt, ..args);
|
||||
os.write(fd, buf);
|
||||
return buf.count;
|
||||
@@ -43,8 +43,8 @@ proc printf(fmt string, args ..any) -> int {
|
||||
|
||||
|
||||
proc fprint_type(fd os.Handle, info ^Type_Info) {
|
||||
var data [PRINT_BUF_SIZE]byte;
|
||||
var buf = data[:0];
|
||||
data :[PRINT_BUF_SIZE]byte;
|
||||
buf := data[:0];
|
||||
bprint_type(^buf, info);
|
||||
os.write(fd, buf);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ proc fprint_type(fd os.Handle, info ^Type_Info) {
|
||||
|
||||
proc print_byte_buffer(buf ^[]byte, b []byte) {
|
||||
if buf.count < buf.capacity {
|
||||
var n = min(buf.capacity-buf.count, b.count);
|
||||
n := min(buf.capacity-buf.count, b.count);
|
||||
if n > 0 {
|
||||
mem.copy(buf.data + buf.count, b.data, n);
|
||||
buf.count += n;
|
||||
@@ -67,21 +67,21 @@ proc bprint_string(buf ^[]byte, s string) {
|
||||
|
||||
|
||||
proc byte_reverse(b []byte) {
|
||||
var n = b.count;
|
||||
for var i = 0; i < n/2; i++ {
|
||||
n := b.count;
|
||||
for i := 0; i < n/2; i++ {
|
||||
b[i], b[n-1-i] = b[n-1-i], b[i];
|
||||
}
|
||||
}
|
||||
|
||||
proc bprint_rune(buf ^[]byte, r rune) {
|
||||
var b, n = utf8.encode_rune(r);
|
||||
b, n := utf8.encode_rune(r);
|
||||
bprint_string(buf, b[:n] as string);
|
||||
}
|
||||
|
||||
proc bprint_space(buf ^[]byte) { bprint_rune(buf, ' '); }
|
||||
proc bprint_nl (buf ^[]byte) { bprint_rune(buf, '\n'); }
|
||||
|
||||
var __NUM_TO_CHAR_TABLE = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
||||
|
||||
proc bprint_bool(buffer ^[]byte, b bool) {
|
||||
if b {
|
||||
@@ -100,9 +100,9 @@ proc bprint_f16 (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64,
|
||||
proc bprint_f32 (buffer ^[]byte, f f32) #inline { print__f64(buffer, f as f64, 7); }
|
||||
proc bprint_f64 (buffer ^[]byte, f f64) #inline { print__f64(buffer, f as f64, 16); }
|
||||
proc bprint_u64(buffer ^[]byte, value u64) {
|
||||
var i = value;
|
||||
var buf [20]byte;
|
||||
var len = 0;
|
||||
i := value;
|
||||
buf :[20]byte;
|
||||
len := 0;
|
||||
if i == 0 {
|
||||
buf[len] = '0';
|
||||
len++;
|
||||
@@ -117,7 +117,7 @@ proc bprint_u64(buffer ^[]byte, value u64) {
|
||||
}
|
||||
proc bprint_i64(buffer ^[]byte, value i64) {
|
||||
// TODO(bill): Cleanup printing
|
||||
var i = value;
|
||||
i := value;
|
||||
if i < 0 {
|
||||
i = -i;
|
||||
bprint_rune(buffer, '-');
|
||||
@@ -127,14 +127,14 @@ proc bprint_i64(buffer ^[]byte, value i64) {
|
||||
|
||||
/*
|
||||
proc bprint_u128(buffer ^[]byte, value u128) {
|
||||
var a = value transmute [2]u64;
|
||||
a := value transmute [2]u64;
|
||||
if a[1] != 0 {
|
||||
bprint_u64(buffer, a[1]);
|
||||
}
|
||||
bprint_u64(buffer, a[0]);
|
||||
}
|
||||
proc bprint_i128(buffer ^[]byte, value i128) {
|
||||
var i = value;
|
||||
i := value;
|
||||
if i < 0 {
|
||||
i = -i;
|
||||
bprint_rune(buffer, '-');
|
||||
@@ -145,7 +145,7 @@ proc bprint_i128(buffer ^[]byte, value i128) {
|
||||
|
||||
|
||||
proc print__f64(buffer ^[]byte, value f64, decimal_places int) {
|
||||
var f = value;
|
||||
f := value;
|
||||
if f == 0 {
|
||||
bprint_rune(buffer, '0');
|
||||
return;
|
||||
@@ -155,13 +155,13 @@ proc print__f64(buffer ^[]byte, value f64, decimal_places int) {
|
||||
f = -f;
|
||||
}
|
||||
|
||||
var i = f as u64;
|
||||
i := f as u64;
|
||||
bprint_u64(buffer, i);
|
||||
f -= i as f64;
|
||||
|
||||
bprint_rune(buffer, '.');
|
||||
|
||||
var mult f64 = 10.0;
|
||||
mult :f64 = 10.0;
|
||||
for ; decimal_places >= 0; decimal_places-- {
|
||||
i = (f * mult) as u64;
|
||||
bprint_u64(buffer, i as u64);
|
||||
@@ -214,7 +214,7 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
if info.params == nil {
|
||||
bprint_string(buf, "()");
|
||||
} else {
|
||||
var count = (info.params as ^Tuple).fields.count;
|
||||
count := (info.params as ^Tuple).fields.count;
|
||||
if count == 1 { bprint_string(buf, "("); }
|
||||
bprint_type(buf, info.params);
|
||||
if count == 1 { bprint_string(buf, ")"); }
|
||||
@@ -224,12 +224,12 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
bprint_type(buf, info.results);
|
||||
}
|
||||
case Tuple:
|
||||
var count = info.fields.count;
|
||||
count := info.fields.count;
|
||||
if count != 1 { bprint_string(buf, "("); }
|
||||
for var i = 0; i < count; i++ {
|
||||
for i := 0; i < count; i++ {
|
||||
if i > 0 { bprint_string(buf, ", "); }
|
||||
|
||||
var f = info.fields[i];
|
||||
f := info.fields[i];
|
||||
|
||||
if f.name.count > 0 {
|
||||
bprint_string(buf, f.name);
|
||||
@@ -259,7 +259,7 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
if info.packed { bprint_string(buf, "#packed "); }
|
||||
if info.ordered { bprint_string(buf, "#ordered "); }
|
||||
bprint_string(buf, "{");
|
||||
for var i = 0; i < info.fields.count; i++ {
|
||||
for i := 0; i < info.fields.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
@@ -271,7 +271,7 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
|
||||
case Union:
|
||||
bprint_string(buf, "union {");
|
||||
for var i = 0; i < info.fields.count; i++ {
|
||||
for i := 0; i < info.fields.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
@@ -283,7 +283,7 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
|
||||
case Raw_Union:
|
||||
bprint_string(buf, "raw_union {");
|
||||
for var i = 0; i < info.fields.count; i++ {
|
||||
for i := 0; i < info.fields.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
@@ -303,7 +303,7 @@ proc bprint_type(buf ^[]byte, ti ^Type_Info) {
|
||||
|
||||
|
||||
proc make_any(type_info ^Type_Info, data rawptr) -> any {
|
||||
var a any;
|
||||
a :any;
|
||||
a.type_info = type_info;
|
||||
a.data = data;
|
||||
return a;
|
||||
@@ -323,20 +323,20 @@ proc bprint_any(buf ^[]byte, arg any) {
|
||||
using Type_Info;
|
||||
match type info : arg.type_info {
|
||||
case Named:
|
||||
var a = make_any(info.base, arg.data);
|
||||
a := make_any(info.base, arg.data);
|
||||
match type b : info.base {
|
||||
case Struct:
|
||||
bprint_string(buf, info.name);
|
||||
bprint_string(buf, "{");
|
||||
for var i = 0; i < b.fields.count; i++ {
|
||||
var f = b.fields[i];
|
||||
for i := 0; i < b.fields.count; i++ {
|
||||
f := b.fields[i];
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
bprint_string(buf, f.name);
|
||||
// bprint_any(buf, f.offset);
|
||||
bprint_string(buf, " = ");
|
||||
var data = arg.data as ^byte + f.offset;
|
||||
data := arg.data as ^byte + f.offset;
|
||||
bprint_any(buf, make_any(f.type_info, data));
|
||||
}
|
||||
bprint_string(buf, "}");
|
||||
@@ -387,8 +387,8 @@ proc bprint_any(buf ^[]byte, arg any) {
|
||||
}
|
||||
|
||||
case Maybe:
|
||||
var size = mem.size_of_type_info(info.elem);
|
||||
var data = slice_ptr(arg.data as ^byte, size+1);
|
||||
size := mem.size_of_type_info(info.elem);
|
||||
data := slice_ptr(arg.data as ^byte, size+1);
|
||||
if data[size] != 0 {
|
||||
bprint_any(buf, make_any(info.elem, arg.data));
|
||||
} else {
|
||||
@@ -399,26 +399,26 @@ proc bprint_any(buf ^[]byte, arg any) {
|
||||
bprintf(buf, "[%]%{", info.count, info.elem);
|
||||
defer bprint_string(buf, "}");
|
||||
|
||||
for var i = 0; i < info.count; i++ {
|
||||
for i := 0; i < info.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
|
||||
var data = arg.data as ^byte + i*info.elem_size;
|
||||
data := arg.data as ^byte + i*info.elem_size;
|
||||
bprint_any(buf, make_any(info.elem, data));
|
||||
}
|
||||
|
||||
case Slice:
|
||||
var slice = arg.data as ^[]byte;
|
||||
slice := arg.data as ^[]byte;
|
||||
bprintf(buf, "[]%{", info.elem);
|
||||
defer bprint_string(buf, "}");
|
||||
|
||||
for var i = 0; i < slice.count; i++ {
|
||||
for i := 0; i < slice.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
|
||||
var data = slice.data + i*info.elem_size;
|
||||
data := slice.data + i*info.elem_size;
|
||||
bprint_any(buf, make_any(info.elem, data));
|
||||
}
|
||||
|
||||
@@ -440,12 +440,12 @@ proc bprint_any(buf ^[]byte, arg any) {
|
||||
return;
|
||||
}
|
||||
|
||||
for var i = 0; i < info.count; i++ {
|
||||
for i := 0; i < info.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
|
||||
var data = arg.data as ^byte + i*info.elem_size;
|
||||
data := arg.data as ^byte + i*info.elem_size;
|
||||
bprint_any(buf, make_any(info.elem, data));
|
||||
}
|
||||
|
||||
@@ -454,14 +454,14 @@ proc bprint_any(buf ^[]byte, arg any) {
|
||||
bprintf(buf, "%{", arg.type_info);
|
||||
defer bprint_string(buf, "}");
|
||||
|
||||
for var i = 0; i < info.fields.count; i++ {
|
||||
for i := 0; i < info.fields.count; i++ {
|
||||
if i > 0 {
|
||||
bprint_string(buf, ", ");
|
||||
}
|
||||
bprint_string(buf, info.fields[i].name);
|
||||
bprint_string(buf, " = ");
|
||||
var data = arg.data as ^byte + info.fields[i].offset;
|
||||
var ti = info.fields[i].type_info;
|
||||
data := arg.data as ^byte + info.fields[i].offset;
|
||||
ti := info.fields[i].type_info;
|
||||
bprint_any(buf, make_any(ti, data));
|
||||
}
|
||||
|
||||
@@ -487,10 +487,10 @@ proc bprintf(buf ^[]byte, fmt string, args ..any) -> int {
|
||||
}
|
||||
|
||||
proc parse_int(s string, offset int) -> (int, int) {
|
||||
var result = 0;
|
||||
result := 0;
|
||||
|
||||
for ; offset < s.count; offset++ {
|
||||
var c = s[offset] as rune;
|
||||
c := s[offset] as rune;
|
||||
if !is_digit(c) {
|
||||
break;
|
||||
}
|
||||
@@ -502,12 +502,12 @@ proc bprintf(buf ^[]byte, fmt string, args ..any) -> int {
|
||||
return result, offset;
|
||||
}
|
||||
|
||||
var prev = 0;
|
||||
var implicit_index = 0;
|
||||
prev := 0;
|
||||
implicit_index := 0;
|
||||
|
||||
for var i = 0; i < fmt.count; i++ {
|
||||
var r = fmt[i] as rune;
|
||||
var index = implicit_index;
|
||||
for i := 0; i < fmt.count; i++ {
|
||||
r := fmt[i] as rune;
|
||||
index := implicit_index;
|
||||
|
||||
if r != '%' {
|
||||
continue;
|
||||
@@ -516,7 +516,7 @@ proc bprintf(buf ^[]byte, fmt string, args ..any) -> int {
|
||||
bprint_string(buf, fmt[prev:i]);
|
||||
i++; // Skip %
|
||||
if i < fmt.count {
|
||||
var next = fmt[i] as rune;
|
||||
next := fmt[i] as rune;
|
||||
|
||||
if next == '%' {
|
||||
bprint_string(buf, "%");
|
||||
@@ -561,10 +561,10 @@ proc bprint(buf ^[]byte, args ..any) -> int {
|
||||
}
|
||||
|
||||
|
||||
var prev_string = false;
|
||||
for var i = 0; i < args.count; i++ {
|
||||
var arg = args[i];
|
||||
var is_string = arg.data != nil && is_type_string(arg.type_info);
|
||||
prev_string := false;
|
||||
for i := 0; i < args.count; i++ {
|
||||
arg := args[i];
|
||||
is_string := arg.data != nil && is_type_string(arg.type_info);
|
||||
if i > 0 && !is_string && !prev_string {
|
||||
bprint_space(buf);
|
||||
}
|
||||
@@ -575,7 +575,7 @@ proc bprint(buf ^[]byte, args ..any) -> int {
|
||||
}
|
||||
|
||||
proc bprintln(buf ^[]byte, args ..any) -> int {
|
||||
for var i = 0; i < args.count; i++ {
|
||||
for i := 0; i < args.count; i++ {
|
||||
if i > 0 {
|
||||
append(buf, ' ');
|
||||
}
|
||||
|
||||
+40
-40
@@ -1,57 +1,57 @@
|
||||
proc crc32(data rawptr, len int) -> u32 {
|
||||
var result = ~(0 as u32);
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
for var i = 0; i < len; i++ {
|
||||
var b = s[i] as u32;
|
||||
result := ~(0 as u32);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
for i := 0; i < len; i++ {
|
||||
b := s[i] as u32;
|
||||
result = result>>8 ~ __CRC32_TABLE[(result ~ b) & 0xff];
|
||||
}
|
||||
return ~result;
|
||||
}
|
||||
proc crc64(data rawptr, len int) -> u64 {
|
||||
var result = ~(0 as u64);
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
for var i = 0; i < len; i++ {
|
||||
var b = s[i] as u64;
|
||||
result := ~(0 as u64);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
for i := 0; i < len; i++ {
|
||||
b := s[i] as u64;
|
||||
result = result>>8 ~ __CRC64_TABLE[(result ~ b) & 0xff];
|
||||
}
|
||||
return ~result;
|
||||
}
|
||||
|
||||
proc fnv32(data rawptr, len int) -> u32 {
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
|
||||
var h u32 = 0x811c9dc5;
|
||||
for var i = 0; i < len; i++ {
|
||||
h :u32 = 0x811c9dc5;
|
||||
for i := 0; i < len; i++ {
|
||||
h = (h * 0x01000193) ~ s[i] as u32;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
proc fnv64(data rawptr, len int) -> u64 {
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
|
||||
var h u64 = 0xcbf29ce484222325;
|
||||
for var i = 0; i < len; i++ {
|
||||
h :u64 = 0xcbf29ce484222325;
|
||||
for i := 0; i < len; i++ {
|
||||
h = (h * 0x100000001b3) ~ s[i] as u64;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
proc fnv32a(data rawptr, len int) -> u32 {
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
|
||||
var h u32 = 0x811c9dc5;
|
||||
for var i = 0; i < len; i++ {
|
||||
h :u32 = 0x811c9dc5;
|
||||
for i := 0; i < len; i++ {
|
||||
h = (h ~ s[i] as u32) * 0x01000193;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
proc fnv64a(data rawptr, len int) -> u64 {
|
||||
var s = slice_ptr(data as ^u8, len);
|
||||
s := slice_ptr(data as ^u8, len);
|
||||
|
||||
var h u64 = 0xcbf29ce484222325;
|
||||
for var i = 0; i < len; i++ {
|
||||
h :u64 = 0xcbf29ce484222325;
|
||||
for i := 0; i < len; i++ {
|
||||
h = (h ~ s[i] as u64) * 0x100000001b3;
|
||||
}
|
||||
return h;
|
||||
@@ -59,19 +59,19 @@ proc fnv64a(data rawptr, len int) -> u64 {
|
||||
|
||||
|
||||
proc murmur64(data_ rawptr, len int) -> u64 {
|
||||
const SEED = 0x9747b28c;
|
||||
SEED :: 0x9747b28c;
|
||||
|
||||
when size_of(int) == 8 {
|
||||
const m = 0xc6a4a7935bd1e995;
|
||||
const r = 47;
|
||||
m :: 0xc6a4a7935bd1e995;
|
||||
r :: 47;
|
||||
|
||||
var h u64 = SEED ~ (len as u64 * m);
|
||||
h: u64 = SEED ~ (len as u64 * m);
|
||||
|
||||
var data = slice_ptr(data_ as ^u64, len/size_of(u64));
|
||||
var data2 = slice_ptr(data_ as ^u8, len);
|
||||
data := slice_ptr(data_ as ^u64, len/size_of(u64));
|
||||
data2 := slice_ptr(data_ as ^u8, len);
|
||||
|
||||
for var i = 0; i < data.count; i++ {
|
||||
var k = data[i];
|
||||
for i := 0; i < data.count; i++ {
|
||||
k := data[i];
|
||||
|
||||
k *= m;
|
||||
k ~= k>>r;
|
||||
@@ -99,17 +99,17 @@ proc murmur64(data_ rawptr, len int) -> u64 {
|
||||
|
||||
return h;
|
||||
} else {
|
||||
const m = 0x5bd1e995;
|
||||
const r = 24;
|
||||
m :: 0x5bd1e995;
|
||||
r :: 24;
|
||||
|
||||
var h1 u32 = SEED as u32 ~ len as u32;
|
||||
var h2 u32 = SEED >> 32;
|
||||
h1: u32 = SEED as u32 ~ len as u32;
|
||||
h2: u32 = SEED >> 32;
|
||||
|
||||
var data = slice_ptr(data_ as ^u32, len/size_of(u32));
|
||||
data := slice_ptr(data_ as ^u32, len/size_of(u32));
|
||||
|
||||
var i = 0;
|
||||
i := 0;
|
||||
for len >= 8 {
|
||||
var k1, k2 u32;
|
||||
k1, k2: u32;
|
||||
k1 = data[i]; i++;
|
||||
k1 *= m;
|
||||
k1 ~= k1>>r;
|
||||
@@ -128,7 +128,7 @@ proc murmur64(data_ rawptr, len int) -> u64 {
|
||||
}
|
||||
|
||||
if (len >= 4) {
|
||||
var k1 u32;
|
||||
k1: u32;
|
||||
k1 = data[i]; i++;
|
||||
k1 *= m;
|
||||
k1 ~= k1>>r;
|
||||
@@ -138,7 +138,7 @@ proc murmur64(data_ rawptr, len int) -> u64 {
|
||||
len -= 4;
|
||||
}
|
||||
|
||||
var data8 = slice_ptr((data.data+i) as ^u8, 3); // NOTE(bill): This is unsafe
|
||||
data8 := slice_ptr((data.data+i) as ^u8, 3); // NOTE(bill): This is unsafe
|
||||
|
||||
match len {
|
||||
case 3: h2 ~= data8[2] as u32 << 16; fallthrough;
|
||||
@@ -157,14 +157,14 @@ proc murmur64(data_ rawptr, len int) -> u64 {
|
||||
h2 ~= h1>>19;
|
||||
h2 *= m;
|
||||
|
||||
var h = (h1 as u64)<<32 | h2 as u64;
|
||||
h := (h1 as u64)<<32 | h2 as u64;
|
||||
return h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
var __CRC32_TABLE = [256]u32{
|
||||
__CRC32_TABLE := [256]u32{
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
|
||||
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
|
||||
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
@@ -230,7 +230,7 @@ var __CRC32_TABLE = [256]u32{
|
||||
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
|
||||
};
|
||||
var __CRC64_TABLE = [256]u64{
|
||||
__CRC64_TABLE := [256]u64{
|
||||
0x0000000000000000, 0x42f0e1eba9ea3693, 0x85e1c3d753d46d26, 0xc711223cfa3e5bb5,
|
||||
0x493366450e42ecdf, 0x0bc387aea7a8da4c, 0xccd2a5925d9681f9, 0x8e224479f47cb76a,
|
||||
0x9266cc8a1c85d9be, 0xd0962d61b56fef2d, 0x17870f5d4f51b498, 0x5577eeb6e6bb820b,
|
||||
|
||||
+87
-89
@@ -1,22 +1,20 @@
|
||||
const {
|
||||
TAU = 6.28318530717958647692528676655900576;
|
||||
PI = 3.14159265358979323846264338327950288;
|
||||
ONE_OVER_TAU = 0.636619772367581343075535053490057448;
|
||||
ONE_OVER_PI = 0.159154943091895335768883763372514362;
|
||||
TAU :: 6.28318530717958647692528676655900576;
|
||||
PI :: 3.14159265358979323846264338327950288;
|
||||
ONE_OVER_TAU :: 0.636619772367581343075535053490057448;
|
||||
ONE_OVER_PI :: 0.159154943091895335768883763372514362;
|
||||
|
||||
E = 2.71828182845904523536;
|
||||
SQRT_TWO = 1.41421356237309504880168872420969808;
|
||||
SQRT_THREE = 1.73205080756887729352744634150587236;
|
||||
SQRT_FIVE = 2.23606797749978969640917366873127623;
|
||||
E :: 2.71828182845904523536;
|
||||
SQRT_TWO :: 1.41421356237309504880168872420969808;
|
||||
SQRT_THREE :: 1.73205080756887729352744634150587236;
|
||||
SQRT_FIVE :: 2.23606797749978969640917366873127623;
|
||||
|
||||
LOG_TWO = 0.693147180559945309417232121458176568;
|
||||
LOG_TEN = 2.30258509299404568401799145468436421;
|
||||
LOG_TWO :: 0.693147180559945309417232121458176568;
|
||||
LOG_TEN :: 2.30258509299404568401799145468436421;
|
||||
|
||||
EPSILON = 1.19209290e-7;
|
||||
EPSILON :: 1.19209290e-7;
|
||||
|
||||
τ = TAU;
|
||||
π = PI;
|
||||
}
|
||||
τ :: TAU;
|
||||
π :: PI;
|
||||
|
||||
type {
|
||||
Vec2 [vector 2]f32;
|
||||
@@ -49,8 +47,8 @@ proc sign64(x f64) -> f64 { if x >= 0 { return +1; } return -1; }
|
||||
|
||||
|
||||
proc copy_sign32(x, y f32) -> f32 {
|
||||
var ix = x transmute u32;
|
||||
var iy = y transmute u32;
|
||||
ix := x transmute u32;
|
||||
iy := y transmute u32;
|
||||
ix &= 0x7fffffff;
|
||||
ix |= iy & 0x80000000;
|
||||
return ix transmute f32;
|
||||
@@ -80,7 +78,7 @@ proc remainder32(x, y f32) -> f32 {
|
||||
|
||||
proc fmod32(x, y f32) -> f32 {
|
||||
y = abs(y);
|
||||
var result = remainder32(abs(x), y);
|
||||
result := remainder32(abs(x), y);
|
||||
if sign32(result) < 0 {
|
||||
result += y;
|
||||
}
|
||||
@@ -94,13 +92,13 @@ proc to_degrees(radians f32) -> f32 { return radians * 360 / TAU; }
|
||||
|
||||
|
||||
|
||||
proc dot2(a, b Vec2) -> f32 { var c = a*b; return c.x + c.y; }
|
||||
proc dot3(a, b Vec3) -> f32 { var c = a*b; return c.x + c.y + c.z; }
|
||||
proc dot4(a, b Vec4) -> f32 { var c = a*b; return c.x + c.y + c.z + c.w; }
|
||||
proc dot2(a, b Vec2) -> f32 { c := a*b; return c.x + c.y; }
|
||||
proc dot3(a, b Vec3) -> f32 { c := a*b; return c.x + c.y + c.z; }
|
||||
proc dot4(a, b Vec4) -> f32 { c := a*b; return c.x + c.y + c.z + c.w; }
|
||||
|
||||
proc cross3(x, y Vec3) -> Vec3 {
|
||||
var a = swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
||||
var b = swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
||||
a := swizzle(x, 1, 2, 0) * swizzle(y, 2, 0, 1);
|
||||
b := swizzle(x, 2, 0, 1) * swizzle(y, 1, 2, 0);
|
||||
return a - b;
|
||||
}
|
||||
|
||||
@@ -114,7 +112,7 @@ proc vec3_norm(v Vec3) -> Vec3 { return v / Vec3{vec3_mag(v)}; }
|
||||
proc vec4_norm(v Vec4) -> Vec4 { return v / Vec4{vec4_mag(v)}; }
|
||||
|
||||
proc vec2_norm0(v Vec2) -> Vec2 {
|
||||
var m = vec2_mag(v);
|
||||
m := vec2_mag(v);
|
||||
if m == 0 {
|
||||
return Vec2{0};
|
||||
}
|
||||
@@ -122,7 +120,7 @@ proc vec2_norm0(v Vec2) -> Vec2 {
|
||||
}
|
||||
|
||||
proc vec3_norm0(v Vec3) -> Vec3 {
|
||||
var m = vec3_mag(v);
|
||||
m := vec3_mag(v);
|
||||
if m == 0 {
|
||||
return Vec3{0};
|
||||
}
|
||||
@@ -130,7 +128,7 @@ proc vec3_norm0(v Vec3) -> Vec3 {
|
||||
}
|
||||
|
||||
proc vec4_norm0(v Vec4) -> Vec4 {
|
||||
var m = vec4_mag(v);
|
||||
m := vec4_mag(v);
|
||||
if m == 0 {
|
||||
return Vec4{0};
|
||||
}
|
||||
@@ -149,8 +147,8 @@ proc mat4_identity() -> Mat4 {
|
||||
}
|
||||
|
||||
proc mat4_transpose(m Mat4) -> Mat4 {
|
||||
for var j = 0; j < 4; j++ {
|
||||
for var i = 0; i < 4; i++ {
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
m[i][j], m[j][i] = m[j][i], m[i][j];
|
||||
}
|
||||
}
|
||||
@@ -158,9 +156,9 @@ proc mat4_transpose(m Mat4) -> Mat4 {
|
||||
}
|
||||
|
||||
proc mat4_mul(a, b Mat4) -> Mat4 {
|
||||
var c Mat4;
|
||||
for var j = 0; j < 4; j++ {
|
||||
for var i = 0; i < 4; i++ {
|
||||
c: Mat4;
|
||||
for j := 0; j < 4; j++ {
|
||||
for i := 0; i < 4; i++ {
|
||||
c[j][i] = a[0][i]*b[j][0] +
|
||||
a[1][i]*b[j][1] +
|
||||
a[2][i]*b[j][2] +
|
||||
@@ -180,27 +178,27 @@ proc mat4_mul_vec4(m Mat4, v Vec4) -> Vec4 {
|
||||
}
|
||||
|
||||
proc mat4_inverse(m Mat4) -> Mat4 {
|
||||
var o Mat4;
|
||||
o: Mat4;
|
||||
|
||||
var sf00 = m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
var sf01 = m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
var sf02 = m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
var sf03 = m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
var sf04 = m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
var sf05 = m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
var sf06 = m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
var sf07 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
var sf08 = m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
var sf09 = m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
var sf10 = m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
var sf11 = m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
var sf12 = m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
var sf13 = m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
var sf14 = m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
var sf15 = m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
var sf16 = m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
var sf17 = m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
var sf18 = m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
sf00 := m[2][2] * m[3][3] - m[3][2] * m[2][3];
|
||||
sf01 := m[2][1] * m[3][3] - m[3][1] * m[2][3];
|
||||
sf02 := m[2][1] * m[3][2] - m[3][1] * m[2][2];
|
||||
sf03 := m[2][0] * m[3][3] - m[3][0] * m[2][3];
|
||||
sf04 := m[2][0] * m[3][2] - m[3][0] * m[2][2];
|
||||
sf05 := m[2][0] * m[3][1] - m[3][0] * m[2][1];
|
||||
sf06 := m[1][2] * m[3][3] - m[3][2] * m[1][3];
|
||||
sf07 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
sf08 := m[1][1] * m[3][2] - m[3][1] * m[1][2];
|
||||
sf09 := m[1][0] * m[3][3] - m[3][0] * m[1][3];
|
||||
sf10 := m[1][0] * m[3][2] - m[3][0] * m[1][2];
|
||||
sf11 := m[1][1] * m[3][3] - m[3][1] * m[1][3];
|
||||
sf12 := m[1][0] * m[3][1] - m[3][0] * m[1][1];
|
||||
sf13 := m[1][2] * m[2][3] - m[2][2] * m[1][3];
|
||||
sf14 := m[1][1] * m[2][3] - m[2][1] * m[1][3];
|
||||
sf15 := m[1][1] * m[2][2] - m[2][1] * m[1][2];
|
||||
sf16 := m[1][0] * m[2][3] - m[2][0] * m[1][3];
|
||||
sf17 := m[1][0] * m[2][2] - m[2][0] * m[1][2];
|
||||
sf18 := m[1][0] * m[2][1] - m[2][0] * m[1][1];
|
||||
|
||||
o[0][0] = +(m[1][1] * sf00 - m[1][2] * sf01 + m[1][3] * sf02);
|
||||
o[0][1] = -(m[1][0] * sf00 - m[1][2] * sf03 + m[1][3] * sf04);
|
||||
@@ -222,7 +220,7 @@ proc mat4_inverse(m Mat4) -> Mat4 {
|
||||
o[3][2] = -(m[0][0] * sf14 - m[0][1] * sf16 + m[0][3] * sf18);
|
||||
o[3][3] = +(m[0][0] * sf15 - m[0][1] * sf17 + m[0][2] * sf18);
|
||||
|
||||
var ood = 1.0 / (m[0][0] * o[0][0] +
|
||||
ood := 1.0 / (m[0][0] * o[0][0] +
|
||||
m[0][1] * o[0][1] +
|
||||
m[0][2] * o[0][2] +
|
||||
m[0][3] * o[0][3]);
|
||||
@@ -249,7 +247,7 @@ proc mat4_inverse(m Mat4) -> Mat4 {
|
||||
|
||||
|
||||
proc mat4_translate(v Vec3) -> Mat4 {
|
||||
var m = mat4_identity();
|
||||
m := mat4_identity();
|
||||
m[3][0] = v.x;
|
||||
m[3][1] = v.y;
|
||||
m[3][2] = v.z;
|
||||
@@ -258,13 +256,13 @@ proc mat4_translate(v Vec3) -> Mat4 {
|
||||
}
|
||||
|
||||
proc mat4_rotate(v Vec3, angle_radians f32) -> Mat4 {
|
||||
var c = cos32(angle_radians);
|
||||
var s = sin32(angle_radians);
|
||||
c := cos32(angle_radians);
|
||||
s := sin32(angle_radians);
|
||||
|
||||
var a = vec3_norm(v);
|
||||
var t = a * Vec3{1-c};
|
||||
a := vec3_norm(v);
|
||||
t := a * Vec3{1-c};
|
||||
|
||||
var rot = mat4_identity();
|
||||
rot := mat4_identity();
|
||||
|
||||
rot[0][0] = c + t.x*a.x;
|
||||
rot[0][1] = 0 + t.x*a.y + s*a.z;
|
||||
@@ -300,11 +298,11 @@ proc mat4_scalef(m Mat4, s f32) -> Mat4 {
|
||||
|
||||
|
||||
proc mat4_look_at(eye, centre, up Vec3) -> Mat4 {
|
||||
var f = vec3_norm(centre - eye);
|
||||
var s = vec3_norm(cross3(f, up));
|
||||
var u = cross3(s, f);
|
||||
f := vec3_norm(centre - eye);
|
||||
s := vec3_norm(cross3(f, up));
|
||||
u := cross3(s, f);
|
||||
|
||||
var m Mat4;
|
||||
m: Mat4;
|
||||
|
||||
m[0] = Vec4{+s.x, +s.y, +s.z, 0};
|
||||
m[1] = Vec4{+u.x, +u.y, +u.z, 0};
|
||||
@@ -314,8 +312,8 @@ proc mat4_look_at(eye, centre, up Vec3) -> Mat4 {
|
||||
return m;
|
||||
}
|
||||
proc mat4_perspective(fovy, aspect, near, far f32) -> Mat4 {
|
||||
var m Mat4;
|
||||
var tan_half_fovy = tan32(0.5 * fovy);
|
||||
m: Mat4;
|
||||
tan_half_fovy := tan32(0.5 * fovy);
|
||||
m[0][0] = 1.0 / (aspect*tan_half_fovy);
|
||||
m[1][1] = 1.0 / (tan_half_fovy);
|
||||
m[2][2] = -(far + near) / (far - near);
|
||||
@@ -326,7 +324,7 @@ proc mat4_perspective(fovy, aspect, near, far f32) -> Mat4 {
|
||||
|
||||
|
||||
proc mat4_ortho3d(left, right, bottom, top, near, far f32) -> Mat4 {
|
||||
var m = mat4_identity();
|
||||
m := mat4_identity();
|
||||
m[0][0] = +2.0 / (right - left);
|
||||
m[1][1] = +2.0 / (top - bottom);
|
||||
m[2][2] = -2.0 / (far - near);
|
||||
@@ -340,31 +338,31 @@ proc mat4_ortho3d(left, right, bottom, top, near, far f32) -> Mat4 {
|
||||
|
||||
|
||||
|
||||
const F32_DIG = 6;
|
||||
const F32_EPSILON = 1.192092896e-07;
|
||||
const F32_GUARD = 0;
|
||||
const F32_MANT_DIG = 24;
|
||||
const F32_MAX = 3.402823466e+38;
|
||||
const F32_MAX_10_EXP = 38;
|
||||
const F32_MAX_EXP = 128;
|
||||
const F32_MIN = 1.175494351e-38;
|
||||
const F32_MIN_10_EXP = -37;
|
||||
const F32_MIN_EXP = -125;
|
||||
const F32_NORMALIZE = 0;
|
||||
const F32_RADIX = 2;
|
||||
const F32_ROUNDS = 1;
|
||||
F32_DIG :: 6;
|
||||
F32_EPSILON :: 1.192092896e-07;
|
||||
F32_GUARD :: 0;
|
||||
F32_MANT_DIG :: 24;
|
||||
F32_MAX :: 3.402823466e+38;
|
||||
F32_MAX_10_EXP :: 38;
|
||||
F32_MAX_EXP :: 128;
|
||||
F32_MIN :: 1.175494351e-38;
|
||||
F32_MIN_10_EXP :: -37;
|
||||
F32_MIN_EXP :: -125;
|
||||
F32_NORMALIZE :: 0;
|
||||
F32_RADIX :: 2;
|
||||
F32_ROUNDS :: 1;
|
||||
|
||||
const F64_DIG = 15; // # of decimal digits of precision
|
||||
const F64_EPSILON = 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
|
||||
const F64_MANT_DIG = 53; // # of bits in mantissa
|
||||
const F64_MAX = 1.7976931348623158e+308; // max value
|
||||
const F64_MAX_10_EXP = 308; // max decimal exponent
|
||||
const F64_MAX_EXP = 1024; // max binary exponent
|
||||
const F64_MIN = 2.2250738585072014e-308; // min positive value
|
||||
const F64_MIN_10_EXP = -307; // min decimal exponent
|
||||
const F64_MIN_EXP = -1021; // min binary exponent
|
||||
const F64_RADIX = 2; // exponent radix
|
||||
const F64_ROUNDS = 1; // addition rounding: near
|
||||
F64_DIG :: 15; // # of decimal digits of precision
|
||||
F64_EPSILON :: 2.2204460492503131e-016; // smallest such that 1.0+F64_EPSILON != 1.0
|
||||
F64_MANT_DIG :: 53; // # of bits in mantissa
|
||||
F64_MAX :: 1.7976931348623158e+308; // max value
|
||||
F64_MAX_10_EXP :: 308; // max decimal exponent
|
||||
F64_MAX_EXP :: 1024; // max binary exponent
|
||||
F64_MIN :: 2.2250738585072014e-308; // min positive value
|
||||
F64_MIN_10_EXP :: -307; // min decimal exponent
|
||||
F64_MIN_EXP :: -1021; // min binary exponent
|
||||
F64_RADIX :: 2; // exponent radix
|
||||
F64_ROUNDS :: 1; // addition rounding: near
|
||||
|
||||
|
||||
|
||||
|
||||
+34
-34
@@ -30,22 +30,22 @@ proc copy_non_overlapping(dst, src rawptr, len int) -> rawptr #link_name "__mem_
|
||||
|
||||
proc compare(dst, src rawptr, n int) -> int #link_name "__mem_compare" {
|
||||
// Translation of http://mgronhol.github.io/fast-strcmp/
|
||||
var a = slice_ptr(dst as ^byte, n);
|
||||
var b = slice_ptr(src as ^byte, n);
|
||||
a := slice_ptr(dst as ^byte, n);
|
||||
b := slice_ptr(src as ^byte, n);
|
||||
|
||||
var fast = n/size_of(int) + 1;
|
||||
var offset = (fast-1)*size_of(int);
|
||||
var curr_block = 0;
|
||||
fast := n/size_of(int) + 1;
|
||||
offset := (fast-1)*size_of(int);
|
||||
curr_block := 0;
|
||||
if n <= size_of(int) {
|
||||
fast = 0;
|
||||
}
|
||||
|
||||
var la = slice_ptr(^a[0] as ^int, fast);
|
||||
var lb = slice_ptr(^b[0] as ^int, fast);
|
||||
la := slice_ptr(^a[0] as ^int, fast);
|
||||
lb := slice_ptr(^b[0] as ^int, fast);
|
||||
|
||||
for ; curr_block < fast; curr_block++ {
|
||||
if (la[curr_block] ~ lb[curr_block]) != 0 {
|
||||
for var pos = curr_block*size_of(int); pos < n; pos++ {
|
||||
for pos := curr_block*size_of(int); pos < n; pos++ {
|
||||
if (a[pos] ~ b[pos]) != 0 {
|
||||
return a[pos] as int - b[pos] as int;
|
||||
}
|
||||
@@ -80,9 +80,9 @@ proc is_power_of_two(x int) -> bool {
|
||||
proc align_forward(ptr rawptr, align int) -> rawptr {
|
||||
assert(is_power_of_two(align));
|
||||
|
||||
var a = align as uint;
|
||||
var p = ptr as uint;
|
||||
var modulo = p & (a-1);
|
||||
a := align as uint;
|
||||
p := ptr as uint;
|
||||
modulo := p & (a-1);
|
||||
if modulo != 0 {
|
||||
p += a - modulo;
|
||||
}
|
||||
@@ -97,14 +97,14 @@ type Allocation_Header struct {
|
||||
|
||||
proc allocation_header_fill(header ^Allocation_Header, data rawptr, size int) {
|
||||
header.size = size;
|
||||
var ptr = (header+1) as ^int;
|
||||
ptr := (header+1) as ^int;
|
||||
|
||||
for var i = 0; ptr as rawptr < data; i++ {
|
||||
for i := 0; ptr as rawptr < data; i++ {
|
||||
(ptr+i)^ = -1;
|
||||
}
|
||||
}
|
||||
proc allocation_header(data rawptr) -> ^Allocation_Header {
|
||||
var p = data as ^int;
|
||||
p := data as ^int;
|
||||
for (p-1)^ == -1 {
|
||||
p = (p-1);
|
||||
}
|
||||
@@ -164,20 +164,20 @@ proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
|
||||
size, alignment int,
|
||||
old_memory rawptr, old_size int, flags u64) -> rawptr {
|
||||
using Allocator_Mode;
|
||||
var arena = allocator_data as ^Arena;
|
||||
arena := allocator_data as ^Arena;
|
||||
|
||||
match mode {
|
||||
case ALLOC:
|
||||
var total_size = size + alignment;
|
||||
total_size := size + alignment;
|
||||
|
||||
if arena.memory.count + total_size > arena.memory.capacity {
|
||||
fmt.fprintln(os.stderr, "Arena out of memory");
|
||||
return nil;
|
||||
}
|
||||
|
||||
#no_bounds_check var end = ^arena.memory[arena.memory.count];
|
||||
#no_bounds_check end := ^arena.memory[arena.memory.count];
|
||||
|
||||
var ptr = align_forward(end, alignment);
|
||||
ptr := align_forward(end, alignment);
|
||||
arena.memory.count += total_size;
|
||||
return zero(ptr, size);
|
||||
|
||||
@@ -196,7 +196,7 @@ proc arena_allocator_proc(allocator_data rawptr, mode Allocator_Mode,
|
||||
}
|
||||
|
||||
proc begin_arena_temp_memory(a ^Arena) -> Arena_Temp_Memory {
|
||||
var tmp Arena_Temp_Memory;
|
||||
tmp: Arena_Temp_Memory;
|
||||
tmp.arena = a;
|
||||
tmp.original_count = a.memory.count;
|
||||
a.temp_count++;
|
||||
@@ -230,8 +230,8 @@ proc align_of_type_info(type_info ^Type_Info) -> int {
|
||||
return n - (n >> 1);
|
||||
}
|
||||
|
||||
const WORD_SIZE = size_of(int);
|
||||
const MAX_ALIGN = size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
WORD_SIZE :: size_of(int);
|
||||
MAX_ALIGN :: size_of([vector 64]f64); // TODO(bill): Should these constants be builtin constants?
|
||||
using Type_Info;
|
||||
|
||||
match type info : type_info {
|
||||
@@ -256,9 +256,9 @@ proc align_of_type_info(type_info ^Type_Info) -> int {
|
||||
case Slice:
|
||||
return WORD_SIZE;
|
||||
case Vector:
|
||||
var size = size_of_type_info(info.elem);
|
||||
var count = max(prev_pow2(info.count as i64), 1) as int;
|
||||
var total = size * count;
|
||||
size := size_of_type_info(info.elem);
|
||||
count := max(prev_pow2(info.count as i64), 1) as int;
|
||||
total := size * count;
|
||||
return clamp(total, 1, MAX_ALIGN);
|
||||
case Struct:
|
||||
return info.align;
|
||||
@@ -272,12 +272,12 @@ proc align_of_type_info(type_info ^Type_Info) -> int {
|
||||
}
|
||||
|
||||
proc align_formula(size, align int) -> int {
|
||||
var result = size + align-1;
|
||||
result := size + align-1;
|
||||
return result - result%align;
|
||||
}
|
||||
|
||||
proc size_of_type_info(type_info ^Type_Info) -> int {
|
||||
const WORD_SIZE = size_of(int);
|
||||
WORD_SIZE :: size_of(int);
|
||||
using Type_Info;
|
||||
match type info : type_info {
|
||||
case Named:
|
||||
@@ -299,13 +299,13 @@ proc size_of_type_info(type_info ^Type_Info) -> int {
|
||||
case Procedure:
|
||||
return WORD_SIZE;
|
||||
case Array:
|
||||
var count = info.count;
|
||||
count := info.count;
|
||||
if count == 0 {
|
||||
return 0;
|
||||
}
|
||||
var size = size_of_type_info(info.elem);
|
||||
var align = align_of_type_info(info.elem);
|
||||
var alignment = align_formula(size, align);
|
||||
size := size_of_type_info(info.elem);
|
||||
align := align_of_type_info(info.elem);
|
||||
alignment := align_formula(size, align);
|
||||
return alignment*(count-1) + size;
|
||||
case Slice:
|
||||
return 3*WORD_SIZE;
|
||||
@@ -320,18 +320,18 @@ proc size_of_type_info(type_info ^Type_Info) -> int {
|
||||
return false;
|
||||
}
|
||||
|
||||
var count = info.count;
|
||||
count := info.count;
|
||||
if count == 0 {
|
||||
return 0;
|
||||
}
|
||||
var bit_size = 8*size_of_type_info(info.elem);
|
||||
bit_size := 8*size_of_type_info(info.elem);
|
||||
if is_bool(info.elem) {
|
||||
// NOTE(bill): LLVM can store booleans as 1 bit because a boolean _is_ an `i1`
|
||||
// Silly LLVM spec
|
||||
bit_size = 1;
|
||||
}
|
||||
var total_size_in_bits = bit_size * count;
|
||||
var total_size = (total_size_in_bits+7)/8;
|
||||
total_size_in_bits := bit_size * count;
|
||||
total_size := (total_size_in_bits+7)/8;
|
||||
return total_size;
|
||||
|
||||
case Struct:
|
||||
|
||||
+48
-50
@@ -30,76 +30,74 @@ proc GetIntegerv(name i32, v ^i32) #foreign "glGetIntegerv"
|
||||
|
||||
|
||||
|
||||
var _libgl = win32.LoadLibraryA(("opengl32.dll\x00" as string).data);
|
||||
_libgl := win32.LoadLibraryA(("opengl32.dll\x00" as string).data);
|
||||
|
||||
proc GetProcAddress(name string) -> proc() #cc_c {
|
||||
assert(name[name.count-1] == 0);
|
||||
var res = win32.wglGetProcAddress(name.data);
|
||||
res := win32.wglGetProcAddress(name.data);
|
||||
if res == nil {
|
||||
res = win32.GetProcAddress(_libgl, name.data);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
var {
|
||||
GenBuffers proc(count i32, buffers ^u32) #cc_c;
|
||||
GenVertexArrays proc(count i32, buffers ^u32) #cc_c;
|
||||
GenSamplers proc(count i32, buffers ^u32) #cc_c;
|
||||
BindBuffer proc(target i32, buffer u32) #cc_c;
|
||||
BindVertexArray proc(buffer u32) #cc_c;
|
||||
BindSampler proc(position i32, sampler u32) #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;
|
||||
GenBuffers: proc(count i32, buffers ^u32) #cc_c;
|
||||
GenVertexArrays: proc(count i32, buffers ^u32) #cc_c;
|
||||
GenSamplers: proc(count i32, buffers ^u32) #cc_c;
|
||||
BindBuffer: proc(target i32, buffer u32) #cc_c;
|
||||
BindVertexArray: proc(buffer u32) #cc_c;
|
||||
BindSampler: proc(position i32, sampler u32) #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;
|
||||
|
||||
DrawArrays proc(mode, first i32, count u32) #cc_c;
|
||||
DrawElements proc(mode i32, count u32, type_ i32, indices rawptr) #cc_c;
|
||||
DrawArrays: proc(mode, first i32, count u32) #cc_c;
|
||||
DrawElements: proc(mode i32, count u32, type_ i32, indices rawptr) #cc_c;
|
||||
|
||||
MapBuffer proc(target, access i32) -> rawptr #cc_c;
|
||||
UnmapBuffer proc(target i32) #cc_c;
|
||||
MapBuffer: proc(target, access i32) -> rawptr #cc_c;
|
||||
UnmapBuffer: proc(target i32) #cc_c;
|
||||
|
||||
VertexAttribPointer proc(index u32, size, type_ i32, normalized i32, stride u32, pointer rawptr) #cc_c;
|
||||
EnableVertexAttribArray proc(index u32) #cc_c;
|
||||
VertexAttribPointer: proc(index u32, size, type_ i32, normalized i32, stride u32, pointer rawptr) #cc_c;
|
||||
EnableVertexAttribArray: proc(index u32) #cc_c;
|
||||
|
||||
CreateShader proc(shader_type i32) -> u32 #cc_c;
|
||||
ShaderSource proc(shader u32, count u32, str ^^byte, length ^i32) #cc_c;
|
||||
CompileShader proc(shader u32) #cc_c;
|
||||
CreateProgram proc() -> u32 #cc_c;
|
||||
AttachShader proc(program, shader u32) #cc_c;
|
||||
DetachShader proc(program, shader u32) #cc_c;
|
||||
DeleteShader proc(shader u32) #cc_c;
|
||||
LinkProgram proc(program u32) #cc_c;
|
||||
UseProgram proc(program u32) #cc_c;
|
||||
DeleteProgram proc(program u32) #cc_c;
|
||||
CreateShader: proc(shader_type i32) -> u32 #cc_c;
|
||||
ShaderSource: proc(shader u32, count u32, str ^^byte, length ^i32) #cc_c;
|
||||
CompileShader: proc(shader u32) #cc_c;
|
||||
CreateProgram: proc() -> u32 #cc_c;
|
||||
AttachShader: proc(program, shader u32) #cc_c;
|
||||
DetachShader: proc(program, shader u32) #cc_c;
|
||||
DeleteShader: proc(shader u32) #cc_c;
|
||||
LinkProgram: proc(program u32) #cc_c;
|
||||
UseProgram: proc(program u32) #cc_c;
|
||||
DeleteProgram: proc(program u32) #cc_c;
|
||||
|
||||
|
||||
GetShaderiv proc(shader 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;
|
||||
GetProgramInfoLog proc(program u32, max_length u32, length ^u32, info_long ^byte) #cc_c;
|
||||
GetShaderiv: proc(shader 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;
|
||||
GetProgramInfoLog: proc(program u32, max_length u32, length ^u32, info_long ^byte) #cc_c;
|
||||
|
||||
ActiveTexture proc(texture i32) #cc_c;
|
||||
GenerateMipmap proc(target i32) #cc_c;
|
||||
ActiveTexture: proc(texture i32) #cc_c;
|
||||
GenerateMipmap: proc(target i32) #cc_c;
|
||||
|
||||
SamplerParameteri proc(sampler u32, pname i32, param i32) #cc_c;
|
||||
SamplerParameterf proc(sampler u32, pname i32, param f32) #cc_c;
|
||||
SamplerParameteriv proc(sampler u32, pname i32, params ^i32) #cc_c;
|
||||
SamplerParameterfv proc(sampler u32, pname i32, params ^f32) #cc_c;
|
||||
SamplerParameterIiv proc(sampler u32, pname i32, params ^i32) #cc_c;
|
||||
SamplerParameterIuiv proc(sampler u32, pname i32, params ^u32) #cc_c;
|
||||
SamplerParameteri: proc(sampler u32, pname i32, param i32) #cc_c;
|
||||
SamplerParameterf: proc(sampler u32, pname i32, param f32) #cc_c;
|
||||
SamplerParameteriv: proc(sampler u32, pname i32, params ^i32) #cc_c;
|
||||
SamplerParameterfv: proc(sampler u32, pname i32, params ^f32) #cc_c;
|
||||
SamplerParameterIiv: proc(sampler u32, pname i32, params ^i32) #cc_c;
|
||||
SamplerParameterIuiv: proc(sampler u32, pname i32, params ^u32) #cc_c;
|
||||
|
||||
|
||||
Uniform1i proc(loc i32, v0 i32) #cc_c;
|
||||
Uniform2i proc(loc i32, v0, v1 i32) #cc_c;
|
||||
Uniform3i proc(loc i32, v0, v1, v2 i32) #cc_c;
|
||||
Uniform4i proc(loc i32, v0, v1, v2, v3 i32) #cc_c;
|
||||
Uniform1f proc(loc i32, v0 f32) #cc_c;
|
||||
Uniform2f proc(loc i32, v0, v1 f32) #cc_c;
|
||||
Uniform3f proc(loc i32, v0, v1, v2 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;
|
||||
Uniform1i: proc(loc i32, v0 i32) #cc_c;
|
||||
Uniform2i: proc(loc i32, v0, v1 i32) #cc_c;
|
||||
Uniform3i: proc(loc i32, v0, v1, v2 i32) #cc_c;
|
||||
Uniform4i: proc(loc i32, v0, v1, v2, v3 i32) #cc_c;
|
||||
Uniform1f: proc(loc i32, v0 f32) #cc_c;
|
||||
Uniform2f: proc(loc i32, v0, v1 f32) #cc_c;
|
||||
Uniform3f: proc(loc i32, v0, v1, v2 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;
|
||||
|
||||
GetUniformLocation proc(program u32, name ^byte) -> i32 #cc_c;
|
||||
}
|
||||
GetUniformLocation: proc(program u32, name ^byte) -> i32 #cc_c;
|
||||
|
||||
proc init() {
|
||||
proc set_proc_address(p rawptr, name string) #inline { (p as ^(proc() #cc_c))^ = GetProcAddress(name); }
|
||||
|
||||
+1367
-1367
File diff suppressed because it is too large
Load Diff
+81
-86
@@ -10,52 +10,48 @@ type {
|
||||
Error int;
|
||||
}
|
||||
|
||||
const INVALID_HANDLE Handle = ~(0 as Handle);
|
||||
INVALID_HANDLE: Handle : ~(0 as Handle);
|
||||
|
||||
const {
|
||||
O_RDONLY = 0x00000;
|
||||
O_WRONLY = 0x00001;
|
||||
O_RDWR = 0x00002;
|
||||
O_CREAT = 0x00040;
|
||||
O_EXCL = 0x00080;
|
||||
O_NOCTTY = 0x00100;
|
||||
O_TRUNC = 0x00200;
|
||||
O_NONBLOCK = 0x00800;
|
||||
O_APPEND = 0x00400;
|
||||
O_SYNC = 0x01000;
|
||||
O_ASYNC = 0x02000;
|
||||
O_CLOEXEC = 0x80000;
|
||||
}
|
||||
|
||||
const {
|
||||
ERROR_NONE Error = 0;
|
||||
ERROR_FILE_NOT_FOUND Error = 2;
|
||||
ERROR_PATH_NOT_FOUND Error = 3;
|
||||
ERROR_ACCESS_DENIED Error = 5;
|
||||
ERROR_NO_MORE_FILES Error = 18;
|
||||
ERROR_HANDLE_EOF Error = 38;
|
||||
ERROR_NETNAME_DELETED Error = 64;
|
||||
ERROR_FILE_EXISTS Error = 80;
|
||||
ERROR_BROKEN_PIPE Error = 109;
|
||||
ERROR_BUFFER_OVERFLOW Error = 111;
|
||||
ERROR_INSUFFICIENT_BUFFER Error = 122;
|
||||
ERROR_MOD_NOT_FOUND Error = 126;
|
||||
ERROR_PROC_NOT_FOUND Error = 127;
|
||||
ERROR_DIR_NOT_EMPTY Error = 145;
|
||||
ERROR_ALREADY_EXISTS Error = 183;
|
||||
ERROR_ENVVAR_NOT_FOUND Error = 203;
|
||||
ERROR_MORE_DATA Error = 234;
|
||||
ERROR_OPERATION_ABORTED Error = 995;
|
||||
ERROR_IO_PENDING Error = 997;
|
||||
ERROR_NOT_FOUND Error = 1168;
|
||||
ERROR_PRIVILEGE_NOT_HELD Error = 1314;
|
||||
WSAEACCES Error = 10013;
|
||||
WSAECONNRESET Error = 10054;
|
||||
}
|
||||
O_RDONLY :: 0x00000;
|
||||
O_WRONLY :: 0x00001;
|
||||
O_RDWR :: 0x00002;
|
||||
O_CREAT :: 0x00040;
|
||||
O_EXCL :: 0x00080;
|
||||
O_NOCTTY :: 0x00100;
|
||||
O_TRUNC :: 0x00200;
|
||||
O_NONBLOCK :: 0x00800;
|
||||
O_APPEND :: 0x00400;
|
||||
O_SYNC :: 0x01000;
|
||||
O_ASYNC :: 0x02000;
|
||||
O_CLOEXEC :: 0x80000;
|
||||
|
||||
const { // Windows reserves errors >= 1<<29 for application use
|
||||
ERROR_FILE_IS_PIPE Error = 1<<29 + 0;
|
||||
}
|
||||
ERROR_NONE : Error : 0;
|
||||
ERROR_FILE_NOT_FOUND : Error : 2;
|
||||
ERROR_PATH_NOT_FOUND : Error : 3;
|
||||
ERROR_ACCESS_DENIED : Error : 5;
|
||||
ERROR_NO_MORE_FILES : Error : 18;
|
||||
ERROR_HANDLE_EOF : Error : 38;
|
||||
ERROR_NETNAME_DELETED : Error : 64;
|
||||
ERROR_FILE_EXISTS : Error : 80;
|
||||
ERROR_BROKEN_PIPE : Error : 109;
|
||||
ERROR_BUFFER_OVERFLOW : Error : 111;
|
||||
ERROR_INSUFFICIENT_BUFFER : Error : 122;
|
||||
ERROR_MOD_NOT_FOUND : Error : 126;
|
||||
ERROR_PROC_NOT_FOUND : Error : 127;
|
||||
ERROR_DIR_NOT_EMPTY : Error : 145;
|
||||
ERROR_ALREADY_EXISTS : Error : 183;
|
||||
ERROR_ENVVAR_NOT_FOUND : Error : 203;
|
||||
ERROR_MORE_DATA : Error : 234;
|
||||
ERROR_OPERATION_ABORTED : Error : 995;
|
||||
ERROR_IO_PENDING : Error : 997;
|
||||
ERROR_NOT_FOUND : Error : 1168;
|
||||
ERROR_PRIVILEGE_NOT_HELD : Error : 1314;
|
||||
WSAEACCES : Error : 10013;
|
||||
WSAECONNRESET : Error : 10054;
|
||||
|
||||
// Windows reserves errors >= 1<<29 for application use
|
||||
ERROR_FILE_IS_PIPE : Error : 1<<29 + 0;
|
||||
|
||||
|
||||
|
||||
@@ -66,7 +62,7 @@ proc open(path string, mode int, perm u32) -> (Handle, Error) {
|
||||
return INVALID_HANDLE, ERROR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
var access u32;
|
||||
access: u32;
|
||||
match mode & (O_RDONLY|O_WRONLY|O_RDWR) {
|
||||
case O_RDONLY: access = FILE_GENERIC_READ;
|
||||
case O_WRONLY: access = FILE_GENERIC_WRITE;
|
||||
@@ -81,14 +77,14 @@ proc open(path string, mode int, perm u32) -> (Handle, Error) {
|
||||
access |= FILE_APPEND_DATA;
|
||||
}
|
||||
|
||||
var share_mode = (FILE_SHARE_READ|FILE_SHARE_WRITE) as u32;
|
||||
var sa ^SECURITY_ATTRIBUTES = nil;
|
||||
var sa_inherit = SECURITY_ATTRIBUTES{length = size_of(SECURITY_ATTRIBUTES), inherit_handle = 1};
|
||||
share_mode := (FILE_SHARE_READ|FILE_SHARE_WRITE) as u32;
|
||||
sa: ^SECURITY_ATTRIBUTES = nil;
|
||||
sa_inherit := SECURITY_ATTRIBUTES{length = size_of(SECURITY_ATTRIBUTES), inherit_handle = 1};
|
||||
if mode&O_CLOEXEC == 0 {
|
||||
sa = ^sa_inherit;
|
||||
}
|
||||
|
||||
var create_mode u32;
|
||||
create_mode: u32;
|
||||
match {
|
||||
case mode&(O_CREAT|O_EXCL) == (O_CREAT | O_EXCL):
|
||||
create_mode = CREATE_NEW;
|
||||
@@ -102,14 +98,14 @@ proc open(path string, mode int, perm u32) -> (Handle, Error) {
|
||||
create_mode = OPEN_EXISTING;
|
||||
}
|
||||
|
||||
var buf [300]byte;
|
||||
buf: [300]byte;
|
||||
copy(buf[:], path as []byte);
|
||||
|
||||
var handle = CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil) as Handle;
|
||||
handle := CreateFileA(^buf[0], access, share_mode, sa, create_mode, FILE_ATTRIBUTE_NORMAL, nil) as Handle;
|
||||
if handle == INVALID_HANDLE {
|
||||
return handle, ERROR_NONE;
|
||||
}
|
||||
var err = GetLastError();
|
||||
err := GetLastError();
|
||||
return INVALID_HANDLE, err as Error;
|
||||
}
|
||||
|
||||
@@ -118,8 +114,8 @@ proc close(fd Handle) {
|
||||
}
|
||||
|
||||
proc write(fd Handle, data []byte) -> (int, Error) {
|
||||
var bytes_written i32;
|
||||
var e = win32.WriteFile(fd as win32.HANDLE, data.data, data.count as i32, ^bytes_written, nil);
|
||||
bytes_written: i32;
|
||||
e := win32.WriteFile(fd as win32.HANDLE, data.data, data.count as i32, ^bytes_written, nil);
|
||||
if e != 0 {
|
||||
return 0, e as Error;
|
||||
}
|
||||
@@ -127,10 +123,10 @@ proc write(fd Handle, data []byte) -> (int, Error) {
|
||||
}
|
||||
|
||||
proc read(fd Handle, data []byte) -> (int, Error) {
|
||||
var bytes_read i32;
|
||||
var e = win32.ReadFile(fd as win32.HANDLE, data.data, data.count as u32, ^bytes_read, nil);
|
||||
bytes_read: i32;
|
||||
e := win32.ReadFile(fd as win32.HANDLE, data.data, data.count as u32, ^bytes_read, nil);
|
||||
if e != win32.FALSE {
|
||||
var err = win32.GetLastError();
|
||||
err := win32.GetLastError();
|
||||
return 0, err as Error;
|
||||
}
|
||||
return bytes_read as int, ERROR_NONE;
|
||||
@@ -138,21 +134,21 @@ proc read(fd Handle, data []byte) -> (int, Error) {
|
||||
|
||||
proc seek(fd Handle, offset i64, whence int) -> (i64, Error) {
|
||||
using win32;
|
||||
var w u32;
|
||||
w: u32;
|
||||
match whence {
|
||||
case 0: w = FILE_BEGIN;
|
||||
case 1: w = FILE_CURRENT;
|
||||
case 2: w = FILE_END;
|
||||
}
|
||||
var hi = (offset>>32) as i32;
|
||||
var lo = offset as i32;
|
||||
var ft = GetFileType(fd as HANDLE);
|
||||
hi := (offset>>32) as i32;
|
||||
lo := offset as i32;
|
||||
ft := GetFileType(fd as HANDLE);
|
||||
if ft == FILE_TYPE_PIPE {
|
||||
return 0, ERROR_FILE_IS_PIPE;
|
||||
}
|
||||
var dw_ptr = SetFilePointer(fd as HANDLE, lo, ^hi, w);
|
||||
dw_ptr := SetFilePointer(fd as HANDLE, lo, ^hi, w);
|
||||
if dw_ptr == INVALID_SET_FILE_POINTER {
|
||||
var err = GetLastError();
|
||||
err := GetLastError();
|
||||
return 0, err as Error;
|
||||
}
|
||||
return (hi as i64)<<32 + (dw_ptr as i64), ERROR_NONE;
|
||||
@@ -160,14 +156,13 @@ proc seek(fd Handle, offset i64, whence int) -> (i64, Error) {
|
||||
|
||||
|
||||
// NOTE(bill): Uses startup to initialize it
|
||||
var {
|
||||
stdin = get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
stdout = get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
stderr = get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
}
|
||||
stdin := get_std_handle(win32.STD_INPUT_HANDLE);
|
||||
stdout := get_std_handle(win32.STD_OUTPUT_HANDLE);
|
||||
stderr := get_std_handle(win32.STD_ERROR_HANDLE);
|
||||
|
||||
|
||||
proc get_std_handle(h int) -> Handle {
|
||||
var fd = win32.GetStdHandle(h as i32);
|
||||
fd := win32.GetStdHandle(h as i32);
|
||||
win32.SetHandleInformation(fd, win32.HANDLE_FLAG_INHERIT, 0);
|
||||
return fd as Handle;
|
||||
}
|
||||
@@ -178,17 +173,17 @@ proc get_std_handle(h int) -> Handle {
|
||||
|
||||
|
||||
proc last_write_time(fd Handle) -> File_Time {
|
||||
var file_info win32.BY_HANDLE_FILE_INFORMATION;
|
||||
file_info: win32.BY_HANDLE_FILE_INFORMATION;
|
||||
win32.GetFileInformationByHandle(fd as win32.HANDLE, ^file_info);
|
||||
var lo = file_info.last_write_time.lo as File_Time;
|
||||
var hi = file_info.last_write_time.hi as File_Time;
|
||||
lo := file_info.last_write_time.lo as File_Time;
|
||||
hi := file_info.last_write_time.hi as File_Time;
|
||||
return lo | hi << 32;
|
||||
}
|
||||
|
||||
proc last_write_time_by_name(name string) -> File_Time {
|
||||
var last_write_time win32.FILETIME;
|
||||
var data win32.FILE_ATTRIBUTE_DATA;
|
||||
var buf [1024]byte;
|
||||
last_write_time: win32.FILETIME;
|
||||
data: win32.FILE_ATTRIBUTE_DATA;
|
||||
buf: [1024]byte;
|
||||
|
||||
assert(buf.count > name.count);
|
||||
|
||||
@@ -198,8 +193,8 @@ proc last_write_time_by_name(name string) -> File_Time {
|
||||
last_write_time = data.last_write_time;
|
||||
}
|
||||
|
||||
var l = last_write_time.lo as File_Time;
|
||||
var h = last_write_time.hi as File_Time;
|
||||
l := last_write_time.lo as File_Time;
|
||||
h := last_write_time.hi as File_Time;
|
||||
return l | h << 32;
|
||||
}
|
||||
|
||||
@@ -208,33 +203,33 @@ proc last_write_time_by_name(name string) -> File_Time {
|
||||
|
||||
|
||||
proc read_entire_file(name string) -> ([]byte, bool) {
|
||||
var buf [300]byte;
|
||||
buf: [300]byte;
|
||||
copy(buf[:], name as []byte);
|
||||
|
||||
var fd, err = open(name, O_RDONLY, 0);
|
||||
fd, err := open(name, O_RDONLY, 0);
|
||||
if err != ERROR_NONE {
|
||||
return nil, false;
|
||||
}
|
||||
defer close(fd);
|
||||
|
||||
var length i64;
|
||||
var file_size_ok = win32.GetFileSizeEx(fd as win32.HANDLE, ^length) != 0;
|
||||
length: i64;
|
||||
file_size_ok := win32.GetFileSizeEx(fd as win32.HANDLE, ^length) != 0;
|
||||
if !file_size_ok {
|
||||
return nil, false;
|
||||
}
|
||||
|
||||
var data = new_slice(u8, length);
|
||||
data := new_slice(u8, length);
|
||||
if data.data == nil {
|
||||
return nil, false;
|
||||
}
|
||||
|
||||
var single_read_length i32;
|
||||
var total_read i64;
|
||||
single_read_length: i32;
|
||||
total_read: i64;
|
||||
|
||||
for total_read < length {
|
||||
var remaining = length - total_read;
|
||||
var to_read u32;
|
||||
const MAX = 1<<32-1;
|
||||
remaining := length - total_read;
|
||||
to_read: u32;
|
||||
MAX :: 1<<32-1;
|
||||
if remaining <= MAX {
|
||||
to_read = remaining as u32;
|
||||
} else {
|
||||
|
||||
+5
-5
@@ -49,7 +49,7 @@ proc mutex_destroy(m ^Mutex) {
|
||||
semaphore_destroy(^m.semaphore);
|
||||
}
|
||||
proc mutex_lock(m ^Mutex) {
|
||||
var thread_id = current_thread_id();
|
||||
thread_id := current_thread_id();
|
||||
if atomic.fetch_add32(^m.counter, 1) > 0 {
|
||||
if thread_id != atomic.load32(^m.owner) {
|
||||
semaphore_wait(^m.semaphore);
|
||||
@@ -59,11 +59,11 @@ proc mutex_lock(m ^Mutex) {
|
||||
m.recursion++;
|
||||
}
|
||||
proc mutex_try_lock(m ^Mutex) -> bool {
|
||||
var thread_id = current_thread_id();
|
||||
thread_id := current_thread_id();
|
||||
if atomic.load32(^m.owner) == thread_id {
|
||||
atomic.fetch_add32(^m.counter, 1);
|
||||
} else {
|
||||
var expected i32 = 0;
|
||||
expected: i32 = 0;
|
||||
if atomic.load32(^m.counter) != 0 {
|
||||
return false;
|
||||
}
|
||||
@@ -76,8 +76,8 @@ proc mutex_try_lock(m ^Mutex) -> bool {
|
||||
return true;
|
||||
}
|
||||
proc mutex_unlock(m ^Mutex) {
|
||||
var recursion i32;
|
||||
var thread_id = current_thread_id();
|
||||
recursion: i32;
|
||||
thread_id := current_thread_id();
|
||||
assert(thread_id == atomic.load32(^m.owner));
|
||||
|
||||
m.recursion--;
|
||||
|
||||
+102
-115
@@ -20,42 +20,42 @@ type {
|
||||
WNDPROC proc(hwnd HWND, msg u32, wparam WPARAM, lparam LPARAM) -> LRESULT;
|
||||
}
|
||||
|
||||
const {
|
||||
INVALID_HANDLE_VALUE = (-1 as int) as HANDLE;
|
||||
|
||||
FALSE BOOL = 0;
|
||||
TRUE BOOL = 1;
|
||||
INVALID_HANDLE_VALUE :: (-1 as int) as HANDLE;
|
||||
|
||||
CS_VREDRAW = 0x0001;
|
||||
CS_HREDRAW = 0x0002;
|
||||
CS_OWNDC = 0x0020;
|
||||
CW_USEDEFAULT = -0x80000000;
|
||||
FALSE: BOOL : 0;
|
||||
TRUE: BOOL : 1;
|
||||
|
||||
WS_OVERLAPPED = 0;
|
||||
WS_MAXIMIZEBOX = 0x00010000;
|
||||
WS_MINIMIZEBOX = 0x00020000;
|
||||
WS_THICKFRAME = 0x00040000;
|
||||
WS_SYSMENU = 0x00080000;
|
||||
WS_CAPTION = 0x00C00000;
|
||||
WS_VISIBLE = 0x10000000;
|
||||
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
|
||||
CS_VREDRAW :: 0x0001;
|
||||
CS_HREDRAW :: 0x0002;
|
||||
CS_OWNDC :: 0x0020;
|
||||
CW_USEDEFAULT :: -0x80000000;
|
||||
|
||||
WM_DESTROY = 0x0002;
|
||||
WM_CLOSE = 0x0010;
|
||||
WM_QUIT = 0x0012;
|
||||
WM_KEYDOWN = 0x0100;
|
||||
WM_KEYUP = 0x0101;
|
||||
WS_OVERLAPPED :: 0;
|
||||
WS_MAXIMIZEBOX :: 0x00010000;
|
||||
WS_MINIMIZEBOX :: 0x00020000;
|
||||
WS_THICKFRAME :: 0x00040000;
|
||||
WS_SYSMENU :: 0x00080000;
|
||||
WS_CAPTION :: 0x00C00000;
|
||||
WS_VISIBLE :: 0x10000000;
|
||||
WS_OVERLAPPEDWINDOW :: WS_OVERLAPPED|WS_CAPTION|WS_SYSMENU|WS_THICKFRAME|WS_MINIMIZEBOX|WS_MAXIMIZEBOX;
|
||||
|
||||
PM_REMOVE = 1;
|
||||
WM_DESTROY :: 0x0002;
|
||||
WM_CLOSE :: 0x0010;
|
||||
WM_QUIT :: 0x0012;
|
||||
WM_KEYDOWN :: 0x0100;
|
||||
WM_KEYUP :: 0x0101;
|
||||
|
||||
COLOR_BACKGROUND = 1 as HBRUSH;
|
||||
BLACK_BRUSH = 4;
|
||||
PM_REMOVE :: 1;
|
||||
|
||||
SM_CXSCREEN = 0;
|
||||
SM_CYSCREEN = 1;
|
||||
COLOR_BACKGROUND :: 1 as HBRUSH;
|
||||
BLACK_BRUSH :: 4;
|
||||
|
||||
SM_CXSCREEN :: 0;
|
||||
SM_CYSCREEN :: 1;
|
||||
|
||||
SW_SHOW :: 5;
|
||||
|
||||
SW_SHOW = 5;
|
||||
}
|
||||
|
||||
type {
|
||||
POINT struct #ordered {
|
||||
@@ -118,10 +118,8 @@ type {
|
||||
|
||||
GET_FILEEX_INFO_LEVELS i32;
|
||||
}
|
||||
const {
|
||||
GetFileExInfoStandard = 0 as GET_FILEEX_INFO_LEVELS;
|
||||
GetFileExMaxInfoLevel = 1 as GET_FILEEX_INFO_LEVELS;
|
||||
}
|
||||
GetFileExInfoStandard: GET_FILEEX_INFO_LEVELS : 0;
|
||||
GetFileExMaxInfoLevel: GET_FILEEX_INFO_LEVELS : 1;
|
||||
|
||||
proc GetLastError () -> i32 #foreign #dll_import
|
||||
proc ExitProcess (exit_code u32) #foreign #dll_import
|
||||
@@ -163,7 +161,7 @@ proc GetActiveWindow () -> HWND #foreign #dll_import
|
||||
|
||||
|
||||
proc GetQueryPerformanceFrequency() -> i64 {
|
||||
var r i64;
|
||||
r: i64;
|
||||
QueryPerformanceFrequency(^r);
|
||||
return r;
|
||||
}
|
||||
@@ -191,60 +189,54 @@ proc SetFilePointer(file_handle HANDLE, distance_to_move i32, distance_to_move_h
|
||||
|
||||
proc SetHandleInformation(obj HANDLE, mask, flags u32) -> BOOL #foreign #dll_import
|
||||
|
||||
const {
|
||||
HANDLE_FLAG_INHERIT = 1;
|
||||
HANDLE_FLAG_PROTECT_FROM_CLOSE = 2;
|
||||
}
|
||||
HANDLE_FLAG_INHERIT :: 1;
|
||||
HANDLE_FLAG_PROTECT_FROM_CLOSE :: 2;
|
||||
|
||||
|
||||
const {
|
||||
FILE_BEGIN = 0;
|
||||
FILE_CURRENT = 1;
|
||||
FILE_END = 2;
|
||||
}
|
||||
FILE_BEGIN :: 0;
|
||||
FILE_CURRENT :: 1;
|
||||
FILE_END :: 2;
|
||||
|
||||
const {
|
||||
FILE_SHARE_READ = 0x00000001;
|
||||
FILE_SHARE_WRITE = 0x00000002;
|
||||
FILE_SHARE_DELETE = 0x00000004;
|
||||
FILE_GENERIC_ALL = 0x10000000;
|
||||
FILE_GENERIC_EXECUTE = 0x20000000;
|
||||
FILE_GENERIC_WRITE = 0x40000000;
|
||||
FILE_GENERIC_READ = 0x80000000;
|
||||
FILE_SHARE_READ :: 0x00000001;
|
||||
FILE_SHARE_WRITE :: 0x00000002;
|
||||
FILE_SHARE_DELETE :: 0x00000004;
|
||||
FILE_GENERIC_ALL :: 0x10000000;
|
||||
FILE_GENERIC_EXECUTE :: 0x20000000;
|
||||
FILE_GENERIC_WRITE :: 0x40000000;
|
||||
FILE_GENERIC_READ :: 0x80000000;
|
||||
|
||||
FILE_APPEND_DATA = 0x0004;
|
||||
FILE_APPEND_DATA :: 0x0004;
|
||||
|
||||
STD_INPUT_HANDLE = -10;
|
||||
STD_OUTPUT_HANDLE = -11;
|
||||
STD_ERROR_HANDLE = -12;
|
||||
STD_INPUT_HANDLE :: -10;
|
||||
STD_OUTPUT_HANDLE :: -11;
|
||||
STD_ERROR_HANDLE :: -12;
|
||||
|
||||
CREATE_NEW = 1;
|
||||
CREATE_ALWAYS = 2;
|
||||
OPEN_EXISTING = 3;
|
||||
OPEN_ALWAYS = 4;
|
||||
TRUNCATE_EXISTING = 5;
|
||||
CREATE_NEW :: 1;
|
||||
CREATE_ALWAYS :: 2;
|
||||
OPEN_EXISTING :: 3;
|
||||
OPEN_ALWAYS :: 4;
|
||||
TRUNCATE_EXISTING :: 5;
|
||||
|
||||
FILE_ATTRIBUTE_READONLY = 0x00000001;
|
||||
FILE_ATTRIBUTE_HIDDEN = 0x00000002;
|
||||
FILE_ATTRIBUTE_SYSTEM = 0x00000004;
|
||||
FILE_ATTRIBUTE_DIRECTORY = 0x00000010;
|
||||
FILE_ATTRIBUTE_ARCHIVE = 0x00000020;
|
||||
FILE_ATTRIBUTE_DEVICE = 0x00000040;
|
||||
FILE_ATTRIBUTE_NORMAL = 0x00000080;
|
||||
FILE_ATTRIBUTE_TEMPORARY = 0x00000100;
|
||||
FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200;
|
||||
FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400;
|
||||
FILE_ATTRIBUTE_COMPRESSED = 0x00000800;
|
||||
FILE_ATTRIBUTE_OFFLINE = 0x00001000;
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000;
|
||||
FILE_ATTRIBUTE_ENCRYPTED = 0x00004000;
|
||||
FILE_ATTRIBUTE_READONLY :: 0x00000001;
|
||||
FILE_ATTRIBUTE_HIDDEN :: 0x00000002;
|
||||
FILE_ATTRIBUTE_SYSTEM :: 0x00000004;
|
||||
FILE_ATTRIBUTE_DIRECTORY :: 0x00000010;
|
||||
FILE_ATTRIBUTE_ARCHIVE :: 0x00000020;
|
||||
FILE_ATTRIBUTE_DEVICE :: 0x00000040;
|
||||
FILE_ATTRIBUTE_NORMAL :: 0x00000080;
|
||||
FILE_ATTRIBUTE_TEMPORARY :: 0x00000100;
|
||||
FILE_ATTRIBUTE_SPARSE_FILE :: 0x00000200;
|
||||
FILE_ATTRIBUTE_REPARSE_POINT :: 0x00000400;
|
||||
FILE_ATTRIBUTE_COMPRESSED :: 0x00000800;
|
||||
FILE_ATTRIBUTE_OFFLINE :: 0x00001000;
|
||||
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED :: 0x00002000;
|
||||
FILE_ATTRIBUTE_ENCRYPTED :: 0x00004000;
|
||||
|
||||
FILE_TYPE_DISK = 0x0001;
|
||||
FILE_TYPE_CHAR = 0x0002;
|
||||
FILE_TYPE_PIPE = 0x0003;
|
||||
FILE_TYPE_DISK :: 0x0001;
|
||||
FILE_TYPE_CHAR :: 0x0002;
|
||||
FILE_TYPE_PIPE :: 0x0003;
|
||||
|
||||
INVALID_SET_FILE_POINTER = ~(0 as u32);
|
||||
}
|
||||
INVALID_SET_FILE_POINTER :: ~(0 as u32);
|
||||
|
||||
|
||||
|
||||
@@ -255,7 +247,7 @@ proc HeapFree (h HANDLE, flags u32, memory rawptr) -> BOOL #f
|
||||
proc GetProcessHeap() -> HANDLE #foreign #dll_import
|
||||
|
||||
|
||||
const HEAP_ZERO_MEMORY = 0x00000008;
|
||||
HEAP_ZERO_MEMORY :: 0x00000008;
|
||||
|
||||
// Synchronization
|
||||
|
||||
@@ -265,7 +257,7 @@ type SECURITY_ATTRIBUTES struct #ordered {
|
||||
inherit_handle BOOL;
|
||||
}
|
||||
|
||||
const INFINITE = 0xffffffff;
|
||||
INFINITE :: 0xffffffff;
|
||||
|
||||
proc CreateSemaphoreA (attributes ^SECURITY_ATTRIBUTES, initial_count, maximum_count i32, name ^byte) -> HANDLE #foreign #dll_import
|
||||
proc ReleaseSemaphore (semaphore HANDLE, release_count i32, previous_count ^i32) -> BOOL #foreign #dll_import
|
||||
@@ -314,11 +306,10 @@ type {
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
BI_RGB = 0;
|
||||
DIB_RGB_COLORS = 0x00;
|
||||
SRCCOPY = 0x00cc0020 as u32;
|
||||
}
|
||||
BI_RGB :: 0;
|
||||
DIB_RGB_COLORS :: 0x00;
|
||||
SRCCOPY: u32 : 0x00cc0020;
|
||||
|
||||
|
||||
proc StretchDIBits(hdc HDC,
|
||||
x_dst, y_dst, width_dst, height_dst i32,
|
||||
@@ -338,29 +329,27 @@ proc GetClientRect(hwnd HWND, rect ^RECT) -> BOOL #foreign
|
||||
|
||||
|
||||
// Windows OpenGL
|
||||
const {
|
||||
PFD_TYPE_RGBA = 0;
|
||||
PFD_TYPE_COLORINDEX = 1;
|
||||
PFD_MAIN_PLANE = 0;
|
||||
PFD_OVERLAY_PLANE = 1;
|
||||
PFD_UNDERLAY_PLANE = -1;
|
||||
PFD_DOUBLEBUFFER = 1;
|
||||
PFD_STEREO = 2;
|
||||
PFD_DRAW_TO_WINDOW = 4;
|
||||
PFD_DRAW_TO_BITMAP = 8;
|
||||
PFD_SUPPORT_GDI = 16;
|
||||
PFD_SUPPORT_OPENGL = 32;
|
||||
PFD_GENERIC_FORMAT = 64;
|
||||
PFD_NEED_PALETTE = 128;
|
||||
PFD_NEED_SYSTEM_PALETTE = 0x00000100;
|
||||
PFD_SWAP_EXCHANGE = 0x00000200;
|
||||
PFD_SWAP_COPY = 0x00000400;
|
||||
PFD_SWAP_LAYER_BUFFERS = 0x00000800;
|
||||
PFD_GENERIC_ACCELERATED = 0x00001000;
|
||||
PFD_DEPTH_DONTCARE = 0x20000000;
|
||||
PFD_DOUBLEBUFFER_DONTCARE = 0x40000000;
|
||||
PFD_STEREO_DONTCARE = 0x80000000;
|
||||
}
|
||||
PFD_TYPE_RGBA :: 0;
|
||||
PFD_TYPE_COLORINDEX :: 1;
|
||||
PFD_MAIN_PLANE :: 0;
|
||||
PFD_OVERLAY_PLANE :: 1;
|
||||
PFD_UNDERLAY_PLANE :: -1;
|
||||
PFD_DOUBLEBUFFER :: 1;
|
||||
PFD_STEREO :: 2;
|
||||
PFD_DRAW_TO_WINDOW :: 4;
|
||||
PFD_DRAW_TO_BITMAP :: 8;
|
||||
PFD_SUPPORT_GDI :: 16;
|
||||
PFD_SUPPORT_OPENGL :: 32;
|
||||
PFD_GENERIC_FORMAT :: 64;
|
||||
PFD_NEED_PALETTE :: 128;
|
||||
PFD_NEED_SYSTEM_PALETTE :: 0x00000100;
|
||||
PFD_SWAP_EXCHANGE :: 0x00000200;
|
||||
PFD_SWAP_COPY :: 0x00000400;
|
||||
PFD_SWAP_LAYER_BUFFERS :: 0x00000800;
|
||||
PFD_GENERIC_ACCELERATED :: 0x00001000;
|
||||
PFD_DEPTH_DONTCARE :: 0x20000000;
|
||||
PFD_DOUBLEBUFFER_DONTCARE :: 0x40000000;
|
||||
PFD_STEREO_DONTCARE :: 0x80000000;
|
||||
|
||||
type {
|
||||
HGLRC HANDLE;
|
||||
@@ -406,13 +395,11 @@ proc ChoosePixelFormat(hdc HDC, pfd ^PIXELFORMATDESCRIPTOR) -> i32 #foreign #dll
|
||||
proc SwapBuffers (hdc HDC) -> BOOL #foreign #dll_import
|
||||
proc ReleaseDC (wnd HWND, hdc HDC) -> i32 #foreign #dll_import
|
||||
|
||||
const {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB = 0x2091;
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB = 0x2092;
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB = 0x9126;
|
||||
WGL_CONTEXT_CORE_PROFILE_BIT_ARB = 0x0001;
|
||||
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x0002;
|
||||
}
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB :: 0x2091;
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB :: 0x2092;
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB :: 0x9126;
|
||||
WGL_CONTEXT_CORE_PROFILE_BIT_ARB :: 0x0001;
|
||||
WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB :: 0x0002;
|
||||
|
||||
proc wglCreateContext (hdc HDC) -> HGLRC #foreign #dll_import
|
||||
proc wglMakeCurrent (hdc HDC, hglrc HGLRC) -> BOOL #foreign #dll_import
|
||||
|
||||
+68
-74
@@ -1,53 +1,49 @@
|
||||
const {
|
||||
RUNE_ERROR = '\ufffd';
|
||||
RUNE_SELF = 0x80;
|
||||
RUNE_BOM = 0xfeff;
|
||||
RUNE_EOF = ~(0 as rune);
|
||||
MAX_RUNE = '\U0010ffff';
|
||||
UTF_MAX = 4;
|
||||
RUNE_ERROR :: '\ufffd';
|
||||
RUNE_SELF :: 0x80;
|
||||
RUNE_BOM :: 0xfeff;
|
||||
RUNE_EOF :: ~(0 as rune);
|
||||
MAX_RUNE :: '\U0010ffff';
|
||||
UTF_MAX :: 4;
|
||||
|
||||
SURROGATE_MIN = 0xd800;
|
||||
SURROGATE_MAX = 0xdfff;
|
||||
}
|
||||
SURROGATE_MIN :: 0xd800;
|
||||
SURROGATE_MAX :: 0xdfff;
|
||||
|
||||
type Accept_Range struct {
|
||||
lo, hi u8;
|
||||
}
|
||||
|
||||
var {
|
||||
accept_ranges = [5]Accept_Range{
|
||||
{0x80, 0xbf},
|
||||
{0xa0, 0xbf},
|
||||
{0x80, 0x9f},
|
||||
{0x90, 0xbf},
|
||||
{0x80, 0x8f},
|
||||
};
|
||||
accept_ranges := [5]Accept_Range{
|
||||
{0x80, 0xbf},
|
||||
{0xa0, 0xbf},
|
||||
{0x80, 0x9f},
|
||||
{0x90, 0xbf},
|
||||
{0x80, 0x8f},
|
||||
};
|
||||
|
||||
accept_sizes = [256]byte{
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x30-0x3f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x40-0x4f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x50-0x5f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x60-0x6f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x70-0x7f
|
||||
accept_sizes := [256]byte{
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x00-0x0f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x10-0x1f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x20-0x2f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x30-0x3f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x40-0x4f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x50-0x5f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x60-0x6f
|
||||
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, // 0x70-0x7f
|
||||
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x80-0x8f
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x90-0x9f
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xa0-0xaf
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xb0-0xbf
|
||||
0xf1, 0xf1, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xc0-0xcf
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xd0-0xdf
|
||||
0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x03, // 0xe0-0xef
|
||||
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
|
||||
};
|
||||
}
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x80-0x8f
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0x90-0x9f
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xa0-0xaf
|
||||
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xb0-0xbf
|
||||
0xf1, 0xf1, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xc0-0xcf
|
||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, // 0xd0-0xdf
|
||||
0x13, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x23, 0x03, 0x03, // 0xe0-0xef
|
||||
0x34, 0x04, 0x04, 0x04, 0x44, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, // 0xf0-0xff
|
||||
};
|
||||
|
||||
proc encode_rune(r rune) -> ([4]byte, int) {
|
||||
var buf [4]byte;
|
||||
var i = r as u32;
|
||||
const mask = 0x3f as byte;
|
||||
buf: [4]byte;
|
||||
i := r as u32;
|
||||
mask: byte : 0x3f;
|
||||
if i <= 1<<7-1 {
|
||||
buf[0] = r as byte;
|
||||
return buf, 1;
|
||||
@@ -79,44 +75,42 @@ proc encode_rune(r rune) -> ([4]byte, int) {
|
||||
}
|
||||
|
||||
proc decode_rune(s string) -> (rune, int) {
|
||||
var n = s.count;
|
||||
n := s.count;
|
||||
if n < 1 {
|
||||
return RUNE_ERROR, 0;
|
||||
}
|
||||
var b0 = s[0];
|
||||
var x = accept_sizes[b0];
|
||||
b0 := s[0];
|
||||
x := accept_sizes[b0];
|
||||
if x >= 0xf0 {
|
||||
var mask = (x as rune << 31) >> 31; // all zeros or all ones
|
||||
mask := (x as rune << 31) >> 31; // all zeros or all ones
|
||||
return (b0 as rune) &~ mask | RUNE_ERROR&mask, 1;
|
||||
}
|
||||
var size = x & 7;
|
||||
var ar = accept_ranges[x>>4];
|
||||
size := x & 7;
|
||||
ar := accept_ranges[x>>4];
|
||||
if n < size as int {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
var b1 = s[1];
|
||||
b1 := s[1];
|
||||
if b1 < ar.lo || ar.hi < b1 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
|
||||
const {
|
||||
MASK_X = 0b00111111;
|
||||
MASK_2 = 0b00011111;
|
||||
MASK_3 = 0b00001111;
|
||||
MASK_4 = 0b00000111;
|
||||
}
|
||||
MASK_X :: 0b00111111;
|
||||
MASK_2 :: 0b00011111;
|
||||
MASK_3 :: 0b00001111;
|
||||
MASK_4 :: 0b00000111;
|
||||
|
||||
if size == 2 {
|
||||
return (b0&MASK_2) as rune <<6 | (b1&MASK_X) as rune, 2;
|
||||
}
|
||||
var b2 = s[2];
|
||||
b2 := s[2];
|
||||
if b2 < 0x80 || 0xbf < b2 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
if size == 3 {
|
||||
return (b0&MASK_3) as rune <<12 | (b1&MASK_X) as rune <<6 | (b2&MASK_X) as rune, 3;
|
||||
}
|
||||
var b3 = s[3];
|
||||
b3 := s[3];
|
||||
if b3 < 0x80 || 0xbf < b3 {
|
||||
return RUNE_ERROR, 1;
|
||||
}
|
||||
@@ -137,31 +131,31 @@ proc valid_rune(r rune) -> bool {
|
||||
}
|
||||
|
||||
proc valid_string(s string) -> bool {
|
||||
var n = s.count;
|
||||
for var i = 0; i < n; {
|
||||
var si = s[i];
|
||||
n := s.count;
|
||||
for i := 0; i < n; {
|
||||
si := s[i];
|
||||
if si < RUNE_SELF { // ascii
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
var x = accept_sizes[si];
|
||||
x := accept_sizes[si];
|
||||
if x == 0xf1 {
|
||||
return false;
|
||||
}
|
||||
var size = (x & 7) as int;
|
||||
size := (x & 7) as int;
|
||||
if i+size > n {
|
||||
return false;
|
||||
}
|
||||
var ar = accept_ranges[x>>4];
|
||||
if var b = s[i+1]; b < ar.lo || ar.hi < b {
|
||||
ar := accept_ranges[x>>4];
|
||||
if b := s[i+1]; b < ar.lo || ar.hi < b {
|
||||
return false;
|
||||
} else if size == 2 {
|
||||
// Okay
|
||||
} else if var b = s[i+2]; b < 0x80 || 0xbf < b {
|
||||
} else if b := s[i+2]; b < 0x80 || 0xbf < b {
|
||||
return false;
|
||||
} else if size == 3 {
|
||||
// Okay
|
||||
} else if var b = s[i+3]; b < 0x80 || 0xbf < b {
|
||||
} else if b := s[i+3]; b < 0x80 || 0xbf < b {
|
||||
return false;
|
||||
}
|
||||
i += size;
|
||||
@@ -170,34 +164,34 @@ proc valid_string(s string) -> bool {
|
||||
}
|
||||
|
||||
proc rune_count(s string) -> int {
|
||||
var count = 0;
|
||||
var n = s.count;
|
||||
for var i = 0; i < n; count++ {
|
||||
var si = s[i];
|
||||
count := 0;
|
||||
n := s.count;
|
||||
for i := 0; i < n; count++ {
|
||||
si := s[i];
|
||||
if si < RUNE_SELF { // ascii
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
var x = accept_sizes[si];
|
||||
x := accept_sizes[si];
|
||||
if x == 0xf1 {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
var size = (x & 7) as int;
|
||||
size := (x & 7) as int;
|
||||
if i+size > n {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
var ar = accept_ranges[x>>4];
|
||||
if var b = s[i+1]; b < ar.lo || ar.hi < b {
|
||||
ar := accept_ranges[x>>4];
|
||||
if b := s[i+1]; b < ar.lo || ar.hi < b {
|
||||
size = 1;
|
||||
} else if size == 2 {
|
||||
// Okay
|
||||
} else if var b = s[i+2]; b < 0x80 || 0xbf < b {
|
||||
} else if b := s[i+2]; b < 0x80 || 0xbf < b {
|
||||
size = 1;
|
||||
} else if size == 3 {
|
||||
// Okay
|
||||
} else if var b = s[i+3]; b < 0x80 || 0xbf < b {
|
||||
} else if b := s[i+3]; b < 0x80 || 0xbf < b {
|
||||
size = 1;
|
||||
}
|
||||
i += size;
|
||||
|
||||
+95
-111
@@ -1075,36 +1075,33 @@ void init_preload(Checker *c) {
|
||||
c->done_preload = true;
|
||||
}
|
||||
|
||||
bool check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init);
|
||||
bool check_arity_match(Checker *c, AstNodeValueDecl *d);
|
||||
|
||||
#include "expr.c"
|
||||
#include "decl.c"
|
||||
#include "stmt.c"
|
||||
|
||||
bool check_arity_match(Checker *c, AstNodeValueSpec *s, AstNodeValueSpec *init) {
|
||||
isize lhs = s->names.count;
|
||||
isize rhs = s->values.count;
|
||||
if (init != NULL) {
|
||||
rhs = init->values.count;
|
||||
}
|
||||
bool check_arity_match(Checker *c, AstNodeValueDecl *d) {
|
||||
isize lhs = d->names.count;
|
||||
isize rhs = d->values.count;
|
||||
|
||||
if (init == NULL && rhs == 0) {
|
||||
if (s->type == NULL) {
|
||||
error_node(s->names.e[0], "Missing type or initial expression");
|
||||
if (rhs == 0) {
|
||||
if (d->type == NULL) {
|
||||
error_node(d->names.e[0], "Missing type or initial expression");
|
||||
return false;
|
||||
}
|
||||
} else if (lhs < rhs) {
|
||||
if (lhs < s->values.count) {
|
||||
AstNode *n = s->values.e[lhs];
|
||||
if (lhs < d->values.count) {
|
||||
AstNode *n = d->values.e[lhs];
|
||||
gbString str = expr_to_string(n);
|
||||
error_node(n, "Extra initial expression `%s`", str);
|
||||
gb_string_free(str);
|
||||
} else {
|
||||
error_node(s->names.e[0], "Extra initial expression");
|
||||
error_node(d->names.e[0], "Extra initial expression");
|
||||
}
|
||||
return false;
|
||||
} else if (lhs > rhs && (init != NULL || rhs != 1)) {
|
||||
AstNode *n = s->names.e[rhs];
|
||||
} else if (lhs > rhs && rhs != 1) {
|
||||
AstNode *n = d->names.e[rhs];
|
||||
gbString str = expr_to_string(n);
|
||||
error_node(n, "Missing expression for `%s`", str);
|
||||
gb_string_free(str);
|
||||
@@ -1160,15 +1157,95 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
||||
switch (decl->kind) {
|
||||
case_ast_node(bd, BadDecl, decl);
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, decl);
|
||||
if (vd->is_var) {
|
||||
// NOTE(bill): You need to store the entity information here unline a constant declaration
|
||||
isize entity_count = vd->names.count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
DeclInfo *di = NULL;
|
||||
if (vd->values.count > 0) {
|
||||
di = make_declaration_info(heap_allocator(), parent_scope);
|
||||
di->entities = entities;
|
||||
di->entity_count = entity_count;
|
||||
di->type_expr = vd->type;
|
||||
di->init_expr = vd->values.e[0];
|
||||
}
|
||||
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
AstNode *value = NULL;
|
||||
if (i < vd->values.count) {
|
||||
value = vd->values.e[i];
|
||||
}
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL);
|
||||
e->identifier = name;
|
||||
entities[entity_index++] = e;
|
||||
|
||||
DeclInfo *d = di;
|
||||
if (d == NULL) {
|
||||
AstNode *init_expr = value;
|
||||
d = make_declaration_info(heap_allocator(), e->scope);
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = init_expr;
|
||||
d->var_decl_tags = vd->tags;
|
||||
}
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
check_arity_match(c, vd);
|
||||
} else {
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
AstNode *init = NULL;
|
||||
if (i < vd->values.count) {
|
||||
init = vd->values.e[i];
|
||||
}
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, parent_scope);
|
||||
Entity *e = NULL;
|
||||
|
||||
AstNode *up_init = unparen_expr(init);
|
||||
if (init != NULL && is_ast_node_type(up_init)) {
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
d->type_expr = init;
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0});
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = init;
|
||||
}
|
||||
GB_ASSERT(e != NULL);
|
||||
e->identifier = name;
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
check_arity_match(c, vd);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, decl);
|
||||
if (!parent_scope->is_file) {
|
||||
// NOTE(bill): Within a procedure, variables must be in order
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNodeValueSpec empty_spec_ = {0}, *empty_spec = &empty_spec_;
|
||||
AstNodeValueSpec *prev_spec = NULL;
|
||||
|
||||
for_array(iota, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[iota];
|
||||
switch (spec->kind) {
|
||||
@@ -1183,99 +1260,6 @@ void check_global_collect_entities_from_file(Checker *c, Scope *parent_scope, As
|
||||
DelayedDecl di = {parent_scope, spec};
|
||||
array_add(&c->delayed_imports, di);
|
||||
case_end;
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
case Token_var: {
|
||||
// NOTE(bill): You need to store the entity information here unline a constant declaration
|
||||
isize entity_count = vs->names.count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
DeclInfo *di = NULL;
|
||||
if (vs->values.count > 0) {
|
||||
di = make_declaration_info(heap_allocator(), parent_scope);
|
||||
di->entities = entities;
|
||||
di->entity_count = entity_count;
|
||||
di->type_expr = vs->type;
|
||||
di->init_expr = vs->values.e[0];
|
||||
}
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
AstNode *value = NULL;
|
||||
if (i < vs->values.count) {
|
||||
value = vs->values.e[i];
|
||||
}
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
Entity *e = make_entity_variable(c->allocator, parent_scope, name->Ident, NULL);
|
||||
e->identifier = name;
|
||||
entities[entity_index++] = e;
|
||||
|
||||
DeclInfo *d = di;
|
||||
if (d == NULL) {
|
||||
AstNode *init_expr = value;
|
||||
d = make_declaration_info(heap_allocator(), e->scope);
|
||||
d->type_expr = vs->type;
|
||||
d->init_expr = init_expr;
|
||||
d->var_decl_tags = gd->tags;
|
||||
}
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
check_arity_match(c, vs, NULL);
|
||||
} break;
|
||||
|
||||
case Token_const: {
|
||||
if (vs->type != NULL || vs->values.count > 0) {
|
||||
prev_spec = vs;
|
||||
} else if (prev_spec == NULL) {
|
||||
prev_spec = empty_spec;
|
||||
}
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
AstNode *init = NULL;
|
||||
if (i < prev_spec->values.count) {
|
||||
init = prev_spec->values.e[i];
|
||||
}
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, parent_scope);
|
||||
Entity *e = NULL;
|
||||
|
||||
ExactValue v_iota = make_exact_value_integer(iota);
|
||||
|
||||
AstNode *up_init = unparen_expr(init);
|
||||
if (init != NULL && is_ast_node_type(up_init)) {
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
d->type_expr = init;
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, v_iota);
|
||||
d->type_expr = prev_spec->type;
|
||||
d->init_expr = init;
|
||||
}
|
||||
GB_ASSERT(e != NULL);
|
||||
e->identifier = name;
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
}
|
||||
|
||||
check_arity_match(c, vs, prev_spec);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(ts, TypeSpec, spec);
|
||||
if (ts->name->kind != AstNode_Ident) {
|
||||
|
||||
+11
-11
@@ -107,14 +107,14 @@ void check_init_variables(Checker *c, Entity **lhs, isize lhs_count, AstNodeArra
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
|
||||
void check_var_spec_node(Checker *c, AstNodeValueSpec *vs) {
|
||||
GB_ASSERT(vs->keyword == Token_var);
|
||||
isize entity_count = vs->names.count;
|
||||
void check_var_decl_node(Checker *c, AstNodeValueDecl *vd) {
|
||||
GB_ASSERT(vd->is_var == true);
|
||||
isize entity_count = vd->names.count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
Entity *entity = NULL;
|
||||
if (name->kind == AstNode_Ident) {
|
||||
Token token = name->Ident;
|
||||
@@ -145,8 +145,8 @@ void check_var_spec_node(Checker *c, AstNodeValueSpec *vs) {
|
||||
}
|
||||
|
||||
Type *init_type = NULL;
|
||||
if (vs->type) {
|
||||
init_type = check_type_extra(c, vs->type, NULL);
|
||||
if (vd->type) {
|
||||
init_type = check_type_extra(c, vd->type, NULL);
|
||||
if (init_type == NULL) {
|
||||
init_type = t_invalid;
|
||||
}
|
||||
@@ -165,12 +165,12 @@ void check_var_spec_node(Checker *c, AstNodeValueSpec *vs) {
|
||||
e->type = init_type;
|
||||
}
|
||||
|
||||
check_arity_match(c, vs, NULL);
|
||||
check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
|
||||
check_arity_match(c, vd);
|
||||
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
|
||||
|
||||
for_array(i, vs->names) {
|
||||
for_array(i, vd->names) {
|
||||
if (entities[i] != NULL) {
|
||||
add_entity(c, c->context.scope, vs->names.e[i], entities[i]);
|
||||
add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+46
-59
@@ -85,71 +85,58 @@ void check_local_collect_entities(Checker *c, AstNodeArray nodes, DelayedEntitie
|
||||
case_ast_node(ws, WhenStmt, node);
|
||||
// Will be handled later
|
||||
case_end;
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
AstNodeValueSpec empty_spec_ = {0}, *empty_spec = &empty_spec_;
|
||||
AstNodeValueSpec *last = NULL;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
// NOTE(bill): Handled later
|
||||
} else {
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *init = NULL;
|
||||
if (i < vd->values.count) {
|
||||
init = vd->values.e[i];
|
||||
}
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope);
|
||||
Entity *e = NULL;
|
||||
|
||||
AstNode *up_init = unparen_expr(init);
|
||||
if (init != NULL && is_ast_node_type(up_init)) {
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
d->type_expr = init;
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, (ExactValue){0});
|
||||
d->type_expr = vd->type;
|
||||
d->init_expr = init;
|
||||
}
|
||||
GB_ASSERT(e != NULL);
|
||||
e->identifier = name;
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
|
||||
DelayedEntity delay = {name, e, d};
|
||||
array_add(delayed_entities, delay);
|
||||
}
|
||||
|
||||
check_arity_match(c, vd);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
for_array(iota, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[iota];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
case Token_var:
|
||||
break;
|
||||
|
||||
case Token_const: {
|
||||
if (vs->type != NULL || vs->values.count > 0) {
|
||||
last = vs;
|
||||
} else if (last == NULL) {
|
||||
last = empty_spec;
|
||||
}
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
if (name->kind != AstNode_Ident) {
|
||||
error_node(name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[name->kind]));
|
||||
continue;
|
||||
}
|
||||
|
||||
AstNode *init = NULL;
|
||||
if (i < vs->values.count) {
|
||||
init = vs->values.e[i];
|
||||
}
|
||||
|
||||
DeclInfo *d = make_declaration_info(c->allocator, c->context.scope);
|
||||
Entity *e = NULL;
|
||||
|
||||
ExactValue v_iota = make_exact_value_integer(iota);
|
||||
|
||||
AstNode *up_init = unparen_expr(init);
|
||||
if (init != NULL && is_ast_node_type(up_init)) {
|
||||
e = make_entity_type_name(c->allocator, d->scope, name->Ident, NULL);
|
||||
d->type_expr = init;
|
||||
d->init_expr = init;
|
||||
} else if (init != NULL && up_init->kind == AstNode_ProcLit) {
|
||||
e = make_entity_procedure(c->allocator, d->scope, name->Ident, NULL, up_init->ProcLit.tags);
|
||||
d->proc_decl = init;
|
||||
} else {
|
||||
e = make_entity_constant(c->allocator, d->scope, name->Ident, NULL, v_iota);
|
||||
d->type_expr = vs->type;
|
||||
d->init_expr = init;
|
||||
}
|
||||
GB_ASSERT(e != NULL);
|
||||
e->identifier = name;
|
||||
|
||||
add_entity_and_decl_info(c, name, e, d);
|
||||
|
||||
DelayedEntity delay = {name, e, d};
|
||||
array_add(delayed_entities, delay);
|
||||
}
|
||||
|
||||
check_arity_match(c, vs, last);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(ts, TypeSpec, spec);
|
||||
if (ts->name->kind != AstNode_Ident) {
|
||||
error_node(ts->name, "A declaration's name must be an identifier, got %.*s", LIT(ast_node_strings[ts->name->kind]));
|
||||
|
||||
+102
-111
@@ -1026,48 +1026,45 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, us->node);
|
||||
for_array(spec_index, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[spec_index];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
if (vs->keyword != Token_var) {
|
||||
error_node(spec, "`using` can only be applied to a variable declaration");
|
||||
return;
|
||||
}
|
||||
case_ast_node(vd, ValueDecl, us->node);
|
||||
if (!vd->is_var) {
|
||||
error_node(us->node, "`using` can only be applied to a variable declaration");
|
||||
return;
|
||||
}
|
||||
|
||||
if (vs->names.count > 1 && vs->type != NULL) {
|
||||
error(us->token, "`using` can only be applied to one variable of the same type");
|
||||
}
|
||||
if (vd->names.count > 1 && vd->type != NULL) {
|
||||
error(us->token, "`using` can only be applied to one variable of the same type");
|
||||
}
|
||||
|
||||
check_var_spec_node(c, vs);
|
||||
check_var_decl_node(c, vd);
|
||||
|
||||
for_array(name_index, vs->names) {
|
||||
AstNode *item = vs->names.e[name_index];
|
||||
ast_node(i, Ident, item);
|
||||
String name = i->string;
|
||||
Entity *e = scope_lookup_entity(c->context.scope, name);
|
||||
Type *t = base_type(type_deref(e->type));
|
||||
if (is_type_struct(t) || is_type_raw_union(t)) {
|
||||
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
|
||||
GB_ASSERT(found != NULL);
|
||||
for_array(i, (*found)->elements.entries) {
|
||||
Entity *f = (*found)->elements.entries.e[i].value;
|
||||
if (f->kind == Entity_Variable) {
|
||||
Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
|
||||
Entity *prev = scope_insert_entity(c->context.scope, uvar);
|
||||
if (prev != NULL) {
|
||||
error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
|
||||
return;
|
||||
}
|
||||
}
|
||||
for_array(name_index, vd->names) {
|
||||
AstNode *item = vd->names.e[name_index];
|
||||
if (item->kind != AstNode_Ident) {
|
||||
// TODO(bill): Handle error here???
|
||||
continue;
|
||||
}
|
||||
ast_node(i, Ident, item);
|
||||
String name = i->string;
|
||||
Entity *e = scope_lookup_entity(c->context.scope, name);
|
||||
Type *t = base_type(type_deref(e->type));
|
||||
if (is_type_struct(t) || is_type_raw_union(t)) {
|
||||
Scope **found = map_scope_get(&c->info.scopes, hash_pointer(t->Record.node));
|
||||
GB_ASSERT(found != NULL);
|
||||
for_array(i, (*found)->elements.entries) {
|
||||
Entity *f = (*found)->elements.entries.e[i].value;
|
||||
if (f->kind == Entity_Variable) {
|
||||
Entity *uvar = make_entity_using_variable(c->allocator, e, f->token, f->type);
|
||||
Entity *prev = scope_insert_entity(c->context.scope, uvar);
|
||||
if (prev != NULL) {
|
||||
error(us->token, "Namespace collision while `using` `%.*s` of: %.*s", LIT(name), LIT(prev->token.string));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
error(us->token, "`using` can only be applied to variables of type struct or raw_union");
|
||||
return;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
} else {
|
||||
error(us->token, "`using` can only be applied to variables of type struct or raw_union");
|
||||
return;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
@@ -1096,7 +1093,76 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
isize entity_count = vd->names.count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
Entity *entity = NULL;
|
||||
if (name->kind == AstNode_Ident) {
|
||||
Token token = name->Ident;
|
||||
String str = token.string;
|
||||
Entity *found = NULL;
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (str_ne(str, str_lit("_"))) {
|
||||
found = current_scope_lookup_entity(c->context.scope, str);
|
||||
}
|
||||
if (found == NULL) {
|
||||
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL);
|
||||
add_entity_definition(&c->info, name, entity);
|
||||
} else {
|
||||
TokenPos pos = found->token.pos;
|
||||
error(token,
|
||||
"Redeclaration of `%.*s` in this scope\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(str), LIT(pos.file), pos.line, pos.column);
|
||||
entity = found;
|
||||
}
|
||||
} else {
|
||||
error_node(name, "A variable declaration must be an identifier");
|
||||
}
|
||||
if (entity == NULL) {
|
||||
entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
|
||||
}
|
||||
entities[entity_index++] = entity;
|
||||
}
|
||||
|
||||
Type *init_type = NULL;
|
||||
if (vd->type) {
|
||||
init_type = check_type_extra(c, vd->type, NULL);
|
||||
if (init_type == NULL) {
|
||||
init_type = t_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < entity_count; i++) {
|
||||
Entity *e = entities[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
if (e->flags & EntityFlag_Visited) {
|
||||
e->type = t_invalid;
|
||||
continue;
|
||||
}
|
||||
e->flags |= EntityFlag_Visited;
|
||||
|
||||
if (e->type == NULL)
|
||||
e->type = init_type;
|
||||
}
|
||||
check_arity_match(c, vd);
|
||||
|
||||
check_init_variables(c, entities, entity_count, vd->values, str_lit("variable declaration"));
|
||||
|
||||
for_array(i, vd->names) {
|
||||
if (entities[i] != NULL) {
|
||||
add_entity(c, c->context.scope, vd->names.e[i], entities[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// NOTE(bill): Handled elsewhere
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
for_array(spec_index, gd->specs) {
|
||||
@@ -1104,81 +1170,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
||||
switch (spec->kind) {
|
||||
case_ast_node(bd, BadDecl, spec);
|
||||
case_end;
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
case Token_var: {
|
||||
isize entity_count = vs->names.count;
|
||||
isize entity_index = 0;
|
||||
Entity **entities = gb_alloc_array(c->allocator, Entity *, entity_count);
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
Entity *entity = NULL;
|
||||
if (name->kind == AstNode_Ident) {
|
||||
Token token = name->Ident;
|
||||
String str = token.string;
|
||||
Entity *found = NULL;
|
||||
// NOTE(bill): Ignore assignments to `_`
|
||||
if (str_ne(str, str_lit("_"))) {
|
||||
found = current_scope_lookup_entity(c->context.scope, str);
|
||||
}
|
||||
if (found == NULL) {
|
||||
entity = make_entity_variable(c->allocator, c->context.scope, token, NULL);
|
||||
add_entity_definition(&c->info, name, entity);
|
||||
} else {
|
||||
TokenPos pos = found->token.pos;
|
||||
error(token,
|
||||
"Redeclaration of `%.*s` in this scope\n"
|
||||
"\tat %.*s(%td:%td)",
|
||||
LIT(str), LIT(pos.file), pos.line, pos.column);
|
||||
entity = found;
|
||||
}
|
||||
} else {
|
||||
error_node(name, "A variable declaration must be an identifier");
|
||||
}
|
||||
if (entity == NULL) {
|
||||
entity = make_entity_dummy_variable(c->allocator, c->global_scope, ast_node_token(name));
|
||||
}
|
||||
entities[entity_index++] = entity;
|
||||
}
|
||||
|
||||
Type *init_type = NULL;
|
||||
if (vs->type) {
|
||||
init_type = check_type_extra(c, vs->type, NULL);
|
||||
if (init_type == NULL) {
|
||||
init_type = t_invalid;
|
||||
}
|
||||
}
|
||||
|
||||
for (isize i = 0; i < entity_count; i++) {
|
||||
Entity *e = entities[i];
|
||||
GB_ASSERT(e != NULL);
|
||||
if (e->flags & EntityFlag_Visited) {
|
||||
e->type = t_invalid;
|
||||
continue;
|
||||
}
|
||||
e->flags |= EntityFlag_Visited;
|
||||
|
||||
if (e->type == NULL)
|
||||
e->type = init_type;
|
||||
}
|
||||
check_arity_match(c, vs, NULL);
|
||||
|
||||
check_init_variables(c, entities, entity_count, vs->values, str_lit("variable declaration"));
|
||||
|
||||
for_array(i, vs->names) {
|
||||
if (entities[i] != NULL) {
|
||||
add_entity(c, c->context.scope, vs->names.e[i], entities[i]);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case Token_const:
|
||||
// NOTE(bill): Handled elsewhere
|
||||
break;
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(ts, TypeSpec, spec);
|
||||
// NOTE(bill): Handled elsewhere
|
||||
case_end;
|
||||
|
||||
+117
-67
@@ -251,12 +251,6 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
||||
AST_NODE_KIND(_ComplexStmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_StmtEnd, "", i32) \
|
||||
AST_NODE_KIND(_SpecBegin, "", i32) \
|
||||
AST_NODE_KIND(ValueSpec, "value specification", struct { \
|
||||
TokenKind keyword; \
|
||||
AstNodeArray names; \
|
||||
AstNode * type; \
|
||||
AstNodeArray values; \
|
||||
}) \
|
||||
AST_NODE_KIND(TypeSpec, "type specification", struct { \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
@@ -280,6 +274,13 @@ AST_NODE_KIND(_DeclBegin, "", i32) \
|
||||
u64 tags; \
|
||||
bool is_using; \
|
||||
}) \
|
||||
AST_NODE_KIND(ValueDecl, "value declaration", struct { \
|
||||
bool is_var; \
|
||||
AstNodeArray names; \
|
||||
AstNode * type; \
|
||||
AstNodeArray values; \
|
||||
u64 tags; \
|
||||
}) \
|
||||
AST_NODE_KIND(ProcDecl, "procedure declaration", struct { \
|
||||
AstNode *name; \
|
||||
AstNode *type; \
|
||||
@@ -498,14 +499,14 @@ Token ast_node_token(AstNode *node) {
|
||||
return node->BadDecl.begin;
|
||||
case AstNode_GenericDecl:
|
||||
return node->GenericDecl.token;
|
||||
case AstNode_ValueDecl:
|
||||
return ast_node_token(node->ValueDecl.names.e[0]);
|
||||
case AstNode_ProcDecl:
|
||||
return ast_node_token(node->ProcDecl.name);
|
||||
|
||||
case AstNode_ForeignLibrary:
|
||||
return node->ForeignLibrary.token;
|
||||
|
||||
case AstNode_ValueSpec:
|
||||
return ast_node_token(node->ValueSpec.names.e[0]);
|
||||
case AstNode_TypeSpec:
|
||||
return ast_node_token(node->TypeSpec.name);
|
||||
case AstNode_ImportSpec:
|
||||
@@ -1076,12 +1077,12 @@ AstNode *make_generic_decl(AstFile *f, Token token, Token open, Token close, Ast
|
||||
return result;
|
||||
}
|
||||
|
||||
AstNode *make_value_spec(AstFile *f, TokenKind keyword, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
||||
AstNode *result = make_node(f, AstNode_ValueSpec);
|
||||
result->ValueSpec.keyword = keyword;
|
||||
result->ValueSpec.names = names;
|
||||
result->ValueSpec.type = type;
|
||||
result->ValueSpec.values = values;
|
||||
AstNode *make_value_decl(AstFile *f, bool is_var, AstNodeArray names, AstNode *type, AstNodeArray values) {
|
||||
AstNode *result = make_node(f, AstNode_ValueDecl);
|
||||
result->ValueDecl.is_var = is_var;
|
||||
result->ValueDecl.names = names;
|
||||
result->ValueDecl.type = type;
|
||||
result->ValueDecl.values = values;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1210,8 +1211,8 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
||||
case Token_Semicolon:
|
||||
return;
|
||||
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
// case Token_var:
|
||||
// case Token_const:
|
||||
case Token_type:
|
||||
case Token_proc:
|
||||
case Token_import:
|
||||
@@ -2139,42 +2140,42 @@ AstNode *parse_generic_decl(AstFile *f, TokenKind keyword, ParserSpecProc spec_p
|
||||
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};
|
||||
// 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 (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");
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// // 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);
|
||||
}
|
||||
// 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);
|
||||
@@ -2239,9 +2240,9 @@ PARSE_SPEC_PROC(parse_include_spec) {
|
||||
|
||||
AstNode *parse_decl(AstFile *f) {
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
return parse_generic_decl(f, f->curr_token.kind, parse_value_spec);
|
||||
// case Token_var:
|
||||
// case Token_const:
|
||||
// return parse_generic_decl(f, f->curr_token.kind, parse_value_spec);
|
||||
|
||||
case Token_type:
|
||||
return parse_generic_decl(f, f->curr_token.kind, parse_type_spec);
|
||||
@@ -2266,12 +2267,7 @@ AstNode *parse_decl(AstFile *f) {
|
||||
|
||||
|
||||
AstNode *parse_simple_stmt(AstFile *f) {
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
return parse_decl(f);
|
||||
}
|
||||
|
||||
Token start_token = f->curr_token;
|
||||
AstNodeArray lhs = parse_lhs_expr_list(f);
|
||||
Token token = f->curr_token;
|
||||
switch (token.kind) {
|
||||
@@ -2302,6 +2298,61 @@ AstNode *parse_simple_stmt(AstFile *f) {
|
||||
}
|
||||
return make_assign_stmt(f, token, lhs, rhs);
|
||||
} break;
|
||||
|
||||
case Token_Colon: {
|
||||
parse_check_name_list_for_reserves(f, lhs);
|
||||
|
||||
AstNode *type = NULL;
|
||||
AstNodeArray values = {0};
|
||||
bool is_mutable = true;
|
||||
|
||||
if (allow_token(f, Token_Colon)) {
|
||||
if (!allow_token(f, Token_type)) {
|
||||
type = parse_type_attempt(f);
|
||||
}
|
||||
} else if (f->curr_token.kind != Token_Eq &&
|
||||
f->curr_token.kind != Token_Semicolon) {
|
||||
syntax_error(f->curr_token, "Expected a type separator `:` or `=`");
|
||||
}
|
||||
|
||||
|
||||
switch (f->curr_token.kind) {
|
||||
case Token_Colon:
|
||||
is_mutable = false;
|
||||
/*fallthrough*/
|
||||
case Token_Eq:
|
||||
next_token(f);
|
||||
values = parse_rhs_expr_list(f);
|
||||
if (values.count > lhs.count) {
|
||||
syntax_error(f->curr_token, "Too many values on the right hand side of the declaration");
|
||||
} else if (values.count < lhs.count && !is_mutable) {
|
||||
syntax_error(f->curr_token, "All constant declarations must be defined");
|
||||
} else if (values.count == 0) {
|
||||
syntax_error(f->curr_token, "Expected an expression for this declaration");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_mutable) {
|
||||
if (type == NULL && values.count == 0) {
|
||||
syntax_error(f->curr_token, "Missing variable type or initialization");
|
||||
return make_bad_decl(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
} else {
|
||||
if (type == NULL && values.count == 0 && lhs.count > 0) {
|
||||
syntax_error(f->curr_token, "Missing constant value");
|
||||
return make_bad_decl(f, f->curr_token, f->curr_token);
|
||||
}
|
||||
}
|
||||
|
||||
if (values.e == NULL) {
|
||||
values = make_ast_node_array(f);
|
||||
}
|
||||
|
||||
AstNodeArray specs = {0};
|
||||
array_init_reserve(&specs, heap_allocator(), 1);
|
||||
return make_value_decl(f, is_mutable, lhs, type, values);
|
||||
} break;
|
||||
}
|
||||
|
||||
if (lhs.count > 1) {
|
||||
@@ -3025,8 +3076,8 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
expect_semicolon(f, s);
|
||||
return s;
|
||||
|
||||
case Token_var:
|
||||
case Token_const:
|
||||
// case Token_var:
|
||||
// case Token_const:
|
||||
case Token_proc:
|
||||
case Token_type:
|
||||
case Token_import:
|
||||
@@ -3063,14 +3114,12 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
while (e->kind == AstNode_SelectorExpr) {
|
||||
e = unparen_expr(e->SelectorExpr.selector);
|
||||
}
|
||||
if (e->kind == AstNode_Ident) {
|
||||
if (e->kind == AstNode_Ident) {
|
||||
valid = true;
|
||||
}
|
||||
} break;
|
||||
case AstNode_GenericDecl:
|
||||
if (node->GenericDecl.token.kind == Token_var) {
|
||||
valid = true;
|
||||
}
|
||||
case AstNode_ValueDecl:
|
||||
valid = node->ValueDecl.is_var;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -3153,8 +3202,8 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
return s;
|
||||
} else if (str_eq(tag, str_lit("thread_local"))) {
|
||||
AstNode *decl = parse_simple_stmt(f);
|
||||
if (decl->kind == AstNode_GenericDecl &&
|
||||
decl->GenericDecl.token.kind != Token_var) {
|
||||
if (decl->kind != AstNode_ValueDecl &&
|
||||
!decl->ValueDecl.is_var) {
|
||||
syntax_error(token, "#thread_local may only be applied to variable declarations");
|
||||
return make_bad_decl(f, token, ast_node_token(decl));
|
||||
}
|
||||
@@ -3162,8 +3211,9 @@ AstNode *parse_stmt(AstFile *f) {
|
||||
syntax_error(token, "#thread_local is only allowed at the file scope");
|
||||
return make_bad_decl(f, token, ast_node_token(decl));
|
||||
}
|
||||
GB_ASSERT(decl->kind == AstNode_GenericDecl);
|
||||
decl->GenericDecl.tags |= VarDeclTag_thread_local;
|
||||
|
||||
GB_ASSERT(decl->kind == AstNode_ValueDecl);
|
||||
decl->ValueDecl.tags |= VarDeclTag_thread_local;
|
||||
return decl;
|
||||
} else if (str_eq(tag, str_lit("bounds_check"))) {
|
||||
s = parse_stmt(f);
|
||||
|
||||
@@ -3924,71 +3924,67 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
|
||||
ssa_build_when_stmt(proc, ws);
|
||||
case_end;
|
||||
|
||||
case_ast_node(vd, ValueDecl, node);
|
||||
if (vd->is_var) {
|
||||
ssaModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
|
||||
if (vd->values.count == 0) { // declared and zero-initialized
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
if (!ssa_is_blank_ident(name)) {
|
||||
ssa_add_local_for_identifier(proc, name, true);
|
||||
}
|
||||
}
|
||||
} else { // Tuple(s)
|
||||
Array(ssaAddr) lvals;
|
||||
ssaValueArray inits;
|
||||
array_init_reserve(&lvals, m->tmp_allocator, vd->names.count);
|
||||
array_init_reserve(&inits, m->tmp_allocator, vd->names.count);
|
||||
|
||||
for_array(i, vd->names) {
|
||||
AstNode *name = vd->names.e[i];
|
||||
ssaAddr lval = ssa_make_addr(NULL, NULL);
|
||||
if (!ssa_is_blank_ident(name)) {
|
||||
ssa_add_local_for_identifier(proc, name, false);
|
||||
lval = ssa_build_addr(proc, name);
|
||||
}
|
||||
|
||||
array_add(&lvals, lval);
|
||||
}
|
||||
|
||||
for_array(i, vd->values) {
|
||||
ssaValue *init = ssa_build_expr(proc, vd->values.e[i]);
|
||||
Type *t = ssa_type(init);
|
||||
if (t->kind == Type_Tuple) {
|
||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||
Entity *e = t->Tuple.variables[i];
|
||||
ssaValue *v = ssa_emit_struct_ev(proc, init, i);
|
||||
array_add(&inits, v);
|
||||
}
|
||||
} else {
|
||||
array_add(&inits, init);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for_array(i, inits) {
|
||||
if (lvals.e[i].addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
ssaValue *v = ssa_emit_conv(proc, inits.e[i], ssa_addr_type(lvals.e[i]));
|
||||
ssa_addr_store(proc, lvals.e[i], v);
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
}
|
||||
case_end;
|
||||
|
||||
case_ast_node(gd, GenericDecl, node);
|
||||
for_array(spec_index, gd->specs) {
|
||||
AstNode *spec = gd->specs.e[spec_index];
|
||||
switch (spec->kind) {
|
||||
case_ast_node(vs, ValueSpec, spec);
|
||||
switch (vs->keyword) {
|
||||
case Token_const:
|
||||
break;
|
||||
case Token_var: {
|
||||
ssaModule *m = proc->module;
|
||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&m->tmp_arena);
|
||||
|
||||
if (vs->values.count == 0) { // declared and zero-initialized
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
if (!ssa_is_blank_ident(name)) {
|
||||
ssa_add_local_for_identifier(proc, name, true);
|
||||
}
|
||||
}
|
||||
} else { // Tuple(s)
|
||||
Array(ssaAddr) lvals;
|
||||
ssaValueArray inits;
|
||||
array_init_reserve(&lvals, m->tmp_allocator, vs->names.count);
|
||||
array_init_reserve(&inits, m->tmp_allocator, vs->names.count);
|
||||
|
||||
for_array(i, vs->names) {
|
||||
AstNode *name = vs->names.e[i];
|
||||
ssaAddr lval = ssa_make_addr(NULL, NULL);
|
||||
if (!ssa_is_blank_ident(name)) {
|
||||
ssa_add_local_for_identifier(proc, name, false);
|
||||
lval = ssa_build_addr(proc, name);
|
||||
}
|
||||
|
||||
array_add(&lvals, lval);
|
||||
}
|
||||
|
||||
for_array(i, vs->values) {
|
||||
ssaValue *init = ssa_build_expr(proc, vs->values.e[i]);
|
||||
Type *t = ssa_type(init);
|
||||
if (t->kind == Type_Tuple) {
|
||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||
Entity *e = t->Tuple.variables[i];
|
||||
ssaValue *v = ssa_emit_struct_ev(proc, init, i);
|
||||
array_add(&inits, v);
|
||||
}
|
||||
} else {
|
||||
array_add(&inits, init);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for_array(i, inits) {
|
||||
if (lvals.e[i].addr == NULL) {
|
||||
continue;
|
||||
}
|
||||
ssaValue *v = ssa_emit_conv(proc, inits.e[i], ssa_addr_type(lvals.e[i]));
|
||||
ssa_addr_store(proc, lvals.e[i], v);
|
||||
}
|
||||
}
|
||||
|
||||
gb_temp_arena_memory_end(tmp);
|
||||
} break;
|
||||
}
|
||||
case_end;
|
||||
case_ast_node(ts, TypeSpec, spec);
|
||||
// NOTE(bill): Generate a new name
|
||||
// parent_proc.name-guid
|
||||
|
||||
+2
-2
@@ -84,8 +84,8 @@ TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||
TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
||||
TOKEN_KIND(Token_type, "type"), \
|
||||
TOKEN_KIND(Token_proc, "proc"), \
|
||||
TOKEN_KIND(Token_var, "var"), \
|
||||
TOKEN_KIND(Token_const, "const"), \
|
||||
/* TOKEN_KIND(Token_var, "var"), */\
|
||||
/* TOKEN_KIND(Token_const, "const"), */\
|
||||
TOKEN_KIND(Token_import, "import"), \
|
||||
TOKEN_KIND(Token_include, "include"), \
|
||||
TOKEN_KIND(Token_macro, "macro"), \
|
||||
|
||||
Reference in New Issue
Block a user