shithub: mc

Download patch

ref: 67e077fe5811a7bc218cb58de5a32e337417268c
parent: 8bcba75efd9dd84da2ba9d9634d456d960580f68
author: Ori Bernstein <ori@eigenstate.org>
date: Sun Dec 20 19:14:33 EST 2015

Iterable traits pass the frontend.

	The backend still needs to lower them, but this is relatively
	easy.

--- a/6/simp.c
+++ b/6/simp.c
@@ -449,7 +449,7 @@
  *           cjmp (match) :body :step
  *      :end
  */
-static void simpiter(Simp *s, Node *n)
+static void simpidxiter(Simp *s, Node *n)
 {
 	Node *lbody, *lload, *lstep, *lcond, *lmatch, *lend;
 	Node *idx, *len, *dcl, *seq, *val, *done;
@@ -508,6 +508,36 @@
 
 	s->nloopstep--;
 	s->nloopexit--;
+}
+
+/* for pat in seq
+ * 	body;;
+ * =>
+ * 	.seq = seq
+ * 	.elt = elt
+ * 	:body
+ * 		..body..
+ * 		__iterfin__(&seq, &elt)
+ * 	:step
+ * 		cond = __iternext__(&seq, &eltout)
+ * 		cjmp (cond) :match :end
+ * 	:match
+ * 		...match...
+ * 		cjmp (match) :body :step
+ * 	:end
+ */
+static void simptraititer(Simp *s, Node *n)
+{
+	die("unimplemented");
+}
+
+static void simpiter(Simp *s, Node *n)
+{
+	switch (tybase(exprtype(n->iterstmt.seq))->type) {
+	case Tyarray:	simpidxiter(s, n);	break;
+	case Tyslice:	simpidxiter(s, n);	break;
+	default:	simptraititer(s, n);	break;
+	}
 }
 
 static Node *uconid(Simp *s, Node *n)
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -40,6 +40,8 @@
 	/* delayed unification -- we fall back to these types in a post pass if we
 	 * haven't unifed to something more specific */
 	Htab *delayed;
+	/* mappings from iterator type to element type */
+	Htab *seqbase;
 	/* the nodes that we've specialized them to, and the scopes they
 	 * appear in */
 	Node **specializations;
@@ -786,15 +788,6 @@
 }
 
 /* Tells us if we have an index hack on the type */
-static int idxhacked(Type *a, Type *b)
-{
-	if (a->type == Tyvar && a->nsub > 0)
-		return 1;
-	if (a->type == Tyarray || a->type == Tyslice)
-		return a->type == b->type;
-	return 0;
-}
-
 /* prevents types that contain themselves in the unification;
  * eg @a U (@a -> foo) */
 static int occurs(Type *a, Type *b)
@@ -813,14 +806,15 @@
  * direction should we unify. A lower ranked type
  * should be mapped to the higher ranked (ie, more
  * specific) type. */
-static int tyrank(Type *t)
+static int tyrank(Inferstate *st, Type *t)
 {
 	/* plain tyvar */
-	if (t->type == Tyvar && t->nsub == 0)
-		return 0;
-	/* parameterized tyvar */
-	if (t->type == Tyvar && t->nsub > 0)
-		return 1;
+	if (t->type == Tyvar) {
+		if (hthas(st->seqbase, t))
+			return 1;
+		else
+			return 0;
+	}
 	/* concrete type */
 	return 2;
 }
@@ -892,11 +886,25 @@
 		structunify(st, ctx, u, v);
 }
 
