summaryrefslogtreecommitdiff
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
parent5e1154d69efc86f5fe3831b047e3531d9cfd3478 (diff)
parent2c113af58d9f63bc4f720adbb6aa8ac2cae52781 (diff)
downloadmc-599feae2daa1392f20e1dc807c58bcd74c20b45e.tar.gz
Merge branch 'autoexpr' into libmath
-rw-r--r--6/isel.c5
-rw-r--r--mi/flatten.c49
-rw-r--r--parse/dump.c1
-rw-r--r--parse/gram.y15
-rw-r--r--parse/infer.c35
-rw-r--r--parse/ops.def2
-rw-r--r--parse/parse.h7
-rw-r--r--parse/stab.c4
-rw-r--r--test/pkgtrait.myr3
9 files changed, 65 insertions, 56 deletions
diff --git a/6/isel.c b/6/isel.c
index bd122b7..9abe40e 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -939,8 +939,9 @@ selexpr(Isel *s, Node *n)
/* These operators should never show up in the reduced trees,
* since they should have been replaced with more primitive
* expressions by now */
- case Obad: case Opreinc: case Opostinc: case Opredec: case Otern:
- case Opostdec: case Olor: case Oland: case Oaddeq:
+<<<<<<< HEAD
+ case Obad: case Oauto: case Opreinc: case Opostinc: case Opredec:
+ case Otern: case Opostdec: case Olor: case Oland: case Oaddeq:
case Osubeq: case Omuleq: case Odiveq: case Omodeq: case Oboreq:
case Obandeq: case Obxoreq: case Obsleq: case Obsreq: case Omemb:
case Oslbase: case Osllen: case Ocast: case Outag: case Oudata:
diff --git a/mi/flatten.c b/mi/flatten.c
index aba73cd..fd1c389 100644
--- a/mi/flatten.c
+++ b/mi/flatten.c
@@ -114,10 +114,10 @@ islbl(Node *n)
static Node *
temp(Flattenctx *flatten, Node *e)
{
- Node *t, *dcl;
+ Node *t;
assert(e->type == Nexpr);
- t = gentemp(e->loc, e->expr.type, &dcl);
+ t = gentemp(e->loc, e->expr.type, NULL);
return t;
}
@@ -225,23 +225,20 @@ traitfn(Srcloc loc, Trait *tr, char *fn, Type *ty)
}
static void
-dispose(Flattenctx *s, Stab *st)
+dispose(Flattenctx *s, Stab *st, size_t n)
{
- Node *d, *call, *func, *val;
+ Node *e, *call, *func;
Trait *tr;
Type *ty;
size_t i;
tr = traittab[Tcdisp];
- /* dispose in reverse order of declaration */
- for (i = st->nautodcl; i-- > 0;) {
- d = st->autodcl[i];
- ty = decltype(d);
- val = mkexpr(Zloc, Ovar, d->decl.name, NULL);
- val->expr.type = ty;
- val->expr.did = d->decl.did;
+ /* dispose in reverse order of appearance */
+ for (i = st->nautotmp; i-- > n;) {
+ e = st->autotmp[i];
+ ty = exprtype(e);
func = traitfn(Zloc, tr, "__dispose__", ty);
- call = mkexpr(Zloc, Ocall, func, val, NULL);
+ call = mkexpr(Zloc, Ocall, func, e, NULL);
call->expr.type = mktype(Zloc, Tyvoid);
flatten(s, call);
}
@@ -460,18 +457,23 @@ assign(Flattenctx *s, Node *lhs, Node *rhs)
/* returns 1 when the exit jump needs to be emitted */
static int
-exitscope(Flattenctx *s, Stab *stop, Srcloc loc, int x)
+exitscope(Flattenctx *s, Stab *stop, Srcloc loc, Exit x)
{
+ Node *exit;
Stab *st;
for (st = s->curst;; st = st->super) {
- if (st->exit[x]) {
- jmp(s, st->exit[x]);
+ exit = st->exit[x];
+ if (st->ndisposed[x] < st->nautotmp) {
+ st->exit[x] = genlbl(loc);
+ flatten(s, st->exit[x]);
+ dispose(s, st, st->ndisposed[x]);
+ st->ndisposed[x] = st->nautotmp;
+ }
+ if (exit) {
+ jmp(s, exit);
return 0;
}
- st->exit[x] = genlbl(loc);
- flatten(s, st->exit[x]);
- dispose(s, st);
if ((!stop && st->isfunc) || st == stop) {
return 1;
}
@@ -503,6 +505,12 @@ rval(Flattenctx *s, Node *n)
r = NULL;
args = n->expr.args;
switch (exprop(n)) {
+ case Oauto:
+ r = rval(s, n->expr.args[0]);
+ t = temp(s, r);
+ r = asn(t, r);
+ lappend(&s->curst->autotmp, &s->curst->nautotmp, t);
+ break;
case Osize:
r = n; /* don't touch subexprs; they're a pseudo decl */
break;
@@ -696,7 +704,10 @@ flattenblk(Flattenctx *s, Node *n)
flatten(s, n->block.stmts[i]);
}
assert(s->curst == n->block.scope);
- dispose(s, s->curst);
+ if (st->isfunc)
+ exitscope(s, NULL, Zloc, Xret);
+ else
+ dispose(s, s->curst, 0);
s->curst = st;
}
diff --git a/parse/dump.c b/parse/dump.c
index 847c0ed..9437984 100644
--- a/parse/dump.c
+++ b/parse/dump.c
@@ -186,7 +186,6 @@ outnode(Node *n, FILE *fd, int depth)
findentf(fd, depth + 1, "isimport=%d\n", n->decl.isimport);
findentf(fd, depth + 1, "isnoret=%d\n", n->decl.isnoret);
findentf(fd, depth + 1, "isexportinit=%d\n", n->decl.isexportinit);
- findentf(fd, depth + 1, "isauto=%d\n", n->decl.isauto);
findentf(fd, depth, ")\n");
outsym(n, fd, depth + 1);
outnode(n->decl.init, fd, depth + 1);
diff --git a/parse/gram.y b/parse/gram.y
index 8fb448b..9d9ddef 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -148,7 +148,7 @@ static void setupinit(Node *n);
%type<node> littok literal lorexpr landexpr borexpr strlit bandexpr
%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr ternexpr
%type<node> postfixexpr funclit seqlit tuplit name block stmt label
-%type<node> use fnparam declbody declcore typedeclcore autodecl structent
+%type<node> use fnparam declbody declcore typedeclcore structent
%type<node> arrayelt structelt tuphead ifstmt forstmt whilestmt
%type<node> matchstmt elifs optexprln loopcond optexpr match
@@ -420,8 +420,8 @@ pkgtydef: attrs tydef {
}
;
-declbody: autodecl Tasn expr {$$ = $1; $1->decl.init = $3;}
- | autodecl
+declbody: declcore Tasn expr {$$ = $1; $1->decl.init = $3;}
+ | declcore
;
declcore: name {$$ = mkdecl($1->loc, $1, mktyvar($1->loc));}
@@ -432,10 +432,6 @@ typedeclcore
: name Tcolon type {$$ = mkdecl($1->loc, $1, $3);}
;
-autodecl: Tauto declcore {$$ = $2; $$->decl.isauto = 1;}
- | declcore
- ;
-
name : Tident {$$ = mkname($1->loc, $1->id);}
| Tident Tdot Tident {
$$ = mknsname($3->loc, $1->id, $3->id);
@@ -771,7 +767,8 @@ shiftexpr
shiftop : Tbsl | Tbsr;
prefixexpr
- : Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
+ : Tauto prefixexpr {$$ = mkexpr($1->loc, Oauto, $2, NULL);}
+ | Tinc prefixexpr {$$ = mkexpr($1->loc, Opreinc, $2, NULL);}
| Tdec prefixexpr {$$ = mkexpr($1->loc, Opredec, $2, NULL);}
| Tband prefixexpr {$$ = mkexpr($1->loc, Oaddr, $2, NULL);}
| Tlnot prefixexpr {$$ = mkexpr($1->loc, Olnot, $2, NULL);}
@@ -930,7 +927,7 @@ params : fnparam {
| /* empty */ {$$.nl = NULL; $$.nn = 0;}
;
-fnparam : autodecl {$$ = $1;}
+fnparam : declcore {$$ = $1;}
| Tgap { $$ = mkpseudodecl($1->loc, mktyvar($1->loc)); }
| Tgap Tcolon type { $$ = mkpseudodecl($1->loc, $3); }
;
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");
}
diff --git a/parse/ops.def b/parse/ops.def
index c29ca1e..909736e 100644
--- a/parse/ops.def
+++ b/parse/ops.def
@@ -1,5 +1,6 @@
/* operator name, is it pure, pretty name */
O(Obad, 1, OTmisc, "BAD")
+O(Oauto, 1, OTpre, "auto")
O(Oadd, 1, OTbin, "+")
O(Osub, 1, OTbin, "-")
O(Omul, 1, OTbin, "*")
@@ -105,4 +106,3 @@ O(Ougt, 1, OTmisc, NULL)
O(Ouge, 1, OTmisc, NULL)
O(Oult, 1, OTmisc, NULL)
O(Oule, 1, OTmisc, NULL)
-
diff --git a/parse/parse.h b/parse/parse.h
index 52946a9..11b28ac 100644
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -108,10 +108,12 @@ struct Stab {
Htab *lbl; /* labels */
Htab *impl; /* trait implementations: really a set of implemented traits. */
- Node **autodcl; /* declarations in dcl marked 'auto' */
- size_t nautodcl;
+ /* See mi/flatten.c for the following. */
+ Node **autotmp; /* temporaries for 'auto' expressions */
+ size_t nautotmp;
Node *exit[Nexits];
+ size_t ndisposed[Nexits];
};
struct Tyenv {
@@ -331,7 +333,6 @@ struct Node {
char isnoret;
char isexportinit;
char isinit;
- char isauto;
} decl;
struct {
diff --git a/parse/stab.c b/parse/stab.c
index 2d190d9..7e1b8c0 100644
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -417,10 +417,6 @@ putdcl(Stab *st, Node *s)
st = findstab(st, s->decl.name);
old = htget(st->dcl, s->decl.name);
- if (s->decl.isauto) {
- assert(!old);
- lappend(&st->autodcl, &st->nautodcl, s);
- }
if (!old)
forcedcl(st, s);
else if (!mergedecl(old, s))
diff --git a/test/pkgtrait.myr b/test/pkgtrait.myr
index 40eb594..3882634 100644
--- a/test/pkgtrait.myr
+++ b/test/pkgtrait.myr
@@ -8,7 +8,6 @@ impl disposable regex.regex# =
;;
const main = {
- var auto r : regex.regex#
- r = std.try(regex.compile(".*"))
+ auto std.try(regex.compile(".*"))
std.exit(42)
}