gingerBill 7 years ago
parent
commit
6a85546b76
4 changed files with 51 additions and 9 deletions
  1. 36 4
      src/check_type.cpp
  2. 1 0
      src/checker.hpp
  3. 6 5
      src/tokenizer.cpp
  4. 8 0
      src/types.cpp

+ 36 - 4
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);

+ 1 - 0
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;
 };
 

+ 6 - 5
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);
 }
 

+ 8 - 0
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) {