From b7b02528d7121b71adced7f79af48d09558dfa85 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Wed, 13 May 2020 21:01:39 -0400 Subject: check for circular includes --- identifiers.c | 4 ++-- main.c | 12 +++++------- misc.c | 11 +++++------ test.toc | 22 ++++------------------ types.c | 18 +++++++++++++++--- 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); diff --git a/main.c b/main.c index a4a48ad..7e58ef1 100644 --- a/main.c +++ b/main.c @@ -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"); diff --git a/misc.c b/misc.c index 655fce8..de9a49f 100644 --- a/misc.c +++ b/misc.c @@ -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" */ diff --git a/test.toc b/test.toc index ec65787..0450b18 100644 --- a/test.toc +++ b/test.toc @@ -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(); } diff --git a/types.c b/types.c index d595075..cda8b16 100644 --- a/types.c +++ b/types.c @@ -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; diff --git a/types.h b/types.h index fec1d01..b4fc615 100644 --- a/types.h +++ b/types.h @@ -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; -- cgit v1.2.3