aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2018-12-14 18:36:06 +0000
committergingerBill <bill@gingerbill.org>2018-12-14 18:36:06 +0000
commitb7eebe5d004380dec34a185bca6e5e343589de69 (patch)
tree6e9b74c045c4c2d3880b25945291703a5f70eeac
parent57d4333ed3a36778a034f144a6998587d61ed831 (diff)
Fix polymorphic record types with constant value parameters
-rw-r--r--src/check_expr.cpp18
-rw-r--r--src/check_type.cpp60
-rw-r--r--src/ir.cpp9
-rw-r--r--src/ir_print.cpp3
-rw-r--r--src/types.cpp18
5 files changed, 82 insertions, 26 deletions
diff --git a/src/check_expr.cpp b/src/check_expr.cpp
index 6e4bf05e6..37a54854c 100644
--- a/src/check_expr.cpp
+++ b/src/check_expr.cpp
@@ -775,6 +775,7 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co
}
}
+
bool is_polymorphic_type_assignable(CheckerContext *c, Type *poly, Type *source, bool compound, bool modify_type) {
Operand o = {Addressing_Value};
o.type = source;
@@ -985,6 +986,7 @@ Entity *check_ident(CheckerContext *c, Operand *o, Ast *n, Type *named_type, Typ
o->expr = n;
String name = n->Ident.token.string;
+
Entity *e = scope_lookup(c->scope, name);
if (e == nullptr) {
if (is_blank_ident(name)) {
@@ -5007,9 +5009,9 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
}
} else {
i64 s = 0;
- if (is_type_generic(o->type)) {
+ if (o->type->kind == Type_Generic) {
// Polymorphic name!
- score += assign_score_function(0);
+ score += assign_score_function(1);
continue;
} else if (!check_is_assignable_to_with_score(c, o, e->type, &s)) {
if (show_error) {
@@ -5028,18 +5030,6 @@ CallArgumentError check_polymorphic_record_type(CheckerContext *c, Operand *oper
}
}
- if (param_count < ordered_operands.count) {
- error(call, "Too many polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
- err = CallArgumentError_TooManyArguments;
- } else if (param_count > ordered_operands.count) {
- error(call, "Too few polymorphic type arguments, expected %td, got %td", param_count, ordered_operands.count);
- err = CallArgumentError_TooFewArguments;
- }
-
- if (err != 0) {
- return err;
- }
-
{
gbAllocator a = c->allocator;
diff --git a/src/check_type.cpp b/src/check_type.cpp
index 33797ba27..63835dd76 100644
--- a/src/check_type.cpp
+++ b/src/check_type.cpp
@@ -627,7 +627,7 @@ void check_union_type(CheckerContext *ctx, Type *union_type, Ast *node, Array<Op
e = alloc_entity_type_name(scope, token, operand.type);
e->TypeName.is_type_alias = true;
} else {
- GB_ASSERT(operand.mode == Addressing_Constant);
+ // GB_ASSERT(operand.mode == Addressing_Constant);
e = alloc_entity_constant(scope, token, operand.type, operand.value);
}
} else {
@@ -1117,9 +1117,8 @@ bool check_type_specialization_to(CheckerContext *ctx, Type *specialization, Typ
if (t->kind != s->kind) {
return false;
}
- // gb_printf_err("#1 %s %s\n", type_to_string(type), type_to_string(specialization));
- if (t->kind == Type_Struct) {
+ if (t->kind == Type_Struct) {
if (t->Struct.polymorphic_parent == specialization) {
return true;
}
@@ -1136,7 +1135,58 @@ bool check_type_specialization_to(CheckerContext *ctx, Type *specialization, Typ
Entity *t_e = t_tuple->variables[i];
Type *st = s_e->type;
Type *tt = t_e->type;
- bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type);
+
+ // NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types
+ if (st->kind == Type_Generic && t_e->kind == Entity_Constant) {
+ Entity *e = scope_lookup(st->Generic.scope, st->Generic.name);
+ GB_ASSERT(e != nullptr);
+ if (modify_type) {
+ e->kind = Entity_Constant;
+ e->Constant.value = t_e->Constant.value;
+ e->type = t_e->type;
+ }
+ } else {
+ bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type);
+ }
+ }
+
+ if (modify_type) {
+ // NOTE(bill): This is needed in order to change the actual type but still have the types defined within it
+ gb_memmove(specialization, type, gb_size_of(Type));
+ }
+
+ return true;
+ }
+ } else if (t->kind == Type_Union) {
+ if (t->Union.polymorphic_parent == specialization) {
+ return true;
+ }
+
+ if (t->Union.polymorphic_parent == s->Union.polymorphic_parent &&
+ s->Union.polymorphic_params != nullptr &&
+ t->Union.polymorphic_params != nullptr) {
+
+ TypeTuple *s_tuple = &s->Union.polymorphic_params->Tuple;
+ TypeTuple *t_tuple = &t->Union.polymorphic_params->Tuple;
+ GB_ASSERT(t_tuple->variables.count == s_tuple->variables.count);
+ for_array(i, s_tuple->variables) {
+ Entity *s_e = s_tuple->variables[i];
+ Entity *t_e = t_tuple->variables[i];
+ Type *st = s_e->type;
+ Type *tt = t_e->type;
+
+ // NOTE(bill, 2018-12-14): This is needed to override polymorphic named constants in types
+ if (st->kind == Type_Generic && t_e->kind == Entity_Constant) {
+ Entity *e = scope_lookup(st->Generic.scope, st->Generic.name);
+ GB_ASSERT(e != nullptr);
+ if (modify_type) {
+ e->kind = Entity_Constant;
+ e->Constant.value = t_e->Constant.value;
+ e->type = t_e->type;
+ }
+ } else {
+ bool ok = is_polymorphic_type_assignable(ctx, st, tt, true, modify_type);
+ }
}
if (modify_type) {
@@ -1168,6 +1218,7 @@ Type *determine_type_from_polymorphic(CheckerContext *ctx, Type *poly_type, Oper
}
return t_invalid;
}
+
if (is_polymorphic_type_assignable(ctx, poly_type, operand.type, false, modify_type)) {
return poly_type;
}
@@ -2290,6 +2341,7 @@ bool check_type_internal(CheckerContext *ctx, Ast *e, Type **type, Type *named_t
entity_scope = ps;
}
Entity *e = alloc_entity_type_name(entity_scope, token, t);
+ t->Generic.entity = e;
e->TypeName.is_type_alias = true;
e->state = EntityState_Resolved;
add_entity(ctx->checker, ps, ident, e);
diff --git a/src/ir.cpp b/src/ir.cpp
index e11d1a054..c2739b387 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -606,12 +606,14 @@ struct irDebugInfo {
} LexicalBlock;
struct {
+ Type * type;
String name;
i32 size;
i32 align;
irDebugEncoding encoding;
} BasicType;
struct {
+ Type * type;
irDebugEncoding tag;
irDebugInfo * base_type;
String name;
@@ -1766,6 +1768,7 @@ irDebugInfo *ir_add_debug_info_field_internal(irModule *module, String name, Typ
// "scope", if set, should be inserted into map prior to calling to ensure no cyclical dependency issues.
irDebugInfo *di = ir_alloc_debug_info(irDebugInfo_DerivedType);
+ // GB_ASSERT_MSG(name.len > 0, "%s", type_to_string(type));
di->DerivedType.name = name;
di->DerivedType.tag = irDebugBasicEncoding_member;
di->DerivedType.size = ir_debug_size_bits(type);
@@ -2350,9 +2353,9 @@ irDebugInfo *ir_add_debug_info_type(irModule *module, Type *type, Entity *e, irD
di->CompositeType.file = file;
di->CompositeType.pos = base->Union.node->UnionType.token.pos;
for_array(field_index, base->Union.variants) {
- array_add(&di->CompositeType.elements->DebugInfoArray.elements,
- ir_add_debug_info_field(module, di, nullptr, type, cast(i32)field_index,
- base->Union.variants[field_index], file));
+ // TODO(bill): Union pseudo-"fields"
+ // irDebugInfo *di = ir_add_debug_info_field(module, di, nullptr, type, cast(i32)field_index, base->Union.variants[field_index], file);
+ // array_add(&di->CompositeType.elements->DebugInfoArray.elements, di);
}
} else if (is_type_enum(type)) {
GB_ASSERT(base->kind == Type_Enum);
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index eadd091bd..457fc57a7 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -2437,7 +2437,8 @@ void print_llvm_ir(irGen *ir) {
case irDebugInfo_DerivedType: {
if (di->DerivedType.tag == irDebugBasicEncoding_member) {
// NOTE(lachsinc): We crash llvm super hard if we don't specify a name :)
- GB_ASSERT(di->DerivedType.name.len > 0);
+ Type *t = di->DerivedType.type;
+ GB_ASSERT_MSG(di->DerivedType.name.len > 0, "%s", type_to_string(di->DerivedType.type));
}
ir_write_str_lit(f, "!DIDerivedType(tag: ");
ir_print_debug_encoding(f, irDebugInfo_DerivedType, di->DerivedType.tag);
diff --git a/src/types.cpp b/src/types.cpp
index 262e4c228..512505007 100644
--- a/src/types.cpp
+++ b/src/types.cpp
@@ -140,10 +140,11 @@ struct TypeUnion {
Entity *type_name; /* Entity_TypeName */ \
}) \
TYPE_KIND(Generic, struct { \
- i64 id; \
- String name; \
- Type * specialized; \
- Scope *scope; \
+ i64 id; \
+ String name; \
+ Type * specialized; \
+ Scope * scope; \
+ Entity *entity; \
}) \
TYPE_KIND(Pointer, struct { Type *elem; }) \
TYPE_KIND(Opaque, struct { Type *elem; }) \
@@ -1988,6 +1989,15 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
return sel;
}
}
+ } else if (type->kind == Type_Union) {
+ Scope *s = type->Union.scope;
+ if (s != nullptr) {
+ Entity *found = scope_lookup_current(s, field_name);
+ if (found != nullptr && found->kind != Entity_Variable) {
+ sel.entity = found;
+ return sel;
+ }
+ }
} else if (type->kind == Type_BitSet) {
return lookup_field_with_selection(type->BitSet.elem, field_name, true, sel, allow_blank_ident);
}