shithub: mc

Download patch

ref: 03857943018a82e1101cecbb026b5e11f4061dc5
parent: 061c7f286ebf2ee6e0afb0a0fb2b90397b848e23
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Feb 6 17:38:29 EST 2016

Generic iterators now seem to work.

--- a/6/simp.c
+++ b/6/simp.c
@@ -507,7 +507,7 @@
 		name = declname(tr->funcs[i]);
 		if (!strcmp(fn, name)) {
 			proto = tr->funcs[i];
-			dcl = htget(proto->decl.__impls, ty);
+			dcl = htget(proto->decl.impls, ty);
 			var = mkexpr(loc, Ovar, dcl->decl.name, NULL);
 			var->expr.type = codetype(dcl->decl.type);
 			var->expr.did = dcl->decl.did;
--- a/lib/std/htab.myr
+++ b/lib/std/htab.myr
@@ -213,6 +213,8 @@
 	-> [.ht = ht, .idx = 0]
 }
 
+extern const put	: (str : byte[:], args : ... -> size)
+
 impl iterable htkviter(@k, @v) -> (@k, @v) =
 	__iternext__ = {itp, valp
 		var i, ht
@@ -219,19 +221,21 @@
 
 		ht = itp.ht
 		for i = itp.idx; i < ht.keys.len; i++
+			std.put("i: {}, ht.hashes[{}]: {}, ht.keys[{}]: {}, ht.dead[{}]: {}\n", \
+				i, i, ht.hashes[i], i, ht.keys[i], i, ht.dead[i])
 			if ht.hashes[i] != 0 && !ht.dead[i]
-				break
+				itp.idx = i + 1
+				valp# = (ht.keys[i], ht.vals[i])
+				std.put("....returning true\n")
+				-> true
 			;;
 		;;
+		std.put("returning false\n")
 		itp.idx = i
-		if i < ht.hashes.len
-			valp# = (ht.keys[i], ht.vals[i])
-			-> true
-		else
-			-> false
-		;;
+		-> false
 	}
 
-	__iterfin__ = {itp, valp
+	__iterfin__ = {itp, valp -> void
+		std.put("fin\n")
 	}
 ;;
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -399,7 +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.impls = mkht(tyhash, tyeq); 
 			$6.nl[i]->decl.isgeneric = 1;
 		}
 	}
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -211,6 +211,28 @@
 	lappend(&st->genericdecls, &st->ngenericdecls, dcl);
 }
 
+static void additerspecializations(Inferstate *st, Node *n, Stab *stab)
+{
+	Trait *tr;
+	Type *ty;
+	size_t i;
+
+	tr = traittab[Tciter];
+	ty = exprtype(n->iterstmt.seq);
+	if (!ty->traits || !bshas(ty->traits, Tciter))
+		return;
+	if (ty->type == Tyslice || ty->type == Tyarray || ty->type == Typtr)
+		return;
+	for (i = 0; i < tr->nfuncs; i++) {
+		ty = exprtype(n->iterstmt.seq);
+		if (hthas(tr->funcs[i]->decl.impls, ty))
+			continue;
+		lappend(&st->specializationscope, &st->nspecializationscope, stab);
+		lappend(&st->specializations, &st->nspecializations, n);
+		lappend(&st->genericdecls, &st->ngenericdecls, tr->funcs[i]);
+	}
+}
+
 static void delayedcheck(Inferstate *st, Node *n, Stab *s)
 {
 	lappend(&st->postcheck, &st->npostcheck, n);
@@ -853,7 +875,6 @@
 			vd = namestr(v->sdecls[j]->decl.name);
 			if (strcmp(ud, vd) == 0) {
 				found = 1;
-				//printf("unifying member %s and %s\n", tystr(type(st, u->sdecls[i])), tystr(type(st, v->sdecls[j])));
 				unify(st, ctx, type(st, u->sdecls[i]), type(st, v->sdecls[j]));
 			}
 		}
@@ -1710,7 +1731,7 @@
 				fname(sym->loc), lnum(sym->loc));
 		dcl->decl.name = name;
 		putdcl(file->file.globls, dcl);
-		htput(proto->decl.__impls, n->impl.type, dcl);
+		htput(proto->decl.impls, n->impl.type, dcl);
 		dcl->decl.isconst = 1;
 		if (n->impl.type->type == Tygeneric || hasparams(n->impl.type)) {
 			dcl->decl.isgeneric = 1;
@@ -1908,7 +1929,7 @@
 static Type *tyfix(Inferstate *st, Node *ctx, Type *orig, int noerr)
 {
 	static Type *tyint, *tyflt;
-	Type *t, *delayed;
+	Type *t, *delayed, *base;
 	char *from, *to;
 	size_t i;
 	char buf[1024];
@@ -1919,6 +1940,7 @@
 		tyflt = mktype(Zloc, Tyflt64);
 
 	t = tysearch(orig);
+	base = htget(st->seqbase, orig);
 	if (orig->type == Tyvar && hthas(st->delayed, orig)) {
 		delayed = htget(st->delayed, orig);
 		if (t->type == Tyvar)
@@ -1970,7 +1992,8 @@
 		free(from);
 		free(to);
 	}
-
+	if (base)
+		htput(st->seqbase, t, base);
 	return t;
 }
 
@@ -2080,7 +2103,7 @@
 	ty = NULL;
 	dcl = NULL;
 	if (n->expr.param)
-		dcl = htget(proto->decl.__impls, tf(st, n->expr.param));
+		dcl = htget(proto->decl.impls, tf(st, n->expr.param));
 	if (dcl)
 		ty = dcl->decl.type;
 	if (!ty)
@@ -2255,6 +2278,7 @@
 		typesub(st, n->iterstmt.elt, noerr);
 		typesub(st, n->iterstmt.seq, noerr);
 		typesub(st, n->iterstmt.body, noerr);
+		additerspecializations(st, n, curstab());
 		break;
 	case Nmatchstmt:
 		typesub(st, n->matchstmt.val, noerr);
@@ -2514,13 +2538,31 @@
 
 }
 
