summaryrefslogtreecommitdiff
path: root/parse/specialize.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2017-07-01 14:43:22 -0700
committerOri Bernstein <ori@eigenstate.org>2017-07-03 23:27:02 -0700
commit871ef281aaf3c2e8bdff5d92355461bedfa5d933 (patch)
tree76db674822cd67fb1cd1772a8d52f40910735d00 /parse/specialize.c
parentca10a1ec838b7d468a2b43894af659c111a0e9b1 (diff)
downloadmc-871ef281aaf3c2e8bdff5d92355461bedfa5d933.tar.gz
Specialize impl declarations on impl type in addition to decl type
This allows multiple specializations of a declarations with a concrete type, which can be selected with the new impl expression if it can't be deduced by its type alone. For example trait hasname @t = Name: byte[:] ;; impl hasname void = Name = "somename" ;; impl hasname bool = Name = "othername" ;; const boolname = impl(Name, void) To do this, pass the param type through to genericname and specializedcl. Since we now need the type parameter to look up trait decls, make sure n->expr.param gets the necessary treatment in typesub, specializenode, pickle, and unpickle. We also need to tag the param types for export.
Diffstat (limited to 'parse/specialize.c')
-rw-r--r--parse/specialize.c16
1 files changed, 11 insertions, 5 deletions
diff --git a/parse/specialize.c b/parse/specialize.c
index e980587..dbc2d07 100644
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -241,7 +241,7 @@ static void fixup(Node *n)
if (!d)
die("Missing decl %s", namestr(n->expr.args[0]));
if (d->decl.isgeneric)
- d = specializedcl(d, n->expr.type, &n->expr.args[0]);
+ d = specializedcl(d, n->expr.param, n->expr.type, &n->expr.args[0]);
n->expr.did = d->decl.did;
}
break;
@@ -328,6 +328,8 @@ static Node *specializenode(Node *n, Tysubst *tsmap)
case Nexpr:
r->expr.op = n->expr.op;
r->expr.type = tysubst(n->expr.type, tsmap);
+ if (n->expr.param)
+ r->expr.param = tysubst(n->expr.param, tsmap);
r->expr.isconst = n->expr.isconst;
r->expr.nargs = n->expr.nargs;
r->expr.idx = specializenode(n->expr.idx, tsmap);
@@ -435,7 +437,7 @@ static Node *specializenode(Node *n, Tysubst *tsmap)
return r;
}
-Node *genericname(Node *n, Type *t)
+Node *genericname(Node *n, Type *param, Type *t)
{
char buf[1024];
char *p;
@@ -447,6 +449,10 @@ Node *genericname(Node *n, Type *t)
p = buf;
end = buf + sizeof buf;
p += bprintf(p, end - p, "%s", n->decl.name->name.name);
+ if (param) {
+ p += bprintf(p, end - p, "$");
+ p += tyidfmt(p, end - p, param);
+ }
p += bprintf(p, end - p, "$");
p += tyidfmt(p, end - p, t);
name = mkname(n->loc, buf);
@@ -574,7 +580,7 @@ Node *bestimpl(Node *n, Type *to)
* duplicate of it with type 'to'. It also generates
* a name for this specialized node, and returns it in '*name'.
*/
-Node *specializedcl(Node *gnode, Type *to, Node **name)
+Node *specializedcl(Node *gnode, Type *param, Type *to, Node **name)
{
extern int stabstkoff;
Tysubst *tsmap;
@@ -584,7 +590,7 @@ Node *specializedcl(Node *gnode, Type *to, Node **name)
assert(gnode->type == Ndecl);
assert(gnode->decl.isgeneric);
- n = genericname(gnode, to);
+ n = genericname(gnode, param, to);
*name = n;
if (n->name.ns)
st = getns(file, n->name.ns);
@@ -598,7 +604,7 @@ Node *specializedcl(Node *gnode, Type *to, Node **name)
if (gnode->decl.trait) {
g = bestimpl(gnode, to);
if (!g)
- fatal(gnode, "no trait implemented for %s:%s", namestr(gnode->decl.name), tystr(to));
+ fatal(gnode, "type %s does not implement %s:%s", tystr(param), namestr(gnode->decl.name), tystr(to));
} else {
g = gnode;
}