ref: d23b4a240fb0b8ad401081e29230737502d13ad4
parent: dd1dcc663ada21c70e41003564e5c57d671981ac
author: Ori Bernstein <[email protected]>
date: Thu Sep 24 19:21:08 EDT 2015
Error out correctly with closures.
--- a/6/simp.c
+++ b/6/simp.c
@@ -25,6 +25,7 @@
typedef struct Simp Simp;
struct Simp {
int isglobl;
+ Bitset *env;
Node **stmts;
size_t nstmts;
@@ -345,6 +346,12 @@
return load(addk(addr(s, sl, tyintptr), Ptrsz));
}
+Node *loadvar(Simp *s, Node *n)
+{
+ if (bshas(s->env, n->expr.did))
+ fatal(n, "closure environment capture has not yet been implemented");
+ return n;
+}
static Node *seqlen(Simp *s, Node *n, Type *ty)
{
@@ -685,12 +692,10 @@
{
size_t i;
- pushstab(n->block.scope);
for (i = 0; i < n->block.nstmts; i++) {
n->block.stmts[i] = fold(n->block.stmts[i], 0);
simp(s, n->block.stmts[i]);
}
- popstab();
}
static Node *simpblob(Simp *s, Node *blob, Node ***l, size_t *nl)
@@ -829,7 +834,7 @@
args = n->expr.args;
switch (exprop(n)) {
- case Ovar: r = n; break;
+ case Ovar: r = loadvar(s, n); break;
case Oidx: r = deref(idxaddr(s, args[0], args[1]), NULL); break;
case Oderef: r = deref(rval(s, args[0], NULL), NULL); break;
case Omemb: r = rval(s, n, NULL); break;
@@ -1458,7 +1463,7 @@
}
break;
case Ovar:
- r = n;
+ r = loadvar(s, n);
break;
case Ogap:
fatal(n, "'_' may not be an rvalue");
@@ -1675,6 +1680,18 @@
return 0;
}
+static void collectenv(Simp *s, Node *fn)
+{
+ size_t nenv, i;
+ Node **env;
+
+ s->env = mkbs();
+ env = getclosure(fn->func.scope, &nenv);
+ for (i = 0; i < nenv; i++)
+ bsput(s->env, env[i]->decl.did);
+ free(env);
+}
+
static Func *simpfn(Simp *s, char *name, Node *dcl)
{
Node *n;
@@ -1690,9 +1707,8 @@
/* unwrap to the function body */
n = n->expr.args[0];
n = n->lit.fnval;
- pushstab(n->func.scope);
+ collectenv(s, n);
flatten(s, n);
- popstab();
if (debugopt['f'] || debugopt['F'])
for (i = 0; i < s->nstmts; i++)
--- a/parse/parse.h
+++ b/parse/parse.h
@@ -488,6 +488,7 @@
Stab *getns(Node *file, char *n);
Node *getdcl(Stab *st, Node *n);
Node *getclosed(Stab *st, Node *n);
+Node **getclosure(Stab *st, size_t *n);
Type *gettype_l(Stab *st, Node *n);
Type *gettype(Stab *st, Node *n);
Node *getimpl(Stab *st, Node *impl);
--- a/parse/stab.c
+++ b/parse/stab.c
@@ -109,6 +109,29 @@
return NULL;
}
+Node **getclosure(Stab *st, size_t *n)
+{
+ size_t nkeys, i;
+ void **keys;
+ Node **vals;
+
+ while (st && !st->env)
+ st = st->super;
+
+ if (!st) {
+ *n = 0;
+ return NULL;
+ }
+
+ vals = NULL;
+ *n = 0;
+ keys = htkeys(st->env, &nkeys);
+ for (i = 0; i < nkeys; i++)
+ lappend(&vals, n, htget(st->env, keys[i]));
+ free(keys);
+ return vals;
+}
+
/*
* Searches for declarations from current
* scope, and all enclosing scopes. Does
@@ -127,14 +150,14 @@
fn = NULL;
do {
s = htget(st->dcl, n);
- if (!fn && st->env)
- fn = st;
if (s) {
/* record that this is in the closure of this scope */
- if (fn && !n->decl.isglobl)
+ if (fn && !s->decl.isglobl)
htput(fn->env, s->decl.name, s);
return s;
}
+ if (!fn && st->env)
+ fn = st;
st = st->super;
} while (st);
return NULL;
--- a/test/closure.myr
+++ b/test/closure.myr
@@ -4,5 +4,5 @@
var f = {b
-> a + b
}
- -> f(13)
+ f(13)
}