summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--6/simp.c2
-rw-r--r--lib/std/htab.myr20
-rw-r--r--parse/gram.y2
-rw-r--r--parse/infer.c85
-rw-r--r--parse/parse.h2
-rw-r--r--parse/specialize.c3
-rw-r--r--parse/type.c4
-rw-r--r--parse/use.c8
8 files changed, 97 insertions, 29 deletions
diff --git a/6/simp.c b/6/simp.c
index 28548c6..2c9ff2f 100644
--- a/6/simp.c
+++ b/6/simp.c
@@ -507,7 +507,7 @@ static Node *itertraitfn(Srcloc loc, Trait *tr, char *fn, Type *ty)
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;
diff --git a/lib/std/htab.myr b/lib/std/htab.myr
index 2833d25..fcf8457 100644
--- a/lib/std/htab.myr
+++ b/lib/std/htab.myr
@@ -213,25 +213,29 @@ generic htbykeyvals = {ht
-> [.ht = ht, .idx = 0]
}
+extern const put : (str : byte[:], args : ... -> size)
+
impl iterable htkviter(@k, @v) -> (@k, @v) =
__iternext__ = {itp, valp
var i, ht
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")
}
;;
diff --git a/parse/gram.y b/parse/gram.y
index cc69635..732ad9b 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -399,7 +399,7 @@ traitdef: Ttrait Tident generictype optauxtypes { /* trait prototype */
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;
}
}
diff --git a/parse/infer.c b/parse/infer.c
index c1f4c8b..b5a6f4f 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -211,6 +211,28 @@ static void addspecialization(Inferstate *st, Node *n, Stab *stab)
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 @@ static void structunify(Inferstate *st, Node *ctx, Type *u, Type *v)
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 @@ static void specializeimpl(Inferstate *st, Node *n)
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 void infernode(Inferstate *st, Node **np, Type *ret, int *sawret)
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 @@ static Type *tyfix(Inferstate *st, Node *ctx, Type *orig, int noerr)
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 @@ static Type *tyfix(Inferstate *st, Node *ctx, Type *orig, int noerr)
free(from);
free(to);
}
-
+ if (base)
+ htput(st->seqbase, t, base);
return t;
}
@@ -2080,7 +2103,7 @@ static void checkvar(Inferstate *st, Node *n)
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 @@ static void typesub(Inferstate *st, Node *n, int noerr)
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 @@ void tagexports(Node *file, int hidelocal)
}
+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 @@ static void specialize(Inferstate *st, Node *f)
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;
-
- /* we need to sub in default types in the specialization, so call
- * typesub on the specialized function */
- typesub(st, d, 0);
+ 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);
+ } 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();
}
}
diff --git a/parse/parse.h b/parse/parse.h
index 301b161..55b530f 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -328,7 +328,7 @@ struct Node {
impl.
*/
Trait *trait;
- Htab *__impls;
+ Htab *impls;
Node **gimpl; /* generic impls of this trait */
size_t ngimpl;
Node **gtype; /* generic impls of this trait */
diff --git a/parse/specialize.c b/parse/specialize.c
index 33f48a4..72f922f 100644
--- a/parse/specialize.c
+++ b/parse/specialize.c
@@ -116,6 +116,7 @@ Type *tyspecialize(Type *orig, Tysubst *tsmap, Htab *delayed, Htab *trbase)
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 @@ Node *bestimpl(Node *n, Type *to)
int score;
int best;
+ if (hthas(n->decl.impls, to))
+ return htget(n->decl.impls, to);
ambig = NULL;
nambig = 0;
best = -1;
diff --git a/parse/type.c b/parse/type.c
index f6cd127..d711b6b 100644
--- a/parse/type.c
+++ b/parse/type.c
@@ -856,7 +856,7 @@ void iterableinit(Stab *st, Trait *tr)
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 @@ void iterableinit(Stab *st, Trait *tr)
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;
diff --git a/parse/use.c b/parse/use.c
index f1dbb71..2033fa7 100644
--- a/parse/use.c
+++ b/parse/use.c
@@ -821,8 +821,10 @@ static void protomap(Trait *tr, Type *ty, Node *dcl)
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 @@ foundextlib:
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':