diff options
author | Quentin Carbonneaux <quentin@c9x.me> | 2018-01-18 11:46:13 +0000 |
---|---|---|
committer | Ori Bernstein <ori@eigenstate.org> | 2018-01-26 22:39:56 -0800 |
commit | 6fb0d750b296506f31cfd0871fdac82ee878834b (patch) | |
tree | 0d6bab181652f7859c6eef913285abfc41d1bc38 /mi | |
parent | 24a566ff1751b246c8b6efd8adea3447975b9efa (diff) | |
download | mc-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.c | 49 |
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; } |