diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-13 21:01:39 -0400 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-05-13 21:01:39 -0400 |
commit | b7b02528d7121b71adced7f79af48d09558dfa85 (patch) | |
tree | f5ee23641d27236c8a62f49a7701028e5571a8e9 | |
parent | 83718e0953f7489bdffd6c75f55ce51b385a1a51 (diff) |
check for circular includes
-rw-r--r-- | identifiers.c | 4 | ||||
-rw-r--r-- | main.c | 12 | ||||
-rw-r--r-- | misc.c | 11 | ||||
-rw-r--r-- | test.toc | 22 | ||||
-rw-r--r-- | types.c | 18 | ||||
-rw-r--r-- | types.h | 14 |
6 files changed, 39 insertions, 42 deletions
diff --git a/identifiers.c b/identifiers.c index cb4de6f..17bbd47 100644 --- a/identifiers.c +++ b/identifiers.c @@ -201,11 +201,11 @@ static void idents_test(void) { allocr_create(&a); idents_create(&ids, &a, NULL); Identifier i1 = ident_insert(&ids, &s); - assert(strs_equal(s, " bar")); + assert(streq(s, " bar")); char b2[] = "foo_variable+6"; s = b2; Identifier i2 = ident_insert(&ids, &s); - assert(strs_equal(s, "+6")); + assert(streq(s, "+6")); assert(i1 == i2); allocr_free_all(&a); @@ -8,8 +8,6 @@ /* @TODO: -detect circular declarations (A ::= B; B ::= A) -either detect circular #includes or set a #include depth limit (maybe sometimes you want finite circular includes with #if) initialization statements (maybe #init(-50), where -50 is the priority and <0 is reserved for standard library) if we do #include "foo.toc", bar; and foo.toc fails, bar should be declared as TYPE_UNKNOWN (right now it's undeclared) improve type_to_str: @@ -147,18 +145,18 @@ int main(int argc, char **argv) { for (int i = 1; i < argc; ++i) { char *arg = argv[i]; - if (strs_equal(arg, "-no-color")) { + if (streq(arg, "-no-color")) { err_ctx.color_enabled = false; - } else if (strs_equal(arg, "-color")) { + } else if (streq(arg, "-color")) { err_ctx.color_enabled = true; - } else if (strs_equal(arg, "-o")) { + } else if (streq(arg, "-o")) { if (i == argc-1) { fprintf(stderr, "-o cannot be the last argument to toc.\n"); return EXIT_FAILURE; } out_filename = argv[i+1]; ++i; - } else if (strs_equal(arg, "-v") || strs_equal(arg, "-verbose")) { + } else if (streq(arg, "-v") || streq(arg, "-verbose")) { printf("Verbose mode enabled\n"); verbose = true; } else { @@ -234,7 +232,7 @@ int main(int argc, char **argv) { Typer tr; Evaluator ev; evalr_create(&ev, &tr, &main_allocr); - typer_create(&tr, &ev, &err_ctx, &main_allocr, &globals); + typer_create(&tr, &ev, &err_ctx, &main_allocr, &globals, &file); if (!types_file(&tr, &f)) { err_text_important(&err_ctx, "Errors occured while determining types.\n"); @@ -66,20 +66,19 @@ static inline char *str_to_cstr(String s) { return cstr(s.str, s.len); } -static bool str_eq_cstr(String s, const char *str) { +static inline bool str_eq_cstr(String s, const char *str) { return strncmp(s.str, str, s.len) == 0; } +static inline bool streq(const char *a, const char *b) { + return strcmp(a, b) == 0; +} + static inline U32 rand_u32(U32 seed) { U64 seed64 = (U64)seed; return (U32)((seed64 * 0x832f0fda4e1a8642 + 0x41d49cd5459a2ab4) >> 32); } - -static inline bool strs_equal(const char *a, const char *b) { - return strcmp(a, b) == 0; -} - #define plural_suffix(x) ((x) == 1 ? "" : "s") static const char *indefinite_article(const char *s) { /* usually, words starting with "u" use "a" - "a unique thing", "a u64" */ @@ -1,23 +1,9 @@ -#include "std/mem.toc", mem; -#include "tests/std/io.toc", io; -use mem; -sum_slice ::= fn(a : &[]int) total := 0 { - for i := 0..a.len-1 { - total += a[i]; - } -} +#include "test.toc"; -thing ::= fn() int { - bar : []int; - defer dels(bar); - bar = news(int, 3); - b := sum_slice(&bar); - b +foo ::= fn() int { + 5 } main ::= fn() { - a := thing(); - b ::= thing(); - io.puti(a); - io.puti(b); + foo(); } @@ -2807,7 +2807,7 @@ static Status types_expr(Typer *tr, Expression *e) { if (!builtin_name) return false; int which = -1; for (BuiltinVal b = 0; b < BUILTIN_VAL_COUNT; b = b + 1) { - if (strs_equal(builtin_val_names[b], builtin_name)) { + if (streq(builtin_val_names[b], builtin_name)) { which = (int)b; } } @@ -3786,12 +3786,20 @@ static Status types_stmt(Typer *tr, Statement *s) { } s->kind = STMT_INLINE_BLOCK; - + if (!(inc->flags & INC_FORCED)) { size_t filename_len = strlen(filename); + if (streq(filename, tr->main_file->filename)) { + err_print(s->where, "Circular #include detected. You can add #force to this #include to force it to be included."); + goto inc_fail; + } inc_f = str_hash_table_get(&tr->included_files, filename, filename_len); if (inc_f) { /* has already been included */ + if (inc_f->flags & INC_FILE_INCLUDING) { + err_print(s->where, "Circular #include detected. You can add #force to this #include to force it to be included."); + goto inc_fail; + } s->inline_block = NULL; /* nothing needed here */ /* just set ident declarations */ if (!include_stmts_link_to_nms(tr, inc_f->main_nms, inc_f->stmts)) @@ -3799,6 +3807,7 @@ static Status types_stmt(Typer *tr, Statement *s) { goto nms_transform; } inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len); + inc_f->flags |= INC_FILE_INCLUDING; inc_f->main_nms = tr->nms; } { @@ -3879,8 +3888,10 @@ static Status types_stmt(Typer *tr, Statement *s) { d->val.nms = inc_nms; d->where = d->expr.where = s->where; } + if (inc_f) inc_f->flags &= (IncFileFlags)~(IncFileFlags)INC_FILE_INCLUDING; break; inc_fail: + if (inc_f) inc_f->flags &= (IncFileFlags)~(IncFileFlags)INC_FILE_INCLUDING; if (inc_nms) { tr->nms = prev_nms; typer_block_exit(tr); @@ -3957,12 +3968,13 @@ success: return true; } -static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents) { +static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *allocr, Identifiers *idents, File *main_file) { tr->block = NULL; tr->blocks = NULL; tr->fn = NULL; tr->nms = NULL; tr->evalr = ev; + tr->main_file = main_file; tr->err_ctx = err_ctx; tr->in_decls = NULL; tr->had_include_err = false; @@ -944,14 +944,15 @@ typedef struct Return { } Return; enum { - INC_FILE_CGEND_SDECLS = 0x01, - INC_FILE_CGEND_DECLS = 0x02, - INC_FILE_CGEND_DEFS = 0x04, - INC_FILE_CGEND = 0x08 + INC_FILE_INCLUDING = 0x01, /* are we currently in the process of including this file (i.e. during typing)? */ + INC_FILE_CGEND_SDECLS = 0x10, + INC_FILE_CGEND_DECLS = 0x20, + INC_FILE_CGEND_DEFS = 0x40, + INC_FILE_CGEND = 0x80 }; - +typedef U8 IncFileFlags; typedef struct IncludedFile { - U8 flags; + IncFileFlags flags; Namespace *main_nms; /* namespace of first inclusion */ struct Statement *stmts; } IncludedFile; @@ -1053,6 +1054,7 @@ typedef struct Typer { Allocator *allocr; Evaluator *evalr; Identifiers *globals; + File *main_file; /* this is the file which the compiler is invoked on. needed for checking for circular includes. */ Use **uses; /* global used things */ Declaration **in_decls; /* array of declarations we are currently inside */ Block *block; |