+static Type *basetype(Inferstate *st, Type *a)
+{
+	Type *t;
+
+	if (a->nsub == 1)
+		t = a->sub[0];
+	else
+		t = htget(st->seqbase, a);
+	if (t)
+		t = tf(st, t);
+	return t;
+}
+
 /* Unifies two types, or errors if the types are not unifiable. */
 static Type *unify(Inferstate *st, Node *ctx, Type *u, Type *v)
 {
 	Type *t, *r;
 	Type *a, *b;
+	Type *ea, *eb;
 	char *from, *to;
 	size_t i;
 
@@ -907,7 +915,7 @@
 		return a;
 
 	/* we unify from lower to higher ranked types */
-	if (tyrank(b) < tyrank(a)) {
+	if (tyrank(st, b) < tyrank(st, a)) {
 		t = a;
 		a = b;
 		b = t;
@@ -917,6 +925,8 @@
 		from = tystr(a);
 		to = tystr(b);
 		indentf(st->indentdepth, "Unify %s => %s\n", from, to);
+		indentf(st->indentdepth + 1, "indexes: %s => %s\n",
+				tystr(htget(st->seqbase, a)), tystr(htget(st->seqbase, b)));
 		free(from);
 		free(to);
 	}
@@ -924,6 +934,10 @@
 	r = NULL;
 	if (a->type == Tyvar) {
 		tytab[a->tid] = b;
+		ea = basetype(st, a);
+		eb = basetype(st, b);
+		if (ea && eb)
+			unify(st, ctx, ea, eb);
 		r = b;
 	}
 
@@ -935,7 +949,7 @@
 
 	/* if the tyrank of a is 0 (ie, a raw tyvar), just unify.
 	 * Otherwise, match up subtypes. */
-	if ((a->type == b->type || idxhacked(a, b)) && tyrank(a) != 0) {
+	if (a->type == b->type && a->type != Tyvar) {
 		if (hasparam(a) && hasparam(b)) {
 			/* Only Tygeneric and Tyname should be able to unify. And they
 			 * should have the same names for this to be true. */
@@ -957,8 +971,7 @@
 		for (i = 0; i < b->nsub; i++)
 			unify(st, ctx, a->sub[i], b->sub[i]);
 		r = b;
-	}
-	else if (a->type != Tyvar) {
+	} else if (a->type != Tyvar) {
 		typeerror(st, a, b, ctx, NULL);
 	}
 	mergetraits(st, ctx, a, b);
@@ -1312,7 +1325,7 @@
 	Node **args;
 	size_t i, nargs;
 	Node *s, *n;
-	Type *t;
+	Type *t, *b;
 	int isconst;
 
 	n = *np;
@@ -1416,19 +1429,23 @@
 		break;
 	case Oidx: /* @a[@b::tcint] -> @a */
 		infersub(st, n, ret, sawret, &isconst);
-		t = mktyidxhack(n->loc, mktyvar(n->loc));
+		b = mktyvar(n->loc);
+		t = mktyvar(n->loc);
+		htput(st->seqbase, t, b);
 		unify(st, n, type(st, args[0]), t);
 		constrain(st, n, type(st, args[0]), traittab[Tcidx]);
 		constrain(st, n, type(st, args[1]), traittab[Tcint]);
-		settype(st, n, t->sub[0]);
+		settype(st, n, b);
 		break;
 	case Oslice: /* @a[@b::tcint,@b::tcint] -> @a[,] */
 		infersub(st, n, ret, sawret, &isconst);
-		t = mktyidxhack(n->loc, mktyvar(n->loc));
+		b = mktyvar(n->loc);
+		t = mktyvar(n->loc);
+		htput(st->seqbase, t, b);
 		unify(st, n, type(st, args[0]), t);
 		constrain(st, n, type(st, args[1]), traittab[Tcint]);
 		constrain(st, n, type(st, args[2]), traittab[Tcint]);
-		settype(st, n, mktyslice(n->loc, t->sub[0]));
+		settype(st, n, mktyslice(n->loc, b));
 		break;
 
 		/* special cases */
@@ -1693,7 +1710,7 @@
 {
 	size_t i, nbound;
 	Node **bound, *n, *pat;
-	Type *t;
+	Type *t, *b;
 
 	n = *np;
 	if (!n)
@@ -1755,10 +1772,12 @@
 		infernode(st, &n->iterstmt.seq, NULL, sawret);
 		infernode(st, &n->iterstmt.body, ret, sawret);
 
-		t = mktyidxhack(n->loc, mktyvar(n->loc));
+		b = mktyvar(n->loc);
+		t = mktyvar(n->loc);
+		htput(st->seqbase, t, b);
 		constrain(st, n, type(st, n->iterstmt.seq), traittab[Tciter]);
 		unify(st, n, type(st, n->iterstmt.seq), t);
-		unify(st, n, type(st, n->iterstmt.elt), t->sub[0]);
+		unify(st, n, type(st, n->iterstmt.elt), b);
 		break;
 	case Nmatchstmt:
 		infernode(st, &n->matchstmt.val, NULL, sawret);
@@ -2422,7 +2441,7 @@
 {
 	size_t i;
 	Node *n;
-	Trait *trait;
+	Trait *tr;
 	Type *ty;
 
 	pushstab(f->file.globls);
@@ -2430,12 +2449,15 @@
 	for (i = 0; i < f->file.nstmts; i++) {
 		if (f->file.stmts[i]->type == Nimpl) {
 			n = f->file.stmts[i];
-			trait = gettrait(f->file.globls, n->impl.traitname);
-			if (!trait)
+			tr = gettrait(f->file.globls, n->impl.traitname);
+			if (!tr)
 				fatal(n, "trait %s does not exist near %s",
 					namestr(n->impl.traitname), ctxstr(st, n));
 			ty = tf(st, n->impl.type);
-			settrait(ty, trait);
+			settrait(ty, tr);
+			if (tr->uid == Tciter) {
+				htput(st->seqbase, tf(st, n->impl.type), tf(st, n->impl.aux[0]));
+			}
 		}
 	}
 	popstab();
@@ -2467,6 +2489,7 @@
 
 	assert(file->type == Nfile);
 	st.delayed = mkht(tyhash, tyeq);
+	st.seqbase = mkht(tyhash, tyeq);
 	/* set up the symtabs */
 	loaduses(file);
 	// mergeexports(&st, file);
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -522,7 +522,6 @@
 Type *mktyunres(Srcloc l, Node *name, Type **params, size_t nparams);
 Type *mktyarray(Srcloc l, Type *base, Node *sz);
 Type *mktyslice(Srcloc l, Type *base);
-Type *mktyidxhack(Srcloc l, Type *base);
 Type *mktyptr(Srcloc l, Type *base);
 Type *mktytuple(Srcloc l, Type **sub, size_t nsub);
 Type *mktyfunc(Srcloc l, Node **args, size_t nargs, Type *ret);
--- a/parse/type.c
+++ b/parse/type.c
@@ -237,17 +237,6 @@
 	return t;
 }
 
-Type *mktyidxhack(Srcloc loc, Type *base)
-{
-	Type *t;
-
-	t = mktype(loc, Tyvar);
-	t->nsub = 1;
-	t->sub = xalloc(sizeof(Type *));
-	t->sub[0] = base;
-	return t;
-}
-
 Type *mktyptr(Srcloc loc, Type *base)
 {
 	Type *t;