summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--6/isel.c2
-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, 63 insertions, 55 deletions
diff --git a/6/isel.c b/6/isel.c
index e695096..0753c60 100644
--- a/6/isel.c
+++ b/6/isel.c
@@ -939,7 +939,7 @@ 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 Obad: case Oauto: case Opreinc: case Opostinc: case Opredec:
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:
diff --git a/mi/flatten.c b/mi/flatten.c
index 37b59e5..4923e1d 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);
}
@@ -433,18 +430,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;
}
@@ -476,6 +478,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;
@@ -666,7 +674,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 5c73295..adc63c4 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -147,7 +147,7 @@ static void setupinit(Node *n);
%type<node> littok literal lorexpr landexpr borexpr strlit bandexpr
%type<node> cmpexpr addexpr mulexpr shiftexpr prefixexpr
%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
@@ -419,8 +419,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));}
@@ -431,10 +431,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);
@@ -764,7 +760,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);}
@@ -923,7 +920,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 1c4d39f..bacd4a3 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) {
@@ -1635,6 +1635,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 */
@@ -2076,8 +2083,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)
@@ -2626,8 +2631,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:
@@ -2674,6 +2677,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)
@@ -2739,7 +2744,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;
@@ -2761,14 +2774,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 dd9447a..d81ace5 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, "*")
@@ -104,4 +105,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 c7b94aa..90dd771 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)
}