mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
while; range is now for; remove ++ and --
This commit is contained in:
+4
-4
@@ -21,13 +21,13 @@ main :: proc() {
|
|||||||
msg := "Hellope";
|
msg := "Hellope";
|
||||||
list := []int{1, 4, 7, 3, 7, 2, 1};
|
list := []int{1, 4, 7, 3, 7, 2, 1};
|
||||||
|
|
||||||
range value : msg {
|
for value : msg {
|
||||||
fmt.println(value);
|
fmt.println(value);
|
||||||
}
|
}
|
||||||
range value : list {
|
for value : list {
|
||||||
fmt.println(value);
|
fmt.println(value);
|
||||||
}
|
}
|
||||||
range x : 0 ..< 5 {
|
for val, idx : 12 ..< 17 {
|
||||||
fmt.println(x);
|
fmt.println(val, idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -313,19 +313,19 @@ __bounds_check_error :: proc(file: string, line, column: int, index, count: int)
|
|||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|
||||||
__slice_expr_error :: proc(file: string, line, column: int, low, high, max: int) {
|
__slice_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
||||||
if 0 <= low && low <= high && high <= max {
|
if 0 <= low && low <= high {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fmt.fprintf(os.stderr, "%(%:%) Invalid slice indices: [%:%:%]\n",
|
fmt.fprintf(os.stderr, "%(%:%) Invalid slice indices: [%:%]\n",
|
||||||
file, line, column, low, high, max);
|
file, line, column, low, high);
|
||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
__substring_expr_error :: proc(file: string, line, column: int, low, high: int) {
|
||||||
if 0 <= low && low <= high {
|
if 0 <= low && low <= high {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fmt.fprintf(os.stderr, "%(%:%) Invalid substring indices: [%:%:%]\n",
|
fmt.fprintf(os.stderr, "%(%:%) Invalid substring indices: [%:%]\n",
|
||||||
file, line, column, low, high);
|
file, line, column, low, high);
|
||||||
__debug_trap();
|
__debug_trap();
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -37,8 +37,8 @@ fetch_or32 :: proc(a: ^i32, operand: i32) -> i32 {
|
|||||||
spin_lock32 :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock32 :: proc(a: ^i32, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange32(a, 1, 0);
|
old_value := compare_exchange32(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
while old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
counter++;
|
counter += 1;
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value = compare_exchange32(a, 1, 0);
|
old_value = compare_exchange32(a, 1, 0);
|
||||||
mfence();
|
mfence();
|
||||||
@@ -81,8 +81,8 @@ fetch_or64 :: proc(a: ^i64, operand: i64) -> i64 {
|
|||||||
spin_lock64 :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
spin_lock64 :: proc(a: ^i64, time_out: int) -> bool { // NOTE(bill) time_out = -1 as default
|
||||||
old_value := compare_exchange64(a, 1, 0);
|
old_value := compare_exchange64(a, 1, 0);
|
||||||
counter := 0;
|
counter := 0;
|
||||||
for old_value != 0 && (time_out < 0 || counter < time_out) {
|
while old_value != 0 && (time_out < 0 || counter < time_out) {
|
||||||
counter++;
|
counter += 1;
|
||||||
yield_thread();
|
yield_thread();
|
||||||
old_value = compare_exchange64(a, 1, 0);
|
old_value = compare_exchange64(a, 1, 0);
|
||||||
mfence();
|
mfence();
|
||||||
|
|||||||
+95
-90
@@ -4,84 +4,90 @@
|
|||||||
|
|
||||||
PRINT_BUF_SIZE :: 1<<12;
|
PRINT_BUF_SIZE :: 1<<12;
|
||||||
|
|
||||||
fprint :: proc(fd: os.Handle, args: ..any) -> int {
|
Buffer :: struct {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: []byte;
|
||||||
buf := data[:0];
|
length: int;
|
||||||
bprint(^buf, ..args);
|
|
||||||
os.write(fd, buf);
|
|
||||||
return buf.count;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintln :: proc(fd: os.Handle, args: ..any) -> int {
|
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
|
||||||
buf := data[:0];
|
|
||||||
bprintln(^buf, ..args);
|
|
||||||
os.write(fd, buf);
|
|
||||||
return buf.count;
|
|
||||||
}
|
|
||||||
fprintf :: proc(fd: os.Handle, fmt: string, args: ..any) -> int {
|
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
|
||||||
buf := data[:0];
|
|
||||||
bprintf(^buf, fmt, ..args);
|
|
||||||
os.write(fd, buf);
|
|
||||||
return buf.count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print :: proc(args: ..any) -> int {
|
fprint :: proc(fd: os.Handle, args: ...any) -> int {
|
||||||
return fprint(os.stdout, ..args);
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
|
buf := Buffer{data[:], 0};
|
||||||
|
bprint(^buf, ...args);
|
||||||
|
os.write(fd, buf.data[:buf.length]);
|
||||||
|
return buf.length;
|
||||||
}
|
}
|
||||||
println :: proc(args: ..any) -> int {
|
|
||||||
return fprintln(os.stdout, ..args);
|
fprintln :: proc(fd: os.Handle, args: ...any) -> int {
|
||||||
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
|
buf := Buffer{data[:], 0};
|
||||||
|
bprintln(^buf, ...args);
|
||||||
|
os.write(fd, buf.data[:buf.length]);
|
||||||
|
return buf.length;
|
||||||
}
|
}
|
||||||
printf :: proc(fmt: string, args: ..any) -> int {
|
fprintf :: proc(fd: os.Handle, fmt: string, args: ...any) -> int {
|
||||||
return fprintf(os.stdout, fmt, ..args);
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
|
buf := Buffer{data[:], 0};
|
||||||
|
bprintf(^buf, fmt, ...args);
|
||||||
|
os.write(fd, buf.data[:buf.length]);
|
||||||
|
return buf.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
print :: proc(args: ...any) -> int {
|
||||||
|
return fprint(os.stdout, ...args);
|
||||||
|
}
|
||||||
|
println :: proc(args: ...any) -> int {
|
||||||
|
return fprintln(os.stdout, ...args);
|
||||||
|
}
|
||||||
|
printf :: proc(fmt: string, args: ...any) -> int {
|
||||||
|
return fprintf(os.stdout, fmt, ...args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
|
fprint_type :: proc(fd: os.Handle, info: ^Type_Info) {
|
||||||
data: [PRINT_BUF_SIZE]byte;
|
data: [PRINT_BUF_SIZE]byte;
|
||||||
buf := data[:0];
|
buf := Buffer{data[:], 0};
|
||||||
bprint_type(^buf, info);
|
bprint_type(^buf, info);
|
||||||
os.write(fd, buf);
|
os.write(fd, buf.data[:buf.length]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print_byte_buffer :: proc(buf: ^[]byte, b: []byte) {
|
print_byte_buffer :: proc(buf: ^Buffer, b: []byte) {
|
||||||
if buf.count < buf.capacity {
|
if buf.length < buf.data.count {
|
||||||
n := min(buf.capacity-buf.count, b.count);
|
n := min(buf.data.count-buf.length, b.count);
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
mem.copy(buf.data + buf.count, b.data, n);
|
copy(buf.data[buf.length:], b[:n]);
|
||||||
buf.count += n;
|
buf.length += n;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_string :: proc(buf: ^[]byte, s: string) {
|
bprint_string :: proc(buf: ^Buffer, s: string) {
|
||||||
print_byte_buffer(buf, s as []byte);
|
print_byte_buffer(buf, s as []byte);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
byte_reverse :: proc(b: []byte) {
|
byte_reverse :: proc(b: []byte) {
|
||||||
n := b.count;
|
n := b.count;
|
||||||
for i := 0; i < n/2; i++ {
|
for i : 0..<n/2 {
|
||||||
b[i], b[n-1-i] = b[n-1-i], b[i];
|
b[i], b[n-1-i] = b[n-1-i], b[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_rune :: proc(buf: ^[]byte, r: rune) {
|
bprint_rune :: proc(buf: ^Buffer, r: rune) {
|
||||||
b, n := utf8.encode_rune(r);
|
b, n := utf8.encode_rune(r);
|
||||||
bprint_string(buf, b[:n] as string);
|
bprint_string(buf, b[:n] as string);
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_space :: proc(buf: ^[]byte) { bprint_rune(buf, ' '); }
|
bprint_space :: proc(buf: ^Buffer) { bprint_rune(buf, ' '); }
|
||||||
bprint_nl :: proc (buf: ^[]byte) { bprint_rune(buf, '\n'); }
|
bprint_nl :: proc (buf: ^Buffer) { bprint_rune(buf, '\n'); }
|
||||||
|
|
||||||
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
__NUM_TO_CHAR_TABLE := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$";
|
||||||
|
|
||||||
bprint_bool :: proc(buffer: ^[]byte, b: bool) {
|
bprint_bool :: proc(buffer: ^Buffer, b: bool) {
|
||||||
if b {
|
if b {
|
||||||
bprint_string(buffer, "true");
|
bprint_string(buffer, "true");
|
||||||
} else {
|
} else {
|
||||||
@@ -89,31 +95,31 @@ bprint_bool :: proc(buffer: ^[]byte, b: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_pointer :: proc(buffer: ^[]byte, p: rawptr) #inline {
|
bprint_pointer :: proc(buffer: ^Buffer, p: rawptr) #inline {
|
||||||
bprint_string(buffer, "0x");
|
bprint_string(buffer, "0x");
|
||||||
bprint_u64(buffer, p as uint as u64);
|
bprint_u64(buffer, p as uint as u64);
|
||||||
}
|
}
|
||||||
|
|
||||||
// bprint_f16 :: proc (buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 4); }
|
// bprint_f16 :: proc (buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 4); }
|
||||||
bprint_f32 :: proc (buffer: ^[]byte, f: f32) #inline { print__f64(buffer, f as f64, 7); }
|
bprint_f32 :: proc (buffer: ^Buffer, f: f32) #inline { print__f64(buffer, f as f64, 7); }
|
||||||
bprint_f64 :: proc (buffer: ^[]byte, f: f64) #inline { print__f64(buffer, f as f64, 16); }
|
bprint_f64 :: proc (buffer: ^Buffer, f: f64) #inline { print__f64(buffer, f as f64, 16); }
|
||||||
bprint_u64 :: proc(buffer: ^[]byte, value: u64) {
|
bprint_u64 :: proc(buffer: ^Buffer, value: u64) {
|
||||||
i := value;
|
i := value;
|
||||||
buf :[20]byte;
|
buf :[20]byte;
|
||||||
len := 0;
|
len := 0;
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
buf[len] = '0';
|
buf[len] = '0';
|
||||||
len++;
|
len += 1;
|
||||||
}
|
}
|
||||||
for i > 0 {
|
while i > 0 {
|
||||||
buf[len] = __NUM_TO_CHAR_TABLE[i % 10];
|
buf[len] = __NUM_TO_CHAR_TABLE[i % 10];
|
||||||
len++;
|
len += 1;
|
||||||
i /= 10;
|
i /= 10;
|
||||||
}
|
}
|
||||||
byte_reverse(buf[:len]);
|
byte_reverse(buf[:len]);
|
||||||
bprint_string(buffer, buf[:len] as string);
|
bprint_string(buffer, buf[:len] as string);
|
||||||
}
|
}
|
||||||
bprint_i64 :: proc(buffer: ^[]byte, value: i64) {
|
bprint_i64 :: proc(buffer: ^Buffer, value: i64) {
|
||||||
// TODO(bill): Cleanup printing
|
// TODO(bill): Cleanup printing
|
||||||
i := value;
|
i := value;
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
@@ -124,14 +130,14 @@ bprint_i64 :: proc(buffer: ^[]byte, value: i64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
bprint_u128 :: proc(buffer: ^[]byte, value u128) {
|
bprint_u128 :: proc(buffer: ^Buffer, value u128) {
|
||||||
a := value transmute [2]u64;
|
a := value transmute [2]u64;
|
||||||
if a[1] != 0 {
|
if a[1] != 0 {
|
||||||
bprint_u64(buffer, a[1]);
|
bprint_u64(buffer, a[1]);
|
||||||
}
|
}
|
||||||
bprint_u64(buffer, a[0]);
|
bprint_u64(buffer, a[0]);
|
||||||
}
|
}
|
||||||
bprint_i128 :: proc(buffer: ^[]byte, value i128) {
|
bprint_i128 :: proc(buffer: ^Buffer, value i128) {
|
||||||
i := value;
|
i := value;
|
||||||
if i < 0 {
|
if i < 0 {
|
||||||
i = -i;
|
i = -i;
|
||||||
@@ -142,7 +148,7 @@ bprint_i128 :: proc(buffer: ^[]byte, value i128) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
print__f64 :: proc(buffer: ^Buffer, value: f64, decimal_places: int) {
|
||||||
f := value;
|
f := value;
|
||||||
if f == 0 {
|
if f == 0 {
|
||||||
bprint_rune(buffer, '0');
|
bprint_rune(buffer, '0');
|
||||||
@@ -159,16 +165,17 @@ print__f64 :: proc(buffer: ^[]byte, value: f64, decimal_places: int) {
|
|||||||
|
|
||||||
bprint_rune(buffer, '.');
|
bprint_rune(buffer, '.');
|
||||||
|
|
||||||
mult :f64 = 10.0;
|
mult: f64 = 10.0;
|
||||||
for ; decimal_places >= 0; decimal_places-- {
|
while decimal_places >= 0 {
|
||||||
i = (f * mult) as u64;
|
i = (f * mult) as u64;
|
||||||
bprint_u64(buffer, i as u64);
|
bprint_u64(buffer, i as u64);
|
||||||
f -= i as f64 / mult;
|
f -= i as f64 / mult;
|
||||||
mult *= 10;
|
mult *= 10;
|
||||||
|
decimal_places -= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
bprint_type :: proc(buf: ^Buffer, ti: ^Type_Info) {
|
||||||
if ti == nil {
|
if ti == nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -224,7 +231,7 @@ bprint_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
case Tuple:
|
case Tuple:
|
||||||
count := info.fields.count;
|
count := info.fields.count;
|
||||||
if count != 1 { bprint_string(buf, "("); }
|
if count != 1 { bprint_string(buf, "("); }
|
||||||
for i := 0; i < count; i++ {
|
for i : 0..<count {
|
||||||
if i > 0 { bprint_string(buf, ", "); }
|
if i > 0 { bprint_string(buf, ", "); }
|
||||||
|
|
||||||
f := info.fields[i];
|
f := info.fields[i];
|
||||||
@@ -257,37 +264,37 @@ bprint_type :: proc(buf: ^[]byte, ti: ^Type_Info) {
|
|||||||
if info.packed { bprint_string(buf, "#packed "); }
|
if info.packed { bprint_string(buf, "#packed "); }
|
||||||
if info.ordered { bprint_string(buf, "#ordered "); }
|
if info.ordered { bprint_string(buf, "#ordered "); }
|
||||||
bprint_string(buf, "{");
|
bprint_string(buf, "{");
|
||||||
for i := 0; i < info.fields.count; i++ {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
bprint_any(buf, info.fields[i].name);
|
bprint_any(buf, field.name);
|
||||||
bprint_string(buf, ": ");
|
bprint_string(buf, ": ");
|
||||||
bprint_type(buf, info.fields[i].type_info);
|
bprint_type(buf, field.type_info);
|
||||||
}
|
}
|
||||||
bprint_string(buf, "}");
|
bprint_string(buf, "}");
|
||||||
|
|
||||||
case Union:
|
case Union:
|
||||||
bprint_string(buf, "union {");
|
bprint_string(buf, "union {");
|
||||||
for i := 0; i < info.fields.count; i++ {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
bprint_any(buf, info.fields[i].name);
|
bprint_any(buf, field.name);
|
||||||
bprint_string(buf, ": ");
|
bprint_string(buf, ": ");
|
||||||
bprint_type(buf, info.fields[i].type_info);
|
bprint_type(buf, field.type_info);
|
||||||
}
|
}
|
||||||
bprint_string(buf, "}");
|
bprint_string(buf, "}");
|
||||||
|
|
||||||
case Raw_Union:
|
case Raw_Union:
|
||||||
bprint_string(buf, "raw_union {");
|
bprint_string(buf, "raw_union {");
|
||||||
for i := 0; i < info.fields.count; i++ {
|
for field, i : info.fields {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
bprint_any(buf, info.fields[i].name);
|
bprint_any(buf, field.name);
|
||||||
bprint_string(buf, ": ");
|
bprint_string(buf, ": ");
|
||||||
bprint_type(buf, info.fields[i].type_info);
|
bprint_type(buf, field.type_info);
|
||||||
}
|
}
|
||||||
bprint_string(buf, "}");
|
bprint_string(buf, "}");
|
||||||
|
|
||||||
@@ -307,7 +314,7 @@ make_any :: proc(type_info: ^Type_Info, data: rawptr) -> any {
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
bprint_any :: proc(buf: ^[]byte, arg: any) {
|
bprint_any :: proc(buf: ^Buffer, arg: any) {
|
||||||
if arg.type_info == nil {
|
if arg.type_info == nil {
|
||||||
bprint_string(buf, "<nil>");
|
bprint_string(buf, "<nil>");
|
||||||
return;
|
return;
|
||||||
@@ -326,8 +333,7 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
case Struct:
|
case Struct:
|
||||||
bprint_string(buf, info.name);
|
bprint_string(buf, info.name);
|
||||||
bprint_string(buf, "{");
|
bprint_string(buf, "{");
|
||||||
for i := 0; i < b.fields.count; i++ {
|
for f, i : b.fields {
|
||||||
f := b.fields[i];
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
@@ -397,7 +403,7 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
bprintf(buf, "[%]%{", info.count, info.elem);
|
bprintf(buf, "[%]%{", info.count, info.elem);
|
||||||
defer bprint_string(buf, "}");
|
defer bprint_string(buf, "}");
|
||||||
|
|
||||||
for i := 0; i < info.count; i++ {
|
for i : 0..<info.count {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
@@ -411,7 +417,7 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
bprintf(buf, "[]%{", info.elem);
|
bprintf(buf, "[]%{", info.elem);
|
||||||
defer bprint_string(buf, "}");
|
defer bprint_string(buf, "}");
|
||||||
|
|
||||||
for i := 0; i < slice.count; i++ {
|
for i : 0..<slice.count {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
@@ -438,7 +444,7 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < info.count; i++ {
|
for i : 0..<info.count {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
@@ -452,14 +458,14 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
bprintf(buf, "%{", arg.type_info);
|
bprintf(buf, "%{", arg.type_info);
|
||||||
defer bprint_string(buf, "}");
|
defer bprint_string(buf, "}");
|
||||||
|
|
||||||
for i := 0; i < info.fields.count; i++ {
|
for f, i : info.fields {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
bprint_string(buf, ", ");
|
bprint_string(buf, ", ");
|
||||||
}
|
}
|
||||||
bprint_string(buf, info.fields[i].name);
|
bprint_string(buf, f.name);
|
||||||
bprint_string(buf, " = ");
|
bprint_string(buf, " = ");
|
||||||
data := arg.data as ^byte + info.fields[i].offset;
|
data := arg.data as ^byte + f.offset;
|
||||||
ti := info.fields[i].type_info;
|
ti := f.type_info;
|
||||||
bprint_any(buf, make_any(ti, data));
|
bprint_any(buf, make_any(ti, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,7 +485,7 @@ bprint_any :: proc(buf: ^[]byte, arg: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
bprintf :: proc(buf: ^Buffer, fmt: string, args: ...any) -> int {
|
||||||
is_digit :: proc(r: rune) -> bool #inline {
|
is_digit :: proc(r: rune) -> bool #inline {
|
||||||
return '0' <= r && r <= '9';
|
return '0' <= r && r <= '9';
|
||||||
}
|
}
|
||||||
@@ -487,7 +493,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
parse_int :: proc(s: string, offset: int) -> (int, int) {
|
||||||
result := 0;
|
result := 0;
|
||||||
|
|
||||||
for ; offset < s.count; offset++ {
|
for _ : offset..<s.count {
|
||||||
c := s[offset] as rune;
|
c := s[offset] as rune;
|
||||||
if !is_digit(c) {
|
if !is_digit(c) {
|
||||||
break;
|
break;
|
||||||
@@ -503,7 +509,7 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
prev := 0;
|
prev := 0;
|
||||||
implicit_index := 0;
|
implicit_index := 0;
|
||||||
|
|
||||||
for i := 0; i < fmt.count; i++ {
|
while i := 0; i < fmt.count { defer i += 1;
|
||||||
r := fmt[i] as rune;
|
r := fmt[i] as rune;
|
||||||
index := implicit_index;
|
index := implicit_index;
|
||||||
|
|
||||||
@@ -512,13 +518,13 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bprint_string(buf, fmt[prev:i]);
|
bprint_string(buf, fmt[prev:i]);
|
||||||
i++; // Skip %
|
i += 1; // Skip %
|
||||||
if i < fmt.count {
|
if i < fmt.count {
|
||||||
next := fmt[i] as rune;
|
next := fmt[i] as rune;
|
||||||
|
|
||||||
if next == '%' {
|
if next == '%' {
|
||||||
bprint_string(buf, "%");
|
bprint_string(buf, "%");
|
||||||
i++;
|
i += 1;
|
||||||
prev = i;
|
prev = i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -540,11 +546,11 @@ bprintf :: proc(buf: ^[]byte, fmt: string, args: ..any) -> int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bprint_string(buf, fmt[prev:]);
|
bprint_string(buf, fmt[prev:]);
|
||||||
return buf.count;
|
return buf.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
bprint :: proc(buf: ^Buffer, args: ...any) -> int {
|
||||||
is_type_string :: proc(info: ^Type_Info) -> bool {
|
is_type_string :: proc(info: ^Type_Info) -> bool {
|
||||||
using Type_Info;
|
using Type_Info;
|
||||||
if info == nil {
|
if info == nil {
|
||||||
@@ -560,8 +566,7 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
|||||||
|
|
||||||
|
|
||||||
prev_string := false;
|
prev_string := false;
|
||||||
for i := 0; i < args.count; i++ {
|
for arg, i : args {
|
||||||
arg := args[i];
|
|
||||||
is_string := arg.data != nil && is_type_string(arg.type_info);
|
is_string := arg.data != nil && is_type_string(arg.type_info);
|
||||||
if i > 0 && !is_string && !prev_string {
|
if i > 0 && !is_string && !prev_string {
|
||||||
bprint_space(buf);
|
bprint_space(buf);
|
||||||
@@ -569,16 +574,16 @@ bprint :: proc(buf: ^[]byte, args: ..any) -> int {
|
|||||||
bprint_any(buf, arg);
|
bprint_any(buf, arg);
|
||||||
prev_string = is_string;
|
prev_string = is_string;
|
||||||
}
|
}
|
||||||
return buf.count;
|
return buf.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
bprintln :: proc(buf: ^[]byte, args: ..any) -> int {
|
bprintln :: proc(buf: ^Buffer, args: ...any) -> int {
|
||||||
for i := 0; i < args.count; i++ {
|
for arg, i : args {
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
append(buf, ' ');
|
bprint_space(buf);
|
||||||
}
|
}
|
||||||
bprint_any(buf, args[i]);
|
bprint_any(buf, arg);
|
||||||
}
|
}
|
||||||
bprint_nl(buf);
|
bprint_nl(buf);
|
||||||
return buf.count;
|
return buf.length;
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-15
@@ -1,7 +1,7 @@
|
|||||||
crc32 :: proc(data: rawptr, len: int) -> u32 {
|
crc32 :: proc(data: rawptr, len: int) -> u32 {
|
||||||
result := ~(0 as u32);
|
result := ~(0 as u32);
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
b := s[i] as u32;
|
b := s[i] as u32;
|
||||||
result = result>>8 ~ __CRC32_TABLE[(result ~ b) & 0xff];
|
result = result>>8 ~ __CRC32_TABLE[(result ~ b) & 0xff];
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ crc32 :: proc(data: rawptr, len: int) -> u32 {
|
|||||||
crc64 :: proc(data: rawptr, len: int) -> u64 {
|
crc64 :: proc(data: rawptr, len: int) -> u64 {
|
||||||
result := ~(0 as u64);
|
result := ~(0 as u64);
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
b := s[i] as u64;
|
b := s[i] as u64;
|
||||||
result = result>>8 ~ __CRC64_TABLE[(result ~ b) & 0xff];
|
result = result>>8 ~ __CRC64_TABLE[(result ~ b) & 0xff];
|
||||||
}
|
}
|
||||||
@@ -20,8 +20,8 @@ crc64 :: proc(data: rawptr, len: int) -> u64 {
|
|||||||
fnv32 :: proc(data: rawptr, len: int) -> u32 {
|
fnv32 :: proc(data: rawptr, len: int) -> u32 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u32 = 0x811c9dc5;
|
h: u32 = 0x811c9dc5;
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
h = (h * 0x01000193) ~ s[i] as u32;
|
h = (h * 0x01000193) ~ s[i] as u32;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
@@ -30,8 +30,8 @@ fnv32 :: proc(data: rawptr, len: int) -> u32 {
|
|||||||
fnv64 :: proc(data: rawptr, len: int) -> u64 {
|
fnv64 :: proc(data: rawptr, len: int) -> u64 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u64 = 0xcbf29ce484222325;
|
h: u64 = 0xcbf29ce484222325;
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
h = (h * 0x100000001b3) ~ s[i] as u64;
|
h = (h * 0x100000001b3) ~ s[i] as u64;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
@@ -40,8 +40,8 @@ fnv64 :: proc(data: rawptr, len: int) -> u64 {
|
|||||||
fnv32a :: proc(data: rawptr, len: int) -> u32 {
|
fnv32a :: proc(data: rawptr, len: int) -> u32 {
|
||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u32 = 0x811c9dc5;
|
h: u32 = 0x811c9dc5;
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
h = (h ~ s[i] as u32) * 0x01000193;
|
h = (h ~ s[i] as u32) * 0x01000193;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
@@ -51,7 +51,7 @@ fnv64a :: proc(data: rawptr, len: int) -> u64 {
|
|||||||
s := slice_ptr(data as ^u8, len);
|
s := slice_ptr(data as ^u8, len);
|
||||||
|
|
||||||
h :u64 = 0xcbf29ce484222325;
|
h :u64 = 0xcbf29ce484222325;
|
||||||
for i := 0; i < len; i++ {
|
for i : 0..<len {
|
||||||
h = (h ~ s[i] as u64) * 0x100000001b3;
|
h = (h ~ s[i] as u64) * 0x100000001b3;
|
||||||
}
|
}
|
||||||
return h;
|
return h;
|
||||||
@@ -70,7 +70,7 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
|||||||
data := slice_ptr(data_ as ^u64, len/size_of(u64));
|
data := slice_ptr(data_ as ^u64, len/size_of(u64));
|
||||||
data2 := slice_ptr(data_ as ^u8, len);
|
data2 := slice_ptr(data_ as ^u8, len);
|
||||||
|
|
||||||
for i := 0; i < data.count; i++ {
|
for i : 0 ..< data.count {
|
||||||
k := data[i];
|
k := data[i];
|
||||||
|
|
||||||
k *= m;
|
k *= m;
|
||||||
@@ -108,9 +108,9 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
|||||||
data := slice_ptr(data_ as ^u32, len/size_of(u32));
|
data := slice_ptr(data_ as ^u32, len/size_of(u32));
|
||||||
|
|
||||||
i := 0;
|
i := 0;
|
||||||
for len >= 8 {
|
while len >= 8 {
|
||||||
k1, k2: u32;
|
k1, k2: u32;
|
||||||
k1 = data[i]; i++;
|
k1 = data[i]; i += 1;
|
||||||
k1 *= m;
|
k1 *= m;
|
||||||
k1 ~= k1>>r;
|
k1 ~= k1>>r;
|
||||||
k1 *= m;
|
k1 *= m;
|
||||||
@@ -118,7 +118,7 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
|||||||
h1 ~= k1;
|
h1 ~= k1;
|
||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
k2 = data[i]; i++;
|
k2 = data[i]; i += 1;
|
||||||
k2 *= m;
|
k2 *= m;
|
||||||
k2 ~= k2>>r;
|
k2 ~= k2>>r;
|
||||||
k2 *= m;
|
k2 *= m;
|
||||||
@@ -127,9 +127,9 @@ murmur64 :: proc(data_: rawptr, len: int) -> u64 {
|
|||||||
len -= 4;
|
len -= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (len >= 4) {
|
if len >= 4 {
|
||||||
k1: u32;
|
k1: u32;
|
||||||
k1 = data[i]; i++;
|
k1 = data[i]; i += 1;
|
||||||
k1 *= m;
|
k1 *= m;
|
||||||
k1 ~= k1>>r;
|
k1 ~= k1>>r;
|
||||||
k1 *= m;
|
k1 *= m;
|
||||||
|
|||||||
+4
-4
@@ -145,8 +145,8 @@ mat4_identity :: proc() -> Mat4 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
||||||
for j := 0; j < 4; j++ {
|
for j : 0..<4 {
|
||||||
for i := 0; i < 4; i++ {
|
for i : 0..<4 {
|
||||||
m[i][j], m[j][i] = m[j][i], m[i][j];
|
m[i][j], m[j][i] = m[j][i], m[i][j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,8 +155,8 @@ mat4_transpose :: proc(m: Mat4) -> Mat4 {
|
|||||||
|
|
||||||
mat4_mul :: proc(a, b: Mat4) -> Mat4 {
|
mat4_mul :: proc(a, b: Mat4) -> Mat4 {
|
||||||
c: Mat4;
|
c: Mat4;
|
||||||
for j := 0; j < 4; j++ {
|
for j : 0..<4 {
|
||||||
for i := 0; i < 4; i++ {
|
for i : 0..<4 {
|
||||||
c[j][i] = a[0][i]*b[j][0] +
|
c[j][i] = a[0][i]*b[j][0] +
|
||||||
a[1][i]*b[j][1] +
|
a[1][i]*b[j][1] +
|
||||||
a[2][i]*b[j][2] +
|
a[2][i]*b[j][2] +
|
||||||
|
|||||||
+15
-12
@@ -40,9 +40,9 @@ compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
|
|||||||
la := slice_ptr(^a[0] as ^int, fast);
|
la := slice_ptr(^a[0] as ^int, fast);
|
||||||
lb := slice_ptr(^b[0] as ^int, fast);
|
lb := slice_ptr(^b[0] as ^int, fast);
|
||||||
|
|
||||||
for ; curr_block < fast; curr_block++ {
|
for _ : curr_block ..< fast {
|
||||||
if (la[curr_block] ~ lb[curr_block]) != 0 {
|
if (la[curr_block] ~ lb[curr_block]) != 0 {
|
||||||
for pos := curr_block*size_of(int); pos < n; pos++ {
|
for pos : curr_block*size_of(int) ..< n {
|
||||||
if (a[pos] ~ b[pos]) != 0 {
|
if (a[pos] ~ b[pos]) != 0 {
|
||||||
return a[pos] as int - b[pos] as int;
|
return a[pos] as int - b[pos] as int;
|
||||||
}
|
}
|
||||||
@@ -51,7 +51,7 @@ compare :: proc(dst, src: rawptr, n: int) -> int #link_name "__mem_compare" {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for ; offset < n; offset++ {
|
for _ : offset ..< n {
|
||||||
if (a[offset] ~ b[offset]) != 0 {
|
if (a[offset] ~ b[offset]) != 0 {
|
||||||
return a[offset] as int - b[offset] as int;
|
return a[offset] as int - b[offset] as int;
|
||||||
}
|
}
|
||||||
@@ -96,13 +96,14 @@ allocation_header_fill :: proc(header: ^Allocation_Header, data: rawptr, size: i
|
|||||||
header.size = size;
|
header.size = size;
|
||||||
ptr := (header+1) as ^int;
|
ptr := (header+1) as ^int;
|
||||||
|
|
||||||
for i := 0; ptr as rawptr < data; i++ {
|
while i := 0; ptr as rawptr < data {
|
||||||
(ptr+i)^ = -1;
|
(ptr+i)^ = -1;
|
||||||
|
i += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
||||||
p := data as ^int;
|
p := data as ^int;
|
||||||
for (p-1)^ == -1 {
|
while (p-1)^ == -1 {
|
||||||
p = (p-1);
|
p = (p-1);
|
||||||
}
|
}
|
||||||
return (p as ^Allocation_Header)-1;
|
return (p as ^Allocation_Header)-1;
|
||||||
@@ -115,6 +116,7 @@ allocation_header :: proc(data: rawptr) -> ^Allocation_Header {
|
|||||||
// Custom allocators
|
// Custom allocators
|
||||||
Arena :: struct {
|
Arena :: struct {
|
||||||
backing: Allocator;
|
backing: Allocator;
|
||||||
|
offset: int;
|
||||||
memory: []byte;
|
memory: []byte;
|
||||||
temp_count: int;
|
temp_count: int;
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,8 @@ free_arena :: proc(using a: ^Arena) {
|
|||||||
if backing.procedure != nil {
|
if backing.procedure != nil {
|
||||||
push_allocator backing {
|
push_allocator backing {
|
||||||
free(memory.data);
|
free(memory.data);
|
||||||
memory = memory[0:0:0];
|
memory = memory[0:0];
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -166,15 +169,15 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
case ALLOC:
|
case ALLOC:
|
||||||
total_size := size + alignment;
|
total_size := size + alignment;
|
||||||
|
|
||||||
if arena.memory.count + total_size > arena.memory.capacity {
|
if arena.offset + total_size > arena.memory.count {
|
||||||
fmt.fprintln(os.stderr, "Arena out of memory");
|
fmt.fprintln(os.stderr, "Arena out of memory");
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
#no_bounds_check end := ^arena.memory[arena.memory.count];
|
#no_bounds_check end := ^arena.memory[arena.offset];
|
||||||
|
|
||||||
ptr := align_forward(end, alignment);
|
ptr := align_forward(end, alignment);
|
||||||
arena.memory.count += total_size;
|
arena.offset += total_size;
|
||||||
return zero(ptr, size);
|
return zero(ptr, size);
|
||||||
|
|
||||||
case FREE:
|
case FREE:
|
||||||
@@ -182,7 +185,7 @@ arena_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
// Use Arena_Temp_Memory if you want to free a block
|
// Use Arena_Temp_Memory if you want to free a block
|
||||||
|
|
||||||
case FREE_ALL:
|
case FREE_ALL:
|
||||||
arena.memory.count = 0;
|
arena.offset = 0;
|
||||||
|
|
||||||
case RESIZE:
|
case RESIZE:
|
||||||
return default_resize_align(old_memory, old_size, size, alignment);
|
return default_resize_align(old_memory, old_size, size, alignment);
|
||||||
@@ -195,7 +198,7 @@ begin_arena_temp_memory :: proc(a: ^Arena) -> Arena_Temp_Memory {
|
|||||||
tmp: Arena_Temp_Memory;
|
tmp: Arena_Temp_Memory;
|
||||||
tmp.arena = a;
|
tmp.arena = a;
|
||||||
tmp.original_count = a.memory.count;
|
tmp.original_count = a.memory.count;
|
||||||
a.temp_count++;
|
a.temp_count += 1;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +206,7 @@ end_arena_temp_memory :: proc(using tmp: Arena_Temp_Memory) {
|
|||||||
assert(arena.memory.count >= original_count);
|
assert(arena.memory.count >= original_count);
|
||||||
assert(arena.temp_count > 0);
|
assert(arena.temp_count > 0);
|
||||||
arena.memory.count = original_count;
|
arena.memory.count = original_count;
|
||||||
arena.temp_count--;
|
arena.temp_count -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ read_entire_file :: proc(name: string) -> ([]byte, bool) {
|
|||||||
single_read_length: i32;
|
single_read_length: i32;
|
||||||
total_read: i64;
|
total_read: i64;
|
||||||
|
|
||||||
for total_read < length {
|
while total_read < length {
|
||||||
remaining := length - total_read;
|
remaining := length - total_read;
|
||||||
to_read: u32;
|
to_read: u32;
|
||||||
MAX :: 1<<32-1;
|
MAX :: 1<<32-1;
|
||||||
|
|||||||
+3
-3
@@ -52,7 +52,7 @@ mutex_lock :: proc(m: ^Mutex) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomic.store32(^m.owner, thread_id);
|
atomic.store32(^m.owner, thread_id);
|
||||||
m.recursion++;
|
m.recursion += 1;
|
||||||
}
|
}
|
||||||
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
||||||
thread_id := current_thread_id();
|
thread_id := current_thread_id();
|
||||||
@@ -68,7 +68,7 @@ mutex_try_lock :: proc(m: ^Mutex) -> bool {
|
|||||||
}
|
}
|
||||||
atomic.store32(^m.owner, thread_id);
|
atomic.store32(^m.owner, thread_id);
|
||||||
}
|
}
|
||||||
m.recursion++;
|
m.recursion += 1;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
mutex_unlock :: proc(m: ^Mutex) {
|
mutex_unlock :: proc(m: ^Mutex) {
|
||||||
@@ -76,7 +76,7 @@ mutex_unlock :: proc(m: ^Mutex) {
|
|||||||
thread_id := current_thread_id();
|
thread_id := current_thread_id();
|
||||||
assert(thread_id == atomic.load32(^m.owner));
|
assert(thread_id == atomic.load32(^m.owner));
|
||||||
|
|
||||||
m.recursion--;
|
m.recursion -= 1;
|
||||||
recursion = m.recursion;
|
recursion = m.recursion;
|
||||||
if recursion == 0 {
|
if recursion == 0 {
|
||||||
atomic.store32(^m.owner, thread_id);
|
atomic.store32(^m.owner, thread_id);
|
||||||
|
|||||||
+9
-6
@@ -132,10 +132,11 @@ valid_rune :: proc(r: rune) -> bool {
|
|||||||
|
|
||||||
valid_string :: proc(s: string) -> bool {
|
valid_string :: proc(s: string) -> bool {
|
||||||
n := s.count;
|
n := s.count;
|
||||||
for i := 0; i < n; {
|
i := 0;
|
||||||
|
while i < n {
|
||||||
si := s[i];
|
si := s[i];
|
||||||
if si < RUNE_SELF { // ascii
|
if si < RUNE_SELF { // ascii
|
||||||
i++;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
x := accept_sizes[si];
|
x := accept_sizes[si];
|
||||||
@@ -166,20 +167,22 @@ valid_string :: proc(s: string) -> bool {
|
|||||||
rune_count :: proc(s: string) -> int {
|
rune_count :: proc(s: string) -> int {
|
||||||
count := 0;
|
count := 0;
|
||||||
n := s.count;
|
n := s.count;
|
||||||
for i := 0; i < n; count++ {
|
i := 0;
|
||||||
|
while i < n {
|
||||||
|
defer count += 1;
|
||||||
si := s[i];
|
si := s[i];
|
||||||
if si < RUNE_SELF { // ascii
|
if si < RUNE_SELF { // ascii
|
||||||
i++;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
x := accept_sizes[si];
|
x := accept_sizes[si];
|
||||||
if x == 0xf1 {
|
if x == 0xf1 {
|
||||||
i++;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
size := (x & 7) as int;
|
size := (x & 7) as int;
|
||||||
if i+size > n {
|
if i+size > n {
|
||||||
i++;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ar := accept_ranges[x>>4];
|
ar := accept_ranges[x>>4];
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ typedef enum BuiltinProcId {
|
|||||||
BuiltinProc_panic,
|
BuiltinProc_panic,
|
||||||
|
|
||||||
BuiltinProc_copy,
|
BuiltinProc_copy,
|
||||||
BuiltinProc_append,
|
// BuiltinProc_append,
|
||||||
|
|
||||||
BuiltinProc_swizzle,
|
BuiltinProc_swizzle,
|
||||||
|
|
||||||
@@ -175,7 +175,7 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_Count] = {
|
|||||||
{STR_LIT("panic"), 1, false, Expr_Stmt},
|
{STR_LIT("panic"), 1, false, Expr_Stmt},
|
||||||
|
|
||||||
{STR_LIT("copy"), 2, false, Expr_Expr},
|
{STR_LIT("copy"), 2, false, Expr_Expr},
|
||||||
{STR_LIT("append"), 2, false, Expr_Expr},
|
// {STR_LIT("append"), 2, false, Expr_Expr},
|
||||||
|
|
||||||
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
{STR_LIT("swizzle"), 1, true, Expr_Expr},
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ struct Entity {
|
|||||||
struct {
|
struct {
|
||||||
i32 field_index;
|
i32 field_index;
|
||||||
i32 field_src_index;
|
i32 field_src_index;
|
||||||
|
bool is_immutable;
|
||||||
} Variable;
|
} Variable;
|
||||||
i32 TypeName;
|
i32 TypeName;
|
||||||
struct {
|
struct {
|
||||||
|
|||||||
+7
-12
@@ -965,9 +965,9 @@ void check_identifier(Checker *c, Operand *o, AstNode *n, Type *named_type) {
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
o->mode = Addressing_Variable;
|
o->mode = Addressing_Variable;
|
||||||
// if (e->Variable.is_let) {
|
if (e->Variable.is_immutable) {
|
||||||
// o->mode = Addressing_Value;
|
o->mode = Addressing_Value;
|
||||||
// }
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -2967,6 +2967,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
#if 0
|
||||||
case BuiltinProc_append: {
|
case BuiltinProc_append: {
|
||||||
// append :: proc(x : ^[]Type, y : Type) -> bool
|
// append :: proc(x : ^[]Type, y : Type) -> bool
|
||||||
Type *x_type = NULL, *y_type = NULL;
|
Type *x_type = NULL, *y_type = NULL;
|
||||||
@@ -3003,6 +3004,7 @@ bool check_builtin_procedure(Checker *c, Operand *operand, AstNode *call, i32 id
|
|||||||
operand->type = t_bool; // Returns if it was successful
|
operand->type = t_bool; // Returns if it was successful
|
||||||
operand->mode = Addressing_Value;
|
operand->mode = Addressing_Value;
|
||||||
} break;
|
} break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
// swizzle :: proc(v: {N}T, T...) -> {M}T
|
// swizzle :: proc(v: {N}T, T...) -> {M}T
|
||||||
@@ -4342,9 +4344,6 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
if (o->mode == Addressing_Constant) {
|
if (o->mode == Addressing_Constant) {
|
||||||
max_count = o->value.value_string.len;
|
max_count = o->value.value_string.len;
|
||||||
}
|
}
|
||||||
if (se->max != NULL) {
|
|
||||||
error_node(se->max, "Max (3rd) index not needed in substring expression");
|
|
||||||
}
|
|
||||||
o->type = t_string;
|
o->type = t_string;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -4375,8 +4374,8 @@ ExprKind check__expr_base(Checker *c, Operand *o, AstNode *node, Type *type_hint
|
|||||||
|
|
||||||
o->mode = Addressing_Value;
|
o->mode = Addressing_Value;
|
||||||
|
|
||||||
i64 indices[3] = {0};
|
i64 indices[2] = {0};
|
||||||
AstNode *nodes[3] = {se->low, se->high, se->max};
|
AstNode *nodes[2] = {se->low, se->high};
|
||||||
for (isize i = 0; i < gb_count_of(nodes); i++) {
|
for (isize i = 0; i < gb_count_of(nodes); i++) {
|
||||||
i64 index = max_count;
|
i64 index = max_count;
|
||||||
if (nodes[i] != NULL) {
|
if (nodes[i] != NULL) {
|
||||||
@@ -4680,10 +4679,6 @@ gbString write_expr_to_string(gbString str, AstNode *node) {
|
|||||||
str = write_expr_to_string(str, se->low);
|
str = write_expr_to_string(str, se->low);
|
||||||
str = gb_string_appendc(str, ":");
|
str = gb_string_appendc(str, ":");
|
||||||
str = write_expr_to_string(str, se->high);
|
str = write_expr_to_string(str, se->high);
|
||||||
if (se->triple_indexed) {
|
|
||||||
str = gb_string_appendc(str, ":");
|
|
||||||
str = write_expr_to_string(str, se->max);
|
|
||||||
}
|
|
||||||
str = gb_string_appendc(str, "]");
|
str = gb_string_appendc(str, "]");
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|||||||
+17
-61
@@ -127,13 +127,13 @@ bool check_is_terminating(AstNode *node) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fs, ForStmt, node);
|
case_ast_node(ws, WhileStmt, node);
|
||||||
if (fs->cond == NULL && !check_has_break(fs->body, true)) {
|
if (ws->cond == NULL && !check_has_break(ws->body, true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rs, RangeStmt, node);
|
case_ast_node(rs, ForStmt, node);
|
||||||
if (!check_has_break(rs->body, true)) {
|
if (!check_has_break(rs->body, true)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -375,48 +375,6 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
check_stmt(c, ts->stmt, flags);
|
check_stmt(c, ts->stmt, flags);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ids, IncDecStmt, node);
|
|
||||||
Token op = ids->op;
|
|
||||||
switch (ids->op.kind) {
|
|
||||||
case Token_Increment:
|
|
||||||
op.kind = Token_Add;
|
|
||||||
op.string.len = 1;
|
|
||||||
break;
|
|
||||||
case Token_Decrement:
|
|
||||||
op.kind = Token_Sub;
|
|
||||||
op.string.len = 1;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
error(ids->op, "Unknown inc/dec operation %.*s", LIT(ids->op.string));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Operand operand = {Addressing_Invalid};
|
|
||||||
check_expr(c, &operand, ids->expr);
|
|
||||||
if (operand.mode == Addressing_Invalid) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!is_type_numeric(operand.type) && !is_type_pointer(operand.type)) {
|
|
||||||
gbString type_str = type_to_string(operand.type);
|
|
||||||
error(ids->op, "Non numeric type `%s`", type_str);
|
|
||||||
gb_string_free(type_str);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode basic_lit = {AstNode_BasicLit};
|
|
||||||
ast_node(bl, BasicLit, &basic_lit);
|
|
||||||
*bl = ids->op;
|
|
||||||
bl->kind = Token_Integer;
|
|
||||||
bl->string = str_lit("1");
|
|
||||||
|
|
||||||
AstNode binary_expr = {AstNode_BinaryExpr};
|
|
||||||
ast_node(be, BinaryExpr, &binary_expr);
|
|
||||||
be->op = op;
|
|
||||||
be->left = ids->expr;
|
|
||||||
be->right = &basic_lit;
|
|
||||||
check_binary_expr(c, &operand, &binary_expr);
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(as, AssignStmt, node);
|
case_ast_node(as, AssignStmt, node);
|
||||||
switch (as->op.kind) {
|
switch (as->op.kind) {
|
||||||
case Token_Eq: {
|
case Token_Eq: {
|
||||||
@@ -567,30 +525,27 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fs, ForStmt, node);
|
case_ast_node(ws, WhileStmt, node);
|
||||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
|
|
||||||
if (fs->init != NULL) {
|
if (ws->init != NULL) {
|
||||||
check_stmt(c, fs->init, 0);
|
check_stmt(c, ws->init, 0);
|
||||||
}
|
}
|
||||||
if (fs->cond) {
|
if (ws->cond) {
|
||||||
Operand operand = {Addressing_Invalid};
|
Operand operand = {Addressing_Invalid};
|
||||||
check_expr(c, &operand, fs->cond);
|
check_expr(c, &operand, ws->cond);
|
||||||
if (operand.mode != Addressing_Invalid &&
|
if (operand.mode != Addressing_Invalid &&
|
||||||
!is_type_boolean(operand.type)) {
|
!is_type_boolean(operand.type)) {
|
||||||
error_node(fs->cond, "Non-boolean condition in `for` statement");
|
error_node(ws->cond, "Non-boolean condition in `while` statement");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fs->post != NULL) {
|
check_stmt(c, ws->body, new_flags);
|
||||||
check_stmt(c, fs->post, 0);
|
|
||||||
}
|
|
||||||
check_stmt(c, fs->body, new_flags);
|
|
||||||
|
|
||||||
check_close_scope(c);
|
check_close_scope(c);
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(rs, RangeStmt, node);
|
case_ast_node(rs, ForStmt, node);
|
||||||
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
u32 new_flags = mod_flags | Stmt_BreakAllowed | Stmt_ContinueAllowed;
|
||||||
check_open_scope(c, node);
|
check_open_scope(c, node);
|
||||||
|
|
||||||
@@ -646,8 +601,8 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
goto skip_expr;
|
goto skip_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_type_integer(x.type) && !is_type_float(x.type)) {
|
if (!is_type_integer(x.type) && !is_type_float(x.type) && !is_type_pointer(x.type)) {
|
||||||
error(ie->op, "Only numerical types are allowed within interval expressions");
|
error(ie->op, "Only numerical and pointer types are allowed within interval expressions");
|
||||||
goto skip_expr;
|
goto skip_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +616,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
bool ok = compare_exact_values(Token_Lt, a, b);
|
bool ok = compare_exact_values(Token_Lt, a, b);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
// TODO(bill): Better error message
|
// TODO(bill): Better error message
|
||||||
error(ie->op, "Invalid interval expression");
|
error(ie->op, "Invalid interval range");
|
||||||
goto skip_expr;
|
goto skip_expr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -723,6 +678,7 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
}
|
}
|
||||||
if (found == NULL) {
|
if (found == NULL) {
|
||||||
entity = make_entity_variable(c->allocator, c->context.scope, token, type);
|
entity = make_entity_variable(c->allocator, c->context.scope, token, type);
|
||||||
|
entity->Variable.is_immutable = true;
|
||||||
add_entity_definition(&c->info, name, entity);
|
add_entity_definition(&c->info, name, entity);
|
||||||
} else {
|
} else {
|
||||||
TokenPos pos = found->token.pos;
|
TokenPos pos = found->token.pos;
|
||||||
@@ -1051,12 +1007,12 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
switch (token.kind) {
|
switch (token.kind) {
|
||||||
case Token_break:
|
case Token_break:
|
||||||
if ((flags & Stmt_BreakAllowed) == 0) {
|
if ((flags & Stmt_BreakAllowed) == 0) {
|
||||||
error(token, "`break` only allowed in `for` or `match` statements");
|
error(token, "`break` only allowed in loops or `match` statements");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token_continue:
|
case Token_continue:
|
||||||
if ((flags & Stmt_ContinueAllowed) == 0) {
|
if ((flags & Stmt_ContinueAllowed) == 0) {
|
||||||
error(token, "`continue` only allowed in `for` statements");
|
error(token, "`continue` only allowed in loops");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Token_fallthrough:
|
case Token_fallthrough:
|
||||||
|
|||||||
+4
-11
@@ -116,6 +116,8 @@ typedef struct TypeRecord {
|
|||||||
ProcCallingConvention calling_convention; \
|
ProcCallingConvention calling_convention; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef enum TypeKind {
|
typedef enum TypeKind {
|
||||||
Type_Invalid,
|
Type_Invalid,
|
||||||
#define TYPE_KIND(k, ...) GB_JOIN2(Type_, k),
|
#define TYPE_KIND(k, ...) GB_JOIN2(Type_, k),
|
||||||
@@ -987,7 +989,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
} else if (type->kind == Type_Slice) {
|
} else if (type->kind == Type_Slice) {
|
||||||
String data_str = str_lit("data");
|
String data_str = str_lit("data");
|
||||||
String count_str = str_lit("count");
|
String count_str = str_lit("count");
|
||||||
String capacity_str = str_lit("capacity");
|
|
||||||
|
|
||||||
if (str_eq(field_name, data_str)) {
|
if (str_eq(field_name, data_str)) {
|
||||||
selection_add_index(&sel, 0);
|
selection_add_index(&sel, 0);
|
||||||
@@ -1002,14 +1003,6 @@ Selection lookup_field_with_selection(gbAllocator a, Type *type_, String field_n
|
|||||||
|
|
||||||
sel.entity = entity__slice_count;
|
sel.entity = entity__slice_count;
|
||||||
return sel;
|
return sel;
|
||||||
} else if (str_eq(field_name, capacity_str)) {
|
|
||||||
selection_add_index(&sel, 2);
|
|
||||||
if (entity__slice_capacity == NULL) {
|
|
||||||
entity__slice_capacity = make_entity_field(a, NULL, make_token_ident(capacity_str), t_int, false, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
sel.entity = entity__slice_capacity;
|
|
||||||
return sel;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1393,8 +1386,8 @@ i64 type_size_of_internal(BaseTypeSizes s, gbAllocator allocator, Type *t, TypeP
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|
||||||
case Type_Slice: // ptr + len + cap
|
case Type_Slice: // ptr + count
|
||||||
return 3 * s.word_size;
|
return 2 * s.word_size;
|
||||||
|
|
||||||
case Type_Maybe: { // value + bool
|
case Type_Maybe: { // value + bool
|
||||||
i64 align, size;
|
i64 align, size;
|
||||||
|
|||||||
+60
-109
@@ -140,8 +140,7 @@ AST_NODE_KIND(_ExprBegin, "", i32) \
|
|||||||
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
AST_NODE_KIND(SliceExpr, "slice expression", struct { \
|
||||||
AstNode *expr; \
|
AstNode *expr; \
|
||||||
Token open, close; \
|
Token open, close; \
|
||||||
AstNode *low, *high, *max; \
|
AstNode *low, *high; \
|
||||||
bool triple_indexed; \
|
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
AST_NODE_KIND(FieldValue, "field value", struct { Token eq; AstNode *field, *value; }) \
|
||||||
AST_NODE_KIND(BlockExpr, "block expr", struct { \
|
AST_NODE_KIND(BlockExpr, "block expr", struct { \
|
||||||
@@ -166,7 +165,6 @@ AST_NODE_KIND(_StmtBegin, "", i32) \
|
|||||||
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
|
AST_NODE_KIND(BadStmt, "bad statement", struct { Token begin, end; }) \
|
||||||
AST_NODE_KIND(EmptyStmt, "empty statement", struct { Token token; }) \
|
AST_NODE_KIND(EmptyStmt, "empty statement", struct { Token token; }) \
|
||||||
AST_NODE_KIND(ExprStmt, "expression statement", struct { AstNode *expr; } ) \
|
AST_NODE_KIND(ExprStmt, "expression statement", struct { AstNode *expr; } ) \
|
||||||
AST_NODE_KIND(IncDecStmt, "increment/decrement statement", struct { Token op; AstNode *expr; }) \
|
|
||||||
AST_NODE_KIND(TagStmt, "tag statement", struct { \
|
AST_NODE_KIND(TagStmt, "tag statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
Token name; \
|
Token name; \
|
||||||
@@ -198,14 +196,13 @@ AST_NODE_KIND(_ComplexStmtBegin, "", i32) \
|
|||||||
Token token; \
|
Token token; \
|
||||||
AstNodeArray results; \
|
AstNodeArray results; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(ForStmt, "for statement", struct { \
|
AST_NODE_KIND(WhileStmt, "while statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *init; \
|
AstNode *init; \
|
||||||
AstNode *cond; \
|
AstNode *cond; \
|
||||||
AstNode *post; \
|
|
||||||
AstNode *body; \
|
AstNode *body; \
|
||||||
}) \
|
}) \
|
||||||
AST_NODE_KIND(RangeStmt, "range statement", struct { \
|
AST_NODE_KIND(ForStmt, "range statement", struct { \
|
||||||
Token token; \
|
Token token; \
|
||||||
AstNode *value; \
|
AstNode *value; \
|
||||||
AstNode *index; \
|
AstNode *index; \
|
||||||
@@ -463,8 +460,6 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return ast_node_token(node->ExprStmt.expr);
|
return ast_node_token(node->ExprStmt.expr);
|
||||||
case AstNode_TagStmt:
|
case AstNode_TagStmt:
|
||||||
return node->TagStmt.token;
|
return node->TagStmt.token;
|
||||||
case AstNode_IncDecStmt:
|
|
||||||
return node->IncDecStmt.op;
|
|
||||||
case AstNode_AssignStmt:
|
case AstNode_AssignStmt:
|
||||||
return node->AssignStmt.op;
|
return node->AssignStmt.op;
|
||||||
case AstNode_BlockStmt:
|
case AstNode_BlockStmt:
|
||||||
@@ -475,8 +470,8 @@ Token ast_node_token(AstNode *node) {
|
|||||||
return node->WhenStmt.token;
|
return node->WhenStmt.token;
|
||||||
case AstNode_ReturnStmt:
|
case AstNode_ReturnStmt:
|
||||||
return node->ReturnStmt.token;
|
return node->ReturnStmt.token;
|
||||||
case AstNode_ForStmt:
|
case AstNode_WhileStmt:
|
||||||
return node->ForStmt.token;
|
return node->WhileStmt.token;
|
||||||
case AstNode_MatchStmt:
|
case AstNode_MatchStmt:
|
||||||
return node->MatchStmt.token;
|
return node->MatchStmt.token;
|
||||||
case AstNode_CaseClause:
|
case AstNode_CaseClause:
|
||||||
@@ -677,15 +672,13 @@ AstNode *make_index_expr(AstFile *f, AstNode *expr, AstNode *index, Token open,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high, AstNode *max, bool triple_indexed) {
|
AstNode *make_slice_expr(AstFile *f, AstNode *expr, Token open, Token close, AstNode *low, AstNode *high) {
|
||||||
AstNode *result = make_node(f, AstNode_SliceExpr);
|
AstNode *result = make_node(f, AstNode_SliceExpr);
|
||||||
result->SliceExpr.expr = expr;
|
result->SliceExpr.expr = expr;
|
||||||
result->SliceExpr.open = open;
|
result->SliceExpr.open = open;
|
||||||
result->SliceExpr.close = close;
|
result->SliceExpr.close = close;
|
||||||
result->SliceExpr.low = low;
|
result->SliceExpr.low = low;
|
||||||
result->SliceExpr.high = high;
|
result->SliceExpr.high = high;
|
||||||
result->SliceExpr.max = max;
|
|
||||||
result->SliceExpr.triple_indexed = triple_indexed;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,13 +803,6 @@ AstNode *make_expr_stmt(AstFile *f, AstNode *expr) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *make_inc_dec_stmt(AstFile *f, Token op, AstNode *expr) {
|
|
||||||
AstNode *result = make_node(f, AstNode_IncDecStmt);
|
|
||||||
result->IncDecStmt.op = op;
|
|
||||||
result->IncDecStmt.expr = expr;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rhs) {
|
AstNode *make_assign_stmt(AstFile *f, Token op, AstNodeArray lhs, AstNodeArray rhs) {
|
||||||
AstNode *result = make_node(f, AstNode_AssignStmt);
|
AstNode *result = make_node(f, AstNode_AssignStmt);
|
||||||
result->AssignStmt.op = op;
|
result->AssignStmt.op = op;
|
||||||
@@ -860,22 +846,21 @@ AstNode *make_return_stmt(AstFile *f, Token token, AstNodeArray results) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *make_for_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *post, AstNode *body) {
|
AstNode *make_while_stmt(AstFile *f, Token token, AstNode *init, AstNode *cond, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_ForStmt);
|
AstNode *result = make_node(f, AstNode_WhileStmt);
|
||||||
result->ForStmt.token = token;
|
result->WhileStmt.token = token;
|
||||||
result->ForStmt.init = init;
|
result->WhileStmt.init = init;
|
||||||
result->ForStmt.cond = cond;
|
result->WhileStmt.cond = cond;
|
||||||
result->ForStmt.post = post;
|
result->WhileStmt.body = body;
|
||||||
result->ForStmt.body = body;
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
AstNode *make_range_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, AstNode *expr, AstNode *body) {
|
AstNode *make_for_stmt(AstFile *f, Token token, AstNode *value, AstNode *index, AstNode *expr, AstNode *body) {
|
||||||
AstNode *result = make_node(f, AstNode_RangeStmt);
|
AstNode *result = make_node(f, AstNode_ForStmt);
|
||||||
result->RangeStmt.token = token;
|
result->ForStmt.token = token;
|
||||||
result->RangeStmt.value = value;
|
result->ForStmt.value = value;
|
||||||
result->RangeStmt.index = index;
|
result->ForStmt.index = index;
|
||||||
result->RangeStmt.expr = expr;
|
result->ForStmt.expr = expr;
|
||||||
result->RangeStmt.body = body;
|
result->ForStmt.body = body;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1224,7 +1209,7 @@ void fix_advance_to_next_stmt(AstFile *f) {
|
|||||||
case Token_if:
|
case Token_if:
|
||||||
case Token_when:
|
case Token_when:
|
||||||
case Token_return:
|
case Token_return:
|
||||||
case Token_for:
|
case Token_while:
|
||||||
case Token_range:
|
case Token_range:
|
||||||
case Token_match:
|
case Token_match:
|
||||||
case Token_defer:
|
case Token_defer:
|
||||||
@@ -1908,7 +1893,7 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
isize colon_count = 0;
|
isize colon_count = 0;
|
||||||
Token colons[2] = {0};
|
Token colons[2] = {0};
|
||||||
|
|
||||||
while (f->curr_token.kind == Token_Colon && colon_count < 2) {
|
while (f->curr_token.kind == Token_Colon && colon_count < 1) {
|
||||||
colons[colon_count++] = f->curr_token;
|
colons[colon_count++] = f->curr_token;
|
||||||
next_token(f);
|
next_token(f);
|
||||||
if (f->curr_token.kind != Token_Colon &&
|
if (f->curr_token.kind != Token_Colon &&
|
||||||
@@ -1924,19 +1909,7 @@ AstNode *parse_atom_expr(AstFile *f, bool lhs) {
|
|||||||
if (colon_count == 0) {
|
if (colon_count == 0) {
|
||||||
operand = make_index_expr(f, operand, indices[0], open, close);
|
operand = make_index_expr(f, operand, indices[0], open, close);
|
||||||
} else {
|
} else {
|
||||||
bool triple_indexed = false;
|
operand = make_slice_expr(f, operand, open, close, indices[0], indices[1]);
|
||||||
if (colon_count == 2) {
|
|
||||||
triple_indexed = true;
|
|
||||||
if (indices[1] == NULL) {
|
|
||||||
syntax_error(colons[0], "Second index is required in a triple indexed slice");
|
|
||||||
indices[1] = make_bad_expr(f, colons[0], colons[1]);
|
|
||||||
}
|
|
||||||
if (indices[2] == NULL) {
|
|
||||||
syntax_error(colons[1], "Third index is required in a triple indexed slice");
|
|
||||||
indices[2] = make_bad_expr(f, colons[1], close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
operand = make_slice_expr(f, operand, open, close, indices[0], indices[1], indices[2], triple_indexed);
|
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
@@ -2239,19 +2212,6 @@ AstNode *parse_simple_stmt(AstFile *f) {
|
|||||||
return make_bad_stmt(f, token, f->curr_token);
|
return make_bad_stmt(f, token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
token = f->curr_token;
|
|
||||||
switch (token.kind) {
|
|
||||||
case Token_Increment:
|
|
||||||
case Token_Decrement:
|
|
||||||
if (f->curr_proc == NULL) {
|
|
||||||
syntax_error(f->curr_token, "You cannot use a simple statement in the file scope");
|
|
||||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
|
||||||
}
|
|
||||||
AstNode *stmt = make_inc_dec_stmt(f, token, lhs.e[0]);
|
|
||||||
next_token(f);
|
|
||||||
return stmt;
|
|
||||||
}
|
|
||||||
|
|
||||||
return make_expr_stmt(f, lhs.e[0]);
|
return make_expr_stmt(f, lhs.e[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2748,6 +2708,41 @@ AstNode *parse_give_stmt(AstFile *f) {
|
|||||||
return make_expr_stmt(f, ge);
|
return make_expr_stmt(f, ge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AstNode *parse_while_stmt(AstFile *f) {
|
||||||
|
if (f->curr_proc == NULL) {
|
||||||
|
syntax_error(f->curr_token, "You cannot use a while statement in the file scope");
|
||||||
|
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Token token = expect_token(f, Token_while);
|
||||||
|
|
||||||
|
AstNode *init = NULL;
|
||||||
|
AstNode *cond = NULL;
|
||||||
|
AstNode *body = NULL;
|
||||||
|
|
||||||
|
isize prev_level = f->expr_level;
|
||||||
|
f->expr_level = -1;
|
||||||
|
|
||||||
|
|
||||||
|
cond = parse_simple_stmt(f);
|
||||||
|
if (is_ast_node_complex_stmt(cond)) {
|
||||||
|
syntax_error(f->curr_token, "You are not allowed that type of statement in a while statement, it is too complex!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allow_token(f, Token_Semicolon)) {
|
||||||
|
init = cond;
|
||||||
|
cond = parse_simple_stmt(f);
|
||||||
|
}
|
||||||
|
f->expr_level = prev_level;
|
||||||
|
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
|
||||||
|
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
|
||||||
|
|
||||||
|
return make_while_stmt(f, token, init, cond, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_for_stmt(AstFile *f) {
|
AstNode *parse_for_stmt(AstFile *f) {
|
||||||
if (f->curr_proc == NULL) {
|
if (f->curr_proc == NULL) {
|
||||||
syntax_error(f->curr_token, "You cannot use a for statement in the file scope");
|
syntax_error(f->curr_token, "You cannot use a for statement in the file scope");
|
||||||
@@ -2755,53 +2750,9 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token token = expect_token(f, Token_for);
|
Token token = expect_token(f, Token_for);
|
||||||
|
|
||||||
AstNode *init = NULL;
|
|
||||||
AstNode *cond = NULL;
|
|
||||||
AstNode *end = NULL;
|
|
||||||
AstNode *body = NULL;
|
|
||||||
|
|
||||||
if (f->curr_token.kind != Token_OpenBrace) {
|
|
||||||
isize prev_level = f->expr_level;
|
|
||||||
f->expr_level = -1;
|
|
||||||
if (f->curr_token.kind != Token_Semicolon) {
|
|
||||||
cond = parse_simple_stmt(f);
|
|
||||||
if (is_ast_node_complex_stmt(cond)) {
|
|
||||||
syntax_error(f->curr_token, "You are not allowed that type of statement in a for statement, it is too complex!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allow_token(f, Token_Semicolon)) {
|
|
||||||
init = cond;
|
|
||||||
cond = NULL;
|
|
||||||
if (f->curr_token.kind != Token_Semicolon) {
|
|
||||||
cond = parse_simple_stmt(f);
|
|
||||||
}
|
|
||||||
expect_token(f, Token_Semicolon);
|
|
||||||
if (f->curr_token.kind != Token_OpenBrace) {
|
|
||||||
end = parse_simple_stmt(f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f->expr_level = prev_level;
|
|
||||||
}
|
|
||||||
body = parse_block_stmt(f, false);
|
|
||||||
|
|
||||||
cond = convert_stmt_to_expr(f, cond, str_lit("boolean expression"));
|
|
||||||
|
|
||||||
return make_for_stmt(f, token, init, cond, end, body);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_range_stmt(AstFile *f) {
|
|
||||||
if (f->curr_proc == NULL) {
|
|
||||||
syntax_error(f->curr_token, "You cannot use a range statement in the file scope");
|
|
||||||
return make_bad_stmt(f, f->curr_token, f->curr_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
Token token = expect_token(f, Token_range);
|
|
||||||
AstNodeArray names = parse_identifier_list(f);
|
AstNodeArray names = parse_identifier_list(f);
|
||||||
parse_check_name_list_for_reserves(f, names);
|
parse_check_name_list_for_reserves(f, names);
|
||||||
Token colon = expect_token_after(f, Token_Colon, "range name list");
|
Token colon = expect_token_after(f, Token_Colon, "for name list");
|
||||||
|
|
||||||
isize prev_level = f->expr_level;
|
isize prev_level = f->expr_level;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
@@ -2830,7 +2781,7 @@ AstNode *parse_range_stmt(AstFile *f) {
|
|||||||
return make_bad_stmt(f, token, f->curr_token);
|
return make_bad_stmt(f, token, f->curr_token);
|
||||||
}
|
}
|
||||||
|
|
||||||
return make_range_stmt(f, token, value, index, expr, body);
|
return make_for_stmt(f, token, value, index, expr, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_case_clause(AstFile *f) {
|
AstNode *parse_case_clause(AstFile *f) {
|
||||||
@@ -3009,8 +2960,8 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
|
|
||||||
case Token_if: return parse_if_stmt(f);
|
case Token_if: return parse_if_stmt(f);
|
||||||
case Token_when: return parse_when_stmt(f);
|
case Token_when: return parse_when_stmt(f);
|
||||||
|
case Token_while: return parse_while_stmt(f);
|
||||||
case Token_for: return parse_for_stmt(f);
|
case Token_for: return parse_for_stmt(f);
|
||||||
case Token_range: return parse_range_stmt(f);
|
|
||||||
case Token_match: return parse_match_stmt(f);
|
case Token_match: return parse_match_stmt(f);
|
||||||
case Token_defer: return parse_defer_stmt(f);
|
case Token_defer: return parse_defer_stmt(f);
|
||||||
case Token_asm: return parse_asm_stmt(f);
|
case Token_asm: return parse_asm_stmt(f);
|
||||||
|
|||||||
@@ -234,7 +234,6 @@ struct ssaProcedure {
|
|||||||
TokenPos pos; \
|
TokenPos pos; \
|
||||||
ssaValue *low; \
|
ssaValue *low; \
|
||||||
ssaValue *high; \
|
ssaValue *high; \
|
||||||
ssaValue *max; \
|
|
||||||
bool is_substring; \
|
bool is_substring; \
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -1016,12 +1015,11 @@ ssaValue *ssa_make_instr_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *i
|
|||||||
v->Instr.BoundsCheck.len = len;
|
v->Instr.BoundsCheck.len = len;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
ssaValue *ssa_make_instr_slice_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *low, ssaValue *high, ssaValue *max, bool is_substring) {
|
ssaValue *ssa_make_instr_slice_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *low, ssaValue *high, bool is_substring) {
|
||||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_SliceBoundsCheck);
|
ssaValue *v = ssa_alloc_instr(p, ssaInstr_SliceBoundsCheck);
|
||||||
v->Instr.SliceBoundsCheck.pos = pos;
|
v->Instr.SliceBoundsCheck.pos = pos;
|
||||||
v->Instr.SliceBoundsCheck.low = low;
|
v->Instr.SliceBoundsCheck.low = low;
|
||||||
v->Instr.SliceBoundsCheck.high = high;
|
v->Instr.SliceBoundsCheck.high = high;
|
||||||
v->Instr.SliceBoundsCheck.max = max;
|
|
||||||
v->Instr.SliceBoundsCheck.is_substring = is_substring;
|
v->Instr.SliceBoundsCheck.is_substring = is_substring;
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -1794,11 +1792,6 @@ ssaValue *ssa_slice_len(ssaProcedure *proc, ssaValue *slice) {
|
|||||||
GB_ASSERT(t->kind == Type_Slice);
|
GB_ASSERT(t->kind == Type_Slice);
|
||||||
return ssa_emit_struct_ev(proc, slice, 1);
|
return ssa_emit_struct_ev(proc, slice, 1);
|
||||||
}
|
}
|
||||||
ssaValue *ssa_slice_cap(ssaProcedure *proc, ssaValue *slice) {
|
|
||||||
Type *t = ssa_type(slice);
|
|
||||||
GB_ASSERT(t->kind == Type_Slice);
|
|
||||||
return ssa_emit_struct_ev(proc, slice, 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssaValue *ssa_string_elem(ssaProcedure *proc, ssaValue *string) {
|
ssaValue *ssa_string_elem(ssaProcedure *proc, ssaValue *string) {
|
||||||
Type *t = ssa_type(string);
|
Type *t = ssa_type(string);
|
||||||
@@ -1813,7 +1806,7 @@ ssaValue *ssa_string_len(ssaProcedure *proc, ssaValue *string) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, ssaValue *low, ssaValue *high, ssaValue *max) {
|
ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *base, ssaValue *low, ssaValue *high) {
|
||||||
// TODO(bill): array bounds checking for slice creation
|
// TODO(bill): array bounds checking for slice creation
|
||||||
// TODO(bill): check that low < high <= max
|
// TODO(bill): check that low < high <= max
|
||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
@@ -1829,17 +1822,8 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
|
|||||||
case Type_Pointer: high = v_one; break;
|
case Type_Pointer: high = v_one; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (max == NULL) {
|
|
||||||
switch (bt->kind) {
|
|
||||||
case Type_Array: max = ssa_array_cap(proc, base); break;
|
|
||||||
case Type_Slice: max = ssa_slice_cap(proc, base); break;
|
|
||||||
case Type_Pointer: max = high; break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GB_ASSERT(max != NULL);
|
|
||||||
|
|
||||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
|
||||||
|
|
||||||
ssaValue *elem = NULL;
|
ssaValue *elem = NULL;
|
||||||
switch (bt->kind) {
|
switch (bt->kind) {
|
||||||
@@ -1859,9 +1843,6 @@ ssaValue *ssa_add_local_slice(ssaProcedure *proc, Type *slice_type, ssaValue *ba
|
|||||||
gep = ssa_emit_struct_ep(proc, slice, 1);
|
gep = ssa_emit_struct_ep(proc, slice, 1);
|
||||||
ssa_emit_store(proc, gep, len);
|
ssa_emit_store(proc, gep, len);
|
||||||
|
|
||||||
gep = ssa_emit_struct_ep(proc, slice, 2);
|
|
||||||
ssa_emit_store(proc, gep, cap);
|
|
||||||
|
|
||||||
return slice;
|
return slice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2103,7 +2084,7 @@ ssaValue *ssa_emit_conv(ssaProcedure *proc, ssaValue *value, Type *t) {
|
|||||||
ssa_emit_store(proc, elem_ptr, elem);
|
ssa_emit_store(proc, elem_ptr, elem);
|
||||||
|
|
||||||
ssaValue *len = ssa_string_len(proc, value);
|
ssaValue *len = ssa_string_len(proc, value);
|
||||||
ssaValue *slice = ssa_add_local_slice(proc, dst, elem_ptr, v_zero, len, len);
|
ssaValue *slice = ssa_add_local_slice(proc, dst, elem_ptr, v_zero, len);
|
||||||
return ssa_emit_load(proc, slice);
|
return ssa_emit_load(proc, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2463,16 +2444,15 @@ void ssa_emit_bounds_check(ssaProcedure *proc, Token token, ssaValue *index, ssa
|
|||||||
// ssa_emit_global_call(proc, "__bounds_check_error", args, 5);
|
// ssa_emit_global_call(proc, "__bounds_check_error", args, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, ssaValue *max, bool is_substring) {
|
void ssa_emit_slice_bounds_check(ssaProcedure *proc, Token token, ssaValue *low, ssaValue *high, bool is_substring) {
|
||||||
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
if ((proc->module->stmt_state_flags & StmtStateFlag_no_bounds_check) != 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
low = ssa_emit_conv(proc, low, t_int);
|
low = ssa_emit_conv(proc, low, t_int);
|
||||||
high = ssa_emit_conv(proc, high, t_int);
|
high = ssa_emit_conv(proc, high, t_int);
|
||||||
max = ssa_emit_conv(proc, max, t_int);
|
|
||||||
|
|
||||||
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, max, is_substring));
|
ssa_emit(proc, ssa_make_instr_slice_bounds_check(proc, token.pos, low, high, is_substring));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2886,7 +2866,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[2]), t_int);
|
cap = ssa_emit_conv(proc, ssa_build_expr(proc, ce->args.e[2]), t_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, len, cap, false);
|
ssa_emit_slice_bounds_check(proc, ast_node_token(ce->args.e[1]), v_zero, len, false);
|
||||||
|
|
||||||
ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
|
ssaValue *slice_size = ssa_emit_arith(proc, Token_Mul, elem_size, cap, t_int);
|
||||||
|
|
||||||
@@ -2995,6 +2975,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
|
|
||||||
return len;
|
return len;
|
||||||
} break;
|
} break;
|
||||||
|
#if 0
|
||||||
case BuiltinProc_append: {
|
case BuiltinProc_append: {
|
||||||
ssa_emit_comment(proc, str_lit("append"));
|
ssa_emit_comment(proc, str_lit("append"));
|
||||||
// append :: proc(s: ^[]Type, item: Type) -> bool
|
// append :: proc(s: ^[]Type, item: Type) -> bool
|
||||||
@@ -3051,6 +3032,7 @@ ssaValue *ssa_build_single_expr(ssaProcedure *proc, AstNode *expr, TypeAndValue
|
|||||||
|
|
||||||
return ssa_emit_conv(proc, cond, t_bool);
|
return ssa_emit_conv(proc, cond, t_bool);
|
||||||
} break;
|
} break;
|
||||||
|
#endif
|
||||||
|
|
||||||
case BuiltinProc_swizzle: {
|
case BuiltinProc_swizzle: {
|
||||||
ssa_emit_comment(proc, str_lit("swizzle"));
|
ssa_emit_comment(proc, str_lit("swizzle"));
|
||||||
@@ -3533,11 +3515,9 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
gbAllocator a = proc->module->allocator;
|
gbAllocator a = proc->module->allocator;
|
||||||
ssaValue *low = v_zero;
|
ssaValue *low = v_zero;
|
||||||
ssaValue *high = NULL;
|
ssaValue *high = NULL;
|
||||||
ssaValue *max = NULL;
|
|
||||||
|
|
||||||
if (se->low != NULL) low = ssa_build_expr(proc, se->low);
|
if (se->low != NULL) low = ssa_build_expr(proc, se->low);
|
||||||
if (se->high != NULL) high = ssa_build_expr(proc, se->high);
|
if (se->high != NULL) high = ssa_build_expr(proc, se->high);
|
||||||
if (se->triple_indexed) max = ssa_build_expr(proc, se->max);
|
|
||||||
ssaValue *addr = ssa_build_addr(proc, se->expr).addr;
|
ssaValue *addr = ssa_build_addr(proc, se->expr).addr;
|
||||||
ssaValue *base = ssa_emit_load(proc, addr);
|
ssaValue *base = ssa_emit_load(proc, addr);
|
||||||
Type *type = base_type(ssa_type(base));
|
Type *type = base_type(ssa_type(base));
|
||||||
@@ -3555,22 +3535,17 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
Type *slice_type = type;
|
Type *slice_type = type;
|
||||||
|
|
||||||
if (high == NULL) high = ssa_slice_len(proc, base);
|
if (high == NULL) high = ssa_slice_len(proc, base);
|
||||||
if (max == NULL) max = ssa_slice_cap(proc, base);
|
|
||||||
GB_ASSERT(max != NULL);
|
|
||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_emit_slice_bounds_check(proc, se->open, low, high, false);
|
||||||
|
|
||||||
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_slice_elem(proc, base), low);
|
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_slice_elem(proc, base), low);
|
||||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
|
|
||||||
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
||||||
ssaValue *gep1 = ssa_emit_struct_ep(proc, slice, 1);
|
ssaValue *gep1 = ssa_emit_struct_ep(proc, slice, 1);
|
||||||
ssaValue *gep2 = ssa_emit_struct_ep(proc, slice, 2);
|
|
||||||
ssa_emit_store(proc, gep0, elem);
|
ssa_emit_store(proc, gep0, elem);
|
||||||
ssa_emit_store(proc, gep1, len);
|
ssa_emit_store(proc, gep1, len);
|
||||||
ssa_emit_store(proc, gep2, cap);
|
|
||||||
|
|
||||||
return ssa_make_addr(slice, expr);
|
return ssa_make_addr(slice, expr);
|
||||||
}
|
}
|
||||||
@@ -3579,22 +3554,17 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
Type *slice_type = make_type_slice(a, type->Array.elem);
|
Type *slice_type = make_type_slice(a, type->Array.elem);
|
||||||
|
|
||||||
if (high == NULL) high = ssa_array_len(proc, base);
|
if (high == NULL) high = ssa_array_len(proc, base);
|
||||||
if (max == NULL) max = ssa_array_cap(proc, base);
|
|
||||||
GB_ASSERT(max != NULL);
|
|
||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, max, false);
|
ssa_emit_slice_bounds_check(proc, se->open, low, high, false);
|
||||||
|
|
||||||
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_array_elem(proc, addr), low);
|
ssaValue *elem = ssa_emit_ptr_offset(proc, ssa_array_elem(proc, addr), low);
|
||||||
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
ssaValue *len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
ssaValue *cap = ssa_emit_arith(proc, Token_Sub, max, low, t_int);
|
|
||||||
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
ssaValue *slice = ssa_add_local_generated(proc, slice_type);
|
||||||
|
|
||||||
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
ssaValue *gep0 = ssa_emit_struct_ep(proc, slice, 0);
|
||||||
ssaValue *gep1 = ssa_emit_struct_ep(proc, slice, 1);
|
ssaValue *gep1 = ssa_emit_struct_ep(proc, slice, 1);
|
||||||
ssaValue *gep2 = ssa_emit_struct_ep(proc, slice, 2);
|
|
||||||
ssa_emit_store(proc, gep0, elem);
|
ssa_emit_store(proc, gep0, elem);
|
||||||
ssa_emit_store(proc, gep1, len);
|
ssa_emit_store(proc, gep1, len);
|
||||||
ssa_emit_store(proc, gep2, cap);
|
|
||||||
|
|
||||||
return ssa_make_addr(slice, expr);
|
return ssa_make_addr(slice, expr);
|
||||||
}
|
}
|
||||||
@@ -3605,7 +3575,7 @@ ssaAddr ssa_build_addr(ssaProcedure *proc, AstNode *expr) {
|
|||||||
high = ssa_string_len(proc, base);
|
high = ssa_string_len(proc, base);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_emit_slice_bounds_check(proc, se->open, low, high, high, true);
|
ssa_emit_slice_bounds_check(proc, se->open, low, high, true);
|
||||||
|
|
||||||
ssaValue *elem, *len;
|
ssaValue *elem, *len;
|
||||||
len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
len = ssa_emit_arith(proc, Token_Sub, high, low, t_int);
|
||||||
@@ -4249,20 +4219,6 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
|
|||||||
}
|
}
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(ids, IncDecStmt, node);
|
|
||||||
ssa_emit_comment(proc, str_lit("IncDecStmt"));
|
|
||||||
TokenKind op = ids->op.kind;
|
|
||||||
if (op == Token_Increment) {
|
|
||||||
op = Token_Add;
|
|
||||||
} else if (op == Token_Decrement) {
|
|
||||||
op = Token_Sub;
|
|
||||||
}
|
|
||||||
ssaAddr lval = ssa_build_addr(proc, ids->expr);
|
|
||||||
ssaValue *one = ssa_emit_conv(proc, v_one, ssa_addr_type(lval));
|
|
||||||
ssa_build_assign_op(proc, lval, one, op);
|
|
||||||
|
|
||||||
case_end;
|
|
||||||
|
|
||||||
case_ast_node(as, AssignStmt, node);
|
case_ast_node(as, AssignStmt, node);
|
||||||
ssa_emit_comment(proc, str_lit("AssignStmt"));
|
ssa_emit_comment(proc, str_lit("AssignStmt"));
|
||||||
|
|
||||||
@@ -4444,56 +4400,44 @@ void ssa_build_stmt_internal(ssaProcedure *proc, AstNode *node) {
|
|||||||
proc->curr_block = done;
|
proc->curr_block = done;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fs, ForStmt, node);
|
case_ast_node(ws, WhileStmt, node);
|
||||||
ssa_emit_comment(proc, str_lit("ForStmt"));
|
ssa_emit_comment(proc, str_lit("WhileStmt"));
|
||||||
if (fs->init != NULL) {
|
if (ws->init != NULL) {
|
||||||
ssaBlock *init = ssa_add_block(proc, node, "for.init");
|
ssaBlock *init = ssa_add_block(proc, node, "while.init");
|
||||||
ssa_emit_jump(proc, init);
|
ssa_emit_jump(proc, init);
|
||||||
proc->curr_block = init;
|
proc->curr_block = init;
|
||||||
ssa_build_stmt(proc, fs->init);
|
ssa_build_stmt(proc, ws->init);
|
||||||
}
|
}
|
||||||
ssaBlock *body = ssa_add_block(proc, node, "for.body");
|
ssaBlock *body = ssa_add_block(proc, node, "while.body");
|
||||||
ssaBlock *done = ssa_add_block(proc, node, "for.done"); // NOTE(bill): Append later
|
ssaBlock *done = ssa_add_block(proc, node, "while.done"); // NOTE(bill): Append later
|
||||||
|
|
||||||
ssaBlock *loop = body;
|
ssaBlock *loop = body;
|
||||||
|
|
||||||
if (fs->cond != NULL) {
|
if (ws->cond != NULL) {
|
||||||
loop = ssa_add_block(proc, node, "for.loop");
|
loop = ssa_add_block(proc, node, "while.loop");
|
||||||
}
|
|
||||||
ssaBlock *cont = loop;
|
|
||||||
if (fs->post != NULL) {
|
|
||||||
cont = ssa_add_block(proc, node, "for.post");
|
|
||||||
|
|
||||||
}
|
}
|
||||||
ssa_emit_jump(proc, loop);
|
ssa_emit_jump(proc, loop);
|
||||||
proc->curr_block = loop;
|
proc->curr_block = loop;
|
||||||
if (loop != body) {
|
if (loop != body) {
|
||||||
ssa_build_cond(proc, fs->cond, body, done);
|
ssa_build_cond(proc, ws->cond, body, done);
|
||||||
proc->curr_block = body;
|
proc->curr_block = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssa_push_target_list(proc, done, cont, NULL);
|
ssa_push_target_list(proc, done, loop, NULL);
|
||||||
|
|
||||||
ssa_open_scope(proc);
|
ssa_open_scope(proc);
|
||||||
ssa_build_stmt(proc, fs->body);
|
ssa_build_stmt(proc, ws->body);
|
||||||
ssa_close_scope(proc, ssaDeferExit_Default, NULL);
|
ssa_close_scope(proc, ssaDeferExit_Default, NULL);
|
||||||
|
|
||||||
ssa_pop_target_list(proc);
|
ssa_pop_target_list(proc);
|
||||||
ssa_emit_jump(proc, cont);
|
ssa_emit_jump(proc, loop);
|
||||||
|
|
||||||
if (fs->post != NULL) {
|
|
||||||
proc->curr_block = cont;
|
|
||||||
ssa_build_stmt(proc, fs->post);
|
|
||||||
ssa_emit_jump(proc, loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
proc->curr_block = done;
|
proc->curr_block = done;
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
|
|
||||||
case_ast_node(rs, RangeStmt, node);
|
case_ast_node(rs, ForStmt, node);
|
||||||
ssa_emit_comment(proc, str_lit("RangeStmt"));
|
ssa_emit_comment(proc, str_lit("ForStmt"));
|
||||||
|
|
||||||
Type *val_type = NULL;
|
Type *val_type = NULL;
|
||||||
Type *idx_type = NULL;
|
Type *idx_type = NULL;
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ void ssa_opt_add_operands(ssaValueArray *ops, ssaInstr *i) {
|
|||||||
case ssaInstr_SliceBoundsCheck:
|
case ssaInstr_SliceBoundsCheck:
|
||||||
array_add(ops, i->SliceBoundsCheck.low);
|
array_add(ops, i->SliceBoundsCheck.low);
|
||||||
array_add(ops, i->SliceBoundsCheck.high);
|
array_add(ops, i->SliceBoundsCheck.high);
|
||||||
array_add(ops, i->SliceBoundsCheck.max);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1225,13 +1225,6 @@ void ssa_print_instr(ssaFileBuffer *f, ssaModule *m, ssaValue *value) {
|
|||||||
ssa_fprintf(f, " ");
|
ssa_fprintf(f, " ");
|
||||||
ssa_print_value(f, m, bc->high, t_int);
|
ssa_print_value(f, m, bc->high, t_int);
|
||||||
|
|
||||||
if (!bc->is_substring) {
|
|
||||||
ssa_fprintf(f, ", ");
|
|
||||||
ssa_print_type(f, m, t_int);
|
|
||||||
ssa_fprintf(f, " ");
|
|
||||||
ssa_print_value(f, m, bc->max, t_int);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssa_fprintf(f, ")\n");
|
ssa_fprintf(f, ")\n");
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+8
-7
@@ -53,8 +53,6 @@ TOKEN_KIND(Token__AssignOpBegin, "_AssignOpBegin"), \
|
|||||||
TOKEN_KIND(Token_CmpAndEq, "&&="), \
|
TOKEN_KIND(Token_CmpAndEq, "&&="), \
|
||||||
TOKEN_KIND(Token_CmpOrEq, "||="), \
|
TOKEN_KIND(Token_CmpOrEq, "||="), \
|
||||||
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
|
TOKEN_KIND(Token__AssignOpEnd, "_AssignOpEnd"), \
|
||||||
TOKEN_KIND(Token_Increment, "++"), \
|
|
||||||
TOKEN_KIND(Token_Decrement, "--"), \
|
|
||||||
TOKEN_KIND(Token_ArrowRight, "->"), \
|
TOKEN_KIND(Token_ArrowRight, "->"), \
|
||||||
TOKEN_KIND(Token_ArrowLeft, "<-"), \
|
TOKEN_KIND(Token_ArrowLeft, "<-"), \
|
||||||
\
|
\
|
||||||
@@ -77,7 +75,7 @@ TOKEN_KIND(Token__ComparisonEnd, "_ComparisonEnd"), \
|
|||||||
TOKEN_KIND(Token_Semicolon, ";"), \
|
TOKEN_KIND(Token_Semicolon, ";"), \
|
||||||
TOKEN_KIND(Token_Period, "."), \
|
TOKEN_KIND(Token_Period, "."), \
|
||||||
TOKEN_KIND(Token_Comma, ","), \
|
TOKEN_KIND(Token_Comma, ","), \
|
||||||
TOKEN_KIND(Token_Ellipsis, ".."), \
|
TOKEN_KIND(Token_Ellipsis, "..."), \
|
||||||
TOKEN_KIND(Token_Interval, "..<"), \
|
TOKEN_KIND(Token_Interval, "..<"), \
|
||||||
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
TOKEN_KIND(Token__OperatorEnd, "_OperatorEnd"), \
|
||||||
\
|
\
|
||||||
@@ -94,6 +92,7 @@ TOKEN_KIND(Token__KeywordBegin, "_KeywordBegin"), \
|
|||||||
TOKEN_KIND(Token_then, "then"), \
|
TOKEN_KIND(Token_then, "then"), \
|
||||||
TOKEN_KIND(Token_if, "if"), \
|
TOKEN_KIND(Token_if, "if"), \
|
||||||
TOKEN_KIND(Token_else, "else"), \
|
TOKEN_KIND(Token_else, "else"), \
|
||||||
|
TOKEN_KIND(Token_while, "while"), \
|
||||||
TOKEN_KIND(Token_for, "for"), \
|
TOKEN_KIND(Token_for, "for"), \
|
||||||
TOKEN_KIND(Token_when, "when"), \
|
TOKEN_KIND(Token_when, "when"), \
|
||||||
TOKEN_KIND(Token_range, "range"), \
|
TOKEN_KIND(Token_range, "range"), \
|
||||||
@@ -837,8 +836,10 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
token = scan_number_to_token(t, true);
|
token = scan_number_to_token(t, true);
|
||||||
} else if (t->curr_rune == '.') { // Could be an ellipsis
|
} else if (t->curr_rune == '.') { // Could be an ellipsis
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
token.kind = Token_Ellipsis;
|
if (t->curr_rune == '.') {
|
||||||
if (t->curr_rune == '<') {
|
advance_to_next_rune(t);
|
||||||
|
token.kind = Token_Ellipsis;
|
||||||
|
} else if (t->curr_rune == '<') {
|
||||||
advance_to_next_rune(t);
|
advance_to_next_rune(t);
|
||||||
token.kind = Token_Interval;
|
token.kind = Token_Interval;
|
||||||
}
|
}
|
||||||
@@ -891,10 +892,10 @@ Token tokenizer_get_token(Tokenizer *t) {
|
|||||||
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
case '~': token.kind = token_kind_variant2(t, Token_Xor, Token_XorEq); break;
|
||||||
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
case '!': token.kind = token_kind_variant2(t, Token_Not, Token_NotEq); break;
|
||||||
case '+':
|
case '+':
|
||||||
token.kind = token_kind_variant3(t, Token_Add, Token_AddEq, '+', Token_Increment);
|
token.kind = token_kind_variant2(t, Token_Add, Token_AddEq);
|
||||||
break;
|
break;
|
||||||
case '-':
|
case '-':
|
||||||
token.kind = token_kind_variant4(t, Token_Sub, Token_SubEq, '-', Token_Decrement, '>', Token_ArrowRight);
|
token.kind = token_kind_variant3(t, Token_Sub, Token_SubEq, '>', Token_ArrowRight);
|
||||||
break;
|
break;
|
||||||
case '/': {
|
case '/': {
|
||||||
if (t->curr_rune == '/') {
|
if (t->curr_rune == '/') {
|
||||||
|
|||||||
Reference in New Issue
Block a user