From 6a85546b761b67fa012a2cd49e32b2211bf02971 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Wed, 14 Feb 2018 21:46:39 +0000 Subject: [PATCH] Fix #187 --- src/check_type.cpp | 40 ++++++++++++++++++++++++++++++++++++---- src/checker.hpp | 1 + src/tokenizer.cpp | 11 ++++++----- src/types.cpp | 8 ++++++++ 4 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/check_type.cpp b/src/check_type.cpp index 46399f7f1..47e27c27d 100644 --- a/src/check_type.cpp +++ b/src/check_type.cpp @@ -920,6 +920,7 @@ bool check_type_specialization_to(Checker *c, Type *specialization, Type *type, } // gb_printf_err("#1 %s %s\n", type_to_string(type), type_to_string(specialization)); if (t->kind == Type_Struct) { + if (t->Struct.polymorphic_parent == specialization) { return true; } @@ -1937,24 +1938,31 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Operand o = {}; check_ident(c, &o, e, named_type, nullptr, false); - gbString err_str; + gbString err_str = nullptr; + defer (gb_string_free(err_str)); + switch (o.mode) { case Addressing_Invalid: break; - case Addressing_Type: + case Addressing_Type: { *type = o.type; + if (!c->context.in_polymorphic_specialization) { + if (is_type_polymorphic_struct_unspecialized(o.type)) { + err_str = expr_to_string(e); + error(e, "Invalid use of a non-specialized polymorphic type '%s'", err_str); + } + } return true; + } case Addressing_NoValue: err_str = expr_to_string(e); error(e, "'%s' used as a type", err_str); - gb_string_free(err_str); break; default: err_str = expr_to_string(e); error(e, "'%s' used as a type when not a type", err_str); - gb_string_free(err_str); break; } case_end; @@ -1980,6 +1988,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) Token token = ident->Ident.token; Type *specific = nullptr; if (pt->specialization != nullptr) { + auto prev_ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = prev_ips); + c->context.in_polymorphic_specialization = true; + AstNode *s = pt->specialization; specific = check_type(c, s); if (false && !is_type_polymorphic_struct(specific)) { @@ -2088,6 +2100,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(st, StructType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_struct(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2098,6 +2114,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(ut, UnionType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_union(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2108,6 +2128,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(et, EnumType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = make_type_enum(c->allocator); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2127,6 +2151,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(pt, ProcType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = alloc_type(c->allocator, Type_Proc); set_base_type(named_type, *type); check_open_scope(c, e); @@ -2136,6 +2164,10 @@ bool check_type_internal(Checker *c, AstNode *e, Type **type, Type *named_type) case_end; case_ast_node(mt, MapType, e); + bool ips = c->context.in_polymorphic_specialization; + defer (c->context.in_polymorphic_specialization = ips); + c->context.in_polymorphic_specialization = false; + *type = alloc_type(c->allocator, Type_Map); set_base_type(named_type, *type); check_map_type(c, *type, e); diff --git a/src/checker.hpp b/src/checker.hpp index 0e453c91d..bb8a11658 100644 --- a/src/checker.hpp +++ b/src/checker.hpp @@ -285,6 +285,7 @@ struct CheckerContext { bool collect_delayed_decls; bool allow_polymorphic_types; bool no_polymorphic_errors; + bool in_polymorphic_specialization; Scope * polymorphic_scope; }; diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index d19024026..404b4cea6 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -200,7 +200,9 @@ void warning_va(Token token, char *fmt, va_list va) { gb_mutex_lock(&global_error_collector.mutex); global_error_collector.warning_count++; // NOTE(bill): Duplicate error, skip it - if (global_error_collector.prev != token.pos) { + if (token.pos.line == 0) { + gb_printf_err("Error: %s\n", gb_bprintf_va(fmt, va)); + } else if (global_error_collector.prev != token.pos) { global_error_collector.prev = token.pos; gb_printf_err("%.*s(%td:%td) Warning: %s\n", LIT(token.pos.file), token.pos.line, token.pos.column, @@ -214,15 +216,14 @@ void error_va(Token token, char *fmt, va_list va) { gb_mutex_lock(&global_error_collector.mutex); global_error_collector.count++; // NOTE(bill): Duplicate error, skip it - if (global_error_collector.prev != token.pos) { + if (token.pos.line == 0) { + gb_printf_err("Error: %s\n", gb_bprintf_va(fmt, va)); + } else if (global_error_collector.prev != token.pos) { global_error_collector.prev = token.pos; gb_printf_err("%.*s(%td:%td) %s\n", LIT(token.pos.file), token.pos.line, token.pos.column, gb_bprintf_va(fmt, va)); - } else if (token.pos.line == 0) { - gb_printf_err("Error: %s\n", gb_bprintf_va(fmt, va)); } - gb_mutex_unlock(&global_error_collector.mutex); } diff --git a/src/types.cpp b/src/types.cpp index c40c076f1..2dcd05361 100644 --- a/src/types.cpp +++ b/src/types.cpp @@ -954,6 +954,14 @@ bool is_type_polymorphic_struct_specialized(Type *t) { return false; } +bool is_type_polymorphic_struct_unspecialized(Type *t) { + t = base_type(t); + if (t->kind == Type_Struct) { + return t->Struct.is_polymorphic && !t->Struct.is_poly_specialized; + } + return false; +} + bool is_type_polymorphic(Type *t) { switch (t->kind) {