diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-27 12:04:19 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-27 12:04:19 -0500 |
commit | cb29bbe47fa67b9da183d39f343f7923c2ddaa7b (patch) | |
tree | e25aded7cc41386488c56582fdc01d2aedc4bb1d | |
parent | 5ae9274e34a6a33753d453e18072c8de2e7686f8 (diff) |
only #include stuff once
-rw-r--r-- | allocator.c | 7 | ||||
-rw-r--r-- | cgen.c | 80 | ||||
-rw-r--r-- | decls_cgen.c | 9 | ||||
-rw-r--r-- | incstuff.toc | 8 | ||||
-rw-r--r-- | main.c | 3 | ||||
-rw-r--r-- | parse.c | 7 | ||||
-rw-r--r-- | sdecls_cgen.c | 53 | ||||
-rw-r--r-- | test.toc | 22 | ||||
-rw-r--r-- | types.c | 36 | ||||
-rw-r--r-- | types.h | 26 |
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;) { @@ -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 @@ -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 @@ -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; } } @@ -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 @@ -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) { @@ -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; |