Dynamic name resolution (non-default)
For some purposes and applications, dynamic name resolution may be desirable, for
example when writing self
in front of every name to access a property of the closure
target object is too cumbersome. For this, the BuildDSL transpiler can generate code that
looks up, sets and deletes keys using subscript syntax on a particular variable name.
Using the builddsl.runtime
package, you can configure the transpiler and runtime
to use dynamic name resolution. Example usage:
from builddsl.transpiler import transpile_to_ast
from builddsl.runtime import Closure
class Project:
def task(self, name: str, *, do: callable): ...
code = ...
filename = ...
# Long form:
module = transpile_to_ast(code, filename, Closure.get_options())
code = compile(module, filename, 'exec')
scope = {'__closure__': Closure(None, None, Project())}
exec(code, scope)
# Shorthand form:
Closure(None, None, Project()).run_code(code, filename)
The Closure.get_options()
function returns TranspileOptions
that instruct the transpiler
to convert name lookups into subscripts on the __closure__
variable, add a
@__closure__.subclosure
decoration before every closure function definition and to add a
__closure__,
argument to their arglist. The Closure
object passed into the scope
on execution deals with the rest.
task "foobar" do: {
return n_times
}
task "belzebub" do: {
def n_times = 1
return n_times
}
task "cheeky" do: {
def n_times = 1
return (() -> n_times )()
}
@__closure__.subclosure
def _closure_1(__closure__, self, *arguments, **kwarguments):
return __closure__['n_times']
__closure__['task']('foobar', do=_closure_1)
@__closure__.subclosure
def _closure_2(__closure__, self, *arguments, **kwarguments):
n_times = 1
return n_times
__closure__['task']('belzebub', do=_closure_2)
@__closure__.subclosure
def _closure_3(__closure__, self, *arguments, **kwarguments):
n_times = 1
@__closure__.subclosure
def _closure_3_closure_3(__closure__):
return n_times
return _closure_3_closure_3()
__closure__['task']('cheeky', do=_closure_3)