diff options
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | cgen.c | 105 | ||||
-rw-r--r-- | data_structures.c | 4 | ||||
-rw-r--r-- | main.c | 4 | ||||
-rw-r--r-- | parse.c | 1 | ||||
-rw-r--r-- | sdecls_cgen.c | 18 | ||||
-rw-r--r-- | test.toc | 4 | ||||
-rw-r--r-- | types.c | 20 | ||||
-rw-r--r-- | types.h | 8 |
9 files changed, 109 insertions, 56 deletions
@@ -62,6 +62,7 @@ Here are all the C99 features which `toc` depends on (I might have forgotten som - `inttypes.h` - Non-constant struct literal initializers (e.g. `int x[2] = {y, z};`) - Flexible array members +- `snprintf` And here are all of its C11 features: @@ -12,6 +12,8 @@ static void cgen_create(CGenerator *g, FILE *out, Identifiers *ids, Evaluator *e g->indent_lvl = 0; g->idents = ids; g->allocr = allocr; + g->nms_prefix = NULL; + *(char *)arr_add(&g->nms_prefix) = '\0'; } static bool cgen_stmt(CGenerator *g, Statement *s); @@ -87,8 +89,10 @@ static bool cgen_defs_decl(CGenerator *g, Declaration *d); return false; \ break; \ case EXPR_NMS: \ + cgen_nms_enter(g, &e->nms); \ if (!block_f(g, &e->nms.body)) \ return false; \ + cgen_nms_exit(g, &e->nms); \ break; \ case EXPR_IF: \ if (e->if_.cond) \ @@ -244,6 +248,73 @@ static inline void cgen_nl(CGenerator *g) { g->will_indent = true; } +static char *cgen_ident_to_str(Identifier i) { + /* TODO: FIXME for unicode idents */ + return ident_to_str(i); +} + +static void cgen_ident_id(CGenerator *g, IdentID id) { + cgen_write(g, "a%lu_", (unsigned long)id); +} +/* used for fields */ +static inline void cgen_ident_simple(CGenerator *g, Identifier i) { + cgen_indent(g); + fprint_ident_reduced_charset(cgen_writing_to(g), i); +} + +static void cgen_ident(CGenerator *g, Identifier i) { + if (g->block && (g->block->flags & BLOCK_IS_NMS)) { + /* namespace prefix */ + cgen_write(g, "%s", g->nms_prefix); + } + if (i == g->main_ident) { + /* don't conflict with C's main! */ + cgen_write(g, "main__"); + } else { + cgen_ident_simple(g, i); + } +} + + +#define CGEN_IDENT_ID_STR_SIZE 48 +/* buffer should be at least CGEN_IDENT_ID_STR_SIZE bytes */ +static inline void cgen_ident_id_to_str(char *buffer, IdentID id) { + snprintf(buffer, 32, "a%lu_", (unsigned long)id); +} + +/* does NOT include __ */ +static char *cgen_nms_prefix(CGenerator *g, Namespace *n) { + char *s; + if (n->associated_ident) { + s = cgen_ident_to_str(n->associated_ident); + } else { + s = malloc(CGEN_IDENT_ID_STR_SIZE); + if (!n->c.id) n->c.id = ++g->ident_counter; + cgen_ident_id_to_str(s, n->c.id); + } + return s; +} + +static void cgen_nms_enter(CGenerator *g, Namespace *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); + arr_set_len(&g->nms_prefix, chars_so_far + new_chars); + for (size_t i = 0; i < new_chars; ++i) { + g->nms_prefix[i+chars_so_far] = s[i]; + } + *(char *)arr_add(&g->nms_prefix) = '_'; + *(char *)arr_add(&g->nms_prefix) = '_'; + *(char *)arr_add(&g->nms_prefix) = '\0'; + free(s); +} + +static void cgen_nms_exit(CGenerator *g, Namespace *n) { + char *s = cgen_nms_prefix(g, n); + arr_set_len(&g->nms_prefix, arr_len(g->nms_prefix) - strlen(s) - 2); /* -2 for "__" */ + free(s); +} + static inline void cgen_writeln(CGenerator *g, const char *fmt, ...) { va_list args; cgen_indent(g); @@ -253,13 +324,9 @@ static inline void cgen_writeln(CGenerator *g, const char *fmt, ...) { cgen_nl(g); } -static void cgen_ident_id(CGenerator *g, IdentID id) { - cgen_write(g, "a%lu_", (unsigned long)id); -} - /* should this declaration be a direct function declaration C? (as opposed to using a function pointer or not being a function) */ static bool cgen_fn_is_direct(CGenerator *g, Declaration *d) { - return g->block == NULL && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1; + return (g->block == NULL || (g->block->flags & BLOCK_IS_NMS)) && (d->flags & DECL_HAS_EXPR) && d->expr.kind == EXPR_FN && arr_len(d->idents) == 1; } static bool cgen_uses_ptr(Type *t) { @@ -283,32 +350,6 @@ static bool cgen_uses_ptr(Type *t) { return false; } -/* used for fields */ -static inline void cgen_ident_simple(CGenerator *g, Identifier i) { - cgen_indent(g); - fprint_ident_reduced_charset(cgen_writing_to(g), i); -} - -static void cgen_ident(CGenerator *g, Identifier i) { - if (i == g->main_ident) { - /* don't conflict with C's main! */ - cgen_write(g, "main__"); - } else { - cgen_ident_simple(g, i); - } -} - - -static char *cgen_ident_to_str(Identifier i) { - return ident_to_str(i); -} - - -/* buffer should be at least 32 bytes */ -static inline void cgen_ident_id_to_str(char *buffer, IdentID id) { - snprintf(buffer, 32, "a%lu_", (unsigned long)id); -} - static inline Identifier cgen_ident_id_to_ident(CGenerator *g, IdentID id) { char s[32]; cgen_ident_id_to_str(s, id); @@ -775,7 +816,7 @@ static bool cgen_set_tuple(CGenerator *g, Expression *exprs, Identifier *idents, static bool cgen_expr_pre(CGenerator *g, Expression *e) { IdentID id = 0; - char ret_name[64]; + char ret_name[CGEN_IDENT_ID_STR_SIZE]; switch (e->kind) { case EXPR_IF: case EXPR_WHILE: diff --git a/data_structures.c b/data_structures.c index 524f916..7580a92 100644 --- a/data_structures.c +++ b/data_structures.c @@ -96,10 +96,6 @@ static void arr_set_len_(void **arr, size_t n, size_t item_sz) { arr_hdr(*arr)->len = n; } static void arr_set_lena_(void **arr, size_t n, size_t item_sz, Allocator *a) { - if (n == 0) { - arr_cleara_(arr, item_sz, a); - return; - } arr_resva_(arr, n, item_sz, a); arr_hdr(*arr)->len = n; } @@ -19,8 +19,12 @@ /* TODO: namespace +try to remember why arr_set_len doesn't shrink, then write that reason there +make sure nms {foo:= 7; } works for cgen make sure #export still works properly +fix cgen_ident_to_str for unicode idents check for leaks +--- constants in structs #if @@ -1061,6 +1061,7 @@ static bool parse_expr(Parser *p, Expression *e, Token *end) { ++t->token; if (!parse_block(p, &n->body)) return false; + n->body.flags |= BLOCK_IS_NMS; arr_foreach(e->nms.body.stmts, Statement, sub) { if (sub->kind != STMT_DECL) { err_print(sub->where, "Only declarations can be in namespaces."); diff --git a/sdecls_cgen.c b/sdecls_cgen.c index f6105a1..049d6a7 100644 --- a/sdecls_cgen.c +++ b/sdecls_cgen.c @@ -50,20 +50,26 @@ static bool cgen_sdecls_block(CGenerator *g, Block *b) { } static bool cgen_sdecls_expr(CGenerator *g, Expression *e) { - cgen_recurse_subexprs(g, e, cgen_sdecls_expr, cgen_sdecls_block, cgen_sdecls_decl); - if (e->kind == EXPR_CAST) { + switch (e->kind) { + case EXPR_CAST: cgen_sdecls_type(g, &e->cast.type); - } - if (e->kind == EXPR_FN) { + break; + case EXPR_FN: /* needs to go before decls_cgen.c... */ e->fn->c.id = ++g->ident_counter; e->fn->c.declared = false; e->fn->c.defined = false; - } - if (e->kind == EXPR_TYPE) { + break; + case EXPR_TYPE: if (!cgen_sdecls_type(g, &e->typeval)) return false; + break; + case EXPR_NMS: + e->nms.c.id = 0; + break; + default: break; } + cgen_recurse_subexprs(g, e, cgen_sdecls_expr, cgen_sdecls_block, cgen_sdecls_decl); return true; } @@ -1,8 +1,4 @@ -foo ::= nms { -bar := 12; -}; yep :: Namespace = nms { -bar := 12; adfasdf ::= fn() {}; }; @@ -2126,6 +2126,7 @@ static bool types_expr(Typer *tr, Expression *e) { case EXPR_NMS: { if (!types_block(tr, &e->nms.body, TYPES_BLOCK_NAMESPACE)) return false; + e->nms.associated_ident = NULL; t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_NMS; } break; @@ -2325,17 +2326,18 @@ static bool types_decl(Typer *tr, Declaration *d) { t->fn.constness = NULL; } } - - { - size_t n_idents = arr_len(d->idents); - if (d->type.kind == TYPE_TUPLE) { - if (n_idents != arr_len(d->type.tuple)) { - err_print(d->where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)n_idents); - success = false; - goto ret; - } + + size_t n_idents; n_idents = arr_len(d->idents); + if (d->type.kind == TYPE_TUPLE) { + if (n_idents != arr_len(d->type.tuple)) { + err_print(d->where, "Expected to have %lu things declared in declaration, but got %lu.", (unsigned long)arr_len(d->type.tuple), (unsigned long)n_idents); + success = false; + goto ret; } } + if (n_idents == 1 && d->expr.kind == EXPR_NMS) { + d->expr.nms.associated_ident = d->idents[0]; + } ret: @@ -474,7 +474,8 @@ typedef struct StructDef { enum { BLOCK_IS_FN = 0x01, - BLOCK_FOUND_TYPES = 0x02, + BLOCK_IS_NMS = 0x02, + BLOCK_FOUND_TYPES = 0x04 }; typedef struct Block { U8 flags; @@ -698,6 +699,10 @@ const char *const builtin_val_names[BUILTIN_VAL_COUNT] = typedef struct Namespace { Block body; Identifiers idents; /* these do not include local variables */ + Identifier associated_ident; /* if this is foo ::= nms { ... }, then associated_ident is foo; can be NULL */ + struct { + IdentID id; /* used as prefix is associated_ident is unavailable */ + } c; } Namespace; enum { @@ -911,6 +916,7 @@ typedef struct CGenerator { Evaluator *evalr; Identifier main_ident; Identifiers *idents; + char *nms_prefix; /* dynamic (null-terminated) array of characters, the current namespace C prefix (e.g. "foo__bar__") */ } CGenerator; #ifdef TOC_DEBUG |