From 2978835a86ef7041f0ff0367882c0d4e82b17635 Mon Sep 17 00:00:00 2001
From: Leo Tenenbaum <pommicket@gmail.com>
Date: Fri, 10 Jul 2020 16:50:20 -0400
Subject: fixed problem where wrong argument type wasnt being detected

---
 eval.c   |  3 ---
 main.c   |  3 ++-
 test.toc |  7 ++++---
 types.c  | 60 ++++++++++++++++++++++++++++++++++--------------------------
 4 files changed, 40 insertions(+), 33 deletions(-)

diff --git a/eval.c b/eval.c
index d6a3487..8542eb4 100644
--- a/eval.c
+++ b/eval.c
@@ -484,9 +484,6 @@ static void val_cast(Value vin, Type *from, Value *vout, Type *to) {
 		case TYPE_PTR:
 			vout->ptr = vin.arr;
 			break;
-		case TYPE_ARR:
-			vout->arr = vin.arr;
-			break;
 		default:
 			assert(0); break;
 		}
diff --git a/main.c b/main.c
index 3e06c41..4515bc9 100644
--- a/main.c
+++ b/main.c
@@ -8,9 +8,10 @@
 
 /* 
 @TODO:
-figure out how printf is gonna work
+error when a template is used after it's defined
 if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared)
 fix #foreign not at global scope - right now the cgen'd definition doesn't use the proper type
+figure out how printf is gonna work
 find out why loop with file output is really slow at compile time; try to improve it
 improve type_to_str:
 	Foo ::= struct(t::Type) {}
diff --git a/test.toc b/test.toc
index 6acebc5..dfcbe51 100644
--- a/test.toc
+++ b/test.toc
@@ -1,4 +1,5 @@
-n ::= nms {
-	putchar ::= #foreign("putchar") fn(#C int) #C int;
+#include "std/mem.toc";
+main ::= fn(){
+	a : []int = news(int, 5);
 }
-main ::= fn(){}
+main();
diff --git a/types.c b/types.c
index 81ebfeb..fc877af 100644
--- a/types.c
+++ b/types.c
@@ -402,6 +402,9 @@ static bool type_eq_exact(Type *a, Type *b) {
 
 /* are a and b equal, allowing implicit conversions? */
 static bool type_eq_implicit(Type *a, Type *b) {
+	assert(a->flags & TYPE_IS_RESOLVED);
+	assert(b->flags & TYPE_IS_RESOLVED);
+	
 	if (a->kind == TYPE_UNKNOWN || b->kind == TYPE_UNKNOWN)
 		return true;
 	if (a->kind != b->kind) return false;
@@ -965,8 +968,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
 				return false;
 			}
 		}
-		if (!eval_expr(tr->evalr, expr, &typeval))
-			return false;
+		if (!eval_expr(tr->evalr, expr, &typeval)) return false;
 		*t = *typeval.type;
 		if (t->kind == TYPE_STRUCT) {
 			if (struct_is_template(t->struc)) {
@@ -1139,7 +1141,6 @@ static CastStatus type_cast_status(Type *from, Type *to) {
 			return CAST_STATUS_NONE;
 		if (to->kind == TYPE_FN)
 			return CAST_STATUS_WARN;
-		/* @TODO: Cast from ptr to arr */
 		return CAST_STATUS_ERR;
 	case TYPE_ARR:
 		return CAST_STATUS_ERR;
@@ -2259,10 +2260,11 @@ static Status types_expr(Typer *tr, Expression *e) {
 						if (!eval_expr(tr->evalr, expr, &arg_val))
 							return false;
 						Type *type = &expr->type;
-						arg_exprs[i].kind = EXPR_VAL;
-						arg_exprs[i].flags = EXPR_FOUND_TYPE;
-						arg_exprs[i].val = arg_val;
-						param_decl->flags |= DECL_FOUND_VAL;
+						expr->kind = EXPR_VAL;
+						expr->flags = EXPR_FOUND_TYPE;
+						expr->val = arg_val;
+						param_decl->expr = *expr;
+						param_decl->flags |= DECL_FOUND_VAL|DECL_HAS_EXPR;
 						copy_val(tr->allocr, &param_decl->val, arg_val, type);
 						if (!(param_decl->flags & DECL_ANNOTATES_TYPE)) {
 							param_decl->type = *type;
@@ -3057,15 +3059,16 @@ static Status types_decl(Typer *tr, Declaration *d) {
 	Type *dtype = &d->type;
 	if (d->flags & DECL_FOUND_TYPE) return true;
 	bool success = true;
-	Expression *e = (d->flags & DECL_HAS_EXPR) ? &d->expr : NULL;
+	DeclFlags flags = d->flags;
+	Expression *e = (flags & DECL_HAS_EXPR) ? &d->expr : NULL;
 
-	if (d->flags & DECL_INFER) {
+	if (flags & DECL_INFER) {
 		dtype->kind = TYPE_UNKNOWN;
 		dtype->flags = 0;
 		return true;
 	}
 	typer_arr_add(tr, tr->in_decls, d);
-	if (d->flags & DECL_ANNOTATES_TYPE) {
+	if (flags & DECL_ANNOTATES_TYPE) {
 		/* type supplied */
 		if (!type_resolve(tr, dtype, d->where)) {
 			success = false;
@@ -3097,11 +3100,15 @@ static Status types_decl(Typer *tr, Declaration *d) {
 			goto ret;
 		}
 		assert(d->expr.type.flags & TYPE_IS_RESOLVED);
-		if (d->flags & DECL_ANNOTATES_TYPE) {
+		if (flags & DECL_ANNOTATES_TYPE) {
 			if (!type_eq_implicit(&e->type, dtype)) {
 				char *decl_type = type_to_str(dtype),
 					*expr_type = type_to_str(&e->type);
-				err_print(e->where, "Declaration type %s does not match expression type %s.", decl_type, expr_type);
+				bool is_parameter = (flags & DECL_IS_PARAM) && (flags & DECL_FOUND_VAL); /* this can happen if the wrong type is passed to a template function */
+				if (is_parameter)
+					err_print(e->where, "Parameter type %s does not match argument type %s.", decl_type, expr_type);
+				else
+					err_print(e->where, "Declaration type %s does not match expression type %s.", decl_type, expr_type);
 				free(decl_type); free(expr_type);
 				success = false;
 				goto ret;
@@ -3116,17 +3123,17 @@ static Status types_decl(Typer *tr, Declaration *d) {
 			*dtype = e->type;
 			dtype->flags &= (TypeFlags)~(TypeFlags)TYPE_IS_FLEXIBLE; /* x := 5; => x is not flexible */
 		}
-		bool need_value = (d->flags & DECL_IS_CONST) || !tr->block || tr->block->kind == BLOCK_NMS;
+		bool need_value = (flags & DECL_IS_CONST) || !tr->block || tr->block->kind == BLOCK_NMS;
 		if (need_value) {
-			if (!(d->flags & DECL_FOUND_VAL)) {
+			if (!(flags & DECL_FOUND_VAL)) {
 				Value val;
 				if (!eval_expr(tr->evalr, e, &val)) {
 					success = false;
 					goto ret;
 				}
 				copy_val(tr->allocr, &d->val, val, dtype);
-				d->flags |= DECL_FOUND_VAL;
-				if (!(d->flags & DECL_IS_CONST)) {
+				flags |= DECL_FOUND_VAL;
+				if (!(flags & DECL_IS_CONST)) {
 					/* 
 						create a value stack for this declaration so that it can be modified by compile time execution,
 						but not permanently (i.e. output will still have old value)
@@ -3161,7 +3168,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 
 
 	if (type_is_compileonly(dtype)) {
-		if (!(d->flags & DECL_IS_CONST) && !type_is_builtin(dtype, BUILTIN_VARARGS)) {
+		if (!(flags & DECL_IS_CONST) && !type_is_builtin(dtype, BUILTIN_VARARGS)) {
 			char *s = type_to_str(dtype);
 			err_print(d->where, "Declarations with type %s must be constant.", s);
 			free(s);
@@ -3184,7 +3191,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 		goto ret;
 	}
 	if (dtype->kind == TYPE_BUILTIN) {
-		if (dtype->builtin == BUILTIN_VARARGS && !(d->flags & DECL_IS_PARAM)) {
+		if (dtype->builtin == BUILTIN_VARARGS && !(flags & DECL_IS_PARAM)) {
 			err_print(d->where, "Only parameters can be varargs.");
 			success = false;
 			goto ret;
@@ -3194,7 +3201,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 			goto ret;
 		}
 	}
-	if (d->flags & DECL_IS_CONST) {
+	if (flags & DECL_IS_CONST) {
 		if (dtype->kind == TYPE_PTR) {
 			err_print(d->where, "You can't have a constant pointer.");
 			success = false;
@@ -3206,7 +3213,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 	for (int i = 0, len = (int)n_idents; i < len; ++i) {
 		Type *t = decl_type_at_index(d, i);
 		if (type_is_builtin(t, BUILTIN_TYPE)) {
-			if (d->flags & DECL_HAS_EXPR) {
+			if (flags & DECL_HAS_EXPR) {
 				Value *val = decl_val_at_index(d, i);
 				if (val->type->kind == TYPE_STRUCT && val->type->struc->params) {
 					/* don't resolve it because it's not really complete */
@@ -3214,7 +3221,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 					if (!type_resolve(tr, val->type, d->where)) return false;
 				}
 			}
-		} else if (!(d->flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn->constness) {
+		} else if (!(flags & DECL_IS_CONST) && t->kind == TYPE_FN && t->fn->constness) {
 			for (size_t p = 0; p < arr_len(t->fn->types)-1; ++p) {
 				if (t->fn->constness[p] == CONSTNESS_YES) {
 					err_print(d->where, "You can't have a pointer to a function with constant parameters.");
@@ -3227,7 +3234,7 @@ static Status types_decl(Typer *tr, Declaration *d) {
 		}
 	}
 
-	if (d->flags & DECL_USE) {
+	if (flags & DECL_USE) {
 		int idx = 0;
 		if (arr_len(d->idents) > 1) {
 			err_print(d->where, "Used declarations cannot have more than one identifier (you're trying to use two things at once).");
@@ -3244,9 +3251,9 @@ static Status types_decl(Typer *tr, Declaration *d) {
 		}
 	}
 
-	if (d->flags & DECL_EXPORT) {
-		if (d->expr.kind == EXPR_FN)
-			d->expr.fn->flags |= FN_EXPR_EXPORT;
+	if (flags & DECL_EXPORT) {
+		if (e->kind == EXPR_FN)
+			e->fn->flags |= FN_EXPR_EXPORT;
 	}
 
 	if (tr->block == NULL || tr->block->kind == BLOCK_NMS) {
@@ -3256,7 +3263,8 @@ static Status types_decl(Typer *tr, Declaration *d) {
 	
  ret:
 	/* pretend we found the type even if we didn't to prevent too many errors */
-	d->flags |= DECL_FOUND_TYPE;
+	flags |= DECL_FOUND_TYPE;
+	d->flags = flags;
 	if (!success) {
 		/* use unknown type if we didn't get the type */
 		dtype->flags = TYPE_IS_RESOLVED;
-- 
cgit v1.2.3