summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c3
-rw-r--r--main.c5
-rw-r--r--parse.c18
-rw-r--r--test.toc25
-rw-r--r--types.c27
5 files changed, 47 insertions, 31 deletions
diff --git a/eval.c b/eval.c
index 2c750a3..023f858 100644
--- a/eval.c
+++ b/eval.c
@@ -1508,6 +1508,9 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) {
Value *element = arr_add(&tuple);
Type *type = decl_type_at_index(d, i);
val_copy(NULL, element, &this_one, type);
+ void *to_free = val_ptr_to_free(element, type);
+ if (to_free)
+ *(void **)arr_add(&ev->to_free) = to_free;
i++;
}
}
diff --git a/main.c b/main.c
index f510b34..e2ec9e4 100644
--- a/main.c
+++ b/main.c
@@ -1,9 +1,6 @@
/*
TODO:
-ah need to be consistent about whether eval_expr returns a value which should be copied or not!!!
-check for leaks
-make sure return declarations with initializers work (also, eval initializers)
-deal with x, y @= fn(x: int, y @ int){}
+:@
don't allow pointers to functions with compile-time arguments
type parameters (e.g. fn(foo @ type) {x: foo;})
diff --git a/parse.c b/parse.c
index 9112a0a..9db0ffb 100644
--- a/parse.c
+++ b/parse.c
@@ -814,19 +814,8 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) {
}
}
t->token--; /* move back to { */
- if (arr_len(f->ret_decls) > 1 || arr_len(f->ret_decls[0].idents) > 1) {
- f->ret_type.kind = TYPE_TUPLE;
- f->ret_type.flags = 0;
- f->ret_type.tuple = NULL;
- arr_foreach(f->ret_decls, Declaration, decl) {
- for (size_t i = 0, len = arr_len(decl->idents); i < len; i++) {
- Type *tuple_type = parser_arr_add(p, &f->ret_type.tuple);
- *tuple_type = decl->type;
- }
- }
- } else {
- f->ret_type = f->ret_decls[0].type;
- }
+ /* just set return type to void. the actual return type will be set by types.c:type_of_fn */
+ f->ret_type.kind = TYPE_VOID;
} else {
if (!parse_type(p, &f->ret_type)) {
ret = false;
@@ -1765,8 +1754,11 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, uint16_
uint16_t expr_flags = 0;
if (ends_with == DECL_END_RPAREN_COMMA)
expr_flags |= EXPR_CAN_END_WITH_COMMA;
+ if (ends_with == DECL_END_LBRACE_COMMA)
+ expr_flags |= EXPR_CAN_END_WITH_LBRACE;
Token *end = expr_find_end(p, expr_flags, NULL);
if (!end || !ends_decl(end, ends_with)) {
+ t->token = end;
tokr_err(t, "Expected %s at end of declaration.", end_str);
goto ret_false;
}
diff --git a/test.toc b/test.toc
index b2499df..98e1063 100644
--- a/test.toc
+++ b/test.toc
@@ -2,22 +2,19 @@ puti @= fn(x: int) {
#C("printf(\"%ld\\n\", (long)x);
");
};
-
-
-Foo @= struct {
- x, y: int;
- z: float;
+putf @= fn(x: float) {
+ #C("printf(\"%f\\n\", (double)x);
+");
};
-
-mkfoo @= fn() f: Foo {
- f.x = 12;
- f.y = -983;
- f.z = 21.34-1.2;
+x,z @= fn(x: int, y @ int) int {
+ x+y
};
-
main @= fn() {
- f @= mkfoo();
- puti(f.x);
- puti(f.y);
+ puti(x(10, 30));
+ a @= x(20, 40);
+ puti(a);
+ puti(z(10, 30));
+ b @= z(20, 40);
+ puti(b);
};
diff --git a/types.c b/types.c
index 2fd0755..c90c2d8 100644
--- a/types.c
+++ b/types.c
@@ -180,6 +180,33 @@ static bool type_of_fn(Typer *tr, Expression *e, Type *t) {
t->fn.constant = NULL; /* OPTIM: constant doesn't need to be a dynamic array */
bool has_constant_params = false;
Type *ret_type = typer_arr_add(tr, &t->fn.types);
+ if (f->ret_decls && f->ret_type.kind == TYPE_VOID /* haven't found return type yet */) {
+ /* find return type */
+ 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))
+ return false;
+ 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;
+ } else {
+ f->ret_type.kind = TYPE_TUPLE;
+ f->ret_type.flags = 0;
+ f->ret_type.tuple = NULL;
+ arr_foreach(f->ret_decls, Declaration, d) {
+ arr_foreach(d->idents, Identifier, i) {
+ *(Type *)arr_add(&f->ret_type.tuple) = d->type;
+ }
+ }
+ }
+ }
if (!type_resolve(tr, &f->ret_type, e->where))
return false;
*ret_type = f->ret_type;