summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cgen.c21
-rw-r--r--eval.c39
-rw-r--r--identifiers.c10
-rw-r--r--parse.c18
-rw-r--r--test.toc2
-rw-r--r--toc.c12
-rw-r--r--typedefs_cgen.c11
-rw-r--r--types.c26
-rw-r--r--types.h12
9 files changed, 80 insertions, 71 deletions
diff --git a/cgen.c b/cgen.c
index 8d31ece..39a56c3 100644
--- a/cgen.c
+++ b/cgen.c
@@ -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;
}
diff --git a/eval.c b/eval.c
index 43cb309..bccc7c2 100644
--- a/eval.c
+++ b/eval.c
@@ -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);
diff --git a/parse.c b/parse.c
index a01dce8..5dc9601 100644
--- a/parse.c
+++ b/parse.c
@@ -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;
+}
+
diff --git a/test.toc b/test.toc
index 99c5235..c54be5f 100644
--- a/test.toc
+++ b/test.toc
@@ -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 }));
};
diff --git a/toc.c b/toc.c
index 85c0404..c7dc473 100644
--- a/toc.c
+++ b/toc.c
@@ -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);
diff --git a/types.c b/types.c
index 1c0bf9c..b831f05 100644
--- a/types.c
+++ b/types.c
@@ -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;
diff --git a/types.h b/types.h
index 2358f45..2ddd648 100644
--- a/types.h
+++ b/types.h
@@ -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 {