summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-02-27 12:04:19 -0500
committerLeo Tenenbaum <pommicket@gmail.com>2020-02-27 12:04:19 -0500
commitcb29bbe47fa67b9da183d39f343f7923c2ddaa7b (patch)
treee25aded7cc41386488c56582fdc01d2aedc4bb1d
parent5ae9274e34a6a33753d453e18072c8de2e7686f8 (diff)
only #include stuff once
-rw-r--r--allocator.c7
-rw-r--r--cgen.c80
-rw-r--r--decls_cgen.c9
-rw-r--r--incstuff.toc8
-rw-r--r--main.c3
-rw-r--r--parse.c7
-rw-r--r--sdecls_cgen.c53
-rw-r--r--test.toc22
-rw-r--r--types.c36
-rw-r--r--types.h26
10 files changed, 161 insertions, 90 deletions
diff --git a/allocator.c b/allocator.c
index acfe7a8..cf747ab 100644
--- a/allocator.c
+++ b/allocator.c
@@ -107,7 +107,12 @@ static void *allocr_realloc(Allocator *a, void *data, size_t old_size, size_t ne
return ret;
}
-
+static char *allocr_strdup(Allocator *a, char const *s) {
+ size_t len = strlen(s);
+ char *ret = allocr_malloc(a, len);
+ memcpy(ret, s, len);
+ return ret;
+}
static void allocr_free_all(Allocator *a) {
for (Page *page = a->first; page;) {
diff --git a/cgen.c b/cgen.c
index d9a9edb..1bef91b 100644
--- a/cgen.c
+++ b/cgen.c
@@ -11,8 +11,7 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Allocator *a
g->indent_lvl = 0;
g->globals = ids;
g->allocr = allocr;
- g->nms_prefix = NULL;
- *(char *)arr_adda(&g->nms_prefix, g->allocr) = '\0';
+ g->nms_prefixes = NULL;
}
static void cgen_stmt(CGenerator *g, Statement *s);
@@ -79,10 +78,7 @@ static void cgen_defs_decl(CGenerator *g, Declaration *d);
block_f(g, &e->block); \
break; \
case EXPR_NMS: { \
- Namespace *prev = g->nms; \
- cgen_nms_enter(g, &e->nms); \
block_f(g, &e->nms.body); \
- cgen_nms_exit(g, &e->nms, prev); \
} break; \
case EXPR_IF: \
if (e->if_.cond) \
@@ -172,6 +168,10 @@ static inline FILE *cgen_writing_to(CGenerator *g) {
return g->outc; /* for now */
}
+static inline void *cgen_malloc(CGenerator *g, size_t sz) {
+ return allocr_malloc(g->allocr, sz);
+}
+
/* indent iff needed */
static inline void cgen_indent(CGenerator *g) {
if (g->will_indent) {
@@ -211,15 +211,8 @@ static inline void cgen_ident_simple(CGenerator *g, Identifier i) {
}
static void cgen_ident(CGenerator *g, Identifier i) {
-
- if (g->block && (g->block->flags & BLOCK_IS_NMS) && !g->fn) {
- /* namespace prefix */
- cgen_write(g, "%s", g->nms_prefix);
- } else {
- /* do prefix for references to siblings */
- if (g->nms && ident_scope(i) == &g->nms->body) {
- cgen_write(g, "%s", g->nms_prefix);
- }
+ if (i->nms) {
+ cgen_write(g, "%s", i->nms->c.prefix);
}
if (i == g->main_ident && i->decl_kind == IDECL_DECL && ident_scope(i) == NULL) {
/* don't conflict with C's main! */
@@ -236,44 +229,6 @@ static inline void cgen_ident_id_to_str(char *buffer, IdentID id) {
snprintf(buffer, CGEN_IDENT_ID_STR_SIZE, "_a%lu", (unsigned long)id);
}
-static char *cgen_nms_prefix(CGenerator *g, Namespace *n) {
- char *s;
- if (n->associated_ident) {
- size_t ident_len = n->associated_ident->len;
- s = malloc(ident_len + 3);
- memcpy(s, n->associated_ident->str, ident_len);
- s[ident_len] = '_';
- s[ident_len+1] = '_';
- s[ident_len+2] = '\0';
- } else {
- s = calloc(CGEN_IDENT_ID_STR_SIZE + 1, 1);
- if (!n->c.id) n->c.id = ++g->ident_counter;
- cgen_ident_id_to_str(s, n->c.id);
- s[strlen(s)] = '_';
-
- }
- return s;
-}
-
-static void cgen_nms_enter(CGenerator *g, Namespace *n) {
- g->nms = n;
- char *s = cgen_nms_prefix(g, n);
- size_t chars_so_far = arr_len(g->nms_prefix) - 1; /* -1 for '\0' byte */
- size_t new_chars = strlen(s) + 1; /* + 1 for '\0' byte */
- arr_set_lena(&g->nms_prefix, chars_so_far + new_chars, g->allocr);
- for (size_t i = 0; i < new_chars; ++i) {
- g->nms_prefix[i+chars_so_far] = s[i];
- }
- free(s);
-}
-
-static void cgen_nms_exit(CGenerator *g, Namespace *n, Namespace *prev) {
- char *s = cgen_nms_prefix(g, n);
- arr_set_lena(&g->nms_prefix, arr_len(g->nms_prefix) - strlen(s), g->allocr);
- g->nms = prev;
- free(s);
-}
-
static inline void cgen_writeln(CGenerator *g, const char *fmt, ...) {
va_list args;
cgen_indent(g);
@@ -1352,10 +1307,9 @@ static void cgen_expr(CGenerator *g, Expression *e) {
cgen_write(g, ")");
} else {
assert(type_is_builtin(struct_type, BUILTIN_NMS));
- char *prefix = cgen_nms_prefix(g, e->binary.lhs->val.nms);
+ char *prefix = e->binary.lhs->val.nms->c.prefix;
cgen_write(g, "%s", prefix);
cgen_ident_simple(g, e->binary.dot.translated_ident);
- free(prefix);
}
handled = true;
} break;
@@ -1951,8 +1905,13 @@ static void cgen_stmt(CGenerator *g, Statement *s) {
cgen_ret(g, has_expr ? &s->ret.expr : NULL);
} break;
case STMT_INCLUDE:
- arr_foreach(s->inc.stmts, Statement, sub)
- cgen_stmt(g, sub);
+ if (s->inc.inc_file && (s->inc.inc_file->flags & INC_FILE_CGEND)){
+ /* already generated */
+ } else {
+ if (s->inc.inc_file) s->inc.inc_file->flags |= INC_FILE_CGEND;
+ arr_foreach(s->inc.stmts, Statement, sub)
+ cgen_stmt(g, sub);
+ }
break;
}
}
@@ -2010,8 +1969,13 @@ static void cgen_defs_stmt(CGenerator *g, Statement *s) {
cgen_defs_expr(g, &s->ret.expr);
break;
case STMT_INCLUDE:
- arr_foreach(s->inc.stmts, Statement, sub)
- cgen_defs_stmt(g, sub);
+ if (s->inc.inc_file && (s->inc.inc_file->flags & INC_FILE_CGEND_DEFS)) {
+ /* already generated */
+ } else {
+ if (s->inc.inc_file) s->inc.inc_file->flags |= INC_FILE_CGEND_DEFS;
+ arr_foreach(s->inc.stmts, Statement, sub)
+ cgen_defs_stmt(g, sub);
+ }
break;
}
}
diff --git a/decls_cgen.c b/decls_cgen.c
index ebf6ed1..c04e433 100644
--- a/decls_cgen.c
+++ b/decls_cgen.c
@@ -200,8 +200,13 @@ static void cgen_decls_stmt(CGenerator *g, Statement *s) {
cgen_decls_expr(g, &s->ret.expr);
break;
case STMT_INCLUDE:
- arr_foreach(s->inc.stmts, Statement, sub)
- cgen_decls_stmt(g, sub);
+ if (s->inc.inc_file && (s->inc.inc_file->flags & INC_FILE_CGEND_DECLS)) {
+ /* already generated */
+ } else {
+ if (s->inc.inc_file) s->inc.inc_file->flags |= INC_FILE_CGEND_DECLS;
+ arr_foreach(s->inc.stmts, Statement, sub)
+ cgen_decls_stmt(g, sub);
+ }
break;
}
}
diff --git a/incstuff.toc b/incstuff.toc
deleted file mode 100644
index c192e06..0000000
--- a/incstuff.toc
+++ /dev/null
@@ -1,8 +0,0 @@
-
- x : arr.Arr(char);
- arr.arr_add(&x, 'H');
- arr.arr_add(&x, 'e');
- arr.arr_add(&x, 'l');
- arr.arr_add(&x, 'l');
- arr.arr_add(&x, 'o');
- arr.arr_add(&x, '!'); \ No newline at end of file
diff --git a/main.c b/main.c
index 8d14dfb..c78630c 100644
--- a/main.c
+++ b/main.c
@@ -8,8 +8,7 @@
/*
TODO:
-run stuff at compile time without assigning it to a constant
-only include stuff once- (#include "io.toc", foo + #include "io.toc", bar => #define foo__puts bar__puts ; this is ok because __ is reserved)
+#include_forced
better #foreign system- something like f := #foreign fn (int,float, #C int);
---
constants in structs
diff --git a/parse.c b/parse.c
index b10f6c8..44b4d25 100644
--- a/parse.c
+++ b/parse.c
@@ -2210,7 +2210,7 @@ static Status parse_stmt(Parser *p, Statement *s, bool *was_a_statement) {
idents_create(&body->idents, p->allocr, body);
Statement *inc_stmt = parser_arr_add(p, &body->stmts);
inc_stmt->kind = STMT_INCLUDE;
- inc_stmt->flags = 0;
+ inc_stmt->flags = STMT_INC_TO_NMS;
inc_stmt->where = s->where;
inc_stmt->inc.filename = filename;
}
@@ -2601,6 +2601,11 @@ static void fprint_stmt(FILE *out, Statement *s) {
}
}
+static void print_stmt(Statement *s) {
+ fprint_stmt(stdout, s);
+ printf("\n");
+}
+
static void fprint_parsed_file(FILE *out, ParsedFile *f) {
arr_foreach(f->stmts, Statement, stmt) {
fprint_stmt(out, stmt);
diff --git a/sdecls_cgen.c b/sdecls_cgen.c
index eb388c3..7eec064 100644
--- a/sdecls_cgen.c
+++ b/sdecls_cgen.c
@@ -42,6 +42,29 @@ static void cgen_sdecls_block(CGenerator *g, Block *b) {
g->block = prev_block;
}
+static char *cgen_nms_prefix_part(CGenerator *g, Namespace *n) {
+ char *s;
+ while (n->points_to) {
+ n = n->points_to;
+ }
+ if (n->associated_ident) {
+ size_t ident_len = n->associated_ident->len;
+ s = malloc(ident_len + 3);
+ memcpy(s, n->associated_ident->str, ident_len);
+ s[ident_len] = '_';
+ s[ident_len+1] = '_';
+ s[ident_len+2] = '\0';
+ } else {
+ s = calloc(CGEN_IDENT_ID_STR_SIZE + 3, 1);
+ cgen_ident_id_to_str(s, ++g->ident_counter);
+ size_t len = strlen(s);
+ s[len] = '_';
+ s[len+1] = '_';
+ s[len+2] = '\0';
+ }
+ return s;
+}
+
static void cgen_sdecls_expr(CGenerator *g, Expression *e) {
switch (e->kind) {
case EXPR_CAST:
@@ -54,12 +77,26 @@ static void cgen_sdecls_expr(CGenerator *g, Expression *e) {
case EXPR_TYPE:
cgen_sdecls_type(g, &e->typeval);
break;
- case EXPR_NMS:
- e->nms.c.id = 0;
- break;
+ case EXPR_NMS: {
+ char *prefix_part = cgen_nms_prefix_part(g, &e->nms);
+ size_t prefix_part_len = strlen(prefix_part);
+ char const *prev_prefix = g->nms_prefixes ? *(char const **)arr_last(g->nms_prefixes)
+ : "";
+ size_t prev_prefix_len = strlen(prev_prefix);
+ char *new_prefix = cgen_malloc(g, prev_prefix_len + prefix_part_len + 1);
+ memcpy(new_prefix, prev_prefix, prev_prefix_len);
+ memcpy(new_prefix + prev_prefix_len, prefix_part, prefix_part_len);
+ free(prefix_part);
+ *(char const **)arr_add(&g->nms_prefixes) = new_prefix;
+ new_prefix[prev_prefix_len + prefix_part_len] = 0;
+ e->nms.c.prefix = new_prefix;
+ } break;
default: break;
}
cgen_recurse_subexprs(g, e, cgen_sdecls_expr, cgen_sdecls_block, cgen_sdecls_decl);
+ if (e->kind == EXPR_NMS) {
+ arr_remove_last(&g->nms_prefixes);
+ }
}
@@ -101,8 +138,14 @@ static void cgen_sdecls_stmt(CGenerator *g, Statement *s) {
cgen_sdecls_expr(g, &s->ret.expr);
break;
case STMT_INCLUDE:
- arr_foreach(s->inc.stmts, Statement, sub)
- cgen_sdecls_stmt(g, sub);
+
+ if (s->inc.inc_file && (s->inc.inc_file->flags & INC_FILE_CGEND_SDECLS)) {
+ /* already generated */
+ } else {
+ if (s->inc.inc_file) s->inc.inc_file->flags |= INC_FILE_CGEND_SDECLS;
+ arr_foreach(s->inc.stmts, Statement, sub)
+ cgen_sdecls_stmt(g, sub);
+ }
break;
}
}
diff --git a/test.toc b/test.toc
index e9ab36b..69794b5 100644
--- a/test.toc
+++ b/test.toc
@@ -1,12 +1,18 @@
#include "std/io.toc", io;
-#include "std/io.toc", super;
-#include "std/io.toc", great;
+#include "std/io.toc", foo;
+#include "std/io.toc";
-main ::= fn() {
- io.puti(7);
- io.puts("Hello!");
- super.puts("hey");
- great.puti(1232);
+a ::= nms {
+ b ::= nms {
+ x := 3;
+ };
+ f ::= fn() { b.x += 1; io.puti(b.x); foo.puti(b.x); puti(b.x);
+ };
};
-main(); \ No newline at end of file
+main ::= fn() {
+ a.f();
+ a.f();
+ a.f();
+
+}; \ No newline at end of file
diff --git a/types.c b/types.c
index 91fe1fa..e772715 100644
--- a/types.c
+++ b/types.c
@@ -2574,9 +2574,15 @@ static Status types_expr(Typer *tr, Expression *e) {
t->builtin = BUILTIN_TYPE;
} break;
case EXPR_NMS: {
+ Namespace *prev_nms = tr->nms;
+ tr->nms = &e->nms;
+ e->nms.points_to = NULL;
e->nms.body.flags |= BLOCK_IS_NMS;
- if (!types_block(tr, &e->nms.body))
+ if (!types_block(tr, &e->nms.body)) {
+ tr->nms = prev_nms;
return false;
+ }
+ tr->nms = prev_nms;
e->nms.associated_ident = NULL; /* set when we type the declaration */
t->kind = TYPE_BUILTIN;
t->builtin = BUILTIN_NMS;
@@ -2808,6 +2814,12 @@ static Status types_decl(Typer *tr, Declaration *d) {
d->expr.nms.associated_ident = d->idents[0];
}
+ if (tr->nms && tr->block == &tr->nms->body) {
+ arr_foreach(d->idents, Identifier, ident) {
+ (*ident)->nms = tr->nms;
+ }
+ }
+
ret:
/* pretend we found the type even if we didn't to prevent too many errors */
@@ -2887,9 +2899,25 @@ static Status types_stmt(Typer *tr, Statement *s) {
char *filename = eval_expr_as_cstr(tr, &s->inc.filename, "import filename");
if (!filename)
return false;
+ size_t filename_len = strlen(filename);
+ IncludedFile *inc_f = NULL;
+ if (s->flags & STMT_INC_TO_NMS) {
+ inc_f = str_hash_table_get(&tr->included_files, filename, filename_len);
+ if (inc_f) {
+ tr->nms->body.idents = inc_f->main_nms->body.idents;
+ tr->nms->body.idents.scope = &tr->nms->body;
+ tr->nms->points_to = inc_f->main_nms;
+ s->inc.inc_file = inc_f;
+ s->inc.stmts = inc_f->stmts;
+ break;
+ }
+ s->inc.inc_file = inc_f = str_hash_table_insert(&tr->included_files, filename, filename_len);
+ inc_f->main_nms = tr->nms;
+ }
char *contents = read_file_contents(tr->allocr, filename, s->where);
if (!contents)
return false;
+
Tokenizer tokr;
tokr_create(&tokr, tr->err_ctx, tr->allocr);
File *file = typer_calloc(tr, 1, sizeof *file);
@@ -2906,11 +2934,15 @@ static Status types_stmt(Typer *tr, Statement *s) {
return false;
}
Statement *stmts_inc = parsed_file.stmts;
+ if (inc_f) {
+ inc_f->stmts = stmts_inc;
+ }
s->inc.stmts = stmts_inc;
arr_foreach(stmts_inc, Statement, s_incd) {
if (!types_stmt(tr, s_incd))
return false;
}
+
} break;
}
s->flags |= STMT_TYPED;
@@ -2921,6 +2953,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a
tr->block = NULL;
tr->blocks = NULL;
tr->fn = NULL;
+ tr->nms = NULL;
tr->evalr = ev;
tr->err_ctx = err_ctx;
tr->in_decls = NULL;
@@ -2928,6 +2961,7 @@ static void typer_create(Typer *tr, Evaluator *ev, ErrCtx *err_ctx, Allocator *a
tr->allocr = allocr;
tr->globals = idents;
*(Block **)arr_adda(&tr->blocks, allocr) = NULL;
+ str_hash_table_create(&tr->included_files, sizeof(IncludedFile), tr->allocr);
}
static Status types_file(Typer *tr, ParsedFile *f) {
diff --git a/types.h b/types.h
index 609f9fb..10525a6 100644
--- a/types.h
+++ b/types.h
@@ -185,6 +185,7 @@ typedef struct IdentSlot {
struct Expression *decl_expr;
};
struct Identifiers *idents;
+ struct Namespace *nms; /* only exists after typing, and only for namespace-level declarations (i.e. not local variables) */
SOURCE_LOCATION
} IdentSlot;
@@ -703,8 +704,9 @@ const char *const builtin_val_names[BUILTIN_VAL_COUNT] =
typedef struct Namespace {
Block body;
Identifier associated_ident; /* if this is foo ::= nms { ... }, then associated_ident is foo; can be NULL */
+ struct Namespace *points_to; /* if not NULL, this namespace just points to another namespace, because something has been included twice */
struct {
- IdentID id; /* used as prefix if prefix is NULL */
+ char *prefix; /* generated during sdecls_cgen */
} c;
} Namespace;
@@ -836,14 +838,29 @@ typedef struct Return {
} Return;
enum {
- STMT_EXPR_NO_SEMICOLON = 0x01,
- STMT_TYPED = 0x02
+ INC_FILE_CGEND_SDECLS = 0x01,
+ INC_FILE_CGEND_DECLS = 0x02,
+ INC_FILE_CGEND_DEFS = 0x04,
+ INC_FILE_CGEND = 0x08
};
+
+typedef struct {
+ U8 flags;
+ Namespace *main_nms; /* namespace of first inclusion */
+ struct Statement *stmts;
+} IncludedFile;
+
typedef union {
Expression filename; /* before typing */
struct Statement *stmts; /* after typing */
+ IncludedFile *inc_file;
} Include;
+enum {
+ STMT_EXPR_NO_SEMICOLON = 0x01,
+ STMT_INC_TO_NMS = 0x01,
+ STMT_TYPED = 0x02
+};
typedef struct Statement {
Location where;
StatementKind kind;
@@ -910,6 +927,7 @@ typedef struct Typer {
ErrCtx *err_ctx;
ParsedFile *parsed_file;
Namespace *nms;
+ StrHashTable included_files; /* maps to IncludedFile */
} Typer;
typedef struct CGenerator {
@@ -924,5 +942,5 @@ typedef struct CGenerator {
FnExpr *fn; /* which function are we in? (NULL for none) - not used during decls */
Identifier main_ident;
Identifiers *globals;
- char *nms_prefix; /* dynamic (null-terminated) array of characters, the current namespace C prefix (e.g. "foo__bar__") */
+ char const **nms_prefixes; /* dynamic (null-terminated) array of namespace prefixes */
} CGenerator;