summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-05-13 21:01:39 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-05-13 21:01:39 -0400
commitb7b02528d7121b71adced7f79af48d09558dfa85 (patch)
treef5ee23641d27236c8a62f49a7701028e5571a8e9
parent83718e0953f7489bdffd6c75f55ce51b385a1a51 (diff)
check for circular includes
-rw-r--r--identifiers.c4
-rw-r--r--main.c12
-rw-r--r--misc.c11
-rw-r--r--test.toc22
-rw-r--r--types.c18
-rw-r--r--types.h14
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;