Dynamic Scope / Continuation Marks

  • From: Brandon Bloom <brandon.d.bloom@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Thu, 3 Nov 2016 17:16:45 -0700

Hello,

Is it possible to accomplish dynamic scope in a way that respects tail
calls with luajit?

I've been approximating dynamic scope for a particular algorithm in the
classic set/restore manner:

function withx(x, body)
  local oldx = globalx
  local result = {body()}
  globalx = oldx
  return unpack(result)
end

Unfortunately, while simple, this approach evaluates the body function in a
non-tail position. Until now, this wasn't a problem, but I've run in to a
recursive use case which now suffers from stack overflows.

Racket accomplishes dynamic scope via "continuation marks" (see [1] and
[2]) that, if manipulated in tail position, modify a cell in the current
frame, so these "marks" with dynamic extent can be used without affecting
space complexity. The documentation for the "parameterize" macro calls out
the body-in-tail-position behavior explicitly [3].

A blog post [4] suggests that dynamic scope can hack-ily be accomplished
via debug.getlocal, but the specific code posted there is incorrect in the
presence of tail calls (try adding a 'return' to the fn call in run_func).
I suppose Lua 5.2's getinfo with what='t' can return istailcall to
workaround this, but we've gotten pretty far in to hack territory and I'd
like to stay on luajit.

I don't care if the resulting code achieves normal variable syntax or not.
I'm fine with function call syntax to get the current dynamic value.

So to recap: Is there a way in luajit to accomplish tail-call-safe dynamic
scope or otherwise associate per-stack-frame data?

Thanks,
Brandon


[1] https://docs.racket-lang.org/reference/contmarks.html
[2] "Adding Delimited and Composable Control to a Production Programming
Environment" - Flatt, et al.
[3]
https://docs.racket-lang.org/reference/parameters.html?q=parameterize#%28form._%28%28lib._racket%2Fprivate%2Fmore-scheme..rkt%29._parameterize%29%29
[4] http://leafo.net/guides/dynamic-scoping-in-lua.html

Other related posts: