diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-07 19:24:25 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2020-02-07 19:24:25 -0500 |
commit | b40db0bcddda8472f3d4f5fbf7d86a4efb77a6a4 (patch) | |
tree | 2d0237797d613b1fd1e964a72e4a9b9a1aee4be4 | |
parent | 26dea17ba28448c1562fe75d183dd9fc2244abc6 (diff) |
allow namespace access with nms[string]
-rw-r--r-- | cgen.c | 2 | ||||
-rw-r--r-- | eval.c | 2 | ||||
-rw-r--r-- | identifiers.c | 9 | ||||
-rw-r--r-- | main.c | 1 | ||||
-rw-r--r-- | test.toc | 17 | ||||
-rw-r--r-- | types.c | 45 |
6 files changed, 61 insertions, 15 deletions
@@ -1403,7 +1403,7 @@ static bool cgen_expr(CGenerator *g, Expression *e) { assert(type_is_builtin(struct_type, BUILTIN_NMS)); char *prefix = cgen_nms_prefix(g, e->binary.lhs->val.nms); cgen_write(g, "%s", prefix); - cgen_ident_simple(g, e->binary.rhs->ident); + cgen_ident_simple(g, e->binary.dot.translated_ident); free(prefix); } handled = true; @@ -783,7 +783,7 @@ static bool eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void * } *p = ptr; } - return false; + return true; } static bool eval_address_of(Evaluator *ev, Expression *e, void **ptr) { diff --git a/identifiers.c b/identifiers.c index 370ad7d..876c55a 100644 --- a/identifiers.c +++ b/identifiers.c @@ -169,10 +169,15 @@ static char *ident_to_str_reduced_charset(Identifier id) { } + +static inline Identifier ident_get_with_len(Identifiers *ids, char *s, size_t len) { + return (Identifier)str_hash_table_get_(&ids->table, s, len); +} + /* NULL = no such identifier. returns identifier "foo" for both "foo\0" and "foo+92384324..." */ -static Identifier ident_get(Identifiers *ids, char *s) { +static inline Identifier ident_get(Identifiers *ids, char *s) { size_t len = ident_str_len(s); - return (Identifier)str_hash_table_get_(&ids->table, s, len); + return ident_get_with_len(ids, s, len); } /* translate and insert if not already there */ @@ -18,7 +18,6 @@ /* TODO: -nms["foo"] make sure #export still works properly check for leaks --- @@ -1,5 +1,20 @@ +io ::= nms { + #include "std/io.toc"; +}; -nms { +n ::= nms { x := 1; + counter ::= fn() int { x += 1; x }; }; + +main ::= fn() { + a := n.counter(); + b := n.counter(); + n.counter(); + c := n.counter(); + io.puts("Hello!"); + io.puti(a); + io.puti(b); + io.puti(c); +}; @@ -2009,6 +2009,12 @@ static bool types_expr(Typer *tr, Expression *e) { err_print(e->where, "The index of an array must be a builtin numerical type."); return false; } + if (lhs_type->kind == TYPE_PTR) { + if (lhs_type->ptr->kind == TYPE_STRUCT + || type_is_builtin(lhs_type->ptr, BUILTIN_NMS)) { + lhs_type = lhs_type->ptr; + } + } switch (lhs_type->kind) { case TYPE_ARR: *t = *lhs_type->arr.of; @@ -2016,10 +2022,6 @@ static bool types_expr(Typer *tr, Expression *e) { case TYPE_SLICE: *t = *lhs_type->slice; break; - case TYPE_PTR: - lhs_type = lhs_type->ptr; - if (lhs_type->kind != TYPE_STRUCT) break; - /* fallthrough */ case TYPE_STRUCT: { /* allow accessing struct members with a string */ if (!type_is_slicechar(rhs_type)) { @@ -2050,12 +2052,37 @@ static bool types_expr(Typer *tr, Expression *e) { return false; } } break; + case TYPE_BUILTIN: + if (lhs_type->builtin == BUILTIN_NMS) { + if (!type_is_slicechar(rhs_type)) + break; + } + /* fallthrough */ default: { - char *s = type_to_str(lhs_type); - err_print(e->where, "Trying to take index of non-array type %s.", s); - free(s); - return false; - } + /* allow accessing namespace members with a string */ + if (!type_is_slicechar(rhs_type)) { + char *s = type_to_str(rhs_type); + err_print(e->where, "Expected a string for namsepace member access with [], but got type %s.", s); + return false; + } + + Value nms_val; + if (!eval_expr(tr->evalr, lhs, &nms_val)) + return false; + Namespace *nms = nms_val.nms; + lhs->kind = EXPR_VAL; + lhs->val.nms = nms; + + Value member_name; + if (!eval_expr(tr->evalr, rhs, &member_name)) return false; + e->binary.op = BINARY_DOT; + e->binary.rhs->kind = EXPR_IDENT; + Identifier ident = e->binary.rhs->ident = e->binary.dot.translated_ident = + ident_get_with_len(&nms->body.idents, member_name.slice.data, (size_t)member_name.slice.n); + if (!type_of_ident(tr, rhs->where, &ident, t)) { + return false; + } + } break; } break; case BINARY_DOT: { |