Re: Add nested-function support in a language the based on a stack-machine

rpw3@rpw3.org (Rob Warnock)
Sat, 3 Mar 2018 16:00:25 -0000 (UTC)

          From comp.compilers

Related articles
| List of all articles for this month |
From: rpw3@rpw3.org (Rob Warnock)
Newsgroups: comp.compilers
Date: Sat, 3 Mar 2018 16:00:25 -0000 (UTC)
Organization: Rob Warnock, Consulting Systems Architect
References: 18-02-009 18-02-034 18-03-002 18-03-006
Injection-Info: gal.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="94344"; mail-complaints-to="abuse@iecc.com"
Keywords: code, design
Posted-Date: 03 Mar 2018 13:17:35 EST
Originator: rpw3@rpw3.org (Rob Warnock)



Kaz Kylheku <217-679-0842@kylheku.com> wrote:
+---------------
| George Neuner <gneuner2@comcast.net> wrote:
| > It certainly is true that closeure conversion is a better solution
| > overall because it flattens all non-local accesses to use a single
| > indirection ... but it also significantly complicates the compiler,
| > and creates a need for handling wide pointers (or equivalent). Many
| > useful languages simply don't need that extra complexity.
|
| How do flat representations handle the fact that different levels
| of the lexical environment have different lifetimes?
+---------------


I'm not sure if this counts as "closure conversion" or not, but some
Common Lisp implementations [such as CMUCL] use flat environments just
fine (even in the interpreter). The trick is to do some minimal
pre-analysis of the code, to see which closed-over variables are *not*
ever mutated or are *not* used in closures which "escape" the original
lexical context. All such variables may be copied into a single "flat"
vector at closure creation time. All other closed-over variables are
converted into "indirect" variables -- such variables are individually
heap-allocated, pointed to by "ref" pointers which are also copied
into a the same flat environment vector at closure creation time.
Then when the closure is called, all of the up-level variables are
either *in* the (flat) environment or available via *one* indirection.
Because all of the "ref" pointers for a given environment variable in
all the (potential) copies point to the same heap location, closures
which mutate a shared variable work just fine. And all the rest are
either read-only [and thus all the copies are the same] or else
mutated and *not* accessed in any interior closure which escapes.


This is normally performs better than linked environments or even
displays, unless there are a *large* number of nested closures. In the
latter case, when each level of closure is created, it will have to
copy all of its free variables from its parent's flat environment into
its own.


[I apologize if I haven't explained this very well.]


This approach is not unique to Lisp. Appel discusses it for ML in his
"Compiling With Continuations".


-Rob


-----
Rob Warnock <rpw3@rpw3.org>
627 26th Avenue <http://rpw3.org/>
San Mateo, CA 94403


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.