diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-25 14:09:30 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-04-25 14:09:30 -0400 |
commit | 7aa21a12d1b5505ba6258f2a74ce8716e72387c3 (patch) | |
tree | b6067441f028cf42708cc065235920aefa25e980 | |
parent | 342f08a7753495f51eb19dfee6d1b23bbddf344e (diff) |
improved #include error handling
-rw-r--r-- | main.c | 2 | ||||
-rw-r--r-- | test.toc | 23 | ||||
-rw-r--r-- | types.c | 25 | ||||
-rw-r--r-- | types.h | 5 |
4 files changed, 29 insertions, 26 deletions
@@ -8,8 +8,6 @@ /* @TODO: -allow `use ???;` if an error has already occurred -if something gets included into a namespace, and its typing fails, the namespace should still be of type namespace, not ??? make sure you can do a[i] where a is &[5]int or &[]char or something do we consistently handle x := &some_array_or_slice; x.len use @@ -1,23 +1,6 @@ -#include "std/io.toc"; -#include "std/mem.toc"; - -generate_numbers ::= fn() []int { - nums := news(int, 10); - for n, i := &nums { - *n = i*i; - } - nums -} - -hw := "hello, world!"; -nums := generate_numbers(); +#include "std/io.toc", io; +use io; main ::= fn() { - hw[0] = 'j'; - nums[5] = 183; - puts(hw); - for x := nums { - puti(x); - } - + puts("hi"); } @@ -1520,10 +1520,16 @@ static Status expr_must_usable_(Expression *e) { return false; } -static Status expr_must_usable(Expression *e) { +static Status expr_must_usable(Typer *tr, Expression *e) { Type *t = &e->type; if (t->kind != TYPE_STRUCT && !type_is_builtin(t, BUILTIN_NMS)) { if (!(t->kind == TYPE_PTR && t->ptr->kind == TYPE_STRUCT)) { + if (t->kind == TYPE_UNKNOWN) { + if (tr->err_ctx->have_errored) { + /* silently fail; this could've been because of an earlier error */ + return false; + } + } char *str = type_to_str(&e->type); err_print(e->where, "You cannot use something of type %s (only Namespaces and structs).", str); free(str); @@ -1548,7 +1554,7 @@ static Status use_ident(Typer *tr, Identifier i, Type *t, Location where) { used->type = *t; used->ident = i; used->where = where; - if (!expr_must_usable(used)) + if (!expr_must_usable(tr, used)) return false; return true; } @@ -3289,6 +3295,10 @@ static Status types_block(Typer *tr, Block *b) { arr_foreach(b->stmts, Statement, s) { if (!types_stmt(tr, s)) { success = false; + if (tr->had_include_err) { + /* stop immediately; prevent too many "undeclared identifier" errors */ + break; + } continue; } if (s->kind == STMT_EXPR && (s->flags & STMT_EXPR_NO_SEMICOLON)) { @@ -3579,8 +3589,10 @@ static Status types_stmt(Typer *tr, Statement *s) { inc_f->main_nms = tr->nms; } char *contents = read_file_contents(tr->allocr, filename, s->where); - if (!contents) + if (!contents) { + tr->had_include_err = true; return false; + } Tokenizer tokr; tokr_create(&tokr, tr->err_ctx, tr->allocr); @@ -3662,7 +3674,7 @@ static Status types_stmt(Typer *tr, Statement *s) { Expression *e = &u->expr; if (!types_expr(tr, e)) return false; - if (!expr_must_usable(e)) { + if (!expr_must_usable(tr, e)) { return false; } if (tr->block) @@ -3684,6 +3696,7 @@ static void typer_create(Typer *tr, Evaluator *ev, File *file, ErrCtx *err_ctx, tr->file = file; tr->err_ctx = err_ctx; tr->in_decls = NULL; + tr->had_include_err = false; tr->allocr = allocr; tr->globals = idents; typer_arr_add(tr, tr->blocks, NULL); @@ -3696,6 +3709,10 @@ static Status types_file(Typer *tr, ParsedFile *f) { tr->uses = NULL; arr_foreach(f->stmts, Statement, s) { if (!types_stmt(tr, s)) { + if (tr->had_include_err) { + /* stop immediately; prevent too many "undeclared identifier" errors */ + return false; + } ret = false; } } @@ -1037,6 +1037,11 @@ typedef struct Typer { Namespace *nms; StrHashTable included_files; /* maps to IncludedFile */ File *file; + /* + have we had an error because we couldn't find a file that was #include'd + (so that we can stop compiling immediately) + */ + bool had_include_err; } Typer; typedef struct CGenerator { |