summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-18 14:30:54 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-18 14:30:54 -0400
commit6fe4515f37bfe6ab12c85c4fa2f0242a922245cd (patch)
treeebd67c2ee4c538df8fa5611fd2027721519fd9b7
parent951d809ec95c89601bfd293fb4f88432d88c288d (diff)
defer seems to be working with functions now
-rw-r--r--cgen.c10
-rw-r--r--main.c8
-rw-r--r--parse.c10
-rw-r--r--test.toc32
-rw-r--r--toc.c1
-rw-r--r--types.c4
6 files changed, 36 insertions, 29 deletions
diff --git a/cgen.c b/cgen.c
index 5641d6f..1cfbff8 100644
--- a/cgen.c
+++ b/cgen.c
@@ -1821,7 +1821,11 @@ static void cgen_fn(CGenerator *g, FnExpr *f, Value *compile_time_args) {
}
cgen_block(g, &f->body, NULL, CGEN_BLOCK_NOBRACES);
+ Block *prev = g->block;
+ g->block = &f->body;
+ /* cgen_ret needs to think it's in the function body */
cgen_ret(g, &f->body, f->body.ret_expr);
+ g->block = prev;
cgen_writeln(g, "}");
g->fn = prev_fn;
@@ -1980,8 +1984,10 @@ static void cgen_ret(CGenerator *g, Block *returning_from, Expression *ret_expr)
} else {
cgen_set(g, NULL, "*ret__", &ret, NULL);
}
- cgen_write(g, " return;");
- } else if (f->ret_type.kind != TYPE_VOID) {
+ cgen_writeln(g, " return;");
+ } else if (f->ret_type.kind == TYPE_VOID) {
+ cgen_writeln(g, "return;");
+ } else {
cgen_writeln(g, "return ret_;");
}
}
diff --git a/main.c b/main.c
index f50b9ac..d1caf33 100644
--- a/main.c
+++ b/main.c
@@ -8,9 +8,12 @@
/*
TODO:
-defer
-make sure defer works with for
+make sure defer works with for, break, continue
make sure you can't return a #C() (because of the current defer system)
+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
use
&&, ||
start making a standard library... (printf; stringbuilder would be nice to have)
@@ -23,6 +26,7 @@ switch to / add as an alternative: libffi
X ::= newtype(int); or something
any odd number of "s for a string
---
+error on x ::= {return; 3}
#returns_code (struct body is a block, to be evaluated at compile time, which returns the actual statements)
- struct varargs
macros
diff --git a/parse.c b/parse.c
index 37bf68e..4fc10e3 100644
--- a/parse.c
+++ b/parse.c
@@ -2448,17 +2448,23 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
return false;
}
goto success;
- case KW_DEFER:
+ case KW_DEFER: {
if (p->block == NULL) {
tokr_err(t, "You can't defer something at global scope.");
return false;
}
- s->kind = STMT_DEFER;
++t->token;
+ s->kind = STMT_DEFER;
+ Token *deferred_start = t->token;
s->defer = parser_malloc(p, sizeof *s->defer);
if (!parse_stmt(p, s->defer, was_a_statement))
return false;
+ if (!*was_a_statement) {
+ err_print(token_location(p->file, deferred_start), "Empty defer");
+ return false;
+ }
goto success;
+ }
default: break;
}
} else if (t->token->kind == TOKEN_DIRECT) {
diff --git a/test.toc b/test.toc
index 790a115..9a5bfd8 100644
--- a/test.toc
+++ b/test.toc
@@ -1,27 +1,13 @@
-#include "std/mem.toc", mem;
#include "std/io.toc", io;
-calculation ::= fn() int {
- total := 0;
- i := mem.new(int);
- *i = 3;
- ns := mem.news(int, 10);
- for n, i := &ns {
- if i % 2 == 0 {
- *n = i;
- }
- }
- for n := ns {
- total += n;
- }
- total += *i;
- mem.del(i);
- mem.dels(ns);
- total
-}
-
main ::= fn() {
- io.puti(calculation());
- x ::= calculation();
- io.puti(x);
+ defer io.puts("second");
+ defer io.puts("third");
+ {
+ defer io.puts("there");
+ io.puts("hey");
+ }
+ io.puts("FIRST");
+ return;
+ io.puts("first");
}
diff --git a/toc.c b/toc.c
index 6c1932d..dd9bd46 100644
--- a/toc.c
+++ b/toc.c
@@ -92,6 +92,7 @@ static void print_token(Token *t);
static void print_type(Type *t);
static void print_block(Block *b);
static void print_decl(Declaration *d);
+static void print_stmt(Statement *s);
static void print_block_location(Block *b);
diff --git a/types.c b/types.c
index 9766997..f2b7db1 100644
--- a/types.c
+++ b/types.c
@@ -3402,6 +3402,10 @@ static Status types_stmt(Typer *tr, Statement *s) {
err_print(s->where, "You can't defer a defer!");
return false;
}
+ if (s->defer->kind == STMT_DECL) {
+ err_print(s->where, "Deferring a declaration doesn't make sense!");
+ return false;
+ }
break;
}
s->flags |= STMT_TYPED;