summaryrefslogtreecommitdiff
path: root/parse/infer.c
diff options
context:
space:
mode:
authorS. Gilles <sgilles@math.umd.edu>2018-03-13 10:53:55 -0400
committerS. Gilles <sgilles@math.umd.edu>2018-03-13 10:53:55 -0400
commit599feae2daa1392f20e1dc807c58bcd74c20b45e (patch)
treea358d75af648afa2aa08a465c374ef32210c48ab /parse/infer.c
parent5e1154d69efc86f5fe3831b047e3531d9cfd3478 (diff)
parent2c113af58d9f63bc4f720adbb6aa8ac2cae52781 (diff)
downloadmc-599feae2daa1392f20e1dc807c58bcd74c20b45e.tar.gz
Merge branch 'autoexpr' into libmath
Diffstat (limited to 'parse/infer.c')
-rw-r--r--parse/infer.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/parse/infer.c b/parse/infer.c
index 5424be9..bb1ea59 100644
--- a/parse/infer.c
+++ b/parse/infer.c
@@ -260,7 +260,7 @@ adddispspecialization(Node *n, Stab *stab)
Type *ty;
tr = traittab[Tcdisp];
- ty = decltype(n);
+ ty = exprtype(n);
assert(tr->nproto == 1);
if (hthas(tr->proto[0]->decl.impls, ty))
return;
@@ -880,7 +880,7 @@ tryconstrain(Type *base, Trait *tr, int update)
if (update)
bsput(ty->trneed, tr->uid);
return 1;
- }
+ }
if (bshas(tm->traits, tr->uid))
return 1;
if (tm->name && ty->type == Tyname) {
@@ -1637,6 +1637,13 @@ inferexpr(Node **np, Type *ret, int *sawret)
infernode(&n->expr.idx, NULL, NULL);
n = checkns(n, np);
switch (exprop(n)) {
+ case Oauto: /* @a -> @a */
+ infersub(n, ret, sawret, &isconst);
+ t = type(args[0]);
+ constrain(n, t, traittab[Tcdisp]);
+ n->expr.isconst = isconst;
+ settype(n, t);
+ break;
/* all operands are same type */
case Oadd: /* @a + @a -> @a */
case Osub: /* @a - @a -> @a */
@@ -2054,8 +2061,6 @@ infernode(Node **np, Type *ret, int *sawret)
inferdecl(n);
if (hasparams(type(n)) && !ingeneric)
fatal(n, "generic type in non-generic near %s", ctxstr(n));
- if (n->decl.isauto)
- constrain(n, type(n), traittab[Tcdisp]);
popenv(n->decl.env);
indentdepth--;
if (n->decl.isgeneric)
@@ -2614,8 +2619,6 @@ typesub(Node *n, int noerr)
if (streq(declname(n), "__init__"))
if (!initcompatible(tybase(decltype(n))))
fatal(n, "__init__ must be (->void), got %s", tystr(decltype(n)));
- if (n->decl.isauto)
- adddispspecialization(n, curstab());
popenv(n->decl.env);
break;
case Nblock:
@@ -2662,6 +2665,8 @@ typesub(Node *n, int noerr)
settype(n->expr.args[0], exprtype(n));
settype(n->expr.args[0]->expr.args[0], exprtype(n));
}
+ if (exprop(n) == Oauto)
+ adddispspecialization(n, curstab());
for (i = 0; i < n->expr.nargs; i++)
typesub(n->expr.args[i], noerr);
if (!noerr)
@@ -2727,7 +2732,15 @@ specialize(void)
for (i = 0; i < nspecializations; i++) {
pushstab(specializationscope[i]);
n = specializations[i];
- if (n->type == Nexpr) {
+ if (n->type == Nexpr && exprop(n) == Oauto) {
+ tr = traittab[Tcdisp];
+ assert(tr->nproto == 1);
+ ty = exprtype(n);
+ dt = mktyfunc(n->loc, NULL, 0, mktype(n->loc, Tyvoid));
+ lappend(&dt->sub, &dt->nsub, ty);
+ d = specializedcl(tr->proto[0], ty, dt, &name);
+ htput(tr->proto[0]->decl.impls, ty, d);
+ } else if (n->type == Nexpr && exprop(n) == Ovar) {
d = specializedcl(genericdecls[i], n->expr.param, n->expr.type, &name);
n->expr.args[0] = name;
n->expr.did = d->decl.did;
@@ -2749,14 +2762,6 @@ specialize(void)
it = itertype(n->iterstmt.seq, mktype(n->loc, Tyvoid));
d = specializedcl(tr->proto[1], ty, it, &name);
htput(tr->proto[1]->decl.impls, ty, d);
- } else if (n->type == Ndecl && n->decl.isauto) {
- tr = traittab[Tcdisp];
- assert(tr->nproto == 1);
- ty = decltype(n);
- dt = mktyfunc(n->loc, NULL, 0, mktype(n->loc, Tyvoid));
- lappend(&dt->sub, &dt->nsub, ty);
- d = specializedcl(tr->proto[0], ty, dt, &name);
- htput(tr->proto[0]->decl.impls, ty, d);
} else {
die("unknown node for specialization\n");
}