summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-03-19 12:08:12 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-03-19 12:08:12 -0400
commitb5daaa00a4b1049f5e2ddc0bb658a17e0ee1e48f (patch)
tree60b22b4e48180e417f5b23756836e58a640889a4
parent614026f24a4abce603ea3499d7241abd9383de48 (diff)
fixed IDECL_EXPR bug; version 0.5
-rw-r--r--README.md1
-rw-r--r--copy.c8
-rw-r--r--eval.c25
-rw-r--r--identifiers.c12
-rw-r--r--main.c1
-rw-r--r--parse.c18
-rw-r--r--test.toc2
-rw-r--r--toc.c1
-rw-r--r--types.c42
-rw-r--r--types.h7
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`.
<tr><td>0.2</td><td>Foreign functions and <code>#include</code>.</td><td>2020 Jan 29</td></tr>
<tr><td>0.3</td><td><code>struct</code> parameters</td><td>2020 Feb 25</td></tr>
<tr><td>0.4</td><td>Variadic functions</td><td>2020 Mar 13</td></tr>
+<tr><td>0.5</td><td><code>break</code>, <code>continue</code>, <code>defer</code></td><td>2020 Mar 19</td></tr>
</table>
---
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) */