From d3df35312cb9caf96ab787a4ee3db2c356060e7e Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Mon, 13 Apr 2020 01:48:47 -0400 Subject: cleaned up struct member access with struct[member_as_string] by replacing it with struct.member --- allocator.c | 2 +- identifiers.c | 13 ++++-- main.c | 5 +-- test.toc | 36 +++++------------ types.c | 127 +++++++++------------------------------------------------- 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); -- cgit v1.2.3