mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 08:08:50 +00:00
Fix map internal type generation
This commit is contained in:
+71
-48
@@ -364,7 +364,7 @@ bool find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity, Typ
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool check_polymorphic_procedure_assignment(Checker *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) {
|
bool check_polymorphic_procedure_assignment(Checker *c, Operand *operand, Type *type, PolyProcData *poly_proc_data) {
|
||||||
if (operand->expr == NULL) return false;
|
if (operand->expr == nullptr) return false;
|
||||||
Entity *base_entity = entity_of_ident(&c->info, operand->expr);
|
Entity *base_entity = entity_of_ident(&c->info, operand->expr);
|
||||||
if (base_entity == nullptr) return false;
|
if (base_entity == nullptr) return false;
|
||||||
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data);
|
return find_or_generate_polymorphic_procedure(c, base_entity, type, nullptr, poly_proc_data);
|
||||||
@@ -1356,7 +1356,6 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ok) {
|
if (ok) {
|
||||||
add_type_info_type(c, t);
|
|
||||||
array_add(&variants, t);
|
array_add(&variants, t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1401,6 +1400,7 @@ void check_union_type(Checker *c, Type *named_type, Type *union_type, AstNode *n
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
// void check_raw_union_type(Checker *c, Type *union_type, AstNode *node) {
|
||||||
@@ -2790,9 +2790,50 @@ Type *make_optional_ok_type(gbAllocator a, Type *value) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_map_struct_type(gbAllocator a, Type *type) {
|
void generate_map_entry_type(gbAllocator a, Type *type) {
|
||||||
GB_ASSERT(type->kind == Type_Map);
|
GB_ASSERT(type->kind == Type_Map);
|
||||||
if (type->Map.generated_struct_type != NULL) return;
|
if (type->Map.entry_type != nullptr) return;
|
||||||
|
|
||||||
|
// NOTE(bill): The preload types may have not been set yet
|
||||||
|
GB_ASSERT(t_map_key != nullptr);
|
||||||
|
|
||||||
|
Type *entry_type = make_type_struct(a);
|
||||||
|
|
||||||
|
/*
|
||||||
|
struct {
|
||||||
|
hash: Map_Key,
|
||||||
|
next: int,
|
||||||
|
key: Key_Type,
|
||||||
|
value: Value_Type,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
AstNode *dummy_node = gb_alloc_item(a, AstNode);
|
||||||
|
dummy_node->kind = AstNode_Invalid;
|
||||||
|
Scope *s = make_scope(universal_scope, a);
|
||||||
|
|
||||||
|
isize field_count = 3;
|
||||||
|
Array<Entity *> fields = {};
|
||||||
|
array_init(&fields, a, 3);
|
||||||
|
array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("key")), t_map_key, false, 0));
|
||||||
|
array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("next")), t_int, false, 1));
|
||||||
|
array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("value")), type->Map.value, false, 2));
|
||||||
|
|
||||||
|
|
||||||
|
entry_type->Struct.fields = fields;
|
||||||
|
entry_type->Struct.fields_in_src_order = fields;
|
||||||
|
|
||||||
|
// type_set_offsets(a, entry_type);
|
||||||
|
type->Map.entry_type = entry_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generate_map_internal_types(gbAllocator a, Type *type) {
|
||||||
|
GB_ASSERT(type->kind == Type_Map);
|
||||||
|
if (type->Map.generated_struct_type != nullptr) return;
|
||||||
|
generate_map_entry_type(a, type);
|
||||||
|
Type *key = type->Map.key;
|
||||||
|
Type *value = type->Map.value;
|
||||||
|
GB_ASSERT(key != nullptr);
|
||||||
|
GB_ASSERT(value != nullptr);
|
||||||
|
|
||||||
Type *generated_struct_type = make_type_struct(a);
|
Type *generated_struct_type = make_type_struct(a);
|
||||||
|
|
||||||
@@ -2809,6 +2850,7 @@ void generate_map_struct_type(gbAllocator a, Type *type) {
|
|||||||
Type *hashes_type = make_type_dynamic_array(a, t_int);
|
Type *hashes_type = make_type_dynamic_array(a, t_int);
|
||||||
Type *entries_type = make_type_dynamic_array(a, type->Map.entry_type);
|
Type *entries_type = make_type_dynamic_array(a, type->Map.entry_type);
|
||||||
|
|
||||||
|
|
||||||
Array<Entity *> fields = {};
|
Array<Entity *> fields = {};
|
||||||
array_init(&fields, a, 2);
|
array_init(&fields, a, 2);
|
||||||
array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("hashes")), hashes_type, false, 0));
|
array_add(&fields, make_entity_field(a, s, make_token_ident(str_lit("hashes")), hashes_type, false, 0));
|
||||||
@@ -2820,6 +2862,7 @@ void generate_map_struct_type(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.lookup_result_type = make_optional_ok_type(a, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void check_map_type(Checker *c, Type *type, AstNode *node) {
|
void check_map_type(Checker *c, Type *type, AstNode *node) {
|
||||||
@@ -2832,7 +2875,7 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
|||||||
|
|
||||||
if (!is_type_valid_for_keys(key)) {
|
if (!is_type_valid_for_keys(key)) {
|
||||||
if (is_type_boolean(key)) {
|
if (is_type_boolean(key)) {
|
||||||
error(node, "A boolean cannot be used as a key for a map");
|
error(node, "A boolean cannot be used as a key for a map, use an array instead for this case");
|
||||||
} else {
|
} else {
|
||||||
gbString str = type_to_string(key);
|
gbString str = type_to_string(key);
|
||||||
error(node, "Invalid type of a key for a map, got `%s`", str);
|
error(node, "Invalid type of a key for a map, got `%s`", str);
|
||||||
@@ -2849,46 +2892,9 @@ void check_map_type(Checker *c, Type *type, AstNode *node) {
|
|||||||
type->Map.key = key;
|
type->Map.key = key;
|
||||||
type->Map.value = value;
|
type->Map.value = value;
|
||||||
|
|
||||||
gbAllocator a = c->allocator;
|
|
||||||
|
|
||||||
{
|
init_preload(c);
|
||||||
// NOTE(bill): The preload types may have not been set yet
|
generate_map_internal_types(c->allocator, type);
|
||||||
init_preload(c);
|
|
||||||
GB_ASSERT(t_map_key != nullptr);
|
|
||||||
|
|
||||||
Type *entry_type = make_type_struct(a);
|
|
||||||
|
|
||||||
/*
|
|
||||||
struct {
|
|
||||||
hash: Map_Key,
|
|
||||||
next: int,
|
|
||||||
key: Key_Type,
|
|
||||||
value: Value_Type,
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
AstNode *dummy_node = gb_alloc_item(a, AstNode);
|
|
||||||
dummy_node->kind = AstNode_Invalid;
|
|
||||||
check_open_scope(c, dummy_node);
|
|
||||||
|
|
||||||
isize field_count = 3;
|
|
||||||
Array<Entity *> fields = {};
|
|
||||||
array_init(&fields, a, 3);
|
|
||||||
array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("key")), t_map_key, false, 0));
|
|
||||||
array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("next")), t_int, false, 1));
|
|
||||||
array_add(&fields, make_entity_field(a, c->context.scope, make_token_ident(str_lit("value")), value, false, 2));
|
|
||||||
|
|
||||||
check_close_scope(c);
|
|
||||||
|
|
||||||
entry_type->Struct.fields = fields;
|
|
||||||
entry_type->Struct.fields_in_src_order = fields;
|
|
||||||
|
|
||||||
type_set_offsets(a, entry_type);
|
|
||||||
type->Map.entry_type = entry_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
generate_map_struct_type(a, type);
|
|
||||||
|
|
||||||
type->Map.lookup_result_type = make_optional_ok_type(a, value);
|
|
||||||
|
|
||||||
// error(node, "`map` types are not yet implemented");
|
// error(node, "`map` types are not yet implemented");
|
||||||
}
|
}
|
||||||
@@ -3244,7 +3250,6 @@ bool check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Token_Add:
|
|
||||||
case Token_Mul:
|
case Token_Mul:
|
||||||
case Token_Quo:
|
case Token_Quo:
|
||||||
case Token_AddEq:
|
case Token_AddEq:
|
||||||
@@ -3256,6 +3261,19 @@ bool check_binary_op(Checker *c, Operand *o, Token op) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case Token_Add:
|
||||||
|
if (is_type_string(type)) {
|
||||||
|
if (o->mode == Addressing_Constant) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
error(op, "String concatenation is only allowed with constant strings");
|
||||||
|
return false;
|
||||||
|
} else if (!is_type_numeric(type)) {
|
||||||
|
error(op, "Operator `%.*s` is only allowed with numeric expressions", LIT(op.string));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case Token_And:
|
case Token_And:
|
||||||
case Token_Or:
|
case Token_Or:
|
||||||
case Token_AndEq:
|
case Token_AndEq:
|
||||||
@@ -4140,7 +4158,9 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
if (op.kind == Token_Quo && is_type_integer(type)) {
|
if (op.kind == Token_Quo && is_type_integer(type)) {
|
||||||
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
op.kind = Token_QuoEq; // NOTE(bill): Hack to get division of integers
|
||||||
}
|
}
|
||||||
|
|
||||||
x->value = exact_binary_operator_value(op.kind, a, b);
|
x->value = exact_binary_operator_value(op.kind, a, b);
|
||||||
|
|
||||||
if (is_type_typed(type)) {
|
if (is_type_typed(type)) {
|
||||||
if (node != nullptr) {
|
if (node != nullptr) {
|
||||||
x->expr = node;
|
x->expr = node;
|
||||||
@@ -4148,6 +4168,10 @@ void check_binary_expr(Checker *c, Operand *x, AstNode *node) {
|
|||||||
check_is_expressible(c, x, type);
|
check_is_expressible(c, x, type);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
} else if (is_type_string(x->type)) {
|
||||||
|
error(node, "String concatenation is only allowed with constant strings");
|
||||||
|
x->mode = Addressing_Invalid;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
x->mode = Addressing_Value;
|
x->mode = Addressing_Value;
|
||||||
@@ -6478,7 +6502,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
if (t == t_invalid) continue;
|
if (t == t_invalid) continue;
|
||||||
GB_ASSERT(t->kind == Type_Proc);
|
GB_ASSERT(t->kind == Type_Proc);
|
||||||
gbString pt;
|
gbString pt;
|
||||||
if (t->Proc.node != NULL) {
|
if (t->Proc.node != nullptr) {
|
||||||
pt = expr_to_string(t->Proc.node);
|
pt = expr_to_string(t->Proc.node);
|
||||||
} else {
|
} else {
|
||||||
pt = type_to_string(t);
|
pt = type_to_string(t);
|
||||||
@@ -6508,7 +6532,7 @@ CallArgumentData check_call_arguments(Checker *c, Operand *operand, Type *proc_t
|
|||||||
TokenPos pos = proc->token.pos;
|
TokenPos pos = proc->token.pos;
|
||||||
Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
|
Type *t = base_type(proc->type); GB_ASSERT(t->kind == Type_Proc);
|
||||||
gbString pt;
|
gbString pt;
|
||||||
if (t->Proc.node != NULL) {
|
if (t->Proc.node != nullptr) {
|
||||||
pt = expr_to_string(t->Proc.node);
|
pt = expr_to_string(t->Proc.node);
|
||||||
} else {
|
} else {
|
||||||
pt = type_to_string(t);
|
pt = type_to_string(t);
|
||||||
@@ -7749,7 +7773,6 @@ ExprKind check_expr_base_internal(Checker *c, Operand *o, AstNode *node, Type *t
|
|||||||
return kind;
|
return kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool src_is_ptr = is_type_pointer(o->type);
|
bool src_is_ptr = is_type_pointer(o->type);
|
||||||
Type *src = type_deref(o->type);
|
Type *src = type_deref(o->type);
|
||||||
Type *dst = t;
|
Type *dst = t;
|
||||||
|
|||||||
+1
-1
@@ -1182,7 +1182,7 @@ void add_type_info_type(Checker *c, Type *t) {
|
|||||||
} break;
|
} break;
|
||||||
|
|
||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
generate_map_struct_type(c->allocator, bt);
|
generate_map_internal_types(c->allocator, bt);
|
||||||
add_type_info_type(c, bt->Map.key);
|
add_type_info_type(c, bt->Map.key);
|
||||||
add_type_info_type(c, bt->Map.value);
|
add_type_info_type(c, bt->Map.value);
|
||||||
add_type_info_type(c, bt->Map.generated_struct_type);
|
add_type_info_type(c, bt->Map.generated_struct_type);
|
||||||
|
|||||||
+15
-5
@@ -565,13 +565,23 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
|
|||||||
}
|
}
|
||||||
return exact_value_complex(real, imag);
|
return exact_value_complex(real, imag);
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
|
case ExactValue_String: {
|
||||||
|
if (op != Token_Add) goto error;
|
||||||
|
|
||||||
|
// NOTE(bill): How do you minimize this over allocation?
|
||||||
|
String sx = x.value_string;
|
||||||
|
String sy = y.value_string;
|
||||||
|
isize len = sx.len+sy.len;
|
||||||
|
u8 *data = gb_alloc_array(heap_allocator(), u8, len);
|
||||||
|
gb_memmove(data, sx.text, sx.len);
|
||||||
|
gb_memmove(data+sx.len, sy.text, sy.len);
|
||||||
|
return exact_value_string(make_string(data, len));
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
|
|
||||||
error:
|
error:; // NOTE(bill): MSVC accepts this??? apparently you cannot declare variables immediately after labels...
|
||||||
; // MSVC accepts this??? apparently you cannot declare variables immediately after labels...
|
return empty_exact_value;
|
||||||
ExactValue error_value = {};
|
|
||||||
// gb_printf_err("Invalid binary operation: %s\n", token_kind_to_string(op));
|
|
||||||
return error_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Add, x, y); }
|
gb_inline ExactValue exact_value_add(ExactValue x, ExactValue y) { return exact_binary_operator_value(Token_Add, x, y); }
|
||||||
|
|||||||
+2
-3
@@ -2231,10 +2231,9 @@ AstNode *parse_operand(AstFile *f, bool lhs) {
|
|||||||
// NOTE(bill): Allow neighbouring string literals to be merge together to
|
// NOTE(bill): Allow neighbouring string literals to be merge together to
|
||||||
// become one big string
|
// become one big string
|
||||||
String s = f->curr_token.string;
|
String s = f->curr_token.string;
|
||||||
Array<u8> data;
|
Array<u8> data = {};
|
||||||
array_init(&data, heap_allocator(), token.string.len+s.len);
|
array_init_count(&data, heap_allocator(), token.string.len+s.len);
|
||||||
gb_memmove(data.data, token.string.text, token.string.len);
|
gb_memmove(data.data, token.string.text, token.string.len);
|
||||||
data.count += token.string.len;
|
|
||||||
|
|
||||||
while (f->curr_token.kind == Token_String) {
|
while (f->curr_token.kind == Token_String) {
|
||||||
String s = f->curr_token.string;
|
String s = f->curr_token.string;
|
||||||
|
|||||||
+3
-3
@@ -390,7 +390,7 @@ i64 type_size_of (gbAllocator allocator, Type *t);
|
|||||||
i64 type_align_of (gbAllocator allocator, Type *t);
|
i64 type_align_of (gbAllocator allocator, Type *t);
|
||||||
i64 type_offset_of (gbAllocator allocator, Type *t, i32 index);
|
i64 type_offset_of (gbAllocator allocator, Type *t, i32 index);
|
||||||
gbString type_to_string (Type *type);
|
gbString type_to_string (Type *type);
|
||||||
void generate_map_struct_type(gbAllocator a, Type *type);
|
void generate_map_internal_types(gbAllocator a, Type *type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1827,7 +1827,7 @@ i64 type_align_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
case Type_Map: {
|
case Type_Map: {
|
||||||
if (t->Map.count == 0) { // Dynamic
|
if (t->Map.count == 0) { // Dynamic
|
||||||
// return build_context.word_size;
|
// return build_context.word_size;
|
||||||
generate_map_struct_type(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.generated_struct_type, path);
|
||||||
}
|
}
|
||||||
GB_PANIC("TODO(bill): Fixed map alignment");
|
GB_PANIC("TODO(bill): Fixed map alignment");
|
||||||
@@ -2057,7 +2057,7 @@ i64 type_size_of_internal(gbAllocator allocator, Type *t, TypePath *path) {
|
|||||||
if (t->Map.count == 0) { // Dynamic
|
if (t->Map.count == 0) { // Dynamic
|
||||||
// i64 da = 3*build_context.word_size + 2*build_context.word_size;
|
// i64 da = 3*build_context.word_size + 2*build_context.word_size;
|
||||||
// return 2 * da;
|
// return 2 * da;
|
||||||
generate_map_struct_type(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.generated_struct_type, path);
|
||||||
}
|
}
|
||||||
GB_PANIC("TODO(bill): Fixed map size");
|
GB_PANIC("TODO(bill): Fixed map size");
|
||||||
|
|||||||
Reference in New Issue
Block a user