summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--eval.c3
-rw-r--r--parse.c56
-rw-r--r--test.toc16
-rw-r--r--types.c9
4 files changed, 49 insertions, 35 deletions
diff --git a/eval.c b/eval.c
index f14ab79..7bea49a 100644
--- a/eval.c
+++ b/eval.c
@@ -110,6 +110,9 @@ static bool eval_expr_as_int(Expression *e, Integer *i) {
case EXPR_CALL:
err_print(e->where, "Compile time function calling not supported yet."); /* TODO */
break;
+ case EXPR_BLOCK:
+ err_print(e->where, "Block eval not supported yet."); /* TODO */
+ break;
case EXPR_DIRECT:
switch (e->direct.which) {
case DIRECT_C:
diff --git a/parse.c b/parse.c
index e9695e6..d5c9e84 100644
--- a/parse.c
+++ b/parse.c
@@ -61,6 +61,7 @@ typedef enum {
EXPR_UNARY_OP,
EXPR_FN,
EXPR_CALL,
+ EXPR_BLOCK,
EXPR_DIRECT
} ExprKind;
@@ -113,6 +114,7 @@ typedef struct Expression {
DirectExpr direct;
Identifier ident;
struct FnExpr *fn;
+ Block block;
};
} Expression;
@@ -393,8 +395,10 @@ static Token *expr_find_end(Parser *p, unsigned flags) {
} else if (square_level > 0) {
tokr_err(t, "Opening square bracket [ was never closed.");
} else {
- tokr_err(t, "Could not find end of expression.");
+ tokr_err(t, "Could not find end of expression (did you forget a semicolon?).");
+ /* FEATURE: improve err message */
}
+ t->token = token; /* don't try to continue */
return NULL;
}
token++;
@@ -476,7 +480,7 @@ static bool parse_type(Parser *p, Type *type) {
t->token++; /* move past ( */
while (1) {
Type *child = arr_add(&type->tuple);
- parse_type(p, child);
+ if (!parse_type(p, child)) return false;
if (token_is_kw(t->token, KW_RPAREN)) { /* we're done with the tuple */
t->token++; /* move past ) */
break;
@@ -859,6 +863,17 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
return true;
}
}
+
+ if (token_is_kw(t->token, KW_LBRACE)) {
+ /* it's a block */
+ e->kind = EXPR_BLOCK;
+ if (!parse_block(p, &e->block)) return false;
+ if (t->token != end) {
+ tokr_err(t, "Expression continues after end of block."); /* TODO: improve this err message */
+ return false;
+ }
+ return true;
+ }
tokr_err(t, "Not implemented yet.");
t->token = end + 1;
return false;
@@ -1040,14 +1055,21 @@ static bool parse_single_type_in_decl(Parser *p, Declaration *d, DeclEndType end
/* OPTIM: switch t->token->kw ? */
if (token_is_kw(t->token, KW_EQ)) {
t->token++;
- if (!parse_expr(p, &d->expr, expr_find_end(p, 0)))
+ Token *end = expr_find_end(p, 0);
+ if (!token_is_kw(end, KW_SEMICOLON)) {
+ tokr_err(t, "Expected ';' at end of declaration.");
return false;
+ }
+ if (!parse_expr(p, &d->expr, end)) {
+ t->token = end + 1; /* move past ; */
+ return false;
+ }
d->flags |= DECL_FLAG_HAS_EXPR;
if (ends_decl(t->token, ends_with)) {
t->token++;
return true;
}
- tokr_err(t, "Expected '%c' at end of expression.",
+ tokr_err(t, "Expected '%c' at end of declaration.",
ends_with == DECL_END_SEMICOLON ? ';' : ')');
return false;
@@ -1087,31 +1109,20 @@ static bool parse_stmt(Parser *p, Statement *s) {
|| token_is_kw(t->token + 1, KW_AT)) {
s->kind = STMT_DECL;
if (!parse_decl(p, &s->decl, DECL_END_SEMICOLON)) {
- /* move to next statement */
- /* TODO: This might cause unhelpful errors if the first semicolon is inside a block, etc. */
- while (!token_is_kw(t->token, KW_SEMICOLON)) {
- if (t->token->kind == TOKEN_EOF) {
- /* don't bother continuing */
- tokr_err(t, "No semicolon found at end of declaration.");
- return false;
- }
- t->token++;
- }
- t->token++; /* move past ; */
return false;
}
return true;
} else {
s->kind = STMT_EXPR;
Token *end = expr_find_end(p, 0);
- if (token_is_kw(end, KW_SEMICOLON)) {
- s->flags |= STMT_FLAG_VOIDED_EXPR;
- }
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)) {
+ s->flags |= STMT_FLAG_VOIDED_EXPR;
+ }
bool success = parse_expr(p, &s->expr, end);
/* go past end regardless of whether successful or not */
@@ -1147,6 +1158,10 @@ static bool parse_file(Parser *p, ParsedFile *f) {
Statement *stmt = arr_add(&f->stmts);
if (!parse_stmt(p, stmt))
ret = false;
+ if (token_is_kw(t->token, KW_RBRACE)) {
+ tokr_err(t, "} without a matching {.");
+ return false;
+ }
}
return ret;
}
@@ -1260,7 +1275,7 @@ static void fprint_expr(FILE *out, Expression *e) {
case EXPR_UNARY_OP:
switch (e->unary.op) {
case UNARY_MINUS:
- fprintf(out, "negate");
+ fprintf(out, "-");
break;
}
fprintf(out, "(");
@@ -1274,6 +1289,9 @@ static void fprint_expr(FILE *out, Expression *e) {
fprint_expr(out, e->call.fn);
fprint_args(out, &e->call.args);
break;
+ case EXPR_BLOCK:
+ fprint_block(out, &e->block);
+ break;
case EXPR_DIRECT:
fprintf(out, "#");
fprintf(out, "%s", directives[e->direct.which]);
diff --git a/test.toc b/test.toc
index a89c6fb..534c5a9 100644
--- a/test.toc
+++ b/test.toc
@@ -1,17 +1,3 @@
-N @= 3;
-foo_func @= fn(x: int) [N][N]int {
- foo : [3]int;
- foo[0] = x*1;
- foo[1] = x*2;
- foo[2] = x*3;
- asdf : [3][3]int;
- asdf[0] = foo;
- asdf[1] = foo;
- asdf[2] = foo;
- asdf
-};
main @= fn() {
- asdf : [3][3]int = foo_func(5);
- foo := fn (x, y, z,w : f32, A:f64) {};
- foo(3,4,5,3,5);
+ x := 7;
};
diff --git a/types.c b/types.c
index e8a95b3..8d70850 100644
--- a/types.c
+++ b/types.c
@@ -1,6 +1,7 @@
static bool type_of_expr(Expression *e);
static bool types_stmt(Statement *s);
static bool types_expr(Expression *e);
+static bool types_block(Block *b);
static bool add_ident_decls(Block *b, Declaration *d) {
bool ret = true;
@@ -224,7 +225,7 @@ static bool type_resolve(Type *t) {
return true;
}
-/* NOTE: this does descend into un/binary ops, calls, etc. but NOT into any blocks */
+/* NOTE: this does descend into un/binary ops, calls, etc. but NOT into any functions */
static bool type_of_expr(Expression *e) {
if (e->flags & EXPR_FLAG_FOUND_TYPE) return true;
Type *t = &e->type;
@@ -306,6 +307,12 @@ static bool type_of_expr(Expression *e) {
*t = *ret_type;
break;
}
+ case EXPR_BLOCK: {
+ Block *b = &e->block;
+ if (!types_block(b))
+ return false;
+ *t = b->ret_expr->type;
+ } break;
case EXPR_DIRECT:
t->kind = TYPE_UNKNOWN;
arr_foreach(&e->direct.args, Expression, arg) {