mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 15:48:51 +00:00
Default result values for procedure types; Named result values in return statements
This commit is contained in:
+25
-35
@@ -121,9 +121,8 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
proc type_info_base(info: ^TypeInfo) -> ^TypeInfo {
|
proc type_info_base(info: ^TypeInfo) -> ^TypeInfo {
|
||||||
if info == nil {
|
if info == nil -> return nil;
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
var base = info;
|
var base = info;
|
||||||
match i in base {
|
match i in base {
|
||||||
case TypeInfo.Named:
|
case TypeInfo.Named:
|
||||||
@@ -134,9 +133,8 @@ proc type_info_base(info: ^TypeInfo) -> ^TypeInfo {
|
|||||||
|
|
||||||
|
|
||||||
proc type_info_base_without_enum(info: ^TypeInfo) -> ^TypeInfo {
|
proc type_info_base_without_enum(info: ^TypeInfo) -> ^TypeInfo {
|
||||||
if info == nil {
|
if info == nil -> return nil;
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
var base = info;
|
var base = info;
|
||||||
match i in base {
|
match i in base {
|
||||||
case TypeInfo.Named:
|
case TypeInfo.Named:
|
||||||
@@ -202,16 +200,20 @@ proc make_source_code_location(file: string, line, column: i64, procedure: strin
|
|||||||
const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
|
const DEFAULT_ALIGNMENT = align_of([vector 4]f32);
|
||||||
|
|
||||||
proc __init_context_from_ptr(c: ^Context, other: ^Context) #cc_contextless {
|
proc __init_context_from_ptr(c: ^Context, other: ^Context) #cc_contextless {
|
||||||
if c == nil {
|
if c == nil -> return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
c^ = other^;
|
c^ = other^;
|
||||||
|
|
||||||
|
if c.allocator.procedure == nil {
|
||||||
|
c.allocator = default_allocator();
|
||||||
|
}
|
||||||
|
if c.thread_id == 0 {
|
||||||
|
c.thread_id = os.current_thread_id();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
proc __init_context(c: ^Context) #cc_contextless {
|
proc __init_context(c: ^Context) #cc_contextless {
|
||||||
if c == nil {
|
if c == nil -> return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
if c.allocator.procedure == nil {
|
if c.allocator.procedure == nil {
|
||||||
c.allocator = default_allocator();
|
c.allocator = default_allocator();
|
||||||
}
|
}
|
||||||
@@ -497,9 +499,7 @@ proc __dynamic_array_make(array_: rawptr, elem_size, elem_align: int, len, cap:
|
|||||||
proc __dynamic_array_reserve(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool {
|
proc __dynamic_array_reserve(array_: rawptr, elem_size, elem_align: int, cap: int) -> bool {
|
||||||
var array = ^raw.DynamicArray(array_);
|
var array = ^raw.DynamicArray(array_);
|
||||||
|
|
||||||
if cap <= array.cap {
|
if cap <= array.cap -> return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// __check_context();
|
// __check_context();
|
||||||
if array.allocator.procedure == nil {
|
if array.allocator.procedure == nil {
|
||||||
@@ -512,9 +512,7 @@ proc __dynamic_array_reserve(array_: rawptr, elem_size, elem_align: int, cap: in
|
|||||||
var allocator = array.allocator;
|
var allocator = array.allocator;
|
||||||
|
|
||||||
var new_data = allocator.procedure(allocator.data, AllocatorMode.Resize, new_size, elem_align, array.data, old_size, 0);
|
var new_data = allocator.procedure(allocator.data, AllocatorMode.Resize, new_size, elem_align, array.data, old_size, 0);
|
||||||
if new_data == nil {
|
if new_data == nil -> return false;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
array.data = new_data;
|
array.data = new_data;
|
||||||
array.cap = cap;
|
array.cap = cap;
|
||||||
@@ -525,9 +523,7 @@ proc __dynamic_array_resize(array_: rawptr, elem_size, elem_align: int, len: int
|
|||||||
var array = ^raw.DynamicArray(array_);
|
var array = ^raw.DynamicArray(array_);
|
||||||
|
|
||||||
var ok = __dynamic_array_reserve(array_, elem_size, elem_align, len);
|
var ok = __dynamic_array_reserve(array_, elem_size, elem_align, len);
|
||||||
if ok {
|
if ok -> array.len = len;
|
||||||
array.len = len;
|
|
||||||
}
|
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,10 +542,9 @@ proc __dynamic_array_append(array_: rawptr, elem_size, elem_align: int,
|
|||||||
var cap = 2 * array.cap + max(8, item_count);
|
var cap = 2 * array.cap + max(8, item_count);
|
||||||
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
||||||
}
|
}
|
||||||
if !ok {
|
// TODO(bill): Better error handling for failed reservation
|
||||||
// TODO(bill): Better error handling for failed reservation
|
if !ok -> return array.len;
|
||||||
return array.len;
|
|
||||||
}
|
|
||||||
var data = ^u8(array.data);
|
var data = ^u8(array.data);
|
||||||
assert(data != nil);
|
assert(data != nil);
|
||||||
__mem_copy(data + (elem_size*array.len), items, elem_size * item_count);
|
__mem_copy(data + (elem_size*array.len), items, elem_size * item_count);
|
||||||
@@ -565,10 +560,9 @@ proc __dynamic_array_append_nothing(array_: rawptr, elem_size, elem_align: int)
|
|||||||
var cap = 2 * array.cap + max(8, 1);
|
var cap = 2 * array.cap + max(8, 1);
|
||||||
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
ok = __dynamic_array_reserve(array, elem_size, elem_align, cap);
|
||||||
}
|
}
|
||||||
if !ok {
|
// TODO(bill): Better error handling for failed reservation
|
||||||
// TODO(bill): Better error handling for failed reservation
|
if !ok -> return array.len;
|
||||||
return array.len;
|
|
||||||
}
|
|
||||||
var data = ^u8(array.data);
|
var data = ^u8(array.data);
|
||||||
assert(data != nil);
|
assert(data != nil);
|
||||||
__mem_zero(data + (elem_size*array.len), elem_size);
|
__mem_zero(data + (elem_size*array.len), elem_size);
|
||||||
@@ -658,9 +652,7 @@ proc __dynamic_map_rehash(using header: __MapHeader, new_count: int) {
|
|||||||
|
|
||||||
__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count);
|
__dynamic_array_resize(nm_hashes, size_of(int), align_of(int), new_count);
|
||||||
__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len);
|
__dynamic_array_reserve(&nm.entries, entry_size, entry_align, m.entries.len);
|
||||||
for i in 0..<new_count {
|
for i in 0..<new_count -> nm.hashes[i] = -1;
|
||||||
nm.hashes[i] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for var i = 0; i < m.entries.len; i++ {
|
for var i = 0; i < m.entries.len; i++ {
|
||||||
if len(nm.hashes) == 0 {
|
if len(nm.hashes) == 0 {
|
||||||
@@ -750,9 +742,7 @@ proc __dynamic_map_full(using h: __MapHeader) -> bool {
|
|||||||
|
|
||||||
proc __dynamic_map_hash_equal(h: __MapHeader, a, b: __MapKey) -> bool {
|
proc __dynamic_map_hash_equal(h: __MapHeader, a, b: __MapKey) -> bool {
|
||||||
if a.hash == b.hash {
|
if a.hash == b.hash {
|
||||||
if h.is_key_string {
|
if h.is_key_string -> return a.str == b.str;
|
||||||
return a.str == b.str;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
+2
-6
@@ -11,9 +11,7 @@ type Decimal struct {
|
|||||||
|
|
||||||
proc decimal_to_string(buf: []u8, a: ^Decimal) -> string {
|
proc decimal_to_string(buf: []u8, a: ^Decimal) -> string {
|
||||||
proc digit_zero(buf: []u8) -> int {
|
proc digit_zero(buf: []u8) -> int {
|
||||||
for _, i in buf {
|
for _, i in buf -> buf[i] = '0';
|
||||||
buf[i] = '0';
|
|
||||||
}
|
|
||||||
return len(buf);
|
return len(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,9 +196,7 @@ proc shift(a: ^Decimal, k: int) {
|
|||||||
proc can_round_up(a: ^Decimal, nd: int) -> bool {
|
proc can_round_up(a: ^Decimal, nd: int) -> bool {
|
||||||
if nd < 0 || nd >= a.count { return false ; }
|
if nd < 0 || nd >= a.count { return false ; }
|
||||||
if a.digits[nd] == '5' && nd+1 == a.count {
|
if a.digits[nd] == '5' && nd+1 == a.count {
|
||||||
if a.trunc {
|
if a.trunc -> return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return nd > 0 && (a.digits[nd-1]-'0')%2 != 0;
|
return nd > 0 && (a.digits[nd-1]-'0')%2 != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+44
-88
@@ -189,9 +189,7 @@ proc fprint_type(fd: os.Handle, info: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
||||||
if ti == nil {
|
if ti == nil -> return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
using TypeInfo;
|
using TypeInfo;
|
||||||
match info in ti {
|
match info in ti {
|
||||||
@@ -242,7 +240,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
var t = info.params.(^Tuple);
|
var t = info.params.(^Tuple);
|
||||||
write_string(buf, "(");
|
write_string(buf, "(");
|
||||||
for t, i in t.types {
|
for t, i in t.types {
|
||||||
if i > 0 { write_string(buf, ", "); }
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_type(buf, t);
|
write_type(buf, t);
|
||||||
}
|
}
|
||||||
write_string(buf, ")");
|
write_string(buf, ")");
|
||||||
@@ -253,9 +251,9 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
case Tuple:
|
case Tuple:
|
||||||
var count = len(info.names);
|
var count = len(info.names);
|
||||||
if count != 1 { write_string(buf, "("); }
|
if count != 1 -> write_string(buf, "(");
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
if i > 0 { write_string(buf, ", "); }
|
if i > 0 -> write_string(buf, ", ");
|
||||||
|
|
||||||
var t = info.types[i];
|
var t = info.types[i];
|
||||||
|
|
||||||
@@ -265,7 +263,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
write_type(buf, t);
|
write_type(buf, t);
|
||||||
}
|
}
|
||||||
if count != 1 { write_string(buf, ")"); }
|
if count != 1 -> write_string(buf, ")");
|
||||||
|
|
||||||
case Array:
|
case Array:
|
||||||
write_string(buf, "[");
|
write_string(buf, "[");
|
||||||
@@ -293,8 +291,8 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
|
|
||||||
case Struct:
|
case Struct:
|
||||||
write_string(buf, "struct ");
|
write_string(buf, "struct ");
|
||||||
if info.packed { write_string(buf, "#packed "); }
|
if info.packed -> write_string(buf, "#packed ");
|
||||||
if info.ordered { write_string(buf, "#ordered "); }
|
if info.ordered -> write_string(buf, "#ordered ");
|
||||||
if info.custom_align {
|
if info.custom_align {
|
||||||
write_string(buf, "#align ");
|
write_string(buf, "#align ");
|
||||||
write_int(buf, i64(info.align), 10);
|
write_int(buf, i64(info.align), 10);
|
||||||
@@ -302,9 +300,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
write_byte(buf, '{');
|
write_byte(buf, '{');
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
write_string(buf, ": ");
|
write_string(buf, ": ");
|
||||||
write_type(buf, info.types[i]);
|
write_type(buf, info.types[i]);
|
||||||
@@ -316,18 +312,14 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
var cf = info.common_fields;
|
var cf = info.common_fields;
|
||||||
var total_count = 0;
|
var total_count = 0;
|
||||||
for name, i in cf.names {
|
for name, i in cf.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
write_string(buf, ": ");
|
write_string(buf, ": ");
|
||||||
write_type(buf, cf.types[i]);
|
write_type(buf, cf.types[i]);
|
||||||
total_count++;
|
total_count++;
|
||||||
}
|
}
|
||||||
for name, i in info.variant_names {
|
for name, i in info.variant_names {
|
||||||
if total_count > 0 || i > 0 {
|
if total_count > 0 || i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
write_byte(buf, '{');
|
write_byte(buf, '{');
|
||||||
defer write_byte(buf, '}');
|
defer write_byte(buf, '}');
|
||||||
@@ -337,9 +329,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
|
|
||||||
var vc = len(variant.names)-len(cf.names);
|
var vc = len(variant.names)-len(cf.names);
|
||||||
for j in 0..vc {
|
for j in 0..vc {
|
||||||
if j > 0 {
|
if j > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
var index = j + len(cf.names);
|
var index = j + len(cf.names);
|
||||||
write_string(buf, variant.names[index]);
|
write_string(buf, variant.names[index]);
|
||||||
write_string(buf, ": ");
|
write_string(buf, ": ");
|
||||||
@@ -351,9 +341,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
case RawUnion:
|
case RawUnion:
|
||||||
write_string(buf, "raw_union {");
|
write_string(buf, "raw_union {");
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
write_string(buf, ": ");
|
write_string(buf, ": ");
|
||||||
write_type(buf, info.types[i]);
|
write_type(buf, info.types[i]);
|
||||||
@@ -365,9 +353,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
write_type(buf, info.base);
|
write_type(buf, info.base);
|
||||||
write_string(buf, " {");
|
write_string(buf, " {");
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
}
|
}
|
||||||
write_string(buf, "}");
|
write_string(buf, "}");
|
||||||
@@ -380,9 +366,7 @@ proc write_type(buf: ^StringBuffer, ti: ^TypeInfo) {
|
|||||||
}
|
}
|
||||||
write_string(buf, " {");
|
write_string(buf, " {");
|
||||||
for name, i in info.names {
|
for name, i in info.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(buf, ", ");
|
||||||
write_string(buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(buf, name);
|
write_string(buf, name);
|
||||||
write_string(buf, ": ");
|
write_string(buf, ": ");
|
||||||
write_int(buf, i64(info.bits[i]), 10);
|
write_int(buf, i64(info.bits[i]), 10);
|
||||||
@@ -404,9 +388,7 @@ proc _parse_int(s: string, offset: int) -> (result: int, offset: int, ok: bool)
|
|||||||
var i = 0;
|
var i = 0;
|
||||||
for i < len(s[offset..]) {
|
for i < len(s[offset..]) {
|
||||||
var c = rune(s[offset+i]);
|
var c = rune(s[offset+i]);
|
||||||
if !is_digit(c) {
|
if !is_digit(c) -> break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
result *= 10;
|
result *= 10;
|
||||||
@@ -500,19 +482,13 @@ proc fmt_bool(using fi: ^FmtInfo, b: bool, verb: rune) {
|
|||||||
|
|
||||||
|
|
||||||
proc fmt_write_padding(fi: ^FmtInfo, width: int) {
|
proc fmt_write_padding(fi: ^FmtInfo, width: int) {
|
||||||
if width <= 0 {
|
if width <= 0 -> return;
|
||||||
return;
|
|
||||||
}
|
var pad_byte: u8 = fi.space ? ' ' : '0';
|
||||||
var pad_byte: u8 = '0';
|
|
||||||
if fi.space {
|
|
||||||
pad_byte = ' ';
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = string_buffer_data(fi.buf^);
|
var data = string_buffer_data(fi.buf^);
|
||||||
var count = min(width, cap(data)-len(data));
|
var count = min(width, cap(data)-len(data));
|
||||||
for _ in 0..<count {
|
for _ in 0..<count -> write_byte(fi.buf, pad_byte);
|
||||||
write_byte(fi.buf, pad_byte);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
proc _fmt_int(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) {
|
proc _fmt_int(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int, digits: string) {
|
||||||
@@ -557,9 +533,9 @@ proc _fmt_int(fi: ^FmtInfo, u: u128, base: int, is_signed: bool, bit_size: int,
|
|||||||
|
|
||||||
|
|
||||||
var flags: strconv.IntFlag;
|
var flags: strconv.IntFlag;
|
||||||
if fi.hash && !fi.zero { flags |= strconv.IntFlag.Prefix; }
|
if fi.hash && !fi.zero -> flags |= strconv.IntFlag.Prefix;
|
||||||
if fi.plus { flags |= strconv.IntFlag.Plus; }
|
if fi.plus -> flags |= strconv.IntFlag.Plus;
|
||||||
if fi.space { flags |= strconv.IntFlag.Space; }
|
if fi.space -> flags |= strconv.IntFlag.Space;
|
||||||
var s = strconv.append_bits(buf[start..<start], u128(u), base, is_signed, bit_size, digits, flags);
|
var s = strconv.append_bits(buf[start..<start], u128(u), base, is_signed, bit_size, digits, flags);
|
||||||
|
|
||||||
if fi.hash && fi.zero {
|
if fi.hash && fi.zero {
|
||||||
@@ -642,11 +618,8 @@ proc fmt_float(fi: ^FmtInfo, v: f64, bit_size: int, verb: rune) {
|
|||||||
// case 'f', 'F', 'v':
|
// case 'f', 'F', 'v':
|
||||||
|
|
||||||
case 'f', 'F', 'v':
|
case 'f', 'F', 'v':
|
||||||
var prec: int = 3;
|
var prec: int = fi.prec_set ? fi.prec : 3;
|
||||||
var buf: [386]u8;
|
var buf: [386]u8;
|
||||||
if fi.prec_set {
|
|
||||||
prec = fi.prec;
|
|
||||||
}
|
|
||||||
|
|
||||||
var str = strconv.append_float(buf[1..<1], v, 'f', prec, bit_size);
|
var str = strconv.append_float(buf[1..<1], v, 'f', prec, bit_size);
|
||||||
str = string(buf[0..len(str)]);
|
str = string(buf[0..len(str)]);
|
||||||
@@ -692,9 +665,7 @@ proc fmt_string(fi: ^FmtInfo, s: string, verb: rune) {
|
|||||||
defer fi.space = space;
|
defer fi.space = space;
|
||||||
|
|
||||||
for i in 0..<len(s) {
|
for i in 0..<len(s) {
|
||||||
if i > 0 && space {
|
if i > 0 && space -> write_byte(fi.buf, ' ');
|
||||||
write_byte(fi.buf, ' ');
|
|
||||||
}
|
|
||||||
_fmt_int(fi, u128(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
|
_fmt_int(fi, u128(s[i]), 16, false, 8, verb == 'x' ? __DIGITS_LOWER : __DIGITS_UPPER);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -810,9 +781,7 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
write_string(fi.buf, info.name);
|
write_string(fi.buf, info.name);
|
||||||
write_byte(fi.buf, '{');
|
write_byte(fi.buf, '{');
|
||||||
for _, i in b.names {
|
for _, i in b.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(fi.buf, b.names[i]);
|
write_string(fi.buf, b.names[i]);
|
||||||
write_string(fi.buf, " = ");
|
write_string(fi.buf, " = ");
|
||||||
|
|
||||||
@@ -846,9 +815,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
write_byte(fi.buf, '[');
|
write_byte(fi.buf, '[');
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
for i in 0..<info.count {
|
for i in 0..<info.count {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
var data = ^u8(v.data) + i*info.elem_size;
|
var data = ^u8(v.data) + i*info.elem_size;
|
||||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
@@ -858,9 +826,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
var array = ^raw.DynamicArray(v.data);
|
var array = ^raw.DynamicArray(v.data);
|
||||||
for i in 0..<array.len {
|
for i in 0..<array.len {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
var data = ^u8(array.data) + i*info.elem_size;
|
var data = ^u8(array.data) + i*info.elem_size;
|
||||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
@@ -870,9 +837,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
var slice = ^[]u8(v.data);
|
var slice = ^[]u8(v.data);
|
||||||
for _, i in slice {
|
for _, i in slice {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
var data = &slice[0] + i*info.elem_size;
|
var data = &slice[0] + i*info.elem_size;
|
||||||
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
fmt_arg(fi, any{rawptr(data), info.elem}, verb);
|
||||||
}
|
}
|
||||||
@@ -882,9 +848,7 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, '>');
|
defer write_byte(fi.buf, '>');
|
||||||
|
|
||||||
for i in 0..<info.count {
|
for i in 0..<info.count {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = ^u8(v.data) + i*info.elem_size;
|
var data = ^u8(v.data) + i*info.elem_size;
|
||||||
fmt_value(fi, any{rawptr(data), info.elem}, verb);
|
fmt_value(fi, any{rawptr(data), info.elem}, verb);
|
||||||
@@ -906,9 +870,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
entry_size = ed.elem_size;
|
entry_size = ed.elem_size;
|
||||||
)
|
)
|
||||||
for i in 0..<entries.len {
|
for i in 0..<entries.len {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
var data = ^u8(entries.data) + i*entry_size;
|
var data = ^u8(entries.data) + i*entry_size;
|
||||||
var header = ^__MapEntryHeader(data);
|
var header = ^__MapEntryHeader(data);
|
||||||
|
|
||||||
@@ -932,9 +895,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
defer write_byte(fi.buf, '}');
|
defer write_byte(fi.buf, '}');
|
||||||
|
|
||||||
for _, i in info.names {
|
for _, i in info.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(fi.buf, info.names[i]);
|
write_string(fi.buf, info.names[i]);
|
||||||
write_string(fi.buf, " = ");
|
write_string(fi.buf, " = ");
|
||||||
var data = ^u8(v.data) + info.offsets[i];
|
var data = ^u8(v.data) + info.offsets[i];
|
||||||
@@ -947,9 +909,8 @@ proc fmt_value(fi: ^FmtInfo, v: any, verb: rune) {
|
|||||||
|
|
||||||
var cf = info.common_fields;
|
var cf = info.common_fields;
|
||||||
for _, i in cf.names {
|
for _, i in cf.names {
|
||||||
if i > 0 {
|
if i > 0 -> write_string(fi.buf, ", ");
|
||||||
write_string(fi.buf, ", ");
|
|
||||||
}
|
|
||||||
write_string(fi.buf, cf.names[i]);
|
write_string(fi.buf, cf.names[i]);
|
||||||
write_string(fi.buf, " = ");
|
write_string(fi.buf, " = ");
|
||||||
var data = ^u8(v.data) + cf.offsets[i];
|
var data = ^u8(v.data) + cf.offsets[i];
|
||||||
@@ -1071,9 +1032,8 @@ proc sbprintln(buf: ^StringBuffer, args: ..any) -> string {
|
|||||||
fi.buf = buf;
|
fi.buf = buf;
|
||||||
|
|
||||||
for arg, i in args {
|
for arg, i in args {
|
||||||
if i > 0 {
|
if i > 0 -> write_byte(buf, ' ');
|
||||||
write_byte(buf, ' ');
|
|
||||||
}
|
|
||||||
fmt_value(&fi, args[i], 'v');
|
fmt_value(&fi, args[i], 'v');
|
||||||
}
|
}
|
||||||
write_byte(buf, '\n');
|
write_byte(buf, '\n');
|
||||||
@@ -1200,14 +1160,10 @@ proc sbprintf(b: ^StringBuffer, fmt: string, args: ..any) -> string {
|
|||||||
if !fi.reordered && arg_index < len(args) {
|
if !fi.reordered && arg_index < len(args) {
|
||||||
write_string(b, "%!(EXTRA ");
|
write_string(b, "%!(EXTRA ");
|
||||||
for arg, index in args[arg_index..] {
|
for arg, index in args[arg_index..] {
|
||||||
if index > 0 {
|
if index > 0 -> write_string(b, ", ");
|
||||||
write_string(b, ", ");
|
|
||||||
}
|
if arg == nil -> write_string(b, "<nil>");
|
||||||
if arg == nil {
|
else -> fmt_arg(&fi, args[index], 'v');
|
||||||
write_string(b, "<nil>");
|
|
||||||
} else {
|
|
||||||
fmt_arg(&fi, args[index], 'v');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
write_string(b, ")");
|
write_string(b, ")");
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
@echo off
|
@echo off
|
||||||
|
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x86 1> NUL
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
call "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat" x64 1> NUL
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64 1> NUL
|
||||||
rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 1> NUL
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x86 1> NUL
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL
|
rem call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64 1> NUL
|
||||||
set _NO_DEBUG_HEAP=1
|
set _NO_DEBUG_HEAP=1
|
||||||
|
|
||||||
set path=w:\Odin\misc;%path%
|
set path=w:\Odin\misc;%path%
|
||||||
|
|||||||
+72
-7
@@ -1221,15 +1221,64 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
|
|||||||
isize variable_index = 0;
|
isize variable_index = 0;
|
||||||
for_array(i, results) {
|
for_array(i, results) {
|
||||||
ast_node(field, Field, results[i]);
|
ast_node(field, Field, results[i]);
|
||||||
Type *type = check_type(c, field->type);
|
AstNode *default_value = unparen_expr(field->default_value);
|
||||||
|
ExactValue value = {};
|
||||||
|
bool default_is_nil = false;
|
||||||
|
|
||||||
|
Type *type = NULL;
|
||||||
|
if (field->type == NULL) {
|
||||||
|
Operand o = {};
|
||||||
|
check_expr(c, &o, default_value);
|
||||||
|
if (is_operand_nil(o)) {
|
||||||
|
default_is_nil = true;
|
||||||
|
} else if (o.mode != Addressing_Constant) {
|
||||||
|
error(default_value, "Default parameter must be a constant");
|
||||||
|
} else {
|
||||||
|
value = o.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = default_type(o.type);
|
||||||
|
} else {
|
||||||
|
type = check_type(c, field->type);
|
||||||
|
|
||||||
|
if (default_value != NULL) {
|
||||||
|
Operand o = {};
|
||||||
|
check_expr_with_type_hint(c, &o, default_value, type);
|
||||||
|
|
||||||
|
if (is_operand_nil(o)) {
|
||||||
|
default_is_nil = true;
|
||||||
|
} else if (o.mode != Addressing_Constant) {
|
||||||
|
error(default_value, "Default parameter must be a constant");
|
||||||
|
} else {
|
||||||
|
value = o.value;
|
||||||
|
}
|
||||||
|
check_is_assignable_to(c, &o, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == NULL) {
|
||||||
|
error(results[i], "Invalid parameter type");
|
||||||
|
type = t_invalid;
|
||||||
|
}
|
||||||
|
if (is_type_untyped(type)) {
|
||||||
|
error(results[i], "Cannot determine parameter type from a nil");
|
||||||
|
type = t_invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (field->names.count == 0) {
|
if (field->names.count == 0) {
|
||||||
Token token = ast_node_token(field->type);
|
Token token = ast_node_token(field->type);
|
||||||
token.string = str_lit("");
|
token.string = str_lit("");
|
||||||
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
|
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
|
||||||
|
param->Variable.default_value = value;
|
||||||
|
param->Variable.default_is_nil = default_is_nil;
|
||||||
variables[variable_index++] = param;
|
variables[variable_index++] = param;
|
||||||
} else {
|
} else {
|
||||||
for_array(j, field->names) {
|
for_array(j, field->names) {
|
||||||
Token token = ast_node_token(field->type);
|
Token token = ast_node_token(results[i]);
|
||||||
|
if (field->type != NULL) {
|
||||||
|
token = ast_node_token(field->type);
|
||||||
|
}
|
||||||
token.string = str_lit("");
|
token.string = str_lit("");
|
||||||
|
|
||||||
AstNode *name = field->names[j];
|
AstNode *name = field->names[j];
|
||||||
@@ -1240,6 +1289,8 @@ Type *check_get_results(Checker *c, Scope *scope, AstNode *_results) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
|
Entity *param = make_entity_param(c->allocator, scope, token, type, false, false);
|
||||||
|
param->Variable.default_value = value;
|
||||||
|
param->Variable.default_is_nil = default_is_nil;
|
||||||
variables[variable_index++] = param;
|
variables[variable_index++] = param;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5002,6 +5053,20 @@ isize lookup_procedure_parameter(TypeProc *pt, String parameter_name) {
|
|||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
isize lookup_procedure_result(TypeProc *pt, String result_name) {
|
||||||
|
isize result_count = pt->result_count;
|
||||||
|
for (isize i = 0; i < result_count; i++) {
|
||||||
|
Entity *e = pt->results->Tuple.variables[i];
|
||||||
|
String name = e->token.string;
|
||||||
|
if (name == "_") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (name == result_name) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
||||||
ast_node(ce, CallExpr, call);
|
ast_node(ce, CallExpr, call);
|
||||||
@@ -5013,7 +5078,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
CallArgumentError err = CallArgumentError_None;
|
CallArgumentError err = CallArgumentError_None;
|
||||||
|
|
||||||
isize param_count = pt->param_count;
|
isize param_count = pt->param_count;
|
||||||
bool *params_visited = gb_alloc_array(c->allocator, bool, param_count);
|
bool *visited = gb_alloc_array(c->allocator, bool, param_count);
|
||||||
|
|
||||||
for_array(i, ce->args) {
|
for_array(i, ce->args) {
|
||||||
AstNode *arg = ce->args[i];
|
AstNode *arg = ce->args[i];
|
||||||
@@ -5036,7 +5101,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
err = CallArgumentError_ParameterNotFound;
|
err = CallArgumentError_ParameterNotFound;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (params_visited[index]) {
|
if (visited[index]) {
|
||||||
if (show_error) {
|
if (show_error) {
|
||||||
error(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name));
|
error(arg, "Duplicate parameter `%.*s` in procedure call", LIT(name));
|
||||||
}
|
}
|
||||||
@@ -5044,7 +5109,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
params_visited[index] = true;
|
visited[index] = true;
|
||||||
Operand *o = &operands[i];
|
Operand *o = &operands[i];
|
||||||
Entity *e = pt->params->Tuple.variables[index];
|
Entity *e = pt->params->Tuple.variables[index];
|
||||||
|
|
||||||
@@ -5076,7 +5141,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
param_count_to_check--;
|
param_count_to_check--;
|
||||||
}
|
}
|
||||||
for (isize i = 0; i < param_count_to_check; i++) {
|
for (isize i = 0; i < param_count_to_check; i++) {
|
||||||
if (!params_visited[i]) {
|
if (!visited[i]) {
|
||||||
Entity *e = pt->params->Tuple.variables[i];
|
Entity *e = pt->params->Tuple.variables[i];
|
||||||
if (e->token.string == "_") {
|
if (e->token.string == "_") {
|
||||||
continue;
|
continue;
|
||||||
@@ -5095,7 +5160,7 @@ CALL_ARGUMENT_CHECKER(check_named_call_arguments) {
|
|||||||
if (show_error) {
|
if (show_error) {
|
||||||
gbString str = type_to_string(e->type);
|
gbString str = type_to_string(e->type);
|
||||||
error(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
error(call, "Parameter `%.*s` of type `%s` is missing in procedure call",
|
||||||
LIT(e->token.string), str);
|
LIT(e->token.string), str);
|
||||||
gb_string_free(str);
|
gb_string_free(str);
|
||||||
}
|
}
|
||||||
err = CallArgumentError_ParameterMissing;
|
err = CallArgumentError_ParameterMissing;
|
||||||
|
|||||||
+126
-22
@@ -786,37 +786,141 @@ void check_stmt_internal(Checker *c, AstNode *node, u32 flags) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool first_is_field_value = false;
|
||||||
|
if (rs->results.count > 0) {
|
||||||
|
bool fail = false;
|
||||||
|
first_is_field_value = (rs->results[0]->kind == AstNode_FieldValue);
|
||||||
|
for_array(i, rs->results) {
|
||||||
|
AstNode *arg = rs->results[i];
|
||||||
|
bool mix = false;
|
||||||
|
if (first_is_field_value) {
|
||||||
|
mix = arg->kind != AstNode_FieldValue;
|
||||||
|
} else {
|
||||||
|
mix = arg->kind == AstNode_FieldValue;
|
||||||
|
}
|
||||||
|
if (mix) {
|
||||||
|
error(arg, "Mixture of `field = value` and value elements in a procedure all is not allowed");
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Type *proc_type = c->proc_stack[c->proc_stack.count-1];
|
Type *proc_type = c->proc_stack[c->proc_stack.count-1];
|
||||||
|
TypeProc *pt = &proc_type->Proc;
|
||||||
isize result_count = 0;
|
isize result_count = 0;
|
||||||
if (proc_type->Proc.results) {
|
if (pt->results) {
|
||||||
result_count = proc_type->Proc.results->Tuple.variable_count;
|
result_count = proc_type->Proc.results->Tuple.variable_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result_count > 0) {
|
|
||||||
Entity **variables = NULL;
|
isize result_count_excluding_defaults = result_count;
|
||||||
if (proc_type->Proc.results != NULL) {
|
for (isize i = result_count-1; i >= 0; i--) {
|
||||||
TypeTuple *tuple = &proc_type->Proc.results->Tuple;
|
Entity *e = pt->results->Tuple.variables[i];
|
||||||
variables = tuple->variables;
|
if (e->kind == Entity_TypeName) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (rs->results.count == 0) {
|
|
||||||
error(node, "Expected %td return values, got 0", result_count);
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
} else {
|
if (e->Variable.default_value.kind != ExactValue_Invalid ||
|
||||||
// TokenPos pos = rs->token.pos;
|
e->Variable.default_is_nil) {
|
||||||
// if (pos.line == 10) {
|
result_count_excluding_defaults--;
|
||||||
// gb_printf_err("%s\n", type_to_string(variables[0]->type));
|
continue;
|
||||||
// }
|
|
||||||
check_init_variables(c, variables, result_count,
|
|
||||||
rs->results, str_lit("return statement"));
|
|
||||||
// if (pos.line == 10) {
|
|
||||||
// AstNode *x = rs->results[0];
|
|
||||||
// gb_printf_err("%s\n", expr_to_string(x));
|
|
||||||
// gb_printf_err("%s\n", type_to_string(type_of_expr(&c->info, x)));
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
} else if (rs->results.count > 0) {
|
break;
|
||||||
error(rs->results[0], "No return values expected");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Array<Operand> operands = {};
|
||||||
|
defer (array_free(&operands));
|
||||||
|
|
||||||
|
if (first_is_field_value) {
|
||||||
|
array_init_count(&operands, heap_allocator(), rs->results.count);
|
||||||
|
for_array(i, rs->results) {
|
||||||
|
AstNode *arg = rs->results[i];
|
||||||
|
ast_node(fv, FieldValue, arg);
|
||||||
|
check_expr(c, &operands[i], fv->value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
array_init(&operands, heap_allocator(), 2*rs->results.count);
|
||||||
|
check_unpack_arguments(c, -1, &operands, rs->results, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (first_is_field_value) {
|
||||||
|
bool *visited = gb_alloc_array(c->allocator, bool, result_count);
|
||||||
|
|
||||||
|
for_array(i, rs->results) {
|
||||||
|
AstNode *arg = rs->results[i];
|
||||||
|
ast_node(fv, FieldValue, arg);
|
||||||
|
if (fv->field->kind != AstNode_Ident) {
|
||||||
|
gbString expr_str = expr_to_string(fv->field);
|
||||||
|
error(arg, "Invalid parameter name `%s` in return statement", expr_str);
|
||||||
|
gb_string_free(expr_str);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String name = fv->field->Ident.string;
|
||||||
|
isize index = lookup_procedure_result(pt, name);
|
||||||
|
if (index < 0) {
|
||||||
|
error(arg, "No result named `%.*s` for this procedure type", LIT(name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (visited[index]) {
|
||||||
|
error(arg, "Duplicate result `%.*s` in return statement", LIT(name));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
visited[index] = true;
|
||||||
|
Operand *o = &operands[i];
|
||||||
|
Entity *e = pt->results->Tuple.variables[index];
|
||||||
|
check_assignment(c, &operands[i], e->type, str_lit("return statement"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (isize i = 0; i < result_count; i++) {
|
||||||
|
if (!visited[i]) {
|
||||||
|
Entity *e = pt->results->Tuple.variables[i];
|
||||||
|
if (e->token.string == "_") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->Variable.default_is_nil) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
gbString str = type_to_string(e->type);
|
||||||
|
error(node, "Return value `%.*s` of type `%s` is missing in return statement",
|
||||||
|
LIT(e->token.string), str);
|
||||||
|
gb_string_free(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// TODO(bill): Cleanup this checking of variables
|
||||||
|
if (result_count == 0 && rs->results.count > 0) {
|
||||||
|
error(rs->results[0], "No return values expected");
|
||||||
|
} else if (operands.count > result_count) {
|
||||||
|
error(node, "Expected a maximum of %td return values, got %td", result_count, operands.count);
|
||||||
|
} else if (operands.count < result_count_excluding_defaults) {
|
||||||
|
error(node, "Expected %td return values, got %td", result_count_excluding_defaults, operands.count);
|
||||||
|
} else if (result_count_excluding_defaults == 0) {
|
||||||
|
return;
|
||||||
|
} else if (rs->results.count == 0) {
|
||||||
|
error(node, "Expected %td return values, got 0", result_count_excluding_defaults);
|
||||||
|
} else {
|
||||||
|
isize max_count = rs->results.count;
|
||||||
|
for (isize i = 0; i < max_count; i++) {
|
||||||
|
Entity *e = pt->results->Tuple.variables[i];
|
||||||
|
check_assignment(c, &operands[i], e->type, str_lit("return statement"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case_end;
|
case_end;
|
||||||
|
|
||||||
case_ast_node(fs, ForStmt, node);
|
case_ast_node(fs, ForStmt, node);
|
||||||
|
|||||||
@@ -117,6 +117,39 @@ f64 float_from_string(String string) {
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (len-i > 2 &&
|
||||||
|
str[i] == '0' &&
|
||||||
|
str[i+1] == 'h') {
|
||||||
|
i += 2;
|
||||||
|
u8 *text = string.text;
|
||||||
|
isize len = string.len;
|
||||||
|
if (has_prefix) {
|
||||||
|
text += 2;
|
||||||
|
len -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 base = 16;
|
||||||
|
|
||||||
|
u64 result = {0};
|
||||||
|
for (isize i = 0; i < len; i++) {
|
||||||
|
Rune r = cast(Rune)text[i];
|
||||||
|
if (r == '_') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
u64 v = bit128__digit_value(r);
|
||||||
|
if (v >= base) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
result *= base;
|
||||||
|
result += v;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return *cast(f64 *)&result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
f64 value = 0.0;
|
f64 value = 0.0;
|
||||||
for (; i < len; i++) {
|
for (; i < len; i++) {
|
||||||
Rune r = cast(Rune)str[i];
|
Rune r = cast(Rune)str[i];
|
||||||
|
|||||||
+82
-8
@@ -6120,21 +6120,81 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
case_ast_node(rs, ReturnStmt, node);
|
case_ast_node(rs, ReturnStmt, node);
|
||||||
ir_emit_comment(proc, str_lit("ReturnStmt"));
|
ir_emit_comment(proc, str_lit("ReturnStmt"));
|
||||||
irValue *v = NULL;
|
irValue *v = NULL;
|
||||||
TypeTuple *return_type_tuple = &proc->type->Proc.results->Tuple;
|
TypeTuple *tuple = &proc->type->Proc.results->Tuple;
|
||||||
isize return_count = proc->type->Proc.result_count;
|
isize return_count = proc->type->Proc.result_count;
|
||||||
if (return_count == 0) {
|
isize res_count = rs->results.count;
|
||||||
|
|
||||||
|
if (res_count > 0 &&
|
||||||
|
rs->results[0]->kind == AstNode_FieldValue) {
|
||||||
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
|
Array<irValue *> results;
|
||||||
|
array_init_count(&results, proc->module->tmp_allocator, return_count);
|
||||||
|
|
||||||
|
for_array(arg_index, rs->results) {
|
||||||
|
AstNode *arg = rs->results[arg_index];
|
||||||
|
ast_node(fv, FieldValue, arg);
|
||||||
|
GB_ASSERT(fv->field->kind == AstNode_Ident);
|
||||||
|
String name = fv->field->Ident.string;
|
||||||
|
isize index = lookup_procedure_result(&proc->type->Proc, name);
|
||||||
|
GB_ASSERT(index >= 0);
|
||||||
|
irValue *expr = ir_build_expr(proc, fv->value);
|
||||||
|
results[index] = expr;
|
||||||
|
}
|
||||||
|
for (isize i = 0; i < return_count; i++) {
|
||||||
|
Entity *e = tuple->variables[i];
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
|
if (results[i] == NULL) {
|
||||||
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
results[i] = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
|
||||||
|
} else {
|
||||||
|
results[i] = ir_value_nil(proc->module->allocator, e->type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results[i] = ir_emit_conv(proc, results[i], e->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (results.count == 1) {
|
||||||
|
v = results[0];
|
||||||
|
} else {
|
||||||
|
GB_ASSERT(results.count == return_count);
|
||||||
|
|
||||||
|
Type *ret_type = proc->type->Proc.results;
|
||||||
|
v = ir_add_local_generated(proc, ret_type);
|
||||||
|
for_array(i, results) {
|
||||||
|
irValue *field = ir_emit_struct_ep(proc, v, i);
|
||||||
|
irValue *res = results[i];
|
||||||
|
ir_emit_store(proc, field, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
v = ir_emit_load(proc, v);
|
||||||
|
}
|
||||||
|
} else if (return_count == 0) {
|
||||||
// No return values
|
// No return values
|
||||||
} else if (return_count == 1) {
|
} else if (return_count == 1) {
|
||||||
Entity *e = return_type_tuple->variables[0];
|
Entity *e = tuple->variables[0];
|
||||||
v = ir_build_expr(proc, rs->results[0]);
|
if (res_count == 0) {
|
||||||
v = ir_emit_conv(proc, v, e->type);
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
v = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
|
||||||
|
} else {
|
||||||
|
v = ir_value_nil(proc->module->allocator, e->type);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
v = ir_build_expr(proc, rs->results[0]);
|
||||||
|
v = ir_emit_conv(proc, v, e->type);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
gbTempArenaMemory tmp = gb_temp_arena_memory_begin(&proc->module->tmp_arena);
|
||||||
|
defer (gb_temp_arena_memory_end(tmp));
|
||||||
|
|
||||||
Array<irValue *> results;
|
Array<irValue *> results;
|
||||||
array_init(&results, proc->module->tmp_allocator, return_count);
|
array_init(&results, proc->module->tmp_allocator, return_count);
|
||||||
|
|
||||||
for_array(res_index, rs->results) {
|
isize total_index = 0;
|
||||||
|
isize res_index = 0;
|
||||||
|
for (; res_index < res_count; res_index++) {
|
||||||
irValue *res = ir_build_expr(proc, rs->results[res_index]);
|
irValue *res = ir_build_expr(proc, rs->results[res_index]);
|
||||||
Type *t = ir_type(res);
|
Type *t = ir_type(res);
|
||||||
if (t->kind == Type_Tuple) {
|
if (t->kind == Type_Tuple) {
|
||||||
@@ -6142,16 +6202,31 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
Entity *e = t->Tuple.variables[i];
|
Entity *e = t->Tuple.variables[i];
|
||||||
irValue *v = ir_emit_struct_ev(proc, res, i);
|
irValue *v = ir_emit_struct_ev(proc, res, i);
|
||||||
array_add(&results, v);
|
array_add(&results, v);
|
||||||
|
total_index++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
array_add(&results, res);
|
array_add(&results, res);
|
||||||
|
total_index++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
while (total_index < return_count) {
|
||||||
|
Entity *e = tuple->variables[total_index];
|
||||||
|
irValue *res = NULL;
|
||||||
|
if (e->Variable.default_value.kind != ExactValue_Invalid) {
|
||||||
|
res = ir_value_constant(proc->module->allocator, e->type, e->Variable.default_value);
|
||||||
|
} else {
|
||||||
|
res = ir_value_nil(proc->module->allocator, e->type);
|
||||||
|
}
|
||||||
|
array_add(&results, res);
|
||||||
|
total_index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
GB_ASSERT(results.count == return_count);
|
||||||
|
|
||||||
Type *ret_type = proc->type->Proc.results;
|
Type *ret_type = proc->type->Proc.results;
|
||||||
v = ir_add_local_generated(proc, ret_type);
|
v = ir_add_local_generated(proc, ret_type);
|
||||||
for_array(i, results) {
|
for_array(i, results) {
|
||||||
Entity *e = return_type_tuple->variables[i];
|
Entity *e = tuple->variables[i];
|
||||||
irValue *res = ir_emit_conv(proc, results[i], e->type);
|
irValue *res = ir_emit_conv(proc, results[i], e->type);
|
||||||
irValue *field = ir_emit_struct_ep(proc, v, i);
|
irValue *field = ir_emit_struct_ep(proc, v, i);
|
||||||
ir_emit_store(proc, field, res);
|
ir_emit_store(proc, field, res);
|
||||||
@@ -6159,7 +6234,6 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
|
|
||||||
v = ir_emit_load(proc, v);
|
v = ir_emit_load(proc, v);
|
||||||
|
|
||||||
gb_temp_arena_memory_end(tmp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ir_emit_return(proc, v);
|
ir_emit_return(proc, v);
|
||||||
|
|||||||
+90
-25
@@ -3158,7 +3158,7 @@ AstNode *parse_block_stmt(AstFile *f, b32 is_when) {
|
|||||||
return parse_body(f);
|
return parse_body(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow);
|
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters);
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_results(AstFile *f) {
|
AstNode *parse_results(AstFile *f) {
|
||||||
@@ -3170,7 +3170,7 @@ AstNode *parse_results(AstFile *f) {
|
|||||||
CommentGroup empty_group = {};
|
CommentGroup empty_group = {};
|
||||||
Token begin_token = f->curr_token;
|
Token begin_token = f->curr_token;
|
||||||
Array<AstNode *> empty_names = {};
|
Array<AstNode *> empty_names = {};
|
||||||
Array<AstNode *> list = make_ast_node_array(f);
|
Array<AstNode *> list = make_ast_node_array(f, 1);
|
||||||
AstNode *type = parse_type(f);
|
AstNode *type = parse_type(f);
|
||||||
array_add(&list, ast_field(f, empty_names, type, NULL, 0, empty_group, empty_group));
|
array_add(&list, ast_field(f, empty_names, type, NULL, 0, empty_group, empty_group));
|
||||||
return ast_field_list(f, begin_token, list);
|
return ast_field_list(f, begin_token, list);
|
||||||
@@ -3178,7 +3178,7 @@ AstNode *parse_results(AstFile *f) {
|
|||||||
|
|
||||||
AstNode *list = NULL;
|
AstNode *list = NULL;
|
||||||
expect_token(f, Token_OpenParen);
|
expect_token(f, Token_OpenParen);
|
||||||
list = parse_field_list(f, NULL, 0, Token_CloseParen);
|
list = parse_field_list(f, NULL, 0, Token_CloseParen, true);
|
||||||
expect_token_after(f, Token_CloseParen, "parameter list");
|
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -3188,7 +3188,7 @@ AstNode *parse_proc_type(AstFile *f, Token proc_token, String *link_name_) {
|
|||||||
AstNode *results = NULL;
|
AstNode *results = NULL;
|
||||||
|
|
||||||
expect_token(f, Token_OpenParen);
|
expect_token(f, Token_OpenParen);
|
||||||
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen);
|
params = parse_field_list(f, NULL, FieldFlag_Signature, Token_CloseParen, true);
|
||||||
expect_token_after(f, Token_CloseParen, "parameter list");
|
expect_token_after(f, Token_CloseParen, "parameter list");
|
||||||
results = parse_results(f);
|
results = parse_results(f);
|
||||||
|
|
||||||
@@ -3357,7 +3357,7 @@ bool parse_expect_field_separator(AstFile *f, AstNode *param) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow) {
|
AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, TokenKind follow, bool allow_default_parameters) {
|
||||||
TokenKind separator = Token_Comma;
|
TokenKind separator = Token_Comma;
|
||||||
Token start_token = f->curr_token;
|
Token start_token = f->curr_token;
|
||||||
|
|
||||||
@@ -3370,13 +3370,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
|
|
||||||
isize total_name_count = 0;
|
isize total_name_count = 0;
|
||||||
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
|
bool allow_ellipsis = allowed_flags&FieldFlag_ellipsis;
|
||||||
bool is_procedure = allowed_flags == FieldFlag_Signature;
|
|
||||||
|
|
||||||
while (f->curr_token.kind != follow &&
|
while (f->curr_token.kind != follow &&
|
||||||
f->curr_token.kind != Token_Colon &&
|
f->curr_token.kind != Token_Colon &&
|
||||||
f->curr_token.kind != Token_EOF) {
|
f->curr_token.kind != Token_EOF) {
|
||||||
u32 flags = parse_field_prefixes(f);
|
u32 flags = parse_field_prefixes(f);
|
||||||
AstNode *param = parse_var_type(f, allow_ellipsis, is_procedure);
|
AstNode *param = parse_var_type(f, allow_ellipsis, allow_default_parameters);
|
||||||
AstNodeAndFlags naf = {param, flags};
|
AstNodeAndFlags naf = {param, flags};
|
||||||
array_add(&list, naf);
|
array_add(&list, naf);
|
||||||
if (f->curr_token.kind != Token_Comma) {
|
if (f->curr_token.kind != Token_Comma) {
|
||||||
@@ -3403,12 +3402,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
|
|
||||||
if (f->curr_token.kind != Token_Eq) {
|
if (f->curr_token.kind != Token_Eq) {
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
type = parse_var_type(f, allow_ellipsis, is_procedure);
|
type = parse_var_type(f, allow_ellipsis, allow_default_parameters);
|
||||||
}
|
}
|
||||||
if (allow_token(f, Token_Eq)) {
|
if (allow_token(f, Token_Eq)) {
|
||||||
// TODO(bill): Should this be true==lhs or false==rhs?
|
// TODO(bill): Should this be true==lhs or false==rhs?
|
||||||
default_value = parse_expr(f, false);
|
default_value = parse_expr(f, false);
|
||||||
if (!is_procedure) {
|
if (!allow_default_parameters) {
|
||||||
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3439,12 +3438,12 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
AstNode *default_value = NULL;
|
AstNode *default_value = NULL;
|
||||||
if (f->curr_token.kind != Token_Eq) {
|
if (f->curr_token.kind != Token_Eq) {
|
||||||
expect_token_after(f, Token_Colon, "field list");
|
expect_token_after(f, Token_Colon, "field list");
|
||||||
type = parse_var_type(f, allow_ellipsis, is_procedure);
|
type = parse_var_type(f, allow_ellipsis, allow_default_parameters);
|
||||||
}
|
}
|
||||||
if (allow_token(f, Token_Eq)) {
|
if (allow_token(f, Token_Eq)) {
|
||||||
// TODO(bill): Should this be true==lhs or false==rhs?
|
// TODO(bill): Should this be true==lhs or false==rhs?
|
||||||
default_value = parse_expr(f, false);
|
default_value = parse_expr(f, false);
|
||||||
if (!is_procedure) {
|
if (!allow_default_parameters) {
|
||||||
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
syntax_error(f->curr_token, "Default parameters are only allowed for procedures");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3486,7 +3485,7 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
|
|
||||||
|
|
||||||
AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
|
AstNode *parse_record_fields(AstFile *f, isize *field_count_, u32 flags, String context) {
|
||||||
return parse_field_list(f, field_count_, flags, Token_CloseBrace);
|
return parse_field_list(f, field_count_, flags, Token_CloseBrace, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *parse_type_or_ident(AstFile *f) {
|
AstNode *parse_type_or_ident(AstFile *f) {
|
||||||
@@ -3821,7 +3820,14 @@ AstNode *parse_if_stmt(AstFile *f) {
|
|||||||
syntax_error(f->curr_token, "Expected condition for if statement");
|
syntax_error(f->curr_token, "Expected condition for if statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
body = parse_block_stmt(f, false);
|
if (allow_token(f, Token_ArrowRight)) {
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (allow_token(f, Token_else)) {
|
if (allow_token(f, Token_else)) {
|
||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
@@ -3831,6 +3837,13 @@ AstNode *parse_if_stmt(AstFile *f) {
|
|||||||
case Token_OpenBrace:
|
case Token_OpenBrace:
|
||||||
else_stmt = parse_block_stmt(f, false);
|
else_stmt = parse_block_stmt(f, false);
|
||||||
break;
|
break;
|
||||||
|
case Token_ArrowRight: {
|
||||||
|
Token arrow = expect_token(f, Token_ArrowRight);
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
syntax_error(f->curr_token, "Expected if statement block statement");
|
syntax_error(f->curr_token, "Expected if statement block statement");
|
||||||
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
|
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
|
||||||
@@ -3858,7 +3871,14 @@ AstNode *parse_when_stmt(AstFile *f) {
|
|||||||
syntax_error(f->curr_token, "Expected condition for when statement");
|
syntax_error(f->curr_token, "Expected condition for when statement");
|
||||||
}
|
}
|
||||||
|
|
||||||
body = parse_block_stmt(f, true);
|
if (allow_token(f, Token_ArrowRight)) {
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = parse_block_stmt(f, true);
|
||||||
|
}
|
||||||
|
|
||||||
if (allow_token(f, Token_else)) {
|
if (allow_token(f, Token_else)) {
|
||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
@@ -3868,6 +3888,13 @@ AstNode *parse_when_stmt(AstFile *f) {
|
|||||||
case Token_OpenBrace:
|
case Token_OpenBrace:
|
||||||
else_stmt = parse_block_stmt(f, true);
|
else_stmt = parse_block_stmt(f, true);
|
||||||
break;
|
break;
|
||||||
|
case Token_ArrowRight: {
|
||||||
|
Token arrow = expect_token(f, Token_ArrowRight);
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
default:
|
default:
|
||||||
syntax_error(f->curr_token, "Expected when statement block statement");
|
syntax_error(f->curr_token, "Expected when statement block statement");
|
||||||
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
|
else_stmt = ast_bad_stmt(f, f->curr_token, f->tokens[f->curr_token_index+1]);
|
||||||
@@ -3890,11 +3917,22 @@ AstNode *parse_return_stmt(AstFile *f) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Token token = expect_token(f, Token_return);
|
Token token = expect_token(f, Token_return);
|
||||||
Array<AstNode *> results;
|
Array<AstNode *> results = make_ast_node_array(f);
|
||||||
if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
|
|
||||||
results = parse_rhs_expr_list(f);
|
while (f->curr_token.kind != Token_Semicolon) {
|
||||||
} else {
|
AstNode *arg = parse_expr(f, false);
|
||||||
results = make_ast_node_array(f);
|
if (f->curr_token.kind == Token_Eq) {
|
||||||
|
Token eq = expect_token(f, Token_Eq);
|
||||||
|
AstNode *value = parse_value(f);
|
||||||
|
arg = ast_field_value(f, arg, value, eq);
|
||||||
|
}
|
||||||
|
|
||||||
|
array_add(&results, arg);
|
||||||
|
if (f->curr_token.kind != Token_Comma ||
|
||||||
|
f->curr_token.kind == Token_EOF) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
next_token(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *end = NULL;
|
AstNode *end = NULL;
|
||||||
@@ -3952,7 +3990,8 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!is_range && f->curr_token.kind == Token_Semicolon) {
|
if (!is_range && (f->curr_token.kind == Token_Semicolon ||
|
||||||
|
f->curr_token.kind == Token_ArrowRight)) {
|
||||||
next_token(f);
|
next_token(f);
|
||||||
init = cond;
|
init = cond;
|
||||||
cond = NULL;
|
cond = NULL;
|
||||||
@@ -3960,7 +3999,8 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
cond = parse_simple_stmt(f, StmtAllowFlag_None);
|
cond = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||||
}
|
}
|
||||||
expect_semicolon(f, cond);
|
expect_semicolon(f, cond);
|
||||||
if (f->curr_token.kind != Token_OpenBrace) {
|
if (f->curr_token.kind != Token_OpenBrace &&
|
||||||
|
f->curr_token.kind != Token_ArrowRight) {
|
||||||
post = parse_simple_stmt(f, StmtAllowFlag_None);
|
post = parse_simple_stmt(f, StmtAllowFlag_None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3968,7 +4008,14 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
f->expr_level = prev_level;
|
f->expr_level = prev_level;
|
||||||
}
|
}
|
||||||
|
|
||||||
body = parse_block_stmt(f, false);
|
if (allow_token(f, Token_ArrowRight)) {
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
if (is_range) {
|
if (is_range) {
|
||||||
GB_ASSERT(cond->kind == AstNode_AssignStmt);
|
GB_ASSERT(cond->kind == AstNode_AssignStmt);
|
||||||
@@ -4002,7 +4049,7 @@ AstNode *parse_for_stmt(AstFile *f) {
|
|||||||
|
|
||||||
AstNode *parse_case_clause(AstFile *f, bool is_type) {
|
AstNode *parse_case_clause(AstFile *f, bool is_type) {
|
||||||
Token token = f->curr_token;
|
Token token = f->curr_token;
|
||||||
Array<AstNode *> list = make_ast_node_array(f);
|
Array<AstNode *> list = {};
|
||||||
expect_token(f, Token_case);
|
expect_token(f, Token_case);
|
||||||
bool prev_allow_range = f->allow_range;
|
bool prev_allow_range = f->allow_range;
|
||||||
f->allow_range = !is_type;
|
f->allow_range = !is_type;
|
||||||
@@ -4224,23 +4271,41 @@ AstNode *parse_stmt(AstFile *f) {
|
|||||||
|
|
||||||
case Token_push_allocator: {
|
case Token_push_allocator: {
|
||||||
next_token(f);
|
next_token(f);
|
||||||
|
AstNode *body = NULL;
|
||||||
isize prev_level = f->expr_level;
|
isize prev_level = f->expr_level;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
AstNode *expr = parse_expr(f, false);
|
AstNode *expr = parse_expr(f, false);
|
||||||
f->expr_level = prev_level;
|
f->expr_level = prev_level;
|
||||||
|
|
||||||
AstNode *body = parse_block_stmt(f, false);
|
if (allow_token(f, Token_ArrowRight)) {
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
return ast_push_allocator(f, token, expr, body);
|
return ast_push_allocator(f, token, expr, body);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Token_push_context: {
|
case Token_push_context: {
|
||||||
next_token(f);
|
next_token(f);
|
||||||
|
AstNode *body = NULL;
|
||||||
isize prev_level = f->expr_level;
|
isize prev_level = f->expr_level;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
AstNode *expr = parse_expr(f, false);
|
AstNode *expr = parse_expr(f, false);
|
||||||
f->expr_level = prev_level;
|
f->expr_level = prev_level;
|
||||||
|
|
||||||
AstNode *body = parse_block_stmt(f, false);
|
if (allow_token(f, Token_ArrowRight)) {
|
||||||
|
body = parse_stmt(f);
|
||||||
|
if (body->kind == AstNode_BlockStmt) {
|
||||||
|
syntax_error(body, "Expected a normal statement rather than a block statement");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = parse_block_stmt(f, false);
|
||||||
|
}
|
||||||
|
|
||||||
return ast_push_context(f, token, expr, body);
|
return ast_push_context(f, token, expr, body);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
|||||||
+8
-1
@@ -546,7 +546,14 @@ Token scan_number_to_token(Tokenizer *t, bool seen_decimal_point) {
|
|||||||
if (t->curr - prev <= 2) {
|
if (t->curr - prev <= 2) {
|
||||||
token.kind = Token_Invalid;
|
token.kind = Token_Invalid;
|
||||||
}
|
}
|
||||||
} else {
|
} /* else if (t->curr_rune == 'h') { // Hexadecimal Float
|
||||||
|
token.kind = Token_Float;
|
||||||
|
advance_to_next_rune(t);
|
||||||
|
scan_mantissa(t, 16);
|
||||||
|
if (t->curr - prev <= 2) {
|
||||||
|
token.kind = Token_Invalid;
|
||||||
|
}
|
||||||
|
} */ else {
|
||||||
seen_decimal_point = false;
|
seen_decimal_point = false;
|
||||||
scan_mantissa(t, 10);
|
scan_mantissa(t, 10);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user