mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-02 20:58:15 +00:00
Revert map to be a value type and not a reference type
(Implement code for "const ref" parameters)
This commit is contained in:
+1
-34
@@ -36,8 +36,7 @@ Calling_Convention :: enum {
|
|||||||
Type_Info_Enum_Value :: union {
|
Type_Info_Enum_Value :: union {
|
||||||
rune,
|
rune,
|
||||||
i8, i16, i32, i64, i128, int,
|
i8, i16, i32, i64, i128, int,
|
||||||
u8, u16, u32, u64, u128, uint,
|
u8, u16, u32, u64, u128, uint, uintptr,
|
||||||
uintptr,
|
|
||||||
f32, f64,
|
f32, f64,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -915,36 +914,13 @@ __default_hash :: proc(data: []byte) -> u128 {
|
|||||||
}
|
}
|
||||||
__default_hash_string :: proc(s: string) -> u128 do return __default_hash(cast([]byte)s);
|
__default_hash_string :: proc(s: string) -> u128 do return __default_hash(cast([]byte)s);
|
||||||
|
|
||||||
__dynamic_map_check_init :: proc(h: __Map_Header) {
|
|
||||||
if h.m.internal == nil {
|
|
||||||
h.m.internal = new(raw.Map_Internal);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__dynamic_map_len :: inline proc "contextless" (p: rawptr) -> int {
|
|
||||||
if m := transmute(raw.Map)p; m.internal != nil {
|
|
||||||
return m.internal.entries.len;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__dynamic_map_cap :: inline proc "contextless" (p: rawptr) -> int {
|
|
||||||
if m := transmute(raw.Map)p; m.internal != nil {
|
|
||||||
return m.internal.entries.cap;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
__dynamic_map_reserve :: proc(using header: __Map_Header, cap: int, loc := #caller_location) {
|
__dynamic_map_reserve :: proc(using header: __Map_Header, cap: int, loc := #caller_location) {
|
||||||
__dynamic_map_check_init(header);
|
|
||||||
__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
|
__dynamic_array_reserve(&m.hashes, size_of(int), align_of(int), cap, loc);
|
||||||
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
|
__dynamic_array_reserve(&m.entries, entry_size, entry_align, cap, loc);
|
||||||
}
|
}
|
||||||
__dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc := #caller_location) {
|
__dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc := #caller_location) {
|
||||||
__dynamic_map_check_init(header);
|
|
||||||
new_header: __Map_Header = header;
|
new_header: __Map_Header = header;
|
||||||
nm: raw.Map;
|
nm: raw.Map;
|
||||||
nm.internal = new(raw.Map_Internal);
|
|
||||||
new_header.m = &nm;
|
new_header.m = &nm;
|
||||||
|
|
||||||
header_hashes := cast(^raw.Dynamic_Array)&header.m.hashes;
|
header_hashes := cast(^raw.Dynamic_Array)&header.m.hashes;
|
||||||
@@ -982,7 +958,6 @@ __dynamic_map_rehash :: proc(using header: __Map_Header, new_count: int, loc :=
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
|
__dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
index := __dynamic_map_find(h, key).entry_index;
|
index := __dynamic_map_find(h, key).entry_index;
|
||||||
if index >= 0 {
|
if index >= 0 {
|
||||||
data := cast(^byte)__dynamic_map_get_entry(h, index);
|
data := cast(^byte)__dynamic_map_get_entry(h, index);
|
||||||
@@ -992,7 +967,6 @@ __dynamic_map_get :: proc(h: __Map_Header, key: __Map_Key) -> rawptr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc := #caller_location) {
|
__dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc := #caller_location) {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
|
|
||||||
index: int;
|
index: int;
|
||||||
assert(value != nil);
|
assert(value != nil);
|
||||||
@@ -1028,13 +1002,11 @@ __dynamic_map_set :: proc(h: __Map_Header, key: __Map_Key, value: rawptr, loc :=
|
|||||||
|
|
||||||
|
|
||||||
__dynamic_map_grow :: proc(using h: __Map_Header, loc := #caller_location) {
|
__dynamic_map_grow :: proc(using h: __Map_Header, loc := #caller_location) {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
new_count := max(2*m.entries.cap + 8, __INITIAL_MAP_CAP);
|
new_count := max(2*m.entries.cap + 8, __INITIAL_MAP_CAP);
|
||||||
__dynamic_map_rehash(h, new_count, loc);
|
__dynamic_map_rehash(h, new_count, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_full :: inline proc(using h: __Map_Header) -> bool {
|
__dynamic_map_full :: inline proc(using h: __Map_Header) -> bool {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
|
return int(0.75 * f64(len(m.hashes))) <= m.entries.cap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1048,7 +1020,6 @@ __dynamic_map_hash_equal :: proc(h: __Map_Header, a, b: __Map_Key) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_Result {
|
__dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_Result {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
fr := __Map_Find_Result{-1, -1, -1};
|
fr := __Map_Find_Result{-1, -1, -1};
|
||||||
if len(m.hashes) > 0 {
|
if len(m.hashes) > 0 {
|
||||||
fr.hash_index = int(key.hash % u128(len(m.hashes)));
|
fr.hash_index = int(key.hash % u128(len(m.hashes)));
|
||||||
@@ -1064,7 +1035,6 @@ __dynamic_map_find :: proc(using h: __Map_Header, key: __Map_Key) -> __Map_Find_
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key, loc := #caller_location) -> int {
|
__dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key, loc := #caller_location) -> int {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
prev := m.entries.len;
|
prev := m.entries.len;
|
||||||
c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
|
c := __dynamic_array_append_nothing(&m.entries, entry_size, entry_align, loc);
|
||||||
if c != prev {
|
if c != prev {
|
||||||
@@ -1076,7 +1046,6 @@ __dynamic_map_add_entry :: proc(using h: __Map_Header, key: __Map_Key, loc := #c
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
|
__dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
fr := __dynamic_map_find(h, key);
|
fr := __dynamic_map_find(h, key);
|
||||||
if fr.entry_index >= 0 {
|
if fr.entry_index >= 0 {
|
||||||
__dynamic_map_erase(h, fr);
|
__dynamic_map_erase(h, fr);
|
||||||
@@ -1084,13 +1053,11 @@ __dynamic_map_delete :: proc(using h: __Map_Header, key: __Map_Key) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_get_entry :: proc(using h: __Map_Header, index: int) -> ^__Map_Entry_Header {
|
__dynamic_map_get_entry :: proc(using h: __Map_Header, index: int) -> ^__Map_Entry_Header {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
assert(0 <= index && index < m.entries.len);
|
assert(0 <= index && index < m.entries.len);
|
||||||
return cast(^__Map_Entry_Header)(cast(^byte)m.entries.data + index*entry_size);
|
return cast(^__Map_Entry_Header)(cast(^byte)m.entries.data + index*entry_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
__dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
|
__dynamic_map_erase :: proc(using h: __Map_Header, fr: __Map_Find_Result) {
|
||||||
__dynamic_map_check_init(h);
|
|
||||||
if fr.entry_prev < 0 {
|
if fr.entry_prev < 0 {
|
||||||
m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
|
m.hashes[fr.hash_index] = __dynamic_map_get_entry(h, fr.entry_index).next;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+3
-2
@@ -815,8 +815,9 @@ fmt_value :: proc(fi: ^Fmt_Info, v: any, verb: rune) {
|
|||||||
write_string(fi.buf, "map[");
|
write_string(fi.buf, "map[");
|
||||||
defer write_byte(fi.buf, ']');
|
defer write_byte(fi.buf, ']');
|
||||||
|
|
||||||
if (^raw.Map)(v.data).internal != nil {
|
m := (^raw.Map)(v.data);
|
||||||
entries := &(^raw.Map)(v.data).entries;
|
if m != nil {
|
||||||
|
entries := &m.entries;
|
||||||
gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
|
gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
|
||||||
ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
|
ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
|
||||||
entry_type := ed.elem.variant.(Type_Info_Struct);
|
entry_type := ed.elem.variant.(Type_Info_Struct);
|
||||||
|
|||||||
+3
-4
@@ -20,14 +20,11 @@ Dynamic_Array :: struct {
|
|||||||
allocator: Allocator,
|
allocator: Allocator,
|
||||||
}
|
}
|
||||||
|
|
||||||
Map_Internal :: struct {
|
Map :: struct {
|
||||||
hashes: [dynamic]int,
|
hashes: [dynamic]int,
|
||||||
entries: Dynamic_Array,
|
entries: Dynamic_Array,
|
||||||
}
|
}
|
||||||
|
|
||||||
Map :: struct {
|
|
||||||
using internal: ^Map_Internal,
|
|
||||||
}
|
|
||||||
|
|
||||||
make_any :: inline proc(data: rawptr, type_info: ^Type_Info) -> any {
|
make_any :: inline proc(data: rawptr, type_info: ^Type_Info) -> any {
|
||||||
return transmute(any)Any{data, type_info};
|
return transmute(any)Any{data, type_info};
|
||||||
@@ -44,3 +41,5 @@ dynamic_array_data :: inline proc(a: $T/[dynamic]$E) -> ^E {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data :: proc[string_data, slice_data, dynamic_array_data];
|
data :: proc[string_data, slice_data, dynamic_array_data];
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+16
-2
@@ -1200,6 +1200,18 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (p->flags&FieldFlag_in) {
|
||||||
|
if (is_type_param) {
|
||||||
|
error(param, "'in' cannot be applied to a type parameter");
|
||||||
|
p->flags &= ~FieldFlag_in;
|
||||||
|
} else if (is_variadic) {
|
||||||
|
error(param, "'in' cannot be applied to a variadic parameter");
|
||||||
|
p->flags &= ~FieldFlag_in;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_in = (p->flags&FieldFlag_in) != 0;
|
||||||
|
|
||||||
for_array(j, p->names) {
|
for_array(j, p->names) {
|
||||||
AstNode *name = p->names[j];
|
AstNode *name = p->names[j];
|
||||||
if (!ast_node_expect(name, AstNode_Ident)) {
|
if (!ast_node_expect(name, AstNode_Ident)) {
|
||||||
@@ -1263,7 +1275,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
param = make_entity_param(c->allocator, scope, name->Ident.token, type, is_using, false);
|
param = make_entity_param(c->allocator, scope, name->Ident.token, type, is_using, is_in);
|
||||||
param->Variable.default_value = value;
|
param->Variable.default_value = value;
|
||||||
param->Variable.default_is_nil = default_is_nil;
|
param->Variable.default_is_nil = default_is_nil;
|
||||||
param->Variable.default_is_location = default_is_location;
|
param->Variable.default_is_location = default_is_location;
|
||||||
@@ -1812,7 +1824,9 @@ void generate_map_entry_type(gbAllocator a, Type *type) {
|
|||||||
void generate_map_internal_types(gbAllocator a, Type *type) {
|
void generate_map_internal_types(gbAllocator a, Type *type) {
|
||||||
GB_ASSERT(type->kind == Type_Map);
|
GB_ASSERT(type->kind == Type_Map);
|
||||||
generate_map_entry_type(a, type);
|
generate_map_entry_type(a, type);
|
||||||
|
if (type->Map.internal_type != nullptr) return;
|
||||||
if (type->Map.generated_struct_type != nullptr) return;
|
if (type->Map.generated_struct_type != nullptr) return;
|
||||||
|
|
||||||
Type *key = type->Map.key;
|
Type *key = type->Map.key;
|
||||||
Type *value = type->Map.value;
|
Type *value = type->Map.value;
|
||||||
GB_ASSERT(key != nullptr);
|
GB_ASSERT(key != nullptr);
|
||||||
@@ -1844,7 +1858,7 @@ void generate_map_internal_types(gbAllocator a, Type *type) {
|
|||||||
|
|
||||||
type_set_offsets(a, generated_struct_type);
|
type_set_offsets(a, generated_struct_type);
|
||||||
type->Map.generated_struct_type = generated_struct_type;
|
type->Map.generated_struct_type = generated_struct_type;
|
||||||
type->Map.internal_type = make_type_pointer(a, generated_struct_type);
|
type->Map.internal_type = generated_struct_type;
|
||||||
type->Map.lookup_result_type = make_optional_ok_type(a, value);
|
type->Map.lookup_result_type = make_optional_ok_type(a, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+76
-63
@@ -388,9 +388,10 @@ struct irValueGlobal {
|
|||||||
|
|
||||||
|
|
||||||
enum irParamPasskind {
|
enum irParamPasskind {
|
||||||
irParamPass_Value, // Pass by value
|
irParamPass_Value, // Pass by value
|
||||||
irParamPass_Pointer, // Pass as a pointer rather than by value
|
irParamPass_Pointer, // Pass as a pointer rather than by value
|
||||||
irParamPass_Integer, // Pass as an integer of the same size
|
irParamPass_Integer, // Pass as an integer of the same size
|
||||||
|
irParamPass_ConstRef, // Pass as a pointer but the value is immutable
|
||||||
};
|
};
|
||||||
|
|
||||||
struct irValueParam {
|
struct irValueParam {
|
||||||
@@ -846,7 +847,11 @@ irValue *ir_value_param(gbAllocator a, irProcedure *parent, Entity *e, Type *abi
|
|||||||
|
|
||||||
if (abi_type != e->type) {
|
if (abi_type != e->type) {
|
||||||
if (is_type_pointer(abi_type)) {
|
if (is_type_pointer(abi_type)) {
|
||||||
|
GB_ASSERT(e->kind == Entity_Variable);
|
||||||
v->Param.kind = irParamPass_Pointer;
|
v->Param.kind = irParamPass_Pointer;
|
||||||
|
if (e->flags&EntityFlag_Value) {
|
||||||
|
v->Param.kind = irParamPass_ConstRef;
|
||||||
|
}
|
||||||
} else if (is_type_integer(abi_type)) {
|
} else if (is_type_integer(abi_type)) {
|
||||||
v->Param.kind = irParamPass_Integer;
|
v->Param.kind = irParamPass_Integer;
|
||||||
} else {
|
} else {
|
||||||
@@ -1445,16 +1450,20 @@ irValue *ir_add_param(irProcedure *proc, Entity *e, AstNode *expr, Type *abi_typ
|
|||||||
ir_emit_store(proc, l, v);
|
ir_emit_store(proc, l, v);
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
case irParamPass_Pointer: {
|
case irParamPass_Pointer:
|
||||||
ir_module_add_value(proc->module, e, v);
|
ir_module_add_value(proc->module, e, v);
|
||||||
return ir_emit_load(proc, v);
|
return ir_emit_load(proc, v);
|
||||||
}
|
|
||||||
case irParamPass_Integer: {
|
case irParamPass_Integer: {
|
||||||
irValue *l = ir_add_local(proc, e, expr, false);
|
irValue *l = ir_add_local(proc, e, expr, false);
|
||||||
irValue *iptr = ir_emit_conv(proc, l, make_type_pointer(proc->module->allocator, p->type));
|
irValue *iptr = ir_emit_conv(proc, l, make_type_pointer(proc->module->allocator, p->type));
|
||||||
ir_emit_store(proc, iptr, v);
|
ir_emit_store(proc, iptr, v);
|
||||||
return ir_emit_load(proc, l);
|
return ir_emit_load(proc, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case irParamPass_ConstRef:
|
||||||
|
ir_module_add_value(proc->module, e, v);
|
||||||
|
return ir_emit_load(proc, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_PANIC("Unreachable");
|
GB_PANIC("Unreachable");
|
||||||
@@ -1570,7 +1579,7 @@ irValue *ir_emit_bitcast(irProcedure *proc, irValue *data, Type *type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t);
|
irValue *ir_emit_transmute(irProcedure *proc, irValue *value, Type *t);
|
||||||
|
irValue *ir_address_from_load_or_generate_local(irProcedure *proc, irValue *val);
|
||||||
|
|
||||||
irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
|
irValue *ir_find_or_generate_context_ptr(irProcedure *proc) {
|
||||||
if (proc->context_stack.count > 0) {
|
if (proc->context_stack.count > 0) {
|
||||||
@@ -1605,11 +1614,16 @@ irValue *ir_emit_call(irProcedure *p, irValue *value, irValue **args, isize arg_
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
GB_ASSERT(e->flags & EntityFlag_Param);
|
GB_ASSERT(e->flags & EntityFlag_Param);
|
||||||
|
|
||||||
Type *original_type = e->type;
|
Type *original_type = e->type;
|
||||||
Type *new_type = pt->Proc.abi_compat_params[i];
|
Type *new_type = pt->Proc.abi_compat_params[i];
|
||||||
if (original_type != new_type) {
|
if (original_type != new_type) {
|
||||||
if (is_type_pointer(new_type)) {
|
if (is_type_pointer(new_type)) {
|
||||||
args[i] = ir_copy_value_to_ptr(p, args[i], original_type, 16);
|
if (e->flags&EntityFlag_Value) {
|
||||||
|
args[i] = ir_address_from_load_or_generate_local(p, args[i]);
|
||||||
|
} else {
|
||||||
|
args[i] = ir_copy_value_to_ptr(p, args[i], original_type, 16);
|
||||||
|
}
|
||||||
} else if (is_type_integer(new_type)) {
|
} else if (is_type_integer(new_type)) {
|
||||||
args[i] = ir_emit_transmute(p, args[i], new_type);
|
args[i] = ir_emit_transmute(p, args[i], new_type);
|
||||||
}
|
}
|
||||||
@@ -2073,19 +2087,41 @@ irValue *ir_build_addr_ptr(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
irValue *ir_dynamic_array_len(irProcedure *proc, irValue *da);
|
||||||
|
irValue *ir_dynamic_array_cap(irProcedure *proc, irValue *da);
|
||||||
|
|
||||||
irValue *ir_map_count(irProcedure *proc, irValue *value) {
|
|
||||||
GB_ASSERT(is_type_map(ir_type(value)));
|
irValue *ir_map_entries(irProcedure *proc, irValue *value) {
|
||||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1);
|
gbAllocator a = proc->module->allocator;
|
||||||
args[0] = ir_emit_transmute(proc, value, t_rawptr);
|
Type *t = base_type(ir_type(value));
|
||||||
return ir_emit_global_call(proc, "__dynamic_map_len", args, 1);
|
GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t));
|
||||||
|
generate_map_internal_types(a, t);
|
||||||
|
Type *gst = t->Map.generated_struct_type;
|
||||||
|
isize index = 1;
|
||||||
|
irValue *entries = ir_emit(proc, ir_instr_struct_extract_value(proc, value, index, gst->Struct.fields[index]->type));
|
||||||
|
return entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
irValue *ir_map_capacity(irProcedure *proc, irValue *value) {
|
irValue *ir_map_entries_ptr(irProcedure *proc, irValue *value) {
|
||||||
GB_ASSERT(is_type_map(ir_type(value)));
|
gbAllocator a = proc->module->allocator;
|
||||||
irValue **args = gb_alloc_array(proc->module->allocator, irValue *, 1);
|
Type *t = base_type(type_deref(ir_type(value)));
|
||||||
args[0] = ir_emit_transmute(proc, value, t_rawptr);
|
GB_ASSERT_MSG(t->kind == Type_Map, "%s", type_to_string(t));
|
||||||
return ir_emit_global_call(proc, "__dynamic_map_cap", args, 1);
|
generate_map_internal_types(a, t);
|
||||||
|
Type *gst = t->Map.generated_struct_type;
|
||||||
|
isize index = 1;
|
||||||
|
Type *ptr_t = make_type_pointer(a, gst->Struct.fields[index]->type);
|
||||||
|
irValue *entries = ir_emit(proc, ir_instr_struct_element_ptr(proc, value, index, ptr_t));
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
irValue *ir_map_len(irProcedure *proc, irValue *value) {
|
||||||
|
irValue *entries = ir_map_entries(proc, value);
|
||||||
|
return ir_dynamic_array_len(proc, entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
irValue *ir_map_cap(irProcedure *proc, irValue *value) {
|
||||||
|
irValue *entries = ir_map_entries(proc, value);
|
||||||
|
return ir_dynamic_array_cap(proc, entries);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2366,7 +2402,7 @@ irValue *ir_emit_comp_against_nil(irProcedure *proc, TokenKind op_kind, irValue
|
|||||||
return ir_emit_arith(proc, Token_And, a, b, t_bool);
|
return ir_emit_arith(proc, Token_And, a, b, t_bool);
|
||||||
}
|
}
|
||||||
} else if (is_type_map(t)) {
|
} else if (is_type_map(t)) {
|
||||||
irValue *len = ir_map_count(proc, x);
|
irValue *len = ir_map_len(proc, x);
|
||||||
return ir_emit_comp(proc, op_kind, len, v_zero);
|
return ir_emit_comp(proc, op_kind, len, v_zero);
|
||||||
} else if (is_type_union(t)) {
|
} else if (is_type_union(t)) {
|
||||||
irValue *tag = ir_emit_union_tag_value(proc, x);
|
irValue *tag = ir_emit_union_tag_value(proc, x);
|
||||||
@@ -2765,7 +2801,7 @@ irValue *ir_slice_elem(irProcedure *proc, irValue *slice) {
|
|||||||
GB_ASSERT(is_type_slice(ir_type(slice)));
|
GB_ASSERT(is_type_slice(ir_type(slice)));
|
||||||
return ir_emit_struct_ev(proc, slice, 0);
|
return ir_emit_struct_ev(proc, slice, 0);
|
||||||
}
|
}
|
||||||
irValue *ir_slice_count(irProcedure *proc, irValue *slice) {
|
irValue *ir_slice_len(irProcedure *proc, irValue *slice) {
|
||||||
GB_ASSERT(is_type_slice(ir_type(slice)));
|
GB_ASSERT(is_type_slice(ir_type(slice)));
|
||||||
return ir_emit_struct_ev(proc, slice, 1);
|
return ir_emit_struct_ev(proc, slice, 1);
|
||||||
}
|
}
|
||||||
@@ -2773,11 +2809,11 @@ irValue *ir_dynamic_array_elem(irProcedure *proc, irValue *da) {
|
|||||||
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
||||||
return ir_emit_struct_ev(proc, da, 0);
|
return ir_emit_struct_ev(proc, da, 0);
|
||||||
}
|
}
|
||||||
irValue *ir_dynamic_array_count(irProcedure *proc, irValue *da) {
|
irValue *ir_dynamic_array_len(irProcedure *proc, irValue *da) {
|
||||||
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
||||||
return ir_emit_struct_ev(proc, da, 1);
|
return ir_emit_struct_ev(proc, da, 1);
|
||||||
}
|
}
|
||||||
irValue *ir_dynamic_array_capacity(irProcedure *proc, irValue *da) {
|
irValue *ir_dynamic_array_cap(irProcedure *proc, irValue *da) {
|
||||||
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
GB_ASSERT(is_type_dynamic_array(ir_type(da)));
|
||||||
return ir_emit_struct_ev(proc, da, 2);
|
return ir_emit_struct_ev(proc, da, 2);
|
||||||
}
|
}
|
||||||
@@ -2836,7 +2872,7 @@ irValue *ir_add_local_slice(irProcedure *proc, Type *slice_type, irValue *base,
|
|||||||
if (high == nullptr) {
|
if (high == nullptr) {
|
||||||
switch (bt->kind) {
|
switch (bt->kind) {
|
||||||
case Type_Array: high = ir_array_len(proc, base); break;
|
case Type_Array: high = ir_array_len(proc, base); break;
|
||||||
case Type_Slice: high = ir_slice_count(proc, base); break;
|
case Type_Slice: high = ir_slice_len(proc, base); break;
|
||||||
case Type_Pointer: high = v_one; break;
|
case Type_Pointer: high = v_one; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3181,7 +3217,7 @@ irValue *ir_emit_conv(irProcedure *proc, irValue *value, Type *t) {
|
|||||||
// []byte/[]u8 <-> string
|
// []byte/[]u8 <-> string
|
||||||
if (is_type_u8_slice(src) && is_type_string(dst)) {
|
if (is_type_u8_slice(src) && is_type_string(dst)) {
|
||||||
irValue *elem = ir_slice_elem(proc, value);
|
irValue *elem = ir_slice_elem(proc, value);
|
||||||
irValue *len = ir_slice_count(proc, value);
|
irValue *len = ir_slice_len(proc, value);
|
||||||
return ir_emit_string(proc, elem, len);
|
return ir_emit_string(proc, elem, len);
|
||||||
}
|
}
|
||||||
if (is_type_string(src) && is_type_u8_slice(dst)) {
|
if (is_type_string(src) && is_type_u8_slice(dst)) {
|
||||||
@@ -4055,11 +4091,11 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
} else if (is_type_array(t)) {
|
} else if (is_type_array(t)) {
|
||||||
GB_PANIC("Array lengths are constant");
|
GB_PANIC("Array lengths are constant");
|
||||||
} else if (is_type_slice(t)) {
|
} else if (is_type_slice(t)) {
|
||||||
return ir_slice_count(proc, v);
|
return ir_slice_len(proc, v);
|
||||||
} else if (is_type_dynamic_array(t)) {
|
} else if (is_type_dynamic_array(t)) {
|
||||||
return ir_dynamic_array_count(proc, v);
|
return ir_dynamic_array_len(proc, v);
|
||||||
} else if (is_type_map(t)) {
|
} else if (is_type_map(t)) {
|
||||||
return ir_map_count(proc, v);
|
return ir_map_len(proc, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_PANIC("Unreachable");
|
GB_PANIC("Unreachable");
|
||||||
@@ -4079,11 +4115,11 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
} else if (is_type_array(t)) {
|
} else if (is_type_array(t)) {
|
||||||
GB_PANIC("Array lengths are constant");
|
GB_PANIC("Array lengths are constant");
|
||||||
} else if (is_type_slice(t)) {
|
} else if (is_type_slice(t)) {
|
||||||
return ir_slice_count(proc, v);
|
return ir_slice_len(proc, v);
|
||||||
} else if (is_type_dynamic_array(t)) {
|
} else if (is_type_dynamic_array(t)) {
|
||||||
return ir_dynamic_array_capacity(proc, v);
|
return ir_dynamic_array_cap(proc, v);
|
||||||
} else if (is_type_map(t)) {
|
} else if (is_type_map(t)) {
|
||||||
return ir_map_capacity(proc, v);
|
return ir_map_cap(proc, v);
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_PANIC("Unreachable");
|
GB_PANIC("Unreachable");
|
||||||
@@ -4463,7 +4499,7 @@ irValue *ir_build_builtin_proc(irProcedure *proc, AstNode *expr, TypeAndValue tv
|
|||||||
|
|
||||||
irValue *item_slice = args[1];
|
irValue *item_slice = args[1];
|
||||||
irValue *items = ir_slice_elem(proc, item_slice);
|
irValue *items = ir_slice_elem(proc, item_slice);
|
||||||
irValue *item_count = ir_slice_count(proc, item_slice);
|
irValue *item_count = ir_slice_len(proc, item_slice);
|
||||||
|
|
||||||
irValue **daa_args = gb_alloc_array(a, irValue *, 5);
|
irValue **daa_args = gb_alloc_array(a, irValue *, 5);
|
||||||
daa_args[0] = array_ptr;
|
daa_args[0] = array_ptr;
|
||||||
@@ -5515,7 +5551,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
irValue *elem = ir_slice_elem(proc, slice);
|
irValue *elem = ir_slice_elem(proc, slice);
|
||||||
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
||||||
irValue *len = ir_slice_count(proc, slice);
|
irValue *len = ir_slice_len(proc, slice);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||||
return ir_addr(v);
|
return ir_addr(v);
|
||||||
@@ -5533,7 +5569,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
irValue *elem = ir_dynamic_array_elem(proc, dynamic_array);
|
irValue *elem = ir_dynamic_array_elem(proc, dynamic_array);
|
||||||
irValue *len = ir_dynamic_array_count(proc, dynamic_array);
|
irValue *len = ir_dynamic_array_len(proc, dynamic_array);
|
||||||
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
irValue *index = ir_emit_conv(proc, ir_build_expr(proc, ie->index), t_int);
|
||||||
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
ir_emit_bounds_check(proc, ast_node_token(ie->index), index, len);
|
||||||
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
irValue *v = ir_emit_ptr_offset(proc, elem, index);
|
||||||
@@ -5596,7 +5632,7 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
case Type_Slice: {
|
case Type_Slice: {
|
||||||
Type *slice_type = type;
|
Type *slice_type = type;
|
||||||
|
|
||||||
if (high == nullptr) high = ir_slice_count(proc, base);
|
if (high == nullptr) high = ir_slice_len(proc, base);
|
||||||
|
|
||||||
ir_emit_slice_bounds_check(proc, se->open, low, high, false);
|
ir_emit_slice_bounds_check(proc, se->open, low, high, false);
|
||||||
|
|
||||||
@@ -5612,8 +5648,8 @@ irAddr ir_build_addr(irProcedure *proc, AstNode *expr) {
|
|||||||
Type *elem_type = type->DynamicArray.elem;
|
Type *elem_type = type->DynamicArray.elem;
|
||||||
Type *slice_type = make_type_slice(a, elem_type);
|
Type *slice_type = make_type_slice(a, elem_type);
|
||||||
|
|
||||||
if (high == nullptr) high = ir_dynamic_array_count(proc, base);
|
if (high == nullptr) high = ir_dynamic_array_len(proc, base);
|
||||||
irValue *cap = ir_dynamic_array_capacity(proc, base);
|
irValue *cap = ir_dynamic_array_cap(proc, base);
|
||||||
|
|
||||||
ir_emit_dynamic_array_bounds_check(proc, se->open, low, high, cap);
|
ir_emit_dynamic_array_bounds_check(proc, se->open, low, high, cap);
|
||||||
|
|
||||||
@@ -6247,11 +6283,7 @@ void ir_build_range_indexed(irProcedure *proc, irValue *expr, Type *val_type, ir
|
|||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
irValue *key = ir_add_local_generated(proc, expr_type->Map.key);
|
irValue *key = ir_add_local_generated(proc, expr_type->Map.key);
|
||||||
|
|
||||||
Type *itp = make_type_pointer(proc->module->allocator, expr_type->Map.internal_type);
|
irValue *entries = ir_map_entries_ptr(proc, expr);
|
||||||
irValue *data_ptr = ir_emit_transmute(proc, expr, itp);
|
|
||||||
irValue *internal_ptr = ir_emit_load(proc, data_ptr);
|
|
||||||
|
|
||||||
irValue *entries = ir_emit_struct_ep(proc, internal_ptr, 1);
|
|
||||||
irValue *elem = ir_emit_struct_ep(proc, entries, 0);
|
irValue *elem = ir_emit_struct_ep(proc, entries, 0);
|
||||||
elem = ir_emit_load(proc, elem);
|
elem = ir_emit_load(proc, elem);
|
||||||
|
|
||||||
@@ -6902,28 +6934,9 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
if (is_type_pointer(type_deref(ir_addr_type(addr)))) {
|
if (is_type_pointer(type_deref(ir_addr_type(addr)))) {
|
||||||
map = ir_addr_load(proc, addr);
|
map = ir_addr_load(proc, addr);
|
||||||
}
|
}
|
||||||
irValue *count_ptr = ir_add_local_generated(proc, t_int);
|
irValue *entries_ptr = ir_map_entries_ptr(proc, map);
|
||||||
irValue *count_ptr_ptr = ir_add_local_generated(proc, t_int_ptr);
|
irValue *count_ptr = ir_emit_struct_ep(proc, entries_ptr, 1);
|
||||||
ir_emit_store(proc, count_ptr_ptr, count_ptr);
|
ir_build_range_indexed(proc, map, val1_type, count_ptr, &val, &key, &loop, &done);
|
||||||
|
|
||||||
irBlock *not_nil_block = ir_new_block(proc, nullptr, "map.not.nil.block");
|
|
||||||
irBlock *end_nil_block = ir_new_block(proc, nullptr, "map.end.nil.block");
|
|
||||||
{
|
|
||||||
Type *itp = make_type_pointer(a, et->Map.internal_type);
|
|
||||||
irValue *data_ptr = ir_emit_transmute(proc, map, itp);
|
|
||||||
irValue *internal_ptr = ir_emit_load(proc, data_ptr);
|
|
||||||
|
|
||||||
irValue *cond = ir_emit_comp(proc, Token_NotEq, internal_ptr, v_raw_nil);
|
|
||||||
ir_emit_if(proc, cond, not_nil_block, end_nil_block);
|
|
||||||
ir_start_block(proc, not_nil_block);
|
|
||||||
|
|
||||||
irValue *entries_ptr = ir_emit_struct_ep(proc, internal_ptr, 1);
|
|
||||||
irValue *cp = ir_emit_struct_ep(proc, entries_ptr, 1);
|
|
||||||
ir_emit_store(proc, count_ptr_ptr, cp);
|
|
||||||
ir_emit_jump(proc, end_nil_block);
|
|
||||||
}
|
|
||||||
ir_start_block(proc, end_nil_block);
|
|
||||||
ir_build_range_indexed(proc, map, val1_type, ir_emit_load(proc, count_ptr_ptr), &val, &key, &loop, &done);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type_Array: {
|
case Type_Array: {
|
||||||
@@ -6955,7 +6968,7 @@ void ir_build_stmt_internal(irProcedure *proc, AstNode *node) {
|
|||||||
slice = ir_emit_load(proc, slice);
|
slice = ir_emit_load(proc, slice);
|
||||||
} else {
|
} else {
|
||||||
count_ptr = ir_add_local_generated(proc, t_int);
|
count_ptr = ir_add_local_generated(proc, t_int);
|
||||||
ir_emit_store(proc, count_ptr, ir_slice_count(proc, slice));
|
ir_emit_store(proc, count_ptr, ir_slice_len(proc, slice));
|
||||||
}
|
}
|
||||||
ir_build_range_indexed(proc, slice, val0_type, count_ptr, &val, &key, &loop, &done);
|
ir_build_range_indexed(proc, slice, val0_type, count_ptr, &val, &key, &loop, &done);
|
||||||
break;
|
break;
|
||||||
|
|||||||
+36
-67
@@ -127,7 +127,9 @@ enum FieldFlag {
|
|||||||
FieldFlag_using = 1<<1,
|
FieldFlag_using = 1<<1,
|
||||||
FieldFlag_no_alias = 1<<2,
|
FieldFlag_no_alias = 1<<2,
|
||||||
FieldFlag_c_vararg = 1<<3,
|
FieldFlag_c_vararg = 1<<3,
|
||||||
|
FieldFlag_in = 1<<4,
|
||||||
|
|
||||||
|
// FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg|FieldFlag_in,
|
||||||
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
|
FieldFlag_Signature = FieldFlag_ellipsis|FieldFlag_using|FieldFlag_no_alias|FieldFlag_c_vararg,
|
||||||
FieldFlag_Struct = FieldFlag_using,
|
FieldFlag_Struct = FieldFlag_using,
|
||||||
};
|
};
|
||||||
@@ -2778,32 +2780,23 @@ AstNode *parse_atom_expr(AstFile *f, AstNode *operand, bool lhs) {
|
|||||||
|
|
||||||
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
|
AstNode *parse_unary_expr(AstFile *f, bool lhs) {
|
||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
|
case Token_transmute:
|
||||||
|
case Token_cast: {
|
||||||
|
Token token = advance_token(f);
|
||||||
|
expect_token(f, Token_OpenParen);
|
||||||
|
AstNode *type = parse_type(f);
|
||||||
|
expect_token(f, Token_CloseParen);
|
||||||
|
return ast_type_cast(f, token, type, parse_unary_expr(f, lhs));
|
||||||
|
}
|
||||||
case Token_Add:
|
case Token_Add:
|
||||||
case Token_Sub:
|
case Token_Sub:
|
||||||
case Token_Not:
|
case Token_Not:
|
||||||
case Token_Xor:
|
case Token_Xor:
|
||||||
case Token_And: {
|
case Token_And:
|
||||||
Token op = advance_token(f);
|
return ast_unary_expr(f, advance_token(f), parse_unary_expr(f, lhs));
|
||||||
return ast_unary_expr(f, op, parse_unary_expr(f, lhs));
|
|
||||||
} break;
|
|
||||||
case Token_cast: {
|
|
||||||
Token token = expect_token(f, Token_cast);
|
|
||||||
Token open = expect_token_after(f, Token_OpenParen, "cast");
|
|
||||||
AstNode *type = parse_type(f);
|
|
||||||
Token close = expect_token(f, Token_CloseParen);
|
|
||||||
return ast_type_cast(f, token, type, parse_unary_expr(f, lhs));
|
|
||||||
} break;
|
|
||||||
case Token_transmute: {
|
|
||||||
Token token = expect_token(f, Token_transmute);
|
|
||||||
Token open = expect_token_after(f, Token_OpenParen, "transmute");
|
|
||||||
AstNode *type = parse_type(f);
|
|
||||||
Token close = expect_token(f, Token_CloseParen);
|
|
||||||
return ast_type_cast(f, token, type, parse_unary_expr(f, lhs));
|
|
||||||
} break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AstNode *operand = parse_operand(f, lhs);
|
return parse_atom_expr(f, parse_operand(f, lhs), lhs);
|
||||||
return parse_atom_expr(f, operand, lhs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_ast_node_a_range(AstNode *expr) {
|
bool is_ast_node_a_range(AstNode *expr) {
|
||||||
@@ -2829,10 +2822,10 @@ i32 token_precedence(AstFile *f, TokenKind t) {
|
|||||||
return 1;
|
return 1;
|
||||||
case Token_Ellipsis:
|
case Token_Ellipsis:
|
||||||
case Token_HalfClosed:
|
case Token_HalfClosed:
|
||||||
if (f->allow_range) {
|
if (!f->allow_range) {
|
||||||
return 2;
|
return 0;
|
||||||
}
|
}
|
||||||
return 0;
|
return 2;
|
||||||
case Token_CmpOr:
|
case Token_CmpOr:
|
||||||
return 3;
|
return 3;
|
||||||
case Token_CmpAnd:
|
case Token_CmpAnd:
|
||||||
@@ -2938,17 +2931,8 @@ Array<AstNode *> parse_ident_list(AstFile *f) {
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AstNode *parse_type_attempt(AstFile *f) {
|
|
||||||
AstNode *type = parse_type_or_ident(f);
|
|
||||||
if (type != nullptr) {
|
|
||||||
// TODO(bill): Handle?
|
|
||||||
}
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
AstNode *parse_type(AstFile *f) {
|
AstNode *parse_type(AstFile *f) {
|
||||||
AstNode *type = parse_type_attempt(f);
|
AstNode *type = parse_type_or_ident(f);
|
||||||
if (type == nullptr) {
|
if (type == nullptr) {
|
||||||
Token token = advance_token(f);
|
Token token = advance_token(f);
|
||||||
syntax_error(token, "Expected a type");
|
syntax_error(token, "Expected a type");
|
||||||
@@ -3021,7 +3005,7 @@ AstNode *parse_value_decl(AstFile *f, Array<AstNode *> names, CommentGroup docs)
|
|||||||
type = ast_type_type(f, advance_token(f), nullptr);
|
type = ast_type_type(f, advance_token(f), nullptr);
|
||||||
is_mutable = false;
|
is_mutable = false;
|
||||||
} else {
|
} else {
|
||||||
type = parse_type_attempt(f);
|
type = parse_type_or_ident(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f->curr_token.kind == Token_Eq ||
|
if (f->curr_token.kind == Token_Eq ||
|
||||||
@@ -3293,12 +3277,7 @@ AstNode *parse_var_type(AstFile *f, bool allow_ellipsis, bool allow_type_token)
|
|||||||
}
|
}
|
||||||
type = ast_type_type(f, token, specialization);
|
type = ast_type_type(f, token, specialization);
|
||||||
} else {
|
} else {
|
||||||
type = parse_type_attempt(f);
|
type = parse_type(f);
|
||||||
}
|
|
||||||
if (type == nullptr) {
|
|
||||||
Token tok = f->curr_token;
|
|
||||||
syntax_error(tok, "Expected a type");
|
|
||||||
type = ast_bad_expr(f, tok, f->curr_token);
|
|
||||||
}
|
}
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -3311,6 +3290,7 @@ enum FieldPrefixKind {
|
|||||||
FieldPrefix_using,
|
FieldPrefix_using,
|
||||||
FieldPrefix_no_alias,
|
FieldPrefix_no_alias,
|
||||||
FieldPrefix_c_var_arg,
|
FieldPrefix_c_var_arg,
|
||||||
|
FieldPrefix_in,
|
||||||
};
|
};
|
||||||
|
|
||||||
FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
||||||
@@ -3321,6 +3301,9 @@ FieldPrefixKind is_token_field_prefix(AstFile *f) {
|
|||||||
case Token_using:
|
case Token_using:
|
||||||
return FieldPrefix_using;
|
return FieldPrefix_using;
|
||||||
|
|
||||||
|
case Token_in:
|
||||||
|
return FieldPrefix_in;
|
||||||
|
|
||||||
case Token_Hash:
|
case Token_Hash:
|
||||||
advance_token(f);
|
advance_token(f);
|
||||||
switch (f->curr_token.kind) {
|
switch (f->curr_token.kind) {
|
||||||
@@ -3342,6 +3325,7 @@ u32 parse_field_prefixes(AstFile *f) {
|
|||||||
i32 using_count = 0;
|
i32 using_count = 0;
|
||||||
i32 no_alias_count = 0;
|
i32 no_alias_count = 0;
|
||||||
i32 c_vararg_count = 0;
|
i32 c_vararg_count = 0;
|
||||||
|
i32 in_count = 0;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
FieldPrefixKind kind = is_token_field_prefix(f);
|
FieldPrefixKind kind = is_token_field_prefix(f);
|
||||||
@@ -3358,17 +3342,20 @@ u32 parse_field_prefixes(AstFile *f) {
|
|||||||
case FieldPrefix_using: using_count += 1; advance_token(f); break;
|
case FieldPrefix_using: using_count += 1; advance_token(f); break;
|
||||||
case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break;
|
case FieldPrefix_no_alias: no_alias_count += 1; advance_token(f); break;
|
||||||
case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break;
|
case FieldPrefix_c_var_arg: c_vararg_count += 1; advance_token(f); break;
|
||||||
|
case FieldPrefix_in: in_count += 1; advance_token(f); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (using_count > 1) syntax_error(f->curr_token, "Multiple 'using' in this field list");
|
if (using_count > 1) syntax_error(f->curr_token, "Multiple 'using' in this field list");
|
||||||
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple '#no_alias' in this field list");
|
if (no_alias_count > 1) syntax_error(f->curr_token, "Multiple '#no_alias' in this field list");
|
||||||
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple '#c_vararg' in this field list");
|
if (c_vararg_count > 1) syntax_error(f->curr_token, "Multiple '#c_vararg' in this field list");
|
||||||
|
if (in_count > 1) syntax_error(f->curr_token, "Multiple 'in' in this field list");
|
||||||
|
|
||||||
|
|
||||||
u32 field_flags = 0;
|
u32 field_flags = 0;
|
||||||
if (using_count > 0) field_flags |= FieldFlag_using;
|
if (using_count > 0) field_flags |= FieldFlag_using;
|
||||||
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
|
if (no_alias_count > 0) field_flags |= FieldFlag_no_alias;
|
||||||
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
|
if (c_vararg_count > 0) field_flags |= FieldFlag_c_vararg;
|
||||||
|
if (in_count > 0) field_flags |= FieldFlag_in;
|
||||||
return field_flags;
|
return field_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3632,12 +3619,17 @@ AstNode *parse_field_list(AstFile *f, isize *name_count_, u32 allowed_flags, Tok
|
|||||||
AstNode *parse_type_or_ident(AstFile *f) {
|
AstNode *parse_type_or_ident(AstFile *f) {
|
||||||
bool prev_allow_type = f->allow_type;
|
bool prev_allow_type = f->allow_type;
|
||||||
isize prev_expr_level = f->expr_level;
|
isize prev_expr_level = f->expr_level;
|
||||||
defer (f->allow_type = prev_allow_type);
|
defer ({
|
||||||
defer (f->expr_level = prev_expr_level);
|
f->allow_type = prev_allow_type;
|
||||||
|
f->expr_level = prev_expr_level;
|
||||||
|
});
|
||||||
|
|
||||||
f->allow_type = true;
|
f->allow_type = true;
|
||||||
f->expr_level = -1;
|
f->expr_level = -1;
|
||||||
AstNode *operand = parse_operand(f, true);
|
|
||||||
AstNode *type = parse_atom_expr(f, operand, true);
|
bool lhs = true;
|
||||||
|
AstNode *operand = parse_operand(f, lhs);
|
||||||
|
AstNode *type = parse_atom_expr(f, operand, lhs);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3810,29 +3802,6 @@ AstNode *parse_return_stmt(AstFile *f) {
|
|||||||
return ast_return_stmt(f, token, results);
|
return ast_return_stmt(f, token, results);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// AstNode *parse_give_stmt(AstFile *f) {
|
|
||||||
// if (f->curr_proc == nullptr) {
|
|
||||||
// syntax_error(f->curr_token, "You cannot use a give statement in the file scope");
|
|
||||||
// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
||||||
// }
|
|
||||||
// if (f->expr_level == 0) {
|
|
||||||
// syntax_error(f->curr_token, "A give statement must be used within an expression");
|
|
||||||
// return ast_bad_stmt(f, f->curr_token, f->curr_token);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Token token = expect_token(f, Token_give);
|
|
||||||
// Array<AstNode *> results;
|
|
||||||
// if (f->curr_token.kind != Token_Semicolon && f->curr_token.kind != Token_CloseBrace) {
|
|
||||||
// results = parse_rhs_expr_list(f);
|
|
||||||
// } else {
|
|
||||||
// results = make_ast_node_array(f);
|
|
||||||
// }
|
|
||||||
// AstNode *ge = ast_give_expr(f, token, results);
|
|
||||||
// expect_semicolon(f, ge);
|
|
||||||
// return ast_expr_stmt(f, ge);
|
|
||||||
// }
|
|
||||||
|
|
||||||
AstNode *parse_for_stmt(AstFile *f) {
|
AstNode *parse_for_stmt(AstFile *f) {
|
||||||
if (f->curr_proc == nullptr) {
|
if (f->curr_proc == nullptr) {
|
||||||
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");
|
||||||
|
|||||||
+2
-5
@@ -1871,9 +1871,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
|
|
||||||
case Type_Map:
|
case Type_Map:
|
||||||
generate_map_internal_types(allocator, t);
|
generate_map_internal_types(allocator, t);
|
||||||
// return type_align_of_internal(allocator, t->Map.generated_struct_type, path);
|
return type_align_of_internal(allocator, t->Map.internal_type, path);
|
||||||
return build_context.word_size;
|
|
||||||
|
|
||||||
case Type_Enum:
|
case Type_Enum:
|
||||||
return type_align_of_internal(allocator, t->Enum.base_type, path);
|
return type_align_of_internal(allocator, t->Enum.base_type, path);
|
||||||
|
|
||||||
@@ -2065,8 +2063,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
|
|
||||||
case Type_Map:
|
case Type_Map:
|
||||||
generate_map_internal_types(allocator, t);
|
generate_map_internal_types(allocator, t);
|
||||||
// return type_size_of_internal(allocator, t->Map.generated_struct_type, path);
|
return type_size_of_internal(allocator, t->Map.internal_type, path);
|
||||||
return build_context.word_size;
|
|
||||||
|
|
||||||
case Type_Tuple: {
|
case Type_Tuple: {
|
||||||
i64 count, align, size;
|
i64 count, align, size;
|
||||||
|
|||||||
Reference in New Issue
Block a user