summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2019-11-25 09:47:03 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2019-11-25 09:47:03 -0500
commit0c1d471fa16aca1840ef792e9f123ecf78d3df25 (patch)
tree26c8a8ee059455913874113e4476ed017117dae0
parent76f800ae81d5530e2b07a1edf97e57710bac0d13 (diff)
fixed problems with return declarations
-rw-r--r--cgen.c2
-rw-r--r--eval.c11
-rw-r--r--main.c2
-rw-r--r--parse.c4
-rw-r--r--test.toc7
-rw-r--r--types.c44
6 files changed, 36 insertions, 34 deletions
diff --git a/cgen.c b/cgen.c
index 76dbd1b..46e221b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1691,7 +1691,7 @@ static bool cgen_val(CGenerator *g, Value v, Type *t, Location where) {
static bool cgen_decl(CGenerator *g, Declaration *d) {
int has_expr = d->flags & DECL_HAS_EXPR;
bool is_tuple = d->type.kind == TYPE_TUPLE;
- if ((d->flags & DECL_IS_CONST) || g->block == NULL) {
+ if ((d->flags & DECL_IS_CONST) || (g->block == NULL && g->fn == NULL)) {
/* declarations where we use a value */
for (size_t idx = 0; idx < arr_len(d->idents); idx++) {
Identifier i = d->idents[idx];
diff --git a/eval.c b/eval.c
index 9619ad7..f4e00a1 100644
--- a/eval.c
+++ b/eval.c
@@ -1431,17 +1431,22 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
}
arr_foreach(fn->ret_decls, Declaration, d) {
int idx = 0;
+ Value val;
+ if (d->flags & DECL_HAS_EXPR)
+ if (!eval_expr(ev, &d->expr, &val))
+ return false;
+
arr_foreach(d->idents, Identifier, i) {
- Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx++] : &d->type;
+ Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type;
IdentDecl *id = ident_decl(*i);
if (d->flags & DECL_HAS_EXPR) {
- assert(d->expr.kind == EXPR_VAL);
- copy_val(NULL, &id->val, &d->expr.val, type);
+ id->val = d->type.kind == TYPE_TUPLE ? val.tuple[idx] : val;
id->flags |= IDECL_HAS_VAL;
} else {
id->flags |= IDECL_HAS_VAL;
id->val = val_zero(type);
}
+ idx++;
}
}
arr_clear(&args);
diff --git a/main.c b/main.c
index cfb010e..1f4655d 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,5 @@
/*
TODO:
-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
diff --git a/parse.c b/parse.c
index b56895a..7268bdc 100644
--- a/parse.c
+++ b/parse.c
@@ -824,10 +824,6 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
return false;
Declaration *new_params = NULL;
arr_foreach(f->params, Declaration, param) {
- if (param->type.kind == TYPE_TUPLE) {
- err_print(param->where, "Functions can't have tuple parameters.");
- return false;
- }
/* whenever there's (x, y: int), turn it into (x: int, y: int) */
arr_foreach(param->idents, Identifier, ident) {
Declaration *new_param = parser_arr_add(p, &new_params);
diff --git a/test.toc b/test.toc
index e0e1525..12fef3a 100644
--- a/test.toc
+++ b/test.toc
@@ -8,10 +8,11 @@ puti @= fn(x: int) {
// };
-f @= fn(x: int) y := x {
- puti(x);
+f @= fn(x: int, r := x) y := x {
};
main @= fn() {
- puti(f(1238));
+R @= f(2837);
+puti(R);
+ puti(f(3218));
}; \ No newline at end of file
diff --git a/types.c b/types.c
index 4bb6506..d5d1eba 100644
--- a/types.c
+++ b/types.c
@@ -198,6 +198,7 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
bool success = true;
bool entered_fn = false;
bool added_param_decls = false;
+ FnExpr *prev_fn = tr->fn;
FnExpr fn_copy;
if (!(flags & TYPE_OF_FN_NO_COPY_EVEN_IF_CONST) && fn_has_any_const_params(f)) {
@@ -211,9 +212,16 @@ 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;
+ tr->fn = f;
+
entered_fn = true;
arr_foreach(f->params, Declaration, decl) {
if (!types_decl(tr, decl)) return false;
+ if (decl->type.kind == TYPE_TUPLE) {
+ err_print(decl->where, "Functions can't have tuple parameters.");
+ return false;
+ }
+
if (!type_resolve(tr, &decl->type, where))
return false;
U32 is_at_all_const = decl->flags & (DECL_IS_CONST | DECL_SEMI_CONST);
@@ -230,13 +238,13 @@ 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;
+ success = false;
+ goto ret;
}
decl->expr.kind = EXPR_VAL;
decl->expr.val = val;
@@ -274,16 +282,6 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
arr_foreach(f->ret_decls, Declaration, d) {
if (!types_decl(tr, d))
return false;
- /* evaluate ret decl initializer */
- if (d->flags & DECL_HAS_EXPR) {
- Value val;
- if (!eval_expr(tr->evalr, &d->expr, &val)) {
- success = false;
- goto ret;
- }
- d->expr.kind = EXPR_VAL;
- d->expr.val = val;
- }
}
if (arr_len(f->ret_decls) == 1 && arr_len(f->ret_decls[0].idents) == 1) {
f->ret_type = f->ret_decls[0].type;
@@ -313,17 +311,21 @@ static bool type_of_fn(Typer *tr, FnExpr *f, Location where, Type *t, U16 flags)
}
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);
+
+ if (entered_fn) {
+ fn_exit(f);
+ tr->fn = prev_fn;
+
+ 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);
+ }
}
}
}
-
- if (entered_fn) fn_exit(f);
return success;
}
@@ -341,7 +343,7 @@ static bool type_of_ident(Typer *tr, Location where, Identifier i, Type *t) {
Declaration *d = decl->decl;
bool captured = false;
if (decl->scope != NULL)
- for (Block *block = tr->block; block != decl->scope; block = block->parent) {
+ for (Block *block = tr->block; block && block != decl->scope; block = block->parent) {
if (block->flags & BLOCK_IS_FN) {
captured = true;
break;