summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--parse.c7
-rw-r--r--test.toc12
-rw-r--r--types.c68
-rw-r--r--types.h4
4 files changed, 50 insertions, 41 deletions
diff --git a/parse.c b/parse.c
index ceb690e..98ba59a 100644
--- a/parse.c
+++ b/parse.c
@@ -1392,6 +1392,12 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
++t->token;
if (!parse_decl(p, &fo->header, PARSE_DECL_IGNORE_EXPR | DECL_CAN_END_WITH_LBRACE))
goto for_fail;
+ if (arr_len(fo->header.idents) > 2) {
+ parser_put_end(p, &fo->header.where);
+ err_print(fo->header.where, "Expected at most 2 identifiers in for declaration (index and value) but got %lu.",
+ (unsigned long)arr_len(fo->header.idents));
+ goto for_fail;
+ }
if (!token_is_kw(t->token, KW_EQ)) {
tokr_err(t, "Expected = to follow for declaration.");
goto for_fail;
@@ -1437,6 +1443,7 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) {
err_print(token_location(p->file, first_end), "Expected { or .. to follow expression in for statement.");
goto for_fail;
}
+ parser_put_end(p, &fo->header.where);
p->block = prev_block;
if (!parse_block(p, &fo->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
goto for_fail;
diff --git a/test.toc b/test.toc
index 8c4d07f..2eacef8 100644
--- a/test.toc
+++ b/test.toc
@@ -1,11 +1,5 @@
-Point ::= struct {
- x, y: int;
-}
-
main ::= fn() {
- use p: Point;
- p.x = 15;
- p.y = 18;
- x += 5;
- x := 18;
+ for i := 1..10 {
+
+ }
}
diff --git a/types.c b/types.c
index 5966e8c..5f6f0ba 100644
--- a/types.c
+++ b/types.c
@@ -1519,17 +1519,26 @@ static Status types_expr(Typer *tr, Expression *e) {
t->builtin = BUILTIN_CHAR;
break;
case EXPR_FOR: {
- /* TODO */
-#if 0
ForExpr *fo = e->for_;
+ Declaration *header = &fo->header;
+ *(Declaration **)typer_arr_add(tr, &tr->in_decls) = header;
bool in_header = true;
- *(ForExpr **)typer_arr_add(tr, &tr->in_fors) = fo;
+
+ if (header->flags & DECL_ANNOTATES_TYPE) {
+ fo->type = &header->type;
+ if (!type_resolve(tr, fo->type, header->where))
+ goto for_fail;
+ } else {
+ fo->type = NULL;
+ }
+
fo->body.uses = NULL;
- typer_block_enter(tr, &fo->body); /* while this block is being typed, fo->body will be in tr->blocks twice. hopefully that doesn't mess anything up! */
+ typer_block_enter(tr, &fo->body);
if (fo->flags & FOR_IS_RANGE) {
if (!types_expr(tr, fo->range.from)) goto for_fail;
{
Type *ft = &fo->range.from->type;
+
if (ft->kind != TYPE_BUILTIN || !type_builtin_is_numerical(ft->builtin)) {
char *s = type_to_str(ft);
err_print(e->where, "from expression of for loop must be a builtin numerical type, not %s", s);
@@ -1558,40 +1567,43 @@ static Status types_expr(Typer *tr, Expression *e) {
}
}
- if (!(fo->flags & FOR_ANNOTATED_TYPE)) {
+ if (fo->type) {
+ if (!type_eq(fo->type, &fo->range.from->type)) {
+ char *exp = type_to_str(fo->type);
+ char *got = type_to_str(&fo->range.from->type);
+ err_print(e->where, "Type of for loop does not match the type of the from expression. Expected %s, but got %s.", exp, got);
+ free(exp); free(got);
+ goto for_fail;
+ }
+ if ((fo->type->flags & TYPE_IS_FLEXIBLE))
+ fo->type = &fo->range.from->type;
+ } else {
fo->type = &fo->range.from->type;
}
-
- if (!type_eq(&fo->type, &fo->range.from->type)) {
- char *exp = type_to_str(&fo->type);
- char *got = type_to_str(&fo->range.from->type);
- err_print(e->where, "Type of for loop does not match the type of the from expression. Expected %s, but got %s.", exp, got);
- free(exp); free(got);
- goto for_fail;
- }
-
- if (fo->range.step && !type_eq(&fo->type, &fo->range.step->type)) {
- char *exp = type_to_str(&fo->type);
+
+ if (fo->range.step && !type_eq(fo->type, &fo->range.step->type)) {
+ char *exp = type_to_str(fo->type);
char *got = type_to_str(&fo->range.step->type);
err_print(e->where, "Type of for loop does not match the type of the step expression. Expected %s, but got %s.", exp, got);
free(exp); free(got);
goto for_fail;
}
- if ((fo->type.flags & TYPE_IS_FLEXIBLE) && fo->range.step)
- fo->type = fo->range.step->type;
+ if ((fo->type->flags & TYPE_IS_FLEXIBLE) && fo->range.step)
+ fo->type = &fo->range.step->type;
- if (fo->range.to && !type_eq(&fo->type, &fo->range.to->type)) {
- char *exp = type_to_str(&fo->type);
+ if (fo->range.to && !type_eq(fo->type, &fo->range.to->type)) {
+ char *exp = type_to_str(fo->type);
char *got = type_to_str(&fo->range.to->type);
err_print(e->where, "Type of for loop does not match the type of the to expression. Expected %s, but got %s.", exp, got);
free(exp); free(got);
goto for_fail;
}
-
- if ((fo->type.flags & TYPE_IS_FLEXIBLE) && fo->range.to)
- fo->type = fo->range.to->type;
- fo->type.flags &= (TypeFlags)~(TypeFlags)TYPE_IS_FLEXIBLE;
+ if (fo->type->flags & TYPE_IS_FLEXIBLE) {
+ if (fo->range.to)
+ fo->type = &fo->range.to->type;
+ fo->type->flags &= (TypeFlags)~(TypeFlags)TYPE_IS_FLEXIBLE;
+ }
} else {
if (!types_expr(tr, fo->of))
goto for_fail;
@@ -1614,12 +1626,11 @@ static Status types_expr(Typer *tr, Expression *e) {
case BUILTIN_VARARGS: {
/* exit for body */
typer_block_exit(tr);
- arr_remove_lasta(&tr->in_fors, tr->allocr);
+ arr_remove_lasta(&tr->in_decls, tr->allocr);
/* create one block, containing a block for each vararg */
/* e.g. for x := varargs { total += x; } => { { x := varargs[0]; total += x; } { x := varargs[0]; total += x; } } */
assert(fo->of->kind == EXPR_IDENT);
Identifier varargs_ident = fo->of->ident;
- assert(varargs_ident->decl_kind == IDECL_DECL);
Declaration *idecl = varargs_ident->decl;
VarArg *varargs = idecl->val.varargs;
size_t nvarargs = arr_len(varargs);
@@ -1728,8 +1739,8 @@ static Status types_expr(Typer *tr, Expression *e) {
ptr_type.ptr = iter_type;
iter_type = &ptr_type;
}
- if (fo->flags & FOR_ANNOTATED_TYPE) {
- if (!type_eq(iter_type, &fo->type)) {
+ if (header->flags & DECL_ANNOTATES_TYPE) {
+ if (!type_eq(iter_type, fo->type)) {
char *exp = type_to_str(iter_type);
char *got = type_to_str(&fo->type);
err_print(e->where, "Expected to iterate over type %s, but it was annotated as iterating over type %s.");
@@ -1765,7 +1776,6 @@ static Status types_expr(Typer *tr, Expression *e) {
arr_remove_lasta(&tr->in_fors, tr->allocr);
typer_block_exit(tr);
return false;
- #endif
};
case EXPR_IDENT: {
Block *b = tr->block;
diff --git a/types.h b/types.h
index e04f025..b61f190 100644
--- a/types.h
+++ b/types.h
@@ -622,8 +622,7 @@ typedef struct WhileExpr {
enum {
- FOR_IS_RANGE = 0x01,
- FOR_ANNOTATED_TYPE = 0x02,
+ FOR_IS_RANGE = 0x01
};
@@ -1025,7 +1024,6 @@ typedef struct Typer {
Evaluator *evalr;
Identifiers *globals;
Use **uses; /* global used things */
- ForExpr **in_fors; /* array of for loop headers we are currently inside */
Declaration **in_decls; /* array of declarations we are currently inside */
Block *block;
Block **blocks; /* dyn array of all the block's we're in ([0] = NULL for global scope) */