summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeo Tenenbaum <pommicket@gmail.com>2020-04-13 01:48:47 -0400
committerLeo Tenenbaum <pommicket@gmail.com>2020-04-13 01:48:47 -0400
commitd3df35312cb9caf96ab787a4ee3db2c356060e7e (patch)
tree2cadc5aa7492db0e742ebcc75a874a8034dbe730
parent3f80b6f659fe7480e537246ea79fbf6a0ec43031 (diff)
cleaned up struct member access with struct[member_as_string] by replacing it with struct.member
-rw-r--r--allocator.c2
-rw-r--r--identifiers.c13
-rw-r--r--main.c5
-rw-r--r--test.toc36
-rw-r--r--types.c127
5 files changed, 39 insertions, 144 deletions
diff --git a/allocator.c b/allocator.c
index 8baedb5..75bdac6 100644
--- a/allocator.c
+++ b/allocator.c
@@ -25,7 +25,7 @@ static void *err_malloc(size_t bytes);
static void *err_calloc(size_t n, size_t sz);
static void *err_realloc(void *prev, size_t new_size);
#ifdef TOC_DEBUG
-#define NO_ALLOCATOR 1 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */
+//#define NO_ALLOCATOR 1 /* useful for debugging; valgrind checks writing past the end of a malloc, but that won't work with an allocator */
#endif
/* number of bytes a page hold, not including the header */
#define PAGE_BYTES (16384 - sizeof(Page))
diff --git a/identifiers.c b/identifiers.c
index a31600c..b5e3f46 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -55,15 +55,20 @@ static inline bool ident_eq_str(Identifier i, const char *s) {
return ident_str_eq_str(i->str, s);
}
+
+static inline Identifier ident_insert_with_len(Identifiers *ids, char *s, size_t len) {
+ IdentSlot *slot = (IdentSlot *)str_hash_table_insert_(&ids->table, s, len);
+ slot->idents = ids;
+ return slot;
+}
+
/* moves s to the char after the identifier */
/* inserts if does not exist. reads until non-ident char is found. */
/* advances past identifier */
-static Identifier ident_insert(Identifiers *ids, char **s) {
+static inline Identifier ident_insert(Identifiers *ids, char **s) {
char *original = *s;
size_t len = ident_str_len_advance(s);
- IdentSlot *slot = (IdentSlot *)str_hash_table_insert_(&ids->table, original, len);
- slot->idents = ids;
- return slot;
+ return ident_insert_with_len(ids, original, len);
}
static char *ident_to_str(Identifier i) {
diff --git a/main.c b/main.c
index ac72097..3006a76 100644
--- a/main.c
+++ b/main.c
@@ -8,12 +8,9 @@
/*
TODO:
-fix "Could not open file" error
+EXPR_IDENT should be a string before typing, also struct member accesses
use
- use with struct members (e.g. SuperPoint ::= struct { use p: Point; })
-for accessing struct members (and other things, potentially) with struct["member"], just replace e with
- a BINARY_DOT
-EXPR_IDENT should be a string before typing
local structs should not be named in C
simplify eval macros with val_to_u/i64
consider replacing weird EXPR_FOR system with just a declaration- would make "for use p := points" easier
diff --git a/test.toc b/test.toc
index c85a94a..a23df05 100644
--- a/test.toc
+++ b/test.toc
@@ -1,35 +1,17 @@
+#include "std/io.toc";
Point ::= struct {
- x, y: float;
+ x, y: int;
}
-sqrt ::= fn(x: float) a := x/2 {
- for _ := 0..20 {
- a = (x + a * a) / (2 * a);
- }
+foo ::= fn() []char {
+ return "y";
}
-normalize ::= fn(use p: &Point) {
- sqdist := x * x + y * y;
- one_over_dist := 1/sqrt(sqdist);
- x *= one_over_dist;
- y *= one_over_dist;
-}
-
-printf ::= #foreign("printf", "libc.so.6") fn(#C &"const char", #C ..);
-
main ::= fn() {
- use p: Point;
- x = 10;
- y = 20;
- normalize(&p);
- fmt := "%f %f\n\0";
- printf(&fmt[0], p.x, p.y);
- ps: [10]Point;
- ps[0].x = 12;
- ps[7].y = 13;
- for p := &ps {
- use p;
- printf(&fmt[0], x, y);
- }
+ p: Point;
+ p["x"] = 5;
+ p[foo()] = 17;
+ puti(p["x"]);
+ puti(p.y);
}
diff --git a/types.c b/types.c
index 1f3261c..fb3f124 100644
--- a/types.c
+++ b/types.c
@@ -7,6 +7,10 @@ static Status types_stmt(Typer *tr, Statement *s);
static Status type_resolve(Typer *tr, Type *t, Location where);
+static inline Identifiers *typer_get_idents(Typer *tr) {
+ return tr->block == NULL ? tr->globals : &tr->block->idents;
+}
+
static inline void *typer_malloc(Typer *tr, size_t bytes) {
return allocr_malloc(tr->allocr, bytes);
}
@@ -2893,16 +2897,25 @@ static Status types_expr(Typer *tr, Expression *e) {
break;
}
case BINARY_AT_INDEX:
- if ((lhs_type->kind == TYPE_ARR || lhs_type->kind == TYPE_SLICE || type_is_builtin(lhs_type, BUILTIN_VARARGS)) &&
- (rhs_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(rhs_type->builtin))) {
+ if (type_is_slicechar(rhs_type)) {
+ /* switch to BINARY_DOT (point["x"] => point.x) */
+ e->binary.op = BINARY_DOT;
+ Value val;
+ if (!eval_expr(tr->evalr, rhs, &val)) {
+ return false;
+ }
+ rhs->kind = EXPR_IDENT;
+ rhs->ident = ident_insert_with_len(typer_get_idents(tr), val.slice.data, (size_t)val.slice.len);
+ /* re-type with new expression */
+ e->flags = (ExprFlags)~(ExprFlags)EXPR_FOUND_TYPE;
+ return types_expr(tr, e);
+ }
+ if (rhs_type->kind != TYPE_BUILTIN || !type_builtin_is_numerical(rhs_type->builtin)) {
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;
- }
+ lhs_type = lhs_type->ptr;
}
switch (lhs_type->kind) {
case TYPE_ARR:
@@ -2911,108 +2924,6 @@ static Status types_expr(Typer *tr, Expression *e) {
case TYPE_SLICE:
*t = *lhs_type->slice;
break;
- case TYPE_STRUCT: {
- /* allow accessing struct 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 struct member access with [], but got type %s.", s);
- return false;
- }
- Value field_name;
- if (!eval_expr(tr->evalr, rhs, &field_name)) return false;
-
- /* get the field, if it exists */
- Identifier ident = ident_get_with_len(&lhs_type->struc->body.idents,
- field_name.slice.data, (size_t)field_name.slice.len);
- if (ident_is_declared(ident)) {
- assert(ident->decl_kind == IDECL_DECL);
- Declaration *decl = ident->decl;
- if (decl->flags & DECL_IS_CONST) {
- /* replace with value of struct constant */
- e->kind = EXPR_VAL;
- assert(decl->flags & DECL_FOUND_VAL);
- int idx = ident_index_in_decl(ident, decl);
- *t = *decl_type_at_index(decl, idx);
- copy_val(tr->allocr, &e->val, *decl_val_at_index(decl, idx), t);
- } else {
- /* replace with BINARY_DOT */
- e->binary.op = BINARY_DOT;
- Field *f = decl->field + ident_index_in_decl(ident, decl);
- e->binary.dot.field = f;
- *t = *f->type;
- }
- } else {
- char *fstr = err_malloc((size_t)(field_name.slice.len + 1));
- memcpy(fstr, field_name.slice.data, (size_t)field_name.slice.len);
- fstr[field_name.slice.len] = 0; /* null-terminate */
- char *typestr = type_to_str(lhs_type);
- err_print(e->where, "%s is not a field of structure %s.", fstr, typestr);
- free(fstr); free(typestr);
- return false;
- }
- } break;
- case TYPE_BUILTIN:
- if (lhs_type->builtin == BUILTIN_NMS) {
- /* 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;
- e->binary.rhs->ident = ident_get_with_len(&nms->body.idents, member_name.slice.data, (size_t)member_name.slice.len);
- if (!ident_is_declared(e->binary.rhs->ident)) {
- char *s = slice_to_cstr(member_name.slice);
- err_print(e->where, "\"%s\" is not a member of this namespace.", s);
- free(s);
- return false;
- }
- if (!type_of_ident(tr, rhs->where, e->binary.rhs->ident, t)) {
- return false;
- }
- break;
- } else if (lhs_type->builtin == BUILTIN_VARARGS) {
- assert(lhs->kind == EXPR_IDENT);
- assert(lhs->ident->decl_kind == IDECL_DECL);
- Declaration *decl = lhs->ident->decl;
- assert(decl->flags & DECL_IS_PARAM);
- Value index_val;
- if (!eval_expr(tr->evalr, rhs, &index_val))
- return false;
- /* NOTE: rhs->type was checked above */
- I64 i = val_to_i64(index_val, rhs->type.builtin);
- VarArg *varargs = decl->val.varargs;
- if (i < 0 || i >= (I64)arr_len(varargs)) {
- err_print(e->where, "Index out of bounds for varargs access (index = " I64_FMT ", length = %lu).", i, (unsigned long)arr_len(varargs));
- return 0;
- }
- VarArg *vararg = &varargs[i];
- if (decl->flags & DECL_IS_CONST) {
- /* replace with value */
- e->kind = EXPR_VAL;
- e->type = *vararg->type;
- copy_val(tr->allocr, &e->val, vararg->val, &e->type);
- } else {
- /* just use vararg's type */
- rhs->kind = EXPR_VAL;
- rhs->val.i64 = i;
- rhs->type.builtin = BUILTIN_I64;
- *t = *vararg->type;
- }
- break;
- }
- /* fallthrough */
default: {
char *s = type_to_str(lhs_type);
err_print(e->where, "Cannot subscript type %s", s);