From 9db4ea5189f6f1a8b264c9948090c822f5e008b1 Mon Sep 17 00:00:00 2001 From: Leo Tenenbaum Date: Thu, 23 Apr 2020 15:58:51 -0400 Subject: made EXPR_IDENT a string before typing --- cgen.c | 2 +- copy.c | 2 -- eval.c | 3 +-- identifiers.c | 5 +++++ infer.c | 2 +- main.c | 6 +++--- misc.c | 12 ++++++++++++ parse.c | 15 ++++++++++++--- test.toc | 11 ++++------- types.c | 52 +++++++++++++++++++++++++++++----------------------- types.h | 15 +++++++++------ 11 files changed, 77 insertions(+), 48 deletions(-) diff --git a/cgen.c b/cgen.c index b2d64f2..f73debd 100644 --- a/cgen.c +++ b/cgen.c @@ -1349,7 +1349,7 @@ static void cgen_expr(CGenerator *g, Expression *e) { cgen_expr(g, lhs); bool is_ptr = lhs->type.kind == TYPE_PTR; cgen_write(g, is_ptr ? "->" :"."); - cgen_ident_simple(g, e->binary.dot.field->name); + cgen_ident_simple(g, e->binary.field->name); cgen_write(g, ")"); } else if (struct_type->kind == TYPE_SLICE) { /* access slice data */ diff --git a/copy.c b/copy.c index 2c746a1..7da09d4 100644 --- a/copy.c +++ b/copy.c @@ -246,9 +246,7 @@ static void copy_expr(Copier *c, Expression *out, Expression *in) { case EXPR_LITERAL_STR: case EXPR_LITERAL_CHAR: case EXPR_LITERAL_BOOL: - break; case EXPR_IDENT: - copier_ident_translate(c, &out->ident); break; case EXPR_UNARY_OP: out->unary.of = copy_expr_(c, in->unary.of); diff --git a/eval.c b/eval.c index 9a8fa98..f8ef498 100644 --- a/eval.c +++ b/eval.c @@ -734,13 +734,12 @@ static Status eval_ptr_to_struct_field(Evaluator *ev, Expression *dot_expr, void } else { struc_data = struc.struc; } - *p = (char *)struc_data + dot_expr->binary.dot.field->offset; + *p = (char *)struc_data + dot_expr->binary.field->offset; } else if (struct_type->kind == TYPE_SLICE) { void *ptr; if (!eval_address_of(ev, dot_expr->binary.lhs, &ptr)) return false; /* access struct data */ - assert(ident_eq_str(dot_expr->binary.rhs->ident, "data")); *p = &((Slice *)ptr)->data; } else { void *ptr; diff --git a/identifiers.c b/identifiers.c index 2daa112..0f5d59a 100644 --- a/identifiers.c +++ b/identifiers.c @@ -55,6 +55,11 @@ static inline bool ident_eq_str(Identifier i, const char *s) { return ident_str_eq_str(i->str, s); } +static inline bool ident_eq_string(Identifier i, String s) { + if (i->len != s.len) return false; + if (memcmp(i->str, s.str, s.len) != 0) return false; + return true; +} 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); diff --git a/infer.c b/infer.c index e131583..8367dce 100644 --- a/infer.c +++ b/infer.c @@ -17,7 +17,7 @@ static bool infer_from_expr(Typer *tr, Expression *match, Value to, Type *to_typ case EXPR_IDENT: /* an identifier! maybe it's one of idents... */ arr_foreach(idents, Identifier, ident) { - if (*ident == match->ident) { + if (ident_eq_string(*ident, match->ident_str)) { long idx = ident - idents; types[idx] = *to_type; vals[idx] = to; diff --git a/main.c b/main.c index 1529b68..930d947 100644 --- a/main.c +++ b/main.c @@ -8,7 +8,6 @@ /* @TODO: -EXPR_IDENT should be a string before typing, also struct member accesses do we need the possibility that IdentSlot.decl is NULL? use - use with struct members (e.g. SuperPoint ::= struct { use p: Point; }) @@ -22,12 +21,13 @@ is there a problem where we can get TYPE_UNKNOWN in cgen, triggering an assert(0 -also make sure you can't do x:#C("5"); local structs should not be named in C make sure global slices work -allow use ??? if an error has already occurred +allow `use ???;` if an error has already occurred if something gets included into a namespace, and its typing fails, the namespace should still be of type namespace, not ??? make sure you can do a[i] where a is &[5]int or &[]char or something do we consistently handle x := &some_array_or_slice; x.len -&void simplify eval macros with val_to_u/i64 +#if should not create a block +&void &&, || start making a standard library... (printf; stringbuilder would be nice to have) switch diff --git a/misc.c b/misc.c index c38996f..4e82ff8 100644 --- a/misc.c +++ b/misc.c @@ -48,6 +48,17 @@ size_t str_copy(char *dest, size_t destsz, const char *src) { return destsz-1; } +static char *cstr(char const *str, size_t len) { + char *ret = malloc(len+1); + memcpy(ret, str, len); + ret[len] = 0; + return ret; +} + +static bool str_eq_cstr(String s, char const *str) { + return strncmp(s.str, str, s.len) == 0; +} + static inline U32 rand_u32(U32 seed) { U64 seed64 = (U64)seed; return (U32)((seed64 * 0x832f0fda4e1a8642 + 0x41d49cd5459a2ab4) >> 32); @@ -65,3 +76,4 @@ static char const *indefinite_article(char const *s) { return "an"; return "a"; } + diff --git a/parse.c b/parse.c index 0de36f8..d7bae47 100644 --- a/parse.c +++ b/parse.c @@ -1241,7 +1241,8 @@ static Status parse_expr(Parser *p, Expression *e, Token *end) { } break; case TOKEN_IDENT: e->kind = EXPR_IDENT; - e->ident = parser_ident_insert(p, t->token->ident); + e->ident_str.str = t->token->ident; + e->ident_str.len = ident_str_len(e->ident_str.str); break; case TOKEN_LITERAL_STR: e->kind = EXPR_LITERAL_STR; @@ -2667,13 +2668,21 @@ static void fprint_expr(FILE *out, Expression *e) { fprint_char_literal(out, e->charl); break; case EXPR_IDENT: - fprint_ident_debug(out, e->ident); + if (found_type) { + fprint_ident_debug(out, e->ident); + } else { + fwrite(e->ident_str.str, 1, e->ident_str.len, out); + } break; case EXPR_BINARY_OP: { fprintf(out, "("); fprint_expr(out, e->binary.lhs); fprintf(out, ")%s(", binary_op_to_str(e->binary.op)); - fprint_expr(out, e->binary.rhs); + if (e->binary.op == BINARY_DOT && found_type && e->binary.lhs->type.kind == TYPE_STRUCT) { + fprint_ident(out, e->binary.field->name); + } else { + fprint_expr(out, e->binary.rhs); + } fprintf(out, ")"); } break; case EXPR_UNARY_OP: diff --git a/test.toc b/test.toc index 10043da..1f6a725 100644 --- a/test.toc +++ b/test.toc @@ -1,6 +1,5 @@ #include "std/io.toc"; /* - sum ::= fn(n::=, t::=, a: [n]t) t { total : t = 0; for x := a { @@ -16,15 +15,13 @@ main ::= fn() { *x = i; } puti(sum(numbers) as int); - } */ - -ll ::= struct (t::Type) { - head: t; - next: &ll(t); +Point ::= struct { + x, y : int; } main ::= fn() { - x: ll(int); + p: Point; + p.x = 12; } diff --git a/types.c b/types.c index b3c794e..22e4350 100644 --- a/types.c +++ b/types.c @@ -1476,14 +1476,14 @@ static void get_builtin_val_type(Allocator *a, BuiltinVal val, Type *t) { /* gets a struct's constant or parameter, and puts it into e->val. */ -static Status get_struct_constant(StructDef *struc, Identifier member, Expression *e) { +static Status get_struct_constant(StructDef *struc, String ident, Expression *e) { if (struc->params && !(struc->params[0].flags & DECL_FOUND_VAL)) { err_print(e->where, "To access constants from a parameterized struct, you must supply its arguments."); return false; } - Identifier i = ident_translate(member, &struc->body.idents); + Identifier i = ident_get_with_len(&struc->body.idents, ident.str, ident.len); if (!i) { - char *member_s = ident_to_str(member); + char *member_s = cstr(ident.str, ident.len); char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct"; err_print(e->where, "%s is not a member of structure %s.", member_s, struc_s); info_print(struc->where, "struct was declared here."); @@ -1505,9 +1505,10 @@ static Status get_struct_constant(StructDef *struc, Identifier member, Expressio e->type = *decl_type_at_index(i->decl, ident_idx); return true; } else { - char *member_s = ident_to_str(member); + char *member_s = cstr(ident.str, ident.len); char *struc_s = struc->name ? ident_to_str(struc->name) : "anonymous struct"; err_print(e->where, "Cannot get value %s from struct %s. Are you missing parameters to this struct?", member_s, struc_s); + free(member_s); return false; } } @@ -1941,11 +1942,13 @@ static Status types_expr(Typer *tr, Expression *e) { } case EXPR_IDENT: { Block *b = tr->block; - Identifier i = e->ident; + char *i_str = e->ident_str.str; + size_t i_len = e->ident_str.len; + Identifier final_ident = NULL; bool undeclared = true; while (1) { /* for each block we are inside... */ /* @OPTIM: only hash once */ - Identifier translated = ident_translate(i, b ? &b->idents : tr->globals); + Identifier translated = ident_get_with_len(b ? &b->idents : tr->globals, i_str, i_len); if (ident_is_declared(translated)) { #if 0 printf("translated %s from\n", ident_to_str(i)); @@ -1953,7 +1956,7 @@ static Status types_expr(Typer *tr, Expression *e) { printf(" to \n"); print_block_location(translated->idents->body); #endif - i = translated; + final_ident = translated; undeclared = false; } Use **uses = b ? b->uses : tr->uses; @@ -1971,7 +1974,7 @@ static Status types_expr(Typer *tr, Expression *e) { Namespace *nms = val.nms; Block *body = &nms->body; /* look up identifier in namespace */ - translated_use = ident_translate(i, &body->idents); + translated_use = ident_get_with_len(&body->idents, i_str, i_len); } else { /* it's a struct */ was_a_struct = true; @@ -1980,16 +1983,17 @@ static Status types_expr(Typer *tr, Expression *e) { struct_type = struct_type->ptr; assert(struct_type->kind == TYPE_STRUCT); StructDef *struc = struct_type->struc; - translated_use = ident_translate(i, &struc->body.idents); + translated_use = ident_get_with_len(&struc->body.idents, i_str, i_len); } if (ident_is_declared(translated_use)) { if (undeclared) { previous_use_which_uses_i = use; undeclared = false; - i = translated_use; + final_ident = translated_use; } else { - char *s = ident_to_str(i); + char *s = cstr(i_str, i_len); err_print(e->where, "Conflicting declarations for identifier %s.", s); + free(s); char *also = ""; if (previous_use_which_uses_i) { /* i was use'd twice */ @@ -2010,7 +2014,8 @@ static Status types_expr(Typer *tr, Expression *e) { e->binary.lhs = used; e->binary.rhs = typer_calloc(tr, 1, sizeof *e->binary.rhs); e->binary.rhs->kind = EXPR_IDENT; - e->binary.rhs->ident = i; + e->binary.rhs->ident_str.str = i_str; + e->binary.rhs->ident_str.len = i_len; /* re-type */ if (!types_expr(tr, e)) return false; @@ -2025,7 +2030,7 @@ static Status types_expr(Typer *tr, Expression *e) { break; } } - e->ident = i; + e->ident = final_ident; if (undeclared) { char *s = ident_to_str(e->ident); err_print(e->where, "Undeclared identifier \"%s\".", s); @@ -3029,7 +3034,8 @@ static Status types_expr(Typer *tr, Expression *e) { return false; } rhs->kind = EXPR_IDENT; - rhs->ident = ident_insert_with_len(typer_get_idents(tr), val.slice.data, (size_t)val.slice.len); + rhs->ident_str.str = val.slice.data; + rhs->ident_str.len = (size_t)val.slice.len; /* re-type with new expression */ e->flags = (ExprFlags)~(ExprFlags)EXPR_FOUND_TYPE; return types_expr(tr, e); @@ -3114,25 +3120,25 @@ static Status types_expr(Typer *tr, Expression *e) { free(s); return false; } - if (!get_struct_constant(struc->struc, rhs->ident, e)) + if (!get_struct_constant(struc->struc, rhs->ident_str, e)) return false; break; } else if (struct_type->kind == TYPE_STRUCT) { StructDef *struc = struct_type->struc; assert(struc->flags & STRUCT_DEF_RESOLVED); - Identifier struct_ident = ident_translate(rhs->ident, &struc->body.idents); + Identifier struct_ident = ident_get_with_len(&struc->body.idents, rhs->ident_str.str, rhs->ident_str.len); if (ident_is_declared(struct_ident) && !(struct_ident->decl->flags & DECL_IS_CONST)) { Field *field = struct_ident->decl->field; field += ident_index_in_decl(struct_ident, struct_ident->decl); - e->binary.dot.field = field; + e->binary.field = field; *t = *field->type; } else { - if (!get_struct_constant(struct_type->struc, rhs->ident, e)) + if (!get_struct_constant(struct_type->struc, rhs->ident_str, e)) return false; } break; } else if (struct_type->kind == TYPE_SLICE || struct_type->kind == TYPE_ARR || type_is_builtin(struct_type, BUILTIN_VARARGS)) { - if (ident_eq_str(rhs->ident, "data") && struct_type->kind == TYPE_SLICE) { + if (str_eq_cstr(rhs->ident_str, "data") && struct_type->kind == TYPE_SLICE) { /* allow access of slice pointer */ t->kind = TYPE_PTR; t->ptr = typer_calloc(tr, 1, sizeof *t->ptr); @@ -3140,7 +3146,7 @@ static Status types_expr(Typer *tr, Expression *e) { t->ptr->flags = TYPE_IS_RESOLVED; break; } - if (!ident_eq_str(rhs->ident, "len")) { + if (!str_eq_cstr(rhs->ident_str, "len")) { char *s = type_to_str(struct_type); err_print(rhs->where, "Field of %s must be .len", s); free(s); @@ -3170,10 +3176,10 @@ static Status types_expr(Typer *tr, Expression *e) { Namespace *nms = nms_val.nms; lhs->kind = EXPR_VAL; lhs->val.nms = nms; - Identifier original = rhs->ident; - rhs->ident = ident_translate(original, &nms->body.idents); + String str = rhs->ident_str; + rhs->ident = ident_get_with_len(&nms->body.idents, str.str, str.len); if (!ident_is_declared(rhs->ident)) { - char *s = ident_to_str(original); + char *s = cstr(str.str, str.len); err_print(e->where, "\"%s\" is not a member of this namespace.", s); free(s); return false; diff --git a/types.h b/types.h index aabf246..d3a4e35 100644 --- a/types.h +++ b/types.h @@ -336,10 +336,12 @@ typedef struct NumLiteral { }; } NumLiteral; -typedef struct StrLiteral { +typedef struct String { char *str; size_t len; -} StrLiteral; +} String; + +typedef String StrLiteral; typedef struct { U32 line; @@ -793,10 +795,10 @@ typedef struct Expression { struct { BinaryOp op; struct Expression *lhs; - struct Expression *rhs; union { - Field *field; /* for struct. */ - } dot; + struct Expression *rhs; + Field *field; /* for struct., after resolving */ + }; } binary; CallExpr call; struct { @@ -808,7 +810,8 @@ typedef struct Expression { BuiltinVal val; } which; } builtin; - Identifier ident; + String ident_str; /* before typing */ + Identifier ident; /* after typing */ NewExpr new; Namespace *nms; struct { -- cgit v1.2.3