summaryrefslogtreecommitdiff
path: root/mi
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2018-01-18 11:46:13 +0000
committerOri Bernstein <ori@eigenstate.org>2018-01-26 22:39:56 -0800
commit6fb0d750b296506f31cfd0871fdac82ee878834b (patch)
tree0d6bab181652f7859c6eef913285abfc41d1bc38 /mi
parent24a566ff1751b246c8b6efd8adea3447975b9efa (diff)
downloadmc-6fb0d750b296506f31cfd0871fdac82ee878834b.tar.gz
New auto operator.
Summary: -------- During the Myrcon in September Ori suggested an 'auto' operator that would evaluate what it applies to, store the result in a temporary t, and call __dispose__(t) when the current block exits. This patch implements this idea under the form of a unary operator. This, for instance, allows to have: impl disposable regex# = __dispose__ = {r; regex.free(r)} ;; regex.exec(auto std.try(regex.compile("f..bar")), "foobar") Like before, it is guaranteed that __dispose__ is called in reverse order of auto appearance. Backward compatibility: ----------------------- Nope. Auto variables are now gone. This should not be a problem, simply rewrite: var auto x = foo() into: var x = auto foo() Implementation: --------------- It largely reuses the code I had written for 'auto' variables but needs a little finer grain tracking because we don't always want to call __dispose__ for *all* auto expression results when leaving a block (some might not be evaluated yet). For example: auto 1 if b -> void ;; auto 2 Only __dispose__(1) must be called when '-> void' is executed. If the block falls through, __dispose__(2) and __dispose__(1) will be called in sequence. TODO: ----- - Err when goto jumps in/out of a block that has auto expressions. - Support auto in patterns. match ... | `std.Some (auto x): ... is essentially rewritten to: match ... | `std.Some (auto x): auto x ... - Test edge cases (e.g., auto in loop condition) Actually, test. Cheers,
Diffstat (limited to 'mi')
-rw-r--r--mi/flatten.c49
1 files changed, 30 insertions, 19 deletions
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;
}