summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c3
-rw-r--r--parse.c29
-rw-r--r--test.toc9
-rw-r--r--types.c8
4 files changed, 29 insertions, 20 deletions
diff --git a/main.c b/main.c
index 9e99839..d94fcaf 100644
--- a/main.c
+++ b/main.c
@@ -1,7 +1,6 @@
/*
TODO:
-float => f32
-fix foo @= foo;
+allow void block expression statements not to have semicolons
don't allow nested functions to capture outer variables (constants are allowed though)
if, else
re-do cgen
diff --git a/parse.c b/parse.c
index e8b7376..114836c 100644
--- a/parse.c
+++ b/parse.c
@@ -366,12 +366,14 @@ static int op_precedence(Keyword op) {
#define EXPR_CAN_END_WITH_COMMA 0x01 /* a comma could end the expression */
-static Token *expr_find_end(Parser *p, unsigned flags) {
+static Token *expr_find_end(Parser *p, uint16_t flags, bool *is_vbs) {
Tokenizer *t = p->tokr;
int paren_level = 0;
int brace_level = 0;
int square_level = 0;
Token *token = t->token;
+ bool could_be_vbs = false; /* could this be a void block statement (whose semicolons can be omitted)? e.g. {x := 5;} */
+ if (is_vbs) *is_vbs = false;
while (1) {
if (token->kind == TOKEN_KW) {
switch (token->kw) {
@@ -401,16 +403,24 @@ static Token *expr_find_end(Parser *p, unsigned flags) {
break;
case KW_RBRACE:
brace_level--;
+ if (brace_level == 0 && could_be_vbs) {
+ if (is_vbs) *is_vbs = true;
+ return token + 1; /* token afer } is end */
+ }
if (brace_level < 0)
return token;
break;
case KW_SEMICOLON:
if (brace_level == 0)
return token;
+ could_be_vbs = true;
break;
default: break;
}
+
}
+ if (!token_is_kw(token, KW_RBRACE) && !token_is_kw(token, KW_SEMICOLON))
+ could_be_vbs = false;
if (token->kind == TOKEN_EOF) {
if (brace_level > 0) {
tokr_err(t, "Opening brace { was never closed."); /* FEATURE: Find out where this is */
@@ -487,7 +497,7 @@ static bool parse_type(Parser *p, Type *type) {
Token *start = t->token;
type->kind = TYPE_ARR;
t->token++; /* move past [ */
- Token *end = expr_find_end(p, 0);
+ Token *end = expr_find_end(p, 0, NULL);
type->arr.n_expr = parser_new_expr(p);
if (!parse_expr(p, type->arr.n_expr, end)) return false;
t->token = end + 1; /* go past ] */
@@ -636,7 +646,7 @@ static bool parse_args(Parser *p, Array *args) {
return false;
}
Expression *arg = arr_add(args);
- if (!parse_expr(p, arg, expr_find_end(p, EXPR_CAN_END_WITH_COMMA))) {
+ if (!parse_expr(p, arg, expr_find_end(p, EXPR_CAN_END_WITH_COMMA, NULL))) {
return false;
}
if (token_is_kw(t->token, KW_RPAREN))
@@ -875,7 +885,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
if (!parse_expr(p, e->binary.lhs, opening_bracket)) return false;
/* parse index */
t->token = opening_bracket + 1;
- Token *index_end = expr_find_end(p, 0);
+ Token *index_end = expr_find_end(p, 0, NULL);
if (!parse_expr(p, e->binary.rhs, index_end))
return false;
t->token++; /* move past ] */
@@ -1131,13 +1141,13 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndType ends_with, uint16_
/* OPTIM: switch t->token->kw ? */
if (token_is_kw(t->token, KW_EQ)) {
t->token++;
- Token *end = expr_find_end(p, 0);
- if (!token_is_kw(end, KW_SEMICOLON)) {
+ d->flags |= DECL_FLAG_HAS_EXPR;
+ Token *end = expr_find_end(p, 0, NULL);
+ if (!end || !token_is_kw(end, KW_SEMICOLON)) {
tokr_err(t, "Expected ';' at end of declaration.");
ret = false;
break;
}
- d->flags |= DECL_FLAG_HAS_EXPR;
if (!parse_expr(p, &d->expr, end)) {
t->token = end + 1; /* move past ; */
ret = false;
@@ -1197,13 +1207,14 @@ static bool parse_stmt(Parser *p, Statement *s) {
return true;
} else {
s->kind = STMT_EXPR;
- Token *end = expr_find_end(p, 0);
+ bool is_vbs;
+ Token *end = expr_find_end(p, 0, &is_vbs);
if (!end) {
tokr_err(t, "No semicolon found at end of statement.");
while (t->token->kind != TOKEN_EOF) t->token++; /* move to end of file */
return false;
}
- if (token_is_kw(end, KW_SEMICOLON)) {
+ if (is_vbs || token_is_kw(end, KW_SEMICOLON)) {
s->flags |= STMT_FLAG_VOIDED_EXPR;
}
bool success = parse_expr(p, &s->expr, end);
diff --git a/test.toc b/test.toc
index de8ee0e..f3a0fc6 100644
--- a/test.toc
+++ b/test.toc
@@ -1,12 +1,7 @@
+
main @= fn() {
-/*
f := main;
f();
- main();
-*/
- N @= {
- foo : [N]int;
- foo[0]
- };
+ { main(); }
};
diff --git a/types.c b/types.c
index 511614c..f5804bc 100644
--- a/types.c
+++ b/types.c
@@ -343,7 +343,11 @@ static bool type_of_expr(Typer *tr, Expression *e) {
Block *b = &e->block;
if (!types_block(tr, b))
return false;
- *t = b->ret_expr->type;
+ if (b->ret_expr) {
+ *t = b->ret_expr->type;
+ } else {
+ t->kind = TYPE_VOID;
+ }
} break;
case EXPR_DIRECT:
t->kind = TYPE_UNKNOWN;
@@ -575,7 +579,7 @@ static bool types_decl(Typer *tr, Declaration *d) {
} else {
if (d->expr.type.kind == TYPE_VOID) {
/* e.g. x := (fn(){})(); */
- err_print(d->expr.where, "Used return value of function which does not return anything.");
+ err_print(d->expr.where, "Use of void value.");
success = false;
goto ret;
}