shithub: mc

Download patch

ref: 0ef6733ca5602407ccec8be6242c9a9ccd7c9cac
parent: 6950e5fccf4ebe1da730493bca2284e092b43e90
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Dec 15 18:55:12 EST 2015

Keep a list of impls for a given type.

	We want to know so we can unify in a post check.

--- a/parse/gram.y
+++ b/parse/gram.y
@@ -382,7 +382,8 @@
 	;
 
 traitdef: Ttrait Tident generictype optauxtypes { /* trait prototype */
-		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+		$$ = mktrait($1->loc,
+			mkname($2->loc, $2->id), $3,
 			$4.types, $4.ntypes,
 			NULL, 0,
 			NULL, 0,
@@ -390,7 +391,8 @@
 	}
 	| Ttrait Tident generictype optauxtypes Tasn traitbody Tendblk /* trait definition */ {
 		size_t i;
-		$$ = mktrait($1->loc, mkname($2->loc, $2->id), $3,
+		$$ = mktrait($1->loc,
+			mkname($2->loc, $2->id), $3,
 			$4.types, $4.ntypes,
 			NULL, 0,
 			$6.nl, $6.nn,
@@ -397,6 +399,7 @@
 			0);
 		for (i = 0; i < $6.nn; i++) {
 			$6.nl[i]->decl.trait = $$;
+			$6.nl[i]->decl.impls = mkht(tyhash, tyeq); 
 			$6.nl[i]->decl.isgeneric = 1;
 		}
 	}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -466,20 +466,28 @@
 	return t;
 }
 
-static Type *tysubst(Inferstate *st, Type *t, Type *orig)
+static Type *tysubstmap(Inferstate *st, Htab *subst, Type *t, Type *orig)
 {
-	Htab *subst;
 	size_t i;
 
-	subst = mkht(tyhash, tyeq);
 	for (i = 0; i < t->ngparam; i++) {
 		htput(subst, t->gparam[i], tf(st, orig->arg[i]));
 	}
 	t = tyfreshen(st, subst, t);
+	return t;
+}
+
+static Type *tysubst(Inferstate *st, Type *t, Type *orig)
+{
+	Htab *subst;
+
+	subst = mkht(tyhash, tyeq);
+	t = tysubstmap(st, subst, t, orig);
 	htfree(subst);
 	return t;
 }
 
+
 /* fixd the most accurate type mapping we have (ie,
  * the end of the unification chain */
 static Type *tf(Inferstate *st, Type *orig)
@@ -1058,16 +1066,27 @@
 
 static Type *initvar(Inferstate *st, Node *n, Node *s)
 {
-	Type *t;
+	Type *t, *param;
+	Htab *subst;
 
 	if (s->decl.ishidden)
 		fatal(n, "attempting to refer to hidden decl %s", ctxstr(st, n));
-	if (s->decl.isgeneric)
-		t = tysubst(st, tf(st, s->decl.type), s->decl.type);
-	else
+
+	param = NULL;
+	if (s->decl.isgeneric) {
+		subst = mkht(tyhash, tyeq);
+		t = tysubstmap(st, subst, tf(st, s->decl.type), s->decl.type);
+		if (s->decl.trait) {
+			param = htget(subst, s->decl.trait->param);
+			delayedcheck(st, n, curstab());
+		}
+		htfree(subst);
+	} else {
 		t = s->decl.type;
+	}
 	n->expr.did = s->decl.did;
 	n->expr.isconst = s->decl.isconst;
+	n->expr.param = param;
 	if (s->decl.isgeneric && !st->ingeneric) {
 		t = tyfreshen(st, NULL, t);
 		addspecialization(st, n, curstab());
@@ -1625,6 +1644,7 @@
 			fatal(n, "trait %s already specialized with %s on %s:%d",
 				namestr(t->name), tystr(n->impl.type),
 				fname(sym->loc), lnum(sym->loc));
+		htput(proto->decl.impls, n->impl.type, ty);
 		dcl->decl.name = name;
 		putdcl(file->file.globls, dcl);
 		if (debugopt['S'])
@@ -1971,7 +1991,11 @@
 	Type *ty;
 
 	dcl = decls[n->expr.did];
-	ty = tyfreshen(st, NULL, type(st, dcl));
+	if (n->expr.param) {
+		ty = htget(dcl->decl.impls, tf(st, n->expr.param));
+	} else {
+		ty = tyfreshen(st, NULL, type(st, dcl));
+	}
 	unify(st, n, type(st, n), ty);
 }
 
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -236,10 +236,11 @@
 		struct {
 			Op op;
 			Type *type;
+			Type *param;	/* for specialized traits, the primary param */
 			int isconst;
-			size_t did; /* for Ovar, we want a mapping to the decl id */
+			size_t did;	/* for Ovar, we want a mapping to the decl id */
 			size_t nargs;
-			Node *idx; /* used when this is in an indexed initializer */
+			Node *idx;	/* used when this is in an indexed initializer */
 			Node **args;
 		} expr;
 
@@ -317,6 +318,7 @@
 			 impl.
 			*/
 			Trait *trait;
+			Htab *impls;
 			char vis;
 
 			/* flags */