+static Type *itertype(Inferstate *st, Node *n, Type *ret)
+{
+	Type *it, *val, *itp, *valp, *fn;
+
+	it = exprtype(n);
+	itp = mktyptr(n->loc, it);
+	val = basetype(st, it);
+	if (!val)
+		die("FAIL! %s", tystr(it));
+	valp = mktyptr(n->loc, val);
+	fn = mktyfunc(n->loc, NULL, 0, ret);
+	lappend(&fn->sub, &fn->nsub, itp);
+	lappend(&fn->sub, &fn->nsub, valp);
+	return fn;
+}
+
 /* Take generics and build new versions of them
  * with the type parameters replaced with the
  * specialized types */
 static void specialize(Inferstate *st, Node *f)
 {
-	Node *d, *name;
+	Node *d, *n, *name;
+	Type *ty, *it;
 	size_t i;
+	Trait *tr;
 
 	for (i = 0; i < st->nimpldecl; i++) {
 		d = st->impldecl[i];
@@ -2530,13 +2572,30 @@
 
 	for (i = 0; i < st->nspecializations; i++) {
 		pushstab(st->specializationscope[i]);
-		d = specializedcl(st->genericdecls[i], st->specializations[i]->expr.type, &name);
-		st->specializations[i]->expr.args[0] = name;
-		st->specializations[i]->expr.did = d->decl.did;
+		n = st->specializations[i];
+		if (n->type == Nexpr) {
+			d = specializedcl(st->genericdecls[i], n->expr.type, &name);
+			n->expr.args[0] = name;
+			n->expr.did = d->decl.did;
 
-		/* we need to sub in default types in the specialization, so call
-		 * typesub on the specialized function */
-		typesub(st, d, 0);
+			/* we need to sub in default types in the specialization, so call
+			 * typesub on the specialized function */
+			typesub(st, d, 0);
+		} else if (n->type == Niterstmt) {
+			tr = traittab[Tciter];
+			assert(tr->nfuncs == 2);
+			ty = exprtype(n->iterstmt.seq);
+
+			it = itertype(st, n->iterstmt.seq, mktype(n->loc, Tybool));
+			d = specializedcl(tr->funcs[0], it, &name);
+			htput(tr->funcs[0]->decl.impls, ty, d);
+
+			it = itertype(st, n->iterstmt.seq, mktype(n->loc, Tyvoid));
+			d = specializedcl(tr->funcs[1], it, &name);
+			htput(tr->funcs[1]->decl.impls, ty, d);
+		} else {
+			die("unknown node for specialization\n");
+		}
 		popstab();
 	}
 }
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -328,7 +328,7 @@
 			 impl.
 			*/
 			Trait *trait;
-			Htab *__impls;
+			Htab *impls;
 			Node **gimpl; /* generic impls of this trait */
 			size_t ngimpl;
 			Node **gtype; /* generic impls of this trait */
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -116,6 +116,7 @@
 		ret->issynth = 1;
 		ret->arg = arg;
 		ret->narg = narg;
+		ret->traits = bsdup(t->traits);
 		tytab[var->tid] = ret;
 		break;
 	case Tyname:
@@ -543,6 +544,8 @@
 	int score;
 	int best;
 
+	if (hthas(n->decl.impls, to))
+		return htget(n->decl.impls, to);
 	ambig = NULL;
 	nambig = 0;
 	best = -1;
--- a/parse/type.c
+++ b/parse/type.c
@@ -856,7 +856,7 @@
 
 	func = mkdecl(Zloc, mkname(Zloc, "__iternext__"), ty);
 	func->decl.trait = tr;
-	func->decl.__impls = mkht(tyhash, tyeq); 
+	func->decl.impls = mkht(tyhash, tyeq); 
 	func->decl.isgeneric = 1;
 	func->decl.isconst = 1;
 	func->decl.isglobl = 1;
@@ -876,7 +876,7 @@
 
 	func = mkdecl(Zloc, mkname(Zloc, "__iterfin__"), ty);
 	func->decl.trait = tr;
-	func->decl.__impls = mkht(tyhash, tyeq); 
+	func->decl.impls = mkht(tyhash, tyeq); 
 	func->decl.isgeneric = 1;
 	func->decl.isconst = 1;
 	func->decl.isglobl = 1;
--- a/parse/use.c
+++ b/parse/use.c
@@ -821,8 +821,10 @@
 		protoname = declname(proto);
 		len = strlen(protoname);
 		p = strstr(dclname, protoname);
-		if (p && p[len] == '$')
-			htput(proto->decl.__impls, ty, dcl);
+		if (!p || p[len] != '$') {
+			continue;
+		}
+		htput(proto->decl.impls, ty, dcl);
 		if (ty->type == Tygeneric || hasparams(ty)) {
 			lappend(&proto->decl.gimpl, &proto->decl.ngimpl, dcl);
 			lappend(&proto->decl.gtype, &proto->decl.ngtype, ty);
@@ -954,7 +956,7 @@
 			  puttrait(s, tr->name, tr);
 			  for (i = 0; i < tr->nfuncs; i++) {
 				  putdcl(s, tr->funcs[i]);
-				  tr->funcs[i]->decl.__impls = mkht(tyhash, tyeq);
+				  tr->funcs[i]->decl.impls = mkht(tyhash, tyeq);
 			  }
 			  break;
 		case 'T':