summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--copy.c8
-rw-r--r--eval.c25
-rw-r--r--identifiers.c14
-rw-r--r--parse.c30
-rw-r--r--test.toc10
-rw-r--r--types.c57
-rw-r--r--types.h6
7 files changed, 97 insertions, 53 deletions
diff --git a/copy.c b/copy.c
index c102eb6..e0306e8 100644
--- a/copy.c
+++ b/copy.c
@@ -248,13 +248,13 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) {
if (fout->index) {
copier_ident_translate(c, &fout->index);
- fout->index->decl_kind = IDECL_FOR;
- fout->index->for_ = fout;
+ fout->index->decl_kind = IDECL_EXPR;
+ fout->index->decl_expr = out;
}
if (fout->value) {
copier_ident_translate(c, &fout->value);
- fout->value->decl_kind = IDECL_FOR;
- fout->value->for_ = fout;
+ fout->value->decl_kind = IDECL_EXPR;
+ fout->value->decl_expr = out;
}
if (fin->flags & FOR_ANNOTATED_TYPE)
copy_type(c, &fout->type, &fin->type);
diff --git a/eval.c b/eval.c
index 46d737d..850984e 100644
--- a/eval.c
+++ b/eval.c
@@ -726,17 +726,22 @@ static bool eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, Typ
static Value *ident_val(Identifier i) {
switch (i->decl_kind) {
- case IDECL_FOR: {
- ForExpr *fo = i->for_;
- Value *v = *(Value **)arr_last(fo->val_stack);
- if (i == fo->index) {
- if (fo->value)
- v = &v->tuple[0];
- } else {
- if (fo->index)
- v = &v->tuple[1];
+ case IDECL_EXPR: {
+ switch (i->decl_expr->kind) {
+ case EXPR_FOR: {
+ ForExpr *fo = i->decl_expr->for_;
+ Value *v = *(Value **)arr_last(fo->val_stack);
+ if (i == fo->index) {
+ if (fo->value)
+ v = &v->tuple[0];
+ } else {
+ if (fo->index)
+ v = &v->tuple[1];
+ }
+ return v;
+ }
+ default: assert(0); return NULL;
}
- return v;
}
case IDECL_DECL: {
Declaration *decl = i->decl;
diff --git a/identifiers.c b/identifiers.c
index 876c55a..a70028d 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -231,3 +231,17 @@ static int ident_index_in_decl(Identifier i, Declaration *d) {
}
return -1;
}
+
+static Location ident_decl_location(Identifier i) {
+ switch (i->decl_kind) {
+ case IDECL_DECL:
+ return i->decl->where;
+ case IDECL_EXPR:
+ return i->decl_expr->where;
+ case IDECL_NONE:
+ break;
+ }
+ assert(0);
+ Location l = {0};
+ return l;
+}
diff --git a/parse.c b/parse.c
index 254d687..90f5fce 100644
--- a/parse.c
+++ b/parse.c
@@ -1042,6 +1042,20 @@ static Identifier parser_ident_insert(Parser *p, char *str) {
return i;
}
+static bool check_ident_redecl(Parser *p, Identifier i) {
+ Tokenizer *t = p->tokr;
+ if (i->idents == &p->block->idents) {
+ if (i->decl_kind != IDECL_NONE) {
+ char *s = ident_to_str(i);
+ tokr_err(t, "Redeclaration of identifier %s.", s);
+ info_print(ident_decl_location(i), "Previous declaration was here.");
+ free(s);
+ return false;
+ }
+ }
+ return true;
+}
+
static bool parse_expr(Parser *p, Expression *e, Token *end) {
Tokenizer *t = p->tokr;
@@ -1254,8 +1268,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
&& token_is_kw(t->token + 3, KW_COLON))))) {
if (t->token->kind == TOKEN_IDENT) {
fo->value = parser_ident_insert(p, t->token->ident);
- fo->value->decl_kind = IDECL_FOR;
- fo->value->for_ = fo;
+ if (!check_ident_redecl(p, fo->value))
+ goto for_fail;
+ fo->value->decl_kind = IDECL_EXPR;
+ fo->value->decl_expr = e;
if (ident_eq_str(fo->value, "_")) /* ignore value */
fo->value = NULL;
++t->token;
@@ -1263,8 +1279,10 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) {
++t->token;
if (t->token->kind == TOKEN_IDENT) {
fo->index = parser_ident_insert(p, t->token->ident);
- fo->index->decl_kind = IDECL_FOR;
- fo->index->for_ = fo;
+ if (!check_ident_redecl(p, fo->index))
+ goto for_fail;
+ fo->index->decl_kind = IDECL_EXPR;
+ fo->index->decl_expr = e;
if (ident_eq_str(fo->index, "_")) /* ignore index */
fo->index = NULL;
++t->token;
@@ -1334,7 +1352,7 @@ static bool 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;
}
-
+ e->where.end = t->token; /* temporarily set end so that redeclaration errors aren't messed up */
if (!parse_block(p, &fo->body, PARSE_BLOCK_DONT_CREATE_IDENTS))
goto for_fail;
p->block = prev_block;
@@ -1931,6 +1949,8 @@ static bool parse_decl(Parser *p, Declaration *d, DeclEndKind ends_with, U16 fla
*ident = parser_ident_insert(p, t->token->ident);
{
Identifier i = *ident;
+ if (!check_ident_redecl(p, i))
+ goto ret_false;
i->decl_kind = IDECL_DECL;
i->decl = d;
}
diff --git a/test.toc b/test.toc
index 5eef11f..c2a951c 100644
--- a/test.toc
+++ b/test.toc
@@ -2,12 +2,10 @@ io ::= nms {
#include "std/io.toc";
};
-f ::= fn(a,b::=3) int {
- a + b
+p ::= struct(x::Type) {
+ y:int;
};
-
main ::= fn() {
- x ::= f();
- io.puti(x);
- io.puti(f());
+z:p(int);
+for z := 1..100 {z:=12;}
}; \ No newline at end of file
diff --git a/types.c b/types.c
index db2f2e2..cd61025 100644
--- a/types.c
+++ b/types.c
@@ -483,24 +483,30 @@ static bool type_of_ident(Typer *tr, Location where, Identifier *ident, Type *t)
}
}
} break;
- case IDECL_FOR: {
- ForExpr *fo = i->for_;
- /* are we inside this for? */
- typedef ForExpr *ForExprPtr;
- arr_foreach(tr->in_fors, ForExprPtr, in_f) {
- if (*in_f == fo) {
+ case IDECL_EXPR: {
+ Expression *e = i->decl_expr;
+ /* are we inside this expr? */
+ typedef Expression *ExprPtr;
+ arr_foreach(tr->in_exprs, ExprPtr, in_e) {
+ if (*in_e == e) {
char *s = ident_to_str(i);
err_print(where, "Use of identifier %s in its own declaration.", s);
free(s);
return false;
}
}
- if (i == fo->index) {
- t->kind = TYPE_BUILTIN;
- t->builtin = BUILTIN_I64;
- } else {
- assert(i == fo->value);
- *t = fo->type;
+ switch (e->kind) {
+ case EXPR_FOR: {
+ ForExpr *fo = e->for_;
+ if (i == fo->index) {
+ t->kind = TYPE_BUILTIN;
+ t->builtin = BUILTIN_I64;
+ } else {
+ assert(i == fo->value);
+ *t = fo->type;
+ }
+ } break;
+ default: assert(0); break;
}
} break;
case IDECL_NONE: {
@@ -1213,7 +1219,7 @@ static bool types_expr(Typer *tr, Expression *e) {
case EXPR_FOR: {
ForExpr *fo = e->for_;
bool in_header = true;
- *(ForExpr **)typer_arr_add(tr, &tr->in_fors) = fo;
+ *(Expression **)typer_arr_add(tr, &tr->in_exprs) = e;
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! */
if (fo->flags & FOR_IS_RANGE) {
/* TODO: allow user-defined numerical types */
@@ -1224,6 +1230,7 @@ static bool types_expr(Typer *tr, Expression *e) {
char *s = type_to_str(ft);
err_print(e->where, "from expression of for loop must be a builtin numerical type, not %s", s);
free(s);
+ goto for_fail;
}
}
if (fo->range.step) {
@@ -1233,6 +1240,7 @@ static bool types_expr(Typer *tr, Expression *e) {
char *s = type_to_str(st);
err_print(e->where, "step expression of for loop must be a builtin numerical type, not %s", s);
free(s);
+ goto for_fail;
}
}
if (fo->range.to) {
@@ -1242,6 +1250,7 @@ static bool types_expr(Typer *tr, Expression *e) {
char *s = type_to_str(tt);
err_print(e->where, "to expression of for loop must be a builtin numerical type, not %s", s);
free(s);
+ goto for_fail;
}
}
@@ -1330,7 +1339,7 @@ static bool types_expr(Typer *tr, Expression *e) {
fo->range.stepval = stepval;
}
- arr_remove_lasta(&tr->in_fors, tr->allocr);
+ arr_remove_lasta(&tr->in_exprs, tr->allocr);
in_header = false;
if (!types_block(tr, &fo->body)) goto for_fail;
@@ -1344,7 +1353,7 @@ static bool types_expr(Typer *tr, Expression *e) {
break;
for_fail:
if (in_header)
- arr_remove_lasta(&tr->in_fors, tr->allocr);
+ arr_remove_lasta(&tr->in_exprs, tr->allocr);
typer_block_exit(tr);
return false;
};
@@ -1535,12 +1544,12 @@ static bool types_expr(Typer *tr, Expression *e) {
int ident_idx = 0;
/* temporarily add this instance to the stack, while we type the decl, in case you, e.g., pass t = float to struct(t::Type, u::t = "hello") */
*(Location *)arr_add(&err_ctx->instance_stack) = e->where;
- if (!types_decl(tr, param)) {
- arr_remove_last(&err_ctx->instance_stack);
- return false;
- }
+ typer_block_enter(tr, &struc.scope);
+ bool success = types_decl(tr, param);
arr_remove_last(&err_ctx->instance_stack);
-
+ typer_block_exit(tr);
+ if (!success) return false;
+
arr_foreach(param->idents, Identifier, ident) {
Type *type = decl_type_at_index(param, ident_idx);
arg_types[p] = *type;
@@ -1599,11 +1608,9 @@ static bool types_expr(Typer *tr, Expression *e) {
struct_t.kind = TYPE_STRUCT;
struct_t.struc = &inst->struc;
*(Location *)arr_add(&err_ctx->instance_stack) = e->where;
- if (!type_resolve(tr, &struct_t, e->where)) /* resolve the struct */ {
- arr_remove_last(&err_ctx->instance_stack);
- return false;
- }
+ bool success = type_resolve(tr, &struct_t, e->where); /* resolve the struct */
arr_remove_last(&err_ctx->instance_stack);
+ if (!success) return false;
inst->struc.instance_id = table->n;
}
@@ -2759,7 +2766,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a
tr->evalr = ev;
tr->err_ctx = err_ctx;
tr->in_decls = NULL;
- tr->in_fors = NULL;
+ tr->in_exprs = NULL;
tr->allocr = allocr;
tr->globals = idents;
tr->is_reference_stack = NULL;
diff --git a/types.h b/types.h
index a6e49dc..04b6dea 100644
--- a/types.h
+++ b/types.h
@@ -170,7 +170,7 @@ typedef union Value {
typedef enum {
IDECL_NONE,
IDECL_DECL,
- IDECL_FOR
+ IDECL_EXPR
} IdentDeclKind;
@@ -181,7 +181,7 @@ typedef struct IdentSlot {
IdentDeclKind decl_kind;
union {
struct Declaration *decl;
- struct ForExpr *for_;
+ struct Expression *decl_expr;
};
struct Identifiers *idents;
SOURCE_LOCATION
@@ -899,7 +899,7 @@ typedef struct Typer {
Allocator *allocr;
Evaluator *evalr;
Identifiers *globals;
- ForExpr **in_fors; /* which fors we are currently inside the header of */
+ Expression **in_exprs; /* which expression declarations we are currently inside (e.g. for x := foo)*/
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) */