diff options
author | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-20 15:32:45 -0500 |
---|---|---|
committer | Leo Tenenbaum <pommicket@gmail.com> | 2019-11-20 15:32:45 -0500 |
commit | 28f41395337955c0d990a07bcae779dde01cf09d (patch) | |
tree | 91154a57b1544c283222bb9555d5d7f7e24096a6 | |
parent | ce130e8da7f41400a9ff45b3d30d34930ce31feb (diff) |
started to turn type parameters into aliases
-rw-r--r-- | parse.c | 2 | ||||
-rw-r--r-- | test.toc | 1 | ||||
-rw-r--r-- | types.c | 18 | ||||
-rw-r--r-- | types.h | 3 |
4 files changed, 22 insertions, 2 deletions
@@ -822,6 +822,8 @@ static bool parse_fn_expr(Parser *p, FnExpr *f) { } else { if (!parse_decl_list(p, &f->params, DECL_END_RPAREN_COMMA)) return false; + arr_foreach(f->params, Declaration, param) + param->flags |= DECL_IS_PARAM; } if (t->token->kind == TOKEN_EOF) { @@ -12,6 +12,7 @@ puti @= fn(x: int) { main @= fn() { puti(g(int)); puti(g()); + puti(g(u8)); }; g @= fn(t @= int) int { @@ -27,6 +27,13 @@ static bool type_eq(Type *a, Type *b) { return true; /* allow things such as 3 + #C("5") */ assert(a->flags & TYPE_IS_RESOLVED); assert(b->flags & TYPE_IS_RESOLVED); + + if (a->kind == TYPE_USER && a->user.is_alias) + return type_eq(type_user_underlying(a), b); + if (b->kind == TYPE_USER && b->user.is_alias) + return type_eq(a, type_user_underlying(b)); + + if (a->kind != b->kind) return false; if (a->flags & TYPE_IS_FLEXIBLE) { if (b->flags & TYPE_IS_FLEXIBLE) return true; @@ -464,6 +471,9 @@ static bool type_resolve(Typer *tr, Type *t, Location where) { /* finally, set decl and index */ t->user.decl = decl; t->user.index = index; + if (decl->flags & DECL_IS_PARAM) { + t->user.is_alias = true; /* type parameters are aliases */ + } } break; case TYPE_STRUCT: arr_foreach(t->struc.fields, Field, f) { @@ -511,9 +521,15 @@ 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, type_user_underlying(from)) ? STATUS_NONE : STATUS_ERR; + if (from->user.is_alias) { + return type_cast_status(type_user_underlying(from), to); + } + return type_eq(type_user_underlying(from), to) ? STATUS_NONE : STATUS_ERR; } if (to->kind == TYPE_USER) { + if (to->user.is_alias) { + return type_cast_status(from, type_user_underlying(to)); + } return type_eq(from, type_user_underlying(to)) ? STATUS_NONE : STATUS_ERR; } switch (from->kind) { @@ -354,7 +354,7 @@ typedef struct Type { }; Identifier ident; }; - + bool is_alias; /* is this an alias for a type, rather than a new type */ } user; struct { Field *fields; @@ -613,6 +613,7 @@ enum { DECL_FOUND_TYPE = 0x10, DECL_ERRORED_ABOUT_SELF_REFERENCE = 0x20, /* has there been an error about this decl referencing itself? */ DECL_FOUND_VAL = 0x40, + DECL_IS_PARAM = 0x80 }; /* OPTIM: Instead of using dynamic arrays, do two passes. */ |