summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c30
-rw-r--r--main.c6
-rw-r--r--parse.c19
-rw-r--r--test.toc50
-rw-r--r--types.c2
5 files changed, 48 insertions, 59 deletions
diff --git a/cgen.c b/cgen.c
index ad0c673..d453149 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1929,13 +1929,22 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr)
FnExpr *f = g->fn;
if (ret_expr) {
cgen_expr_pre(g, ret_expr);
- /* set ret_ to ret_expr */
- cgen_type_pre(g, &ret_expr->type);
- cgen_write(g, " ret_");
- cgen_type_post(g, &ret_expr->type);
- cgen_write(g, "; ");
- cgen_set(g, NULL, "ret_", ret_expr, NULL);
- cgen_nl(g);
+ if (cgen_uses_ptr(&f->ret_type)) {
+ if (f->ret_type.kind == TYPE_TUPLE) {
+ cgen_set_tuple(g, NULL, NULL, "*ret__", ret_expr);
+ } else {
+ cgen_set(g, NULL, "*ret__", ret_expr, NULL);
+ }
+ } else {
+ /* set ret_ to ret_expr */
+ cgen_type_pre(g, &ret_expr->type);
+ cgen_write(g, " ret_");
+ cgen_type_post(g, &ret_expr->type);
+ cgen_write(g, "; ");
+ cgen_set(g, NULL, "ret_", ret_expr, NULL);
+ cgen_nl(g);
+ }
+
}
cgen_deferred_up_to(g, returning_from);
if (f->ret_decls) {
@@ -1976,16 +1985,13 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr)
return;
}
if (cgen_uses_ptr(&f->ret_type)) {
+ #if 0
Expression ret = {0};
ret.kind = EXPR_IDENT;
ret.ident = ident_get(g->globals, "ret_");
ret.flags = EXPR_FOUND_TYPE;
ret.type = f->ret_type;
- if (f->ret_type.kind == TYPE_TUPLE) {
- cgen_set_tuple(g, NULL, NULL, "*ret__", &ret);
- } else {
- cgen_set(g, NULL, "*ret__", &ret, NULL);
- }
+ #endif
cgen_writeln(g, " return;");
} else if (f->ret_type.kind == TYPE_VOID) {
cgen_writeln(g, "return;");
diff --git a/main.c b/main.c
index 3134bca..3038587 100644
--- a/main.c
+++ b/main.c
@@ -8,10 +8,10 @@
/*
TODO:
-switch to:
- static void
- foo() {
get rid of angle brackets for tuple types - just check if a TYPE_EXPR which is an EXPR_TUPLE is returned
+allow #ifs in structs
+ - you can just have a dyn array of stmts and when you want to resolve the struct,
+ just type the statements, then loop over them (going into blocks if necessary)
use
&&, ||
start making a standard library... (printf; stringbuilder would be nice to have)
diff --git a/parse.c b/parse.c
index 4fc10e3..5818eb3 100644
--- a/parse.c
+++ b/parse.c
@@ -455,6 +455,22 @@ static Status parse_args(Parser *p, Argument **args) {
++t->token; /* move past ) */
return true;
}
+static void correct_ret_type(Parser *p, Type *ret_type) {
+ if (ret_type->kind == TYPE_EXPR && ret_type->expr->kind == EXPR_TUPLE) {
+ /* it's returning a tuple! */
+ Expression *tuple_members = ret_type->expr->tuple;
+ size_t ntuple_members = arr_len(tuple_members);
+ ret_type->kind = TYPE_TUPLE;
+ ret_type->tuple = NULL;
+ arr_set_lena(&ret_type->tuple, ntuple_members, p->allocr);
+ for (size_t i = 0; i < ntuple_members; ++i) {
+ Type *out_type = &ret_type->tuple[i];
+ out_type->flags = 0;
+ out_type->kind = TYPE_EXPR;
+ out_type->expr = &tuple_members[i];
+ }
+ }
+}
/* where will be filled out with the location, if not NULL */
static Status parse_type(Parser *p, Type *type, Location *where) {
@@ -521,6 +537,7 @@ static Status parse_type(Parser *p, Type *type, Location *where) {
} else {
if (!parse_type(p, ret_type, NULL))
return false;
+ correct_ret_type(p, ret_type);
}
break;
}
@@ -1003,6 +1020,7 @@ static Status parse_fn_expr(Parser *p, FnExpr *f) {
success = false;
goto ret;
}
+ correct_ret_type(p, &f->ret_type);
}
p->block = prev_block; /* be nice to parse_block */
if (!parse_block(p, &f->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
@@ -1759,6 +1777,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
Token *new_end = end - 1; /* parse to ending ) */
if (!parse_expr(p, e, new_end))
return false;
+ e->where.start = start; /* make sure we keep e->where.start intact */
++t->token; /* move past closing ) */
goto success;
}
diff --git a/test.toc b/test.toc
index 1ecc9ce..c185a7f 100644
--- a/test.toc
+++ b/test.toc
@@ -1,48 +1,12 @@
#include "std/io.toc", io;
-
-plusone ::= fn(n : int) x := n {
+f ::= fn() (int, int) {
+ x := 5;
+ y := 88;
defer x += 1;
+ x, y
}
-
-same ::= fn(n : int) int {
- x := n;
- defer x += 1;
- x
-}
-
main ::= fn() {
- io.puti(plusone(3));
- io.puti(same(3));
- defer io.puts("deferred from main()");
- for i := 1..10 {
- defer io.puts("deferred from for");
- io.puti(i);
- if i == 2 {
- defer io.puts("deferred from if1");
- defer io.puts("deferred from if2");
- defer io.puts("deferred from if3");
- defer io.puts("deferred from if4");
- defer io.puts("deferred from if5");
- defer io.puts("deferred from if6");
- defer io.puts("deferred from if7");
- defer io.puts("deferred from if8");
- continue;
- }
- if i == 8 {
- break;
- }
- }
- i := 0;
- while {
- defer io.puts("deferred from while");
- i += 1;
- io.puti(i);
- if i % 2 == 0 { continue; }
- if i == 7 {
- defer io.puts("deferred from if");
- break;
- }
-
- }
- io.puts("end of main()");
+ a,b := f();
+ io.puti(a);
+ io.puti(b);
}
diff --git a/types.c b/types.c
index 8f64879..cee5698 100644
--- a/types.c
+++ b/types.c
@@ -828,7 +828,7 @@ static Status type_resolve(Typer *tr, Type *t, Location where) {
if (t->expr->type.kind == TYPE_UNKNOWN && tr->err_ctx->have_errored)
return false; /* silently fail (e.g. if a function couldn't be typed) */
if (!type_is_builtin(&t->expr->type, BUILTIN_TYPE)) {
- err_print(where, "This expression is not a type, but it's being used as one.");
+ err_print(t->expr->where, "This expression is not a type, but it's being used as one.");
return false;
}
Expression *expr = t->expr;