summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-25 09:09:39 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-25 09:09:39 -0500
commitd238a47bb8b324084a81748e2d320e0bc2973d25 (patch)
tree9648b09d5651b6a726e7b796d690eda7ba1ad9ca
parent9dbd9539c2f93faa24b71917a5a961b79522e876 (diff)
fixed problem with flexible types
-rw-r--r--main.c5
-rw-r--r--test.toc4
-rw-r--r--types.c70
3 files changed, 51 insertions, 28 deletions
diff --git a/main.c b/main.c
index 73f0306..6be7848 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,5 @@
/*
TODO:
-remove declarations , exit fn even on failure
-fix flexible types (example program should not need those casts)
get fn(x, y@ int) to work, you'll need to add back in tuple parameters (one decl multiple values)
can we get the instance before calling type_of_fn?
@@ -9,6 +7,9 @@ can we get the instance before calling type_of_fn?
get fn(x: int) y := x {} to work
don't cgen decls etc. in parameter initializers (hey we have a parameter flag now)
check for leaks
+clean up
+
+
switch to enums for flags
struct parameters
diff --git a/test.toc b/test.toc
index 75a69aa..4933289 100644
--- a/test.toc
+++ b/test.toc
@@ -9,11 +9,11 @@ puti @= fn(x: int) {
f @= fn(t @ Type, x: t) t {
- x + 1 as t
+ x + 1
};
main @= fn() {
puti(f(int, 3));
- puti(f(u8, 255 as u8) as int);
+ puti(f(u8, 255) as int);
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 6b89ebe..7052e4a 100644
--- a/types.c
+++ b/types.c
@@ -35,6 +35,12 @@ static bool type_eq(Type *a, Type *b) {
if (a->kind != b->kind) return false;
+ if (b->flags & TYPE_IS_FLEXIBLE) {
+ Type *tmp = a;
+ a = b;
+ b = tmp;
+ }
+
if (a->flags & TYPE_IS_FLEXIBLE) {
if (b->flags & TYPE_IS_FLEXIBLE) return true;
assert(a->kind == TYPE_BUILTIN);
@@ -45,11 +51,6 @@ static bool type_eq(Type *a, Type *b) {
assert(a->builtin == BUILTIN_I64);
return type_builtin_is_numerical(b->builtin);
}
- if (b->flags & TYPE_IS_FLEXIBLE) {
- Type *tmp = a;
- a = b;
- b = tmp;
- }
switch (a->kind) {
case TYPE_VOID: return true;
case TYPE_UNKNOWN: assert(0); return false;
@@ -194,7 +195,10 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
t->kind = TYPE_FN;
t->fn.types = NULL;
t->fn.constness = NULL; /* OPTIM: constness doesn't need to be a dynamic array */
-
+ bool success = true;
+ bool entered_fn = false;
+ bool added_param_decls = false;
+
FnExpr fn_copy;
if (!(flags & TYPE_OF_FN_NO_COPY_EVEN_IF_CONST) && fn_has_any_const_params(f)) {
Copier cop = {.allocr = tr->allocr, .block = tr->block};
@@ -207,6 +211,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
Type *ret_type = typer_arr_add(tr, &t->fn.types);
if (!fn_enter(f, SCOPE_CHECK_REDECL))
return false;
+ entered_fn = true;
arr_foreach(f->params, Declaration, decl) {
if (!types_decl(tr, decl)) return false;
if (!type_resolve(tr, &decl->type, where))
@@ -225,6 +230,12 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
Value val;
if (!eval_expr(tr->evalr, &decl->expr, &val)) {
info_print(decl->where, "Was trying to evaluate default arguments (which must be constants!)");
+ fn_exit(f);
+ for (Declaration *p = f->params; p != decl; p++) {
+ if (p->flags & DECL_IS_CONST)
+ arr_foreach(p->idents, Identifier, ident)
+ arr_remove_last(&(*ident)->decls);
+ }
return false;
}
decl->expr.kind = EXPR_VAL;
@@ -255,6 +266,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
}
}
}
+ added_param_decls = true;
if (f->ret_decls && f->ret_type.kind == TYPE_VOID /* haven't found return type yet */) {
@@ -265,8 +277,10 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
/* evaluate ret decl initializer */
if (d->flags & DECL_HAS_EXPR) {
Value val;
- if (!eval_expr(tr->evalr, &d->expr, &val))
- return false;
+ if (!eval_expr(tr->evalr, &d->expr, &val)) {
+ success = false;
+ goto ret;
+ }
d->expr.kind = EXPR_VAL;
d->expr.val = val;
}
@@ -284,24 +298,33 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
}
}
}
- if (!type_resolve(tr, &f->ret_type, where))
- return false;
+ if (!type_resolve(tr, &f->ret_type, where)) {
+ success = false;
+ goto ret;
+ }
*ret_type = f->ret_type;
+
- /* TODO: IMPORTANT: remove declarations even on failure */
-
- arr_foreach(f->params, Declaration, param) {
- if (param->flags & DECL_IS_CONST) {
- arr_foreach(param->idents, Identifier, ident)
- arr_remove_last(&(*ident)->decls);
+ arr_foreach(f->ret_decls, Declaration, decl) {
+ if (!types_decl(tr, decl)) {
+ success = false;
+ goto ret;
}
}
- fn_exit(f);
-
- arr_foreach(f->ret_decls, Declaration, decl) {
- if (!types_decl(tr, decl)) return false;
+ ret:
+ /* cleanup */
+ if (added_param_decls) {
+ /* remove constant parameter ident decls */
+ arr_foreach(f->params, Declaration, param) {
+ if (param->flags & DECL_IS_CONST) {
+ arr_foreach(param->idents, Identifier, ident)
+ arr_remove_last(&(*ident)->decls);
+ }
+ }
}
- return true;
+
+ if (entered_fn) fn_exit(f);
+ return success;
}
static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
@@ -878,7 +901,6 @@ static bool types_expr(Typer *tr, Expression *e) {
} break;
case EXPR_IDENT: {
if (!type_of_ident(tr, e->where, e->ident, t)) return false;
- assert(t->flags & TYPE_IS_RESOLVED);
} break;
case EXPR_CAST: {
CastExpr *c = &e->cast;
@@ -1415,8 +1437,8 @@ static bool types_expr(Typer *tr, Expression *e) {
}
/* numerical binary ops */
- if (lhs_type->kind == rhs_type->kind && lhs_type->kind == TYPE_BUILTIN
- && type_builtin_is_numerical(lhs_type->builtin) && lhs_type->builtin == rhs_type->builtin) {
+ if (lhs_type->kind == TYPE_BUILTIN && type_eq(lhs_type, rhs_type)) {
+ /* int + int, etc. */
valid = true;
}
if (o == BINARY_ADD || o == BINARY_SUB || o == BINARY_SET_ADD || o == BINARY_SET_SUB) {