diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-25 09:09:39 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-25 09:09:39 -0500 |
commit | d238a47bb8b324084a81748e2d320e0bc2973d25 (patch) | |
tree | 9648b09d5651b6a726e7b796d690eda7ba1ad9ca | |
parent | 9dbd9539c2f93faa24b71917a5a961b79522e876 (diff) |
fixed problem with flexible types
-rw-r--r-- | main.c | 5 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | types.c | 70 |
3 files changed, 51 insertions, 28 deletions
@@ -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 @@ -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 @@ -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) { |