summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md1
-rw-r--r--cgen.c105
-rw-r--r--data_structures.c4
-rw-r--r--main.c4
-rw-r--r--parse.c1
-rw-r--r--sdecls_cgen.c18
-rw-r--r--test.toc4
-rw-r--r--types.c20
-rw-r--r--types.h8
9 files changed, 109 insertions, 56 deletions
diff --git a/README.md b/README.md
index f602920..4cea135 100644
--- a/README.md
+++ b/README.md
@@ -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:
diff --git a/cgen.c b/cgen.c
index bf9c5cb..c5be2d5 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
}
diff --git a/main.c b/main.c
index fe09cf1..d8b6094 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/parse.c b/parse.c
index 0235ace..8f3f393 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
}
diff --git a/test.toc b/test.toc
index 2c5d7e7..1fb9876 100644
--- a/test.toc
+++ b/test.toc
@@ -1,8 +1,4 @@
-foo ::= nms {
-bar := 12;
-};
yep :: Namespace = nms {
-bar := 12;
adfasdf ::= fn() {};
};
diff --git a/types.c b/types.c
index b911ca9..80bd561 100644
--- a/types.c
+++ b/types.c
@@ -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:
diff --git a/types.h b/types.h
index 7f9328a..78d4b42 100644
--- a/types.h
+++ b/types.h
@@ -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