summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c2
-rw-r--r--eval.c2
-rw-r--r--identifiers.c9
-rw-r--r--main.c1
-rw-r--r--test.toc17
-rw-r--r--types.c45
6 files changed, 61 insertions, 15 deletions
diff --git a/cgen.c b/cgen.c
index bfcd389..a193d6d 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
diff --git a/eval.c b/eval.c
index 0b4e380..a6ff7aa 100644
--- a/eval.c
+++ b/eval.c
@@ -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 */
diff --git a/main.c b/main.c
index 959b58f..3e9ee3d 100644
--- a/main.c
+++ b/main.c
@@ -18,7 +18,6 @@
/*
TODO:
-nms["foo"]
make sure #export still works properly
check for leaks
---
diff --git a/test.toc b/test.toc
index 767ef38..32c2955 100644
--- a/test.toc
+++ b/test.toc
@@ -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);
+};
diff --git a/types.c b/types.c
index 4483d2e..ede7275 100644
--- a/types.c
+++ b/types.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: {