Browse Source

Fixed demo

Ginger Bill 8 years ago
parent
commit
5df854fcef
4 changed files with 65 additions and 39 deletions
  1. 11 5
      code/demo.odin
  2. 38 24
      src/check_expr.cpp
  3. 5 10
      src/checker.cpp
  4. 11 0
      src/types.cpp

+ 11 - 5
code/demo.odin

@@ -31,6 +31,7 @@ proc general_stuff() {
 
 	// By default, all variables are zeroed
 	// This can be overridden with the "uninitialized value"
+	// This is similar to `nil` but applied to everything
 	var undef_int: int = ---;
 
 
@@ -41,7 +42,8 @@ proc general_stuff() {
 	//
 	// It does mean that a pointer is implicitly passed procedures with the default
 	// Odin calling convention (#cc_odin)
-	// This can be overridden with something like #cc_contextless or #cc_c
+	// This can be overridden with something like #cc_contextless or #cc_c if performance
+	// is worried about
 
 }
 
@@ -80,7 +82,8 @@ proc named_arguments() {
 
 
 	// As the procedures have more and more parameters, it is very easy
-	// to get many of the arguments in the wrong order
+	// to get many of the arguments in the wrong order especialy if the
+	// types are the same
 	make_character("¡Ay, caramba!", "Frank", Green, Blue);
 
 	// Named arguments help to disambiguate this problem
@@ -102,7 +105,8 @@ proc named_arguments() {
 
 
 	// Named arguments can also aid with default arguments
-	proc numerous_things(s : string, a = 1, b = 2, c = 3.14, d = "The Best String!", e = false, f = 10.3/3.1, g = false) {
+	proc numerous_things(s : string, a = 1, b = 2, c = 3.14,
+	                     d = "The Best String!", e = false, f = 10.3/3.1, g = false) {
 		var g_str = g ? "true" : "false";
 		fmt.printf("How many?! %s: %v\n", s, g_str);
 	}
@@ -169,9 +173,11 @@ proc default_return_values() {
 
 proc call_location() {
 	proc amazing(n: int, using loc = #caller_location) {
-		fmt.printf("%s(%d:%d) just asked to do something amazing to %d.\n",
+		fmt.printf("%s(%d:%d) just asked to do something amazing.\n",
 		           fully_pathed_filename, line, column);
+		fmt.printf("Normal -> %d\n", n);
 		fmt.printf("Amazing -> %d\n", n+1);
+		fmt.println();
 	}
 
 	var loc = #location(main);
@@ -232,7 +238,7 @@ proc explicit_parametric_polymorphic_procedures() {
 
 
 	// A more complicated example using subtyping
-	// Something like this could be used a game
+	// Something like this could be used in a game
 	type Vector2 struct {x, y: f32};
 
 	type Entity struct {

+ 38 - 24
src/check_expr.cpp

@@ -1077,14 +1077,17 @@ void check_bit_field_type(Checker *c, Type *bit_field_type, Type *named_type, As
 
 
 
-Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, Array<Operand> *operands) {
+Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_variadic_, bool *success_, Array<Operand> *operands) {
 	if (_params == NULL) {
 		return NULL;
 	}
+
+	bool success = true;
 	ast_node(field_list, FieldList, _params);
 	Array<AstNode *> params = field_list->list;
 
 	if (params.count == 0) {
+		if (success_) *success_ = success;
 		return NULL;
 	}
 
@@ -1120,6 +1123,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 		ExactValue value = {};
 		bool default_is_nil = false;
 		bool default_is_location = false;
+		bool is_type_param = false;
+
 
 		if (type_expr == NULL) {
 			if (default_value->kind == AstNode_BasicDirective &&
@@ -1147,15 +1152,19 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 					is_variadic = true;
 				} else {
 					error(param, "Invalid AST: Invalid variadic parameter");
+					success = false;
 				}
 			}
 			if (type_expr->kind == AstNode_HelperType) {
+				is_type_param = true;
 				if (operands != NULL) {
 					Operand o = (*operands)[variable_index];
 					if (o.mode == Addressing_Type) {
 						type = o.type;
 					} else {
-						error(o.expr, "Expected a type to assign to a type parameter");
+						error(o.expr, "Expected a type to assign to the type parameter");
+						type = t_invalid;
+						success = false;
 					}
 				} else {
 					type = make_type_generic(c->allocator, 0);
@@ -1197,7 +1206,11 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 			type = t_invalid;
 		}
 		if (is_type_untyped(type)) {
-			error(params[i], "Cannot determine parameter type from a nil");
+			if (is_type_untyped_undef(type)) {
+				error(params[i], "Cannot determine parameter type from ---");
+			} else {
+				error(params[i], "Cannot determine parameter type from a nil");
+			}
 			type = t_invalid;
 		}
 
@@ -1221,16 +1234,8 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 			AstNode *name = p->names[j];
 			if (ast_node_expect(name, AstNode_Ident)) {
 				Entity *param = NULL;
-				bool is_generic = type->kind == Type_Generic;
-				Type *gen_type = type;
-				if (operands != NULL) {
-					Operand o = (*operands)[variable_index];
-					is_generic = o.mode == Addressing_Type && o.type == type;
-					if (is_generic) gen_type = o.type;
-				}
-
-				if (is_generic) {
-					param = make_entity_type_name(c->allocator, scope, name->Ident, gen_type);
+				if (is_type_param) {
+					param = make_entity_type_name(c->allocator, scope, name->Ident, type);
 					param->TypeName.is_type_alias = true;
 				} else {
 					param = make_entity_param(c->allocator, scope, name->Ident, type,
@@ -1267,6 +1272,7 @@ Type *check_get_params(Checker *c, Scope *scope, AstNode *_params, bool *is_vari
 	tuple->Tuple.variables = variables;
 	tuple->Tuple.variable_count = variable_count;
 
+	if (success_) *success_ = success;
 	if (is_variadic_) *is_variadic_ = is_variadic;
 
 	return tuple;
@@ -1574,11 +1580,12 @@ bool abi_compat_return_by_value(gbAllocator a, ProcCallingConvention cc, Type *a
 }
 
 // NOTE(bill): `operands` is for generating non generic procedure type
-void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array<Operand> *operands = NULL) {
+bool check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array<Operand> *operands = NULL) {
 	ast_node(pt, ProcType, proc_type_node);
 
 	bool variadic = false;
-	Type *params  = check_get_params(c, c->context.scope, pt->params, &variadic, operands);
+	bool success = true;
+	Type *params  = check_get_params(c, c->context.scope, pt->params, &variadic, &success, operands);
 	Type *results = check_get_results(c, c->context.scope, pt->results);
 
 	isize param_count = 0;
@@ -1637,6 +1644,8 @@ void check_procedure_type(Checker *c, Type *type, AstNode *proc_type_node, Array
 	// NOTE(bill): The types are the same
 	type->Proc.abi_compat_result_type = type_to_abi_compat_result_type(c->allocator, type->Proc.results);
 	type->Proc.return_by_pointer = abi_compat_return_by_value(c->allocator, pt->calling_convention, type->Proc.abi_compat_result_type);
+
+	return success;
 }
 
 
@@ -5002,15 +5011,18 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 	// NOTE(bill): This is slightly memory leaking if the type already exists
 	// Maybe it's better to check with the previous types first?
 	Type *final_proc_type = make_type_proc(c->allocator, c->context.scope, NULL, 0, NULL, 0, false, pt->calling_convention);
-	check_procedure_type(c, final_proc_type, pt->node, operands);
+	bool success = check_procedure_type(c, final_proc_type, pt->node, operands);
+	// if (!success) {
+		// return NULL;
+	// }
 
 	auto *found_gen_procs = map_get(&c->info.gen_procs, hash_pointer(base_entity->identifier));
 	if (found_gen_procs) {
 		for_array(i, *found_gen_procs) {
 			Entity *other = (*found_gen_procs)[i];
 			if (are_types_identical(other->type, final_proc_type)) {
-			// NOTE(bill): This scope is not needed any more, destroy it
-				destroy_scope(scope);
+				// NOTE(bill): This scope is not needed any more, destroy it
+				// destroy_scope(scope);
 				return other;
 			}
 		}
@@ -5039,12 +5051,14 @@ Entity *find_or_generate_polymorphic_procedure(Checker *c, Entity *base_entity,
 	entity->scope = base_entity->scope;
 
 	ProcedureInfo proc_info = {};
-	proc_info.file = c->curr_ast_file;
-	proc_info.token = token;
-	proc_info.decl  = d;
-	proc_info.type  = final_proc_type;
-	proc_info.body  = pd->body;
-	proc_info.tags  = tags;
+	if (success) {
+		proc_info.file = c->curr_ast_file;
+		proc_info.token = token;
+		proc_info.decl  = d;
+		proc_info.type  = final_proc_type;
+		proc_info.body  = pd->body;
+		proc_info.tags  = tags;
+	}
 
 	if (found_gen_procs) {
 		array_add(found_gen_procs, entity);

+ 5 - 10
src/checker.cpp

@@ -1448,19 +1448,10 @@ void check_procedure_overloading(Checker *c, Entity *e) {
 
 			TokenPos pos = q->token.pos;
 
-			if (q->type == NULL) {
+			if (q->type == NULL || q->type == t_invalid) {
 				continue;
 			}
 
-			if (is_type_proc(q->type)) {
-				TypeProc *ptq = &base_type(q->type)->Proc;
-				if (ptq->is_generic) {
-					q->type = t_invalid;
-					error(q->token, "Polymorphic procedure `%.*s` cannot be overloaded", LIT(name));
-					continue;
-				}
-			}
-
 			ProcTypeOverloadKind kind = are_proc_types_overload_safe(p->type, q->type);
 			switch (kind) {
 			case ProcOverload_Identical:
@@ -1480,6 +1471,10 @@ void check_procedure_overloading(Checker *c, Entity *e) {
 				error(p->token, "Overloaded procedure `%.*s` as the same parameters but different results in this scope", LIT(name));
 				is_invalid = true;
 				break;
+			case ProcOverload_Polymorphic:
+				error(p->token, "Overloaded procedure `%.*s` has a polymorphic counterpart in this scope which is not allowed", LIT(name));
+				is_invalid = true;
+				break;
 			case ProcOverload_ParamCount:
 			case ProcOverload_ParamTypes:
 				// This is okay :)

+ 11 - 0
src/types.cpp

@@ -1083,6 +1083,12 @@ bool are_types_identical(Type *x, Type *y) {
 	}
 
 	switch (x->kind) {
+	case Type_Generic:
+		if (y->kind == Type_Generic) {
+			return true; // TODO(bill): Is this correct?
+		}
+		break;
+
 	case Type_Basic:
 		if (y->kind == Type_Basic) {
 			return x->Basic.kind == y->Basic.kind;
@@ -1321,6 +1327,7 @@ enum ProcTypeOverloadKind {
 	ProcOverload_ParamTypes,
 	ProcOverload_ResultCount,
 	ProcOverload_ResultTypes,
+	ProcOverload_Polymorphic,
 
 	ProcOverload_NotProcedure,
 
@@ -1340,6 +1347,10 @@ ProcTypeOverloadKind are_proc_types_overload_safe(Type *x, Type *y) {
 		// return ProcOverload_CallingConvention;
 	// }
 
+	if (px.is_generic != py.is_generic) {
+		return ProcOverload_Polymorphic;
+	}
+
 	if (px.param_count != py.param_count) {
 		return ProcOverload_ParamCount;
 	}