From b5daaa00a4b1049f5e2ddc0bb658a17e0ee1e48f Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 19 Mar 2020 12:08:12 -0400 Subject: fixed IDECL_EXPR bug; version 0.5 --- README.md | 1 + copy.c | 8 ++++---- eval.c | 25 ++++++++++--------------- identifiers.c | 12 +++++++++--- main.c | 1 - parse.c | 18 +++++++++++------- test.toc | 2 +- toc.c | 1 + types.c | 42 ++++++++++++++++++------------------------ types.h | 7 ++++--- 10 files changed, 59 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index f409b19..a7aa712 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,7 @@ Here are the major versions of `toc`. 0.2Foreign functions and #include.2020 Jan 29 0.3struct parameters2020 Feb 25 0.4Variadic functions2020 Mar 13 +0.5break, continue, defer2020 Mar 19 --- diff --git a/copy.c b/copy.c index 3919e46..e57dc51 100644 --- a/copy.c +++ b/copy.c @@ -291,13 +291,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_EXPR; - fout->index->decl_expr = out; + fout->index->decl_kind = IDECL_FOR; + fout->index->decl_for = fout; } if (fout->value) { copier_ident_translate(c, &fout->value); - fout->value->decl_kind = IDECL_EXPR; - fout->value->decl_expr = out; + fout->value->decl_kind = IDECL_FOR; + fout->value->decl_for = fout; } if (fin->flags & FOR_ANNOTATED_TYPE) copy_type(c, &fout->type, &fin->type); diff --git a/eval.c b/eval.c index c694c41..78307e3 100644 --- a/eval.c +++ b/eval.c @@ -656,22 +656,17 @@ static Status eval_expr_ptr_at_index(Evaluator *ev, Expression *e, void **ptr, T static Value *ident_val(Identifier i) { switch (i->decl_kind) { - 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; + case IDECL_FOR: { + ForExpr *fo = i->decl_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; } case IDECL_DECL: { Declaration *decl = i->decl; diff --git a/identifiers.c b/identifiers.c index 585ee52..b03a7be 100644 --- a/identifiers.c +++ b/identifiers.c @@ -206,12 +206,18 @@ static int ident_index_in_decl(Identifier i, Declaration *d) { return -1; } -static Location ident_decl_location(Identifier i) { +static Location ident_decl_location(File *file, Identifier i) { switch (i->decl_kind) { case IDECL_DECL: return i->decl->where; - case IDECL_EXPR: - return i->decl_expr->where; + case IDECL_FOR: + if (i == i->decl_for->index) { + return token_location(file, i->decl_for->index_token); + } else { + assert(i == i->decl_for->value); + return token_location(file, i->decl_for->value_token); + } + break; case IDECL_NONE: break; } diff --git a/main.c b/main.c index 3038587..e89af41 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,6 @@ /* TODO: -get rid of angle brackets for tuple types - just check if a TYPE_EXPR which is an EXPR_TUPLE is returned allow #ifs in structs - you can just have a dyn array of stmts and when you want to resolve the struct, just type the statements, then loop over them (going into blocks if necessary) diff --git a/parse.c b/parse.c index df49dbb..66f847d 100644 --- a/parse.c +++ b/parse.c @@ -1034,7 +1034,7 @@ static Status check_ident_redecl(Parser *p, Identifier i) { 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."); + info_print(ident_decl_location(p->file, i), "Previous declaration was here."); free(s); return false; } @@ -1434,10 +1434,12 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { fo->value = parser_ident_insert(p, t->token->ident); 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 */ + if (ident_eq_str(fo->value, "_")) { /* ignore value */ fo->value = NULL; + } else { + fo->value->decl_kind = IDECL_FOR; + fo->value->decl_for = fo; + } ++t->token; if (token_is_kw(t->token, KW_COMMA)) { ++t->token; @@ -1445,10 +1447,12 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { fo->index = parser_ident_insert(p, t->token->ident); 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 */ + if (ident_eq_str(fo->index, "_")) { /* ignore index */ fo->index = NULL; + } else { + fo->index->decl_kind = IDECL_FOR; + fo->index->decl_for = fo; + } ++t->token; } else { tokr_err(t, "Expected identifier after , in for loop."); diff --git a/test.toc b/test.toc index 6c2a304..8797e39 100644 --- a/test.toc +++ b/test.toc @@ -1,4 +1,4 @@ -#include "io.toc", io; +#include "std/io.toc", io; plusone ::= fn(n : int) x := n { defer x += 1; diff --git a/toc.c b/toc.c index dd9bd46..1b5ce6d 100644 --- a/toc.c +++ b/toc.c @@ -154,6 +154,7 @@ static char *read_file_contents(Allocator *a, const char *filename, Location whe } +static Location token_location(File *file, Token *t); #include "identifiers.c" #include "copy.c" diff --git a/types.c b/types.c index d67596f..852e142 100644 --- a/types.c +++ b/types.c @@ -698,31 +698,25 @@ static Status type_of_ident(Typer *tr, Location where, Identifier *ident, Type * } } } break; - 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) { + case IDECL_FOR: { + ForExpr *fo = i->decl_for; + /* are we inside this for loop? */ + typedef ForExpr *ForExprPtr; + arr_foreach(tr->in_fors, ForExprPtr, in_f) { + if (*in_f == fo) { char *s = ident_to_str(i); err_print(where, "Use of identifier %s in its own declaration.", s); free(s); return false; } } - switch (e->kind) { - case EXPR_FOR: { - ForExpr *fo = e->for_; - if (i == fo->index) { - t->kind = TYPE_BUILTIN; - t->builtin = BUILTIN_I64; - t->flags = TYPE_IS_RESOLVED; - } else { - assert(i == fo->value); - *t = fo->type; - } - } break; - default: assert(0); break; + if (i == fo->index) { + t->kind = TYPE_BUILTIN; + t->builtin = BUILTIN_I64; + t->flags = TYPE_IS_RESOLVED; + } else { + assert(i == fo->value); + *t = fo->type; } } break; case IDECL_NONE: { @@ -1510,7 +1504,7 @@ static Status types_expr(Typer *tr, Expression *e) { case EXPR_FOR: { ForExpr *fo = e->for_; bool in_header = true; - *(Expression **)typer_arr_add(tr, &tr->in_exprs) = e; + *(ForExpr **)typer_arr_add(tr, &tr->in_fors) = fo; 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) { if (!types_expr(tr, fo->range.from)) goto for_fail; @@ -1600,7 +1594,7 @@ static Status types_expr(Typer *tr, Expression *e) { case BUILTIN_VARARGS: { /* exit for body */ typer_block_exit(tr); - arr_remove_lasta(&tr->in_exprs, tr->allocr); + arr_remove_lasta(&tr->in_fors, 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); @@ -1733,7 +1727,7 @@ static Status types_expr(Typer *tr, Expression *e) { fo->range.stepval = stepval; } - arr_remove_lasta(&tr->in_exprs, tr->allocr); + arr_remove_lasta(&tr->in_fors, tr->allocr); in_header = false; if (!types_block(tr, &fo->body)) goto for_fail; if (fo->body.ret_expr) { @@ -1747,7 +1741,7 @@ static Status types_expr(Typer *tr, Expression *e) { break; for_fail: if (in_header) - arr_remove_lasta(&tr->in_exprs, tr->allocr); + arr_remove_lasta(&tr->in_fors, tr->allocr); typer_block_exit(tr); return false; }; @@ -3422,7 +3416,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_exprs = NULL; + tr->in_fors = NULL; tr->allocr = allocr; tr->globals = idents; *(Block **)arr_adda(&tr->blocks, allocr) = NULL; diff --git a/types.h b/types.h index 3549ad6..d6f6e24 100644 --- a/types.h +++ b/types.h @@ -185,7 +185,7 @@ typedef struct VarArg { typedef enum { IDECL_NONE, IDECL_DECL, - IDECL_EXPR + IDECL_FOR } IdentDeclKind; @@ -196,7 +196,7 @@ typedef struct IdentSlot { IdentDeclKind decl_kind; union { struct Declaration *decl; - struct Expression *decl_expr; + struct ForExpr *decl_for; }; struct Identifiers *idents; struct Namespace *nms; /* only exists after typing, and only for namespace-level declarations (i.e. not local variables) */ @@ -643,6 +643,7 @@ typedef struct ForExpr { Type type; /* uninitialized unless typed or flags & FOR_ANNOTATED_TYPE */ Identifier index; /* NULL = no index */ Identifier value; /* NULL = no value */ + Token *index_token, *value_token; /* used for errors */ Block body; union { struct { @@ -1034,7 +1035,7 @@ typedef struct Typer { Allocator *allocr; Evaluator *evalr; Identifiers *globals; - Expression **in_exprs; /* which expression declarations we are currently inside (e.g. for x := foo)*/ + 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) */ -- cgit v1.2.3