From 75fc567dfdb4a6500990d79dc3f167d3262a96c5 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Tue, 4 Feb 2020 14:25:48 -0500 Subject: nms . typing and fixing cgen for local namespaces --- cgen.c | 6 ++++-- identifiers.c | 9 ++++++-- main.c | 1 + parse.c | 2 +- scope.c | 6 ++++++ test.toc | 10 +++++---- types.c | 68 ++++++++++++++++++++++++++++++----------------------------- 7 files changed, 60 insertions(+), 42 deletions(-) diff --git a/cgen.c b/cgen.c index 563a15c..e33aac9 100644 --- a/cgen.c +++ b/cgen.c @@ -307,14 +307,16 @@ static void cgen_nms_enter(CGenerator *g, Namespace *n) { g->nms_prefix[i+chars_so_far] = s[i]; } *(char *)arr_add(&g->nms_prefix) = '_'; - *(char *)arr_add(&g->nms_prefix) = '_'; + if (n->associated_ident) + *(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 "__" */ + bool double_underscore = n->associated_ident != NULL; + arr_set_len(&g->nms_prefix, arr_len(g->nms_prefix) - strlen(s) - (double_underscore ? 2 : 1)); free(s); } diff --git a/identifiers.c b/identifiers.c index 25eaea1..da1db17 100644 --- a/identifiers.c +++ b/identifiers.c @@ -169,8 +169,13 @@ static Identifier ident_get(Identifiers *ids, char *s) { static Identifier ident_translate_forced(Identifier i, Identifiers *to_idents) { if (!i || i->anonymous) return NULL; char *p = i->str; - Identifier new_ident = ident_insert(to_idents, &p); - return new_ident; + return ident_insert(to_idents, &p); +} + +/* translate but don't add it if it's not there */ +static Identifier ident_translate(Identifier i, Identifiers *to_idents) { + if (!i || i->anonymous) return NULL; + return ident_get(to_idents, i->str); } static IdentDecl *ident_add_decl(Identifier i, struct Declaration *d, struct Block *b) { diff --git a/main.c b/main.c index d8b6094..9cd967f 100644 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ TODO: namespace try to remember why arr_set_len doesn't shrink, then write that reason there +nms["foo"] make sure nms {foo:= 7; } works for cgen make sure #export still works properly fix cgen_ident_to_str for unicode idents diff --git a/parse.c b/parse.c index 8f3f393..3d923f5 100644 --- a/parse.c +++ b/parse.c @@ -1061,7 +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; + /* don't set BLOCK_IS_NMS yet (done by types.c) */ 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/scope.c b/scope.c index 1b116b7..1f3f687 100644 --- a/scope.c +++ b/scope.c @@ -59,6 +59,9 @@ static void remove_ident_decls(Block *b, Declaration *d) { /* pass NULL for block for global scope */ static bool block_enter(Block *b, Statement *stmts, U16 flags) { + if (b && (b->flags & BLOCK_IS_NMS)) /* we only enter namespaces once, when they're created */ + return true; + bool ret = true; arr_foreach(stmts, Statement, stmt) { if (stmt->kind == STMT_DECL) { @@ -71,6 +74,9 @@ static bool block_enter(Block *b, Statement *stmts, U16 flags) { } static void block_exit(Block *b, Statement *stmts) { + if (b && (b->flags & BLOCK_IS_NMS)) + return; + arr_foreach(stmts, Statement, stmt) { if (stmt->kind == STMT_DECL) { Declaration *decl = &stmt->decl; diff --git a/test.toc b/test.toc index c1fa02c..206d903 100644 --- a/test.toc +++ b/test.toc @@ -1,8 +1,10 @@ -n :: Namespace = nms { -f ::= fn() {}; -}; main ::= fn() { - n.f(); + x ::= nms { + f ::= fn() { + + }; + }; + // x.g(); }; \ No newline at end of file diff --git a/types.c b/types.c index 80bd561..5ba03a3 100644 --- a/types.c +++ b/types.c @@ -2024,14 +2024,11 @@ static bool types_expr(Typer *tr, Expression *e) { } if (struct_type->kind == TYPE_STRUCT) { bool is_field = false; - if (rhs->kind == EXPR_IDENT) { - /* maybe accessing a field? */ - arr_foreach(struct_type->struc->fields, Field, f) { - if (ident_eq(f->name, rhs->ident)) { - is_field = true; - *t = f->type; - e->binary.dot.field = f; - } + arr_foreach(struct_type->struc->fields, Field, f) { + if (ident_eq(f->name, rhs->ident)) { + is_field = true; + *t = f->type; + e->binary.dot.field = f; } } @@ -2042,30 +2039,11 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } } else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR) { - if (!(rhs->kind == EXPR_IDENT && ident_eq_str(rhs->ident, "len"))) { - - Value field_name; - if (!types_expr(tr, rhs)) return false; - if (!type_is_slicechar(rhs_type)) { - char *s = type_to_str(rhs_type); - err_print(e->where, "Invalid field of type %s.", s); - free(s); - return false; - } - if (!eval_expr(tr->evalr, rhs, &field_name)) return false; - char *str = field_name.slice.data; - if (field_name.slice.n != 3 || strcmp(str, "len") != 0) { - char *fstr = err_malloc((size_t)(field_name.slice.n + 1)); - memcpy(fstr, field_name.slice.data, (size_t)field_name.slice.n); - fstr[field_name.slice.n] = 0; /* null-terminate */ - char *typestr = type_to_str(lhs_type); - err_print(e->where, "%s is not a field of type %s.", fstr, typestr); - free(fstr); free(typestr); - return false; - } + if (!ident_eq_str(rhs->ident, "len")) { + err_print(rhs->where, "Field of array or slice must be .len"); + return false; } - - /* length of slice/arr */ + /* length of slice/arr is i64 */ t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_I64; /* change expr to UNARY_LEN */ @@ -2073,6 +2051,20 @@ static bool types_expr(Typer *tr, Expression *e) { Expression *of = lhs; e->unary.op = UNARY_LEN; e->unary.of = of; + } else if (type_is_builtin(struct_type, BUILTIN_NMS)) { + Value nms_val; + if (!eval_expr(tr->evalr, lhs, &nms_val)) + return false; + Namespace *nms = nms_val.nms; + Identifier translated = ident_translate(rhs->ident, &nms->idents); + if (!translated) { + char *s = ident_to_str(rhs->ident); + err_print(rhs->where, "%s is not a member of this namespace.", s); + return false; + } + if (!type_of_ident(tr, rhs->where, translated, t)) { + return false; + } } else { char *s = type_to_str(lhs_type); err_print(e->where, "Operator . applied to type %s, which is not a structure or pointer to structure.", s); @@ -2126,7 +2118,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; + e->nms.associated_ident = NULL; /* set when we type the declaration */ t->kind = TYPE_BUILTIN; t->builtin = BUILTIN_NMS; } break; @@ -2193,6 +2185,7 @@ static bool types_block(Typer *tr, Block *b, U16 flags) { ret: if (flags & TYPES_BLOCK_NAMESPACE) { /* don't exit block because we don't want to have to re-enter each time we grab something from the namespace */ + b->flags |= BLOCK_IS_NMS; arr_remove_last(&tr->blocks); tr->block = *(Block **)arr_last(tr->blocks); } else { @@ -2336,7 +2329,16 @@ static bool types_decl(Typer *tr, Declaration *d) { } } if (n_idents == 1 && d->expr.kind == EXPR_NMS) { - d->expr.nms.associated_ident = d->idents[0]; + bool is_at_top_level = true; + typedef Block *BlockPtr; + arr_foreach(tr->blocks, BlockPtr, b) { + if (*b && !((*b)->flags & BLOCK_IS_NMS)) { + is_at_top_level = false; + break; + } + } + if (is_at_top_level) + d->expr.nms.associated_ident = d->idents[0]; } -- cgit v1.2.3