summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--identifiers.c3
-rw-r--r--parse.c7
-rw-r--r--types.c32
3 files changed, 29 insertions, 13 deletions
diff --git a/identifiers.c b/identifiers.c
index d86dba1..a9b4540 100644
--- a/identifiers.c
+++ b/identifiers.c
@@ -177,8 +177,7 @@ static void idents_test(void) {
idents_free(&ids);
}
-
-static inline Type *ident_typeval(Identifier i) {
+static Type *ident_typeval(Identifier i) {
Value *val;
IdentDecl *idecl = ident_decl(i);
if (!idecl) return NULL;
diff --git a/parse.c b/parse.c
index 618336a..6ea1362 100644
--- a/parse.c
+++ b/parse.c
@@ -1973,3 +1973,10 @@ 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;
+}
diff --git a/types.c b/types.c
index b64fb36..a370ba9 100644
--- a/types.c
+++ b/types.c
@@ -362,21 +362,31 @@ static bool type_resolve(Typer *tr, Type *t, Location where) {
if (!type_resolve(tr, t->slice, where))
return false;
break;
- case TYPE_USER:
- /* just check if it's actually defined */
- if (!ident_typeval(t->user.name)) {
+ case TYPE_USER: {
+ /* check if it's actually defined */
+ IdentDecl *idecl = ident_decl(t->user.name);
+ if (!idecl) {
char *s = ident_to_str(t->user.name);
- IdentDecl *idecl = ident_decl(t->user.name);
- if (idecl) {
- err_print(where, "Use of non-type identifier %s as type.", s);
- info_print(idecl->decl->where, "%s is declared here.", s);
- } else {
- err_print(where, "Use of undeclared type %s.", s);
- }
+ err_print(where, "Use of undeclared type %s.", s);
free(s);
return false;
}
- break;
+ Declaration *decl = idecl->decl;
+ /* now, type the declaration (in case we are using it before its declaration) */
+ if (!types_decl(tr, decl))
+ return false;
+ /* make sure it's actually a type */
+ if (idecl->decl->type.kind != TYPE_TYPE) {
+ char *s = ident_to_str(t->user.name);
+ 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);
+ if (!type_resolve(tr, val->type, decl->where)) return false;
+ } break;
case TYPE_STRUCT:
arr_foreach(t->struc.fields, Field, f) {
if (!type_resolve(tr, f->type, where))