In the Positron templates, I'm adding a wrapping functionality. Wrapping functionality is like file inclusion, only nested. In typical file inclusion, you start in template A, and in some place you say "please include template B at this spot". You end up with template B included in template A, like this:
With wrapping, one starts in template A, and then says "please include template B at this spot, using this part of template A" and delineate a small part of A, which we will call C. The template B usually includes a marker, at which point C is included in turn. So you have
Incidently, this is another idea I found in the Template Toolkit, specifically the WRAPPER directive.
Now the thing is, C is a regular part of the template. It has its own directives, constructs, loops, replacements and everything else. These will need to be replaced at some time, but the question is: is this time before the inclusion, or during the inclusion? Because the results could be different, depending on what environment B places C in; for example within a loop or under an assignement construct.
It turns out that this mirrors function calls in typical programming languages.
In a typical function call,
f(a(b)), the parameters are evaluated first, and then the function is called. In our example,
b would be evaluated first, then
a(b), and finally
f called with the result of
as its parameter.
Following this model, C should be evaluated before evaluating B. The constructs of C are resolved with the environment that A has at the time
the wrapping construct is first encountered. The template B gets passed a simple chunk of HTML, or data, or text, which it may look at, but not touch.
There is one difference, though: in programming languages, it is considered unusual, or downright dangerous, for the callback C to have access to the scoped variables (the environment) of B. In the case of closures, C may even access local variables at the point it is defined, but this is in A, not B. This is referred to as dynamic vs. lexical binding.
I'm going to choose the dynamic evaluation (the "callback" variant). If template A wraps template B around subtemplate C, then C is evaluated every time B calls it. And it will be called in the innermost environment, that of B. This environment will differ from that of A only when B calls C inside a loop, or an assignment construct, or similar. Now C acts as a blueprint or behaviour modifier for B, so it is assumed that C can access the variables B is passing too it. After all, in Positron (and other template languages), most of the variables are "global", and only a few special cases are "local".