diff options
-rw-r--r-- | cgen.c | 21 | ||||
-rw-r--r-- | eval.c | 39 | ||||
-rw-r--r-- | identifiers.c | 10 | ||||
-rw-r--r-- | parse.c | 18 | ||||
-rw-r--r-- | test.toc | 2 | ||||
-rw-r--r-- | toc.c | 12 | ||||
-rw-r--r-- | typedefs_cgen.c | 11 | ||||
-rw-r--r-- | types.c | 26 | ||||
-rw-r--r-- | types.h | 12 |
9 files changed, 80 insertions, 71 deletions
@@ -105,7 +105,7 @@ static bool cgen_uses_ptr(Type *t) { case TYPE_TYPE: return false; case TYPE_USER: - return cgen_uses_ptr(ident_typeval(t->user.name)); + return cgen_uses_ptr(type_user_underlying(t)); } assert(0); return false; @@ -196,13 +196,8 @@ static bool cgen_type_pre(CGenerator *g, Type *t, Location where) { assert(0); return false; case TYPE_USER: { - Declaration *d = ident_decl(t->user.name)->decl; - assert(d->c.ids); - long i = decl_ident_index(d, t->user.name); - if (d->c.ids[i]) - cgen_ident_id(g, d->c.ids[i]); - else - cgen_ident(g, t->user.name); + Identifier i = t->user.decl->idents[t->user.index]; + cgen_ident(g, i); } break; } return true; @@ -363,9 +358,7 @@ static bool cgen_set(CGenerator *g, Expression *set_expr, const char *set_str, E where = to_expr->where; if (!cgen_expr_pre(g, to_expr)) return false; } - while (type->kind == TYPE_USER) { - type = ident_typeval(type->user.name); - } + type = type_inner(type); switch (type->kind) { case TYPE_BUILTIN: case TYPE_FN: @@ -1083,7 +1076,7 @@ static void cgen_zero_value(CGenerator *g, Type *t) { cgen_write(g, "{0}"); break; case TYPE_USER: - cgen_zero_value(g, ident_typeval(t->user.name)); + cgen_zero_value(g, type_inner(t)); break; case TYPE_TYPE: case TYPE_VOID: @@ -1159,7 +1152,7 @@ static bool cgen_val_ptr_pre(CGenerator *g, void *v, Type *t, Location where) { } break; case TYPE_USER: - if (!cgen_val_ptr_pre(g, v, ident_typeval(t->user.name), where)) + if (!cgen_val_ptr_pre(g, v, type_inner(t), where)) return false; break; case TYPE_FN: @@ -1225,7 +1218,7 @@ static bool cgen_val_ptr(CGenerator *g, void *v, Type *t, Location where) { } break; case TYPE_USER: - if (!cgen_val_ptr(g, v, ident_typeval(t->user.name), where)) + if (!cgen_val_ptr(g, v, type_inner(t), where)) return false; break; } @@ -71,7 +71,7 @@ static size_t compiler_alignof(Type *t) { case TYPE_TYPE: return sizeof(Type *); case TYPE_USER: - return compiler_alignof(ident_typeval(t->user.name)); + return compiler_alignof(type_user_underlying(t)); case TYPE_STRUCT: { /* assume the align of a struct is (at most) the greatest align out of its children's */ size_t align = 1; @@ -129,7 +129,7 @@ static size_t compiler_sizeof(Type *t) { case TYPE_TYPE: return sizeof(Type *); case TYPE_USER: - return compiler_sizeof(ident_typeval(t->user.name)); + return compiler_sizeof(type_user_underlying(t)); case TYPE_STRUCT: { eval_struct_find_offsets(t); return t->struc.size; @@ -269,7 +269,7 @@ static void val_copy(Evaluator *ev, Value *dest, Value *src, Type *t) { memcpy(dest->struc, src->struc, bytes); } break; case TYPE_USER: - val_copy(ev, dest, src, ident_typeval(t->user.name)); + val_copy(ev, dest, src, type_user_underlying(t)); break; } } @@ -291,7 +291,7 @@ static void *val_ptr_to_free(Value *v, Type *t) { case TYPE_STRUCT: return v->struc; case TYPE_USER: - return val_ptr_to_free(v, ident_typeval(t->user.name)); + return val_ptr_to_free(v, type_user_underlying(t)); } assert(0); return NULL; } @@ -561,7 +561,7 @@ static void eval_deref(Value *v, void *ptr, Type *type) { v->type = *(Type **)ptr; break; case TYPE_USER: - eval_deref(v, ptr, ident_typeval(type->user.name)); + eval_deref(v, ptr, type_user_underlying(type)); break; case TYPE_VOID: case TYPE_UNKNOWN: @@ -600,7 +600,7 @@ static void eval_deref_set(void *set, Value *to, Type *type) { *(Type **)set = to->type; break; case TYPE_USER: - eval_deref_set(set, to, ident_typeval(type->user.name)); + eval_deref_set(set, to, type_user_underlying(type)); break; case TYPE_VOID: case TYPE_UNKNOWN: @@ -1077,20 +1077,15 @@ static bool eval_expr(Evaluator *ev, Expression *e, Value *v) { d->flags |= DECL_FLAG_FOUND_VAL; } - long index = 0; - arr_foreach(d->idents, Identifier, decl_i) { - if (*decl_i == e->ident) { - break; - } - index++; - assert(index < (long)arr_len(d->idents)); /* identifier got its declaration set to here, but it's not here */ - } + int index = ident_index_in_decl(e->ident, d); + assert(index != -1); if (e->type.kind == TYPE_TYPE) { /* set v to a user type, not the underlying type */ v->type = evalr_malloc(ev, sizeof *v->type); /* TODO: fix this (free eventually) */ - v->type->flags = 0; + v->type->flags = TYPE_FLAG_RESOLVED; v->type->kind = TYPE_USER; - v->type->user.name = d->idents[index]; + v->type->user.decl = d; + v->type->user.index = index; } else { *v = d->type.kind == TYPE_TUPLE ? d->val.tuple[index] : d->val; } @@ -1259,13 +1254,11 @@ static bool eval_decl(Evaluator *ev, Declaration *d) { Value *thisval = NULL; if (has_expr) thisval = d->type.kind == TYPE_TUPLE ? &val.tuple[index] : &val; - Type *inner_type = type; - while (inner_type->kind == TYPE_USER) - inner_type = ident_typeval(type->user.name); - if (inner_type->kind == TYPE_STRUCT) { - id->val.struc = err_calloc(1, compiler_sizeof(inner_type)); - } else if (inner_type->kind == TYPE_ARR) { - id->val.arr = err_calloc(inner_type->arr.n, compiler_sizeof(inner_type->arr.of)); + Type *inner = type_inner(type); + if (inner->kind == TYPE_STRUCT) { + id->val.struc = err_calloc(1, compiler_sizeof(inner)); + } else if (inner->kind == TYPE_ARR) { + id->val.arr = err_calloc(inner->arr.n, compiler_sizeof(inner->arr.of)); } if (has_expr) diff --git a/identifiers.c b/identifiers.c index a9b4540..030ec76 100644 --- a/identifiers.c +++ b/identifiers.c @@ -177,6 +177,16 @@ static void idents_test(void) { idents_free(&ids); } +static int ident_index_in_decl(Identifier i, Declaration *d) { + int index = 0; + arr_foreach(d->idents, Identifier, j) { + if (i == *j) + return index; + index++; + } + return -1; +} + static Type *ident_typeval(Identifier i) { Value *val; IdentDecl *idecl = ident_decl(i); @@ -218,7 +218,9 @@ static size_t type_to_str_(Type *t, char *buffer, size_t bufsize) { case TYPE_TYPE: return str_copy(buffer, bufsize, "<type>"); case TYPE_USER: { - char *ident_str = ident_to_str(t->user.name); + char *ident_str = ident_to_str((t->flags & TYPE_FLAG_RESOLVED) + ? t->user.decl->idents[t->user.index] + : t->user.ident); size_t ret = str_copy(buffer, bufsize, ident_str); return ret; } @@ -513,7 +515,7 @@ static bool parse_type(Parser *p, Type *type) { case TOKEN_IDENT: /* user-defined type */ type->kind = TYPE_USER; - type->user.name = t->token->ident; + type->user.ident = t->token->ident; t->token++; break; default: @@ -2009,9 +2011,11 @@ static long decl_ident_index(Declaration *d, Identifier i) { return -1; } -static Value *decl_ident_val(Declaration *d, Identifier i) { - if (d->type.kind == TYPE_TUPLE) - return &d->val.tuple[decl_ident_index(d, i)]; - else - return &d->val; +static inline Value *decl_val_at_index(Declaration *d, int i) { + return d->type.kind == TYPE_TUPLE ? &d->val.tuple[i] : &d->val; } + +static inline Type *decl_type_at_index(Declaration *d, int i) { + return d->type.kind == TYPE_TUPLE ? &d->type.tuple[i] : &d->type; +} + @@ -28,5 +28,5 @@ main @= fn() { puti(X); puti(#sizeof(int)); puti(#alignof(int)); - puti(#sizeof({ Foo @= struct { x: i64; y: char; } ; f: Foo; f })); + puti(#sizeof({ Foo, Bar @= int, struct { x: i64; y: char; } ; f: Foo; f })); }; @@ -23,10 +23,18 @@ #include "parse.c" #include "scope.c" +static Type *type_user_underlying(Type *t) { + assert(t->kind == TYPE_USER); + Declaration *d = t->user.decl; + assert(d->flags & DECL_FLAG_FOUND_VAL); + return (d->type.kind == TYPE_TUPLE ? d->val.tuple[t->user.index] : d->val).type; +} static Type *type_inner(Type *t) { - while (t && t->kind == TYPE_USER) - t = ident_typeval(t->user.name); + assert(t->flags & TYPE_FLAG_RESOLVED); + while (t->kind == TYPE_USER) { + t = type_user_underlying(t); + } return t; } diff --git a/typedefs_cgen.c b/typedefs_cgen.c index d34514a..58b9767 100644 --- a/typedefs_cgen.c +++ b/typedefs_cgen.c @@ -90,7 +90,6 @@ static bool typedefs_expr(CGenerator *g, Expression *e) { } static bool typedefs_decl(CGenerator *g, Declaration *d) { - d->c.ids = NULL; for (size_t idx = 0; idx < arr_len(d->idents); idx++) { Identifier i = d->idents[idx]; Type *type = d->type.kind == TYPE_TUPLE ? &d->type.tuple[idx] : &d->type; @@ -100,15 +99,7 @@ static bool typedefs_decl(CGenerator *g, Declaration *d) { cgen_write(g, "typedef "); if (!cgen_type_pre(g, val->type, d->where)) return false; cgen_write(g, " "); - /* can we use the name directly? */ - if (!d->c.ids) - d->c.ids = evalr_calloc(g->evalr, arr_len(d->idents), sizeof *d->c.ids); - if (g->block == NULL) { - d->c.ids[idx] = 0; /* yes! */ - cgen_ident(g, i); - } else { - cgen_ident_id(g, d->c.ids[idx] = g->ident_counter++); /* no ): */ - } + cgen_ident(g, i); if (!cgen_type_post(g, val->type, d->where)) return false; cgen_write(g, ";"); cgen_nl(g); @@ -25,6 +25,8 @@ static inline bool type_is_builtin(Type *t, BuiltinType b) { static bool type_eq(Type *a, Type *b) { if (a->kind == TYPE_UNKNOWN || b->kind == TYPE_UNKNOWN) return true; /* allow things such as 3 + #C("5") */ + assert(a->flags & TYPE_FLAG_RESOLVED); + assert(b->flags & TYPE_FLAG_RESOLVED); if (a->kind != b->kind) return false; if (a->flags & TYPE_FLAG_FLEXIBLE) { if (b->flags & TYPE_FLAG_FLEXIBLE) return true; @@ -46,12 +48,11 @@ static bool type_eq(Type *a, Type *b) { case TYPE_UNKNOWN: assert(0); return false; case TYPE_TYPE: return true; case TYPE_USER: - return a->user.name == b->user.name; + return a->user.decl == b->user.decl && a->user.index == b->user.index; case TYPE_BUILTIN: return a->builtin == b->builtin; case TYPE_STRUCT: return false; case TYPE_FN: { - if (arr_len(a->fn.types) != arr_len(b->fn.types)) return false; Type *a_types = a->fn.types, *b_types = b->fn.types; for (size_t i = 0; i < arr_len(a->fn.types); i++) { @@ -378,10 +379,11 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { return false; break; case TYPE_USER: { - /* check if it's actually defined */ - IdentDecl *idecl = ident_decl(t->user.name); + /* find declaration */ + Identifier ident = t->user.ident; + IdentDecl *idecl = ident_decl(ident); if (!idecl) { - char *s = ident_to_str(t->user.name); + char *s = ident_to_str(ident); err_print(where, "Use of undeclared type %s.", s); free(s); return false; @@ -390,17 +392,21 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { /* now, type the declaration (in case we are using it before its declaration) */ if (!types_decl(tr, decl)) return false; + int index = ident_index_in_decl(ident, idecl->decl); /* make sure it's actually a type */ - if (idecl->decl->type.kind != TYPE_TYPE) { - char *s = ident_to_str(t->user.name); + if (decl_type_at_index(decl, index)->kind != TYPE_TYPE) { + char *s = ident_to_str(ident); err_print(where, "Use of non-type identifier %s as type.", s); info_print(decl->where, "%s is declared here.", s); free(s); return s; } /* resolve inner type */ - Value *val = decl_ident_val(decl, t->user.name); + Value *val = decl_val_at_index(decl, index); if (!type_resolve(tr, val->type, decl->where)) return false; + /* finally, set decl and index */ + t->user.decl = decl; + t->user.index = index; } break; case TYPE_STRUCT: arr_foreach(t->struc.fields, Field, f) { @@ -448,10 +454,10 @@ static Status type_cast_status(Type *from, Type *to) { if (to->kind == TYPE_UNKNOWN) return STATUS_NONE; if (from->kind == TYPE_USER) { - return type_eq(to, ident_typeval(from->user.name)) ? STATUS_NONE : STATUS_ERR; + return type_eq(to, type_user_underlying(from)) ? STATUS_NONE : STATUS_ERR; } if (to->kind == TYPE_USER) { - return type_eq(from, ident_typeval(to->user.name)) ? STATUS_NONE : STATUS_ERR; + return type_eq(from, type_user_underlying(to)) ? STATUS_NONE : STATUS_ERR; } switch (from->kind) { case TYPE_UNKNOWN: return STATUS_NONE; @@ -302,7 +302,14 @@ typedef struct Type { struct Type *ptr; struct Type *slice; struct { - Identifier name; + union { + struct { + struct Declaration *decl; + int index; /* index in decl */ + }; + Identifier ident; + }; + } user; struct { Field *fields; @@ -506,9 +513,6 @@ typedef struct Declaration { Expression expr; Value val; /* only for constant decls. */ - struct { - IdentID *ids; /* array of IDs used in place of ident names. unfortunately needed for user defined types. this is NOT a dynamic array, but is of length arr_len(idents). */ - } c; } Declaration; typedef enum { |