Issues

Issue #28 resolved

"caller" should not be defined for a regular def call even if youre nested in a <%call>'ed def

Mike Bayer
repo owner created an issue

easier to illustrate:

<%def name="a()"> % if caller: ${ caller.body() }\ % endif AAA ${ b() } </%def>

<%def name="b()"> % if caller: ${ caller.body() }\ % endif BBB ${ c() } </%def>

<%def name="c()"> % if caller: ${ caller.body() }\ % endif CCC </%def>

<%call expr="a()"> CALL </%call>

result:

CALL AAA CALL BBB CALL CCC

should be:

CALL AAA BBB CCC

Comments (2)

  1. Mike Bayer reporter
    • marked as

    im not really sure if theres a fix for this...it may be more or less a rewrite of how all function calls work, which while it shouldnt be ruled out, would most likely add a significant layer of interpretation to Mako and slow it down at least a little bit, but maybe more than we'd like (i want this thing to stay really fast).

    Mako has no runtime "stack frame" that is actually tracking callers or anything else about the call stack. theres some extra tricks used in the case of the `<%call>` tag to propigate the `caller` around, but theres nothing going on in the case of normal `<%def>` calls to track the `caller` in those cases; so it stays set to what the caller already was from the last <%call>. what we're looking at is pushing/popping caller context for every def call not just <%call>s, thereby implementing an interpreted callstack. hopefully all the wacky unit tests we have would still all work (i made some attempts just now and they didnt...so this will be a lot of work to get it going).

    i have in the past tried hanging on to Python's own stack frame system but did not have good results (since the stack frames do not line up cleanly with actual <%defs> and <%calls>).

  2. Mike Bayer reporter

    OK, I added the call stack and as expected everything works great, but also the speed diference, at least in the basic.py speed test which has three def calls per run, the difference in execution time is negligible. in a page with a lot of def calls, it probably makes more of a difference, but its still tiny overhead compared to a more heavily interpreted language. we also get heavier generated modules since most defs have a stack/push/pop step fed into a try/finally.

    the call stack code makes the whole `callable` system a lot simpler and transparent, with the new `CallerStack` being very simple without all the weirdness that `_StackFacade` had. so because its much simpler now i was also able to get better control of 'caller' scope within the callables that are actually within the `<%call>` tag - the body uses the caller that was already in scope, the other callables pull from the context...anyway, the approach is more stable so itll stay, in [changeset:257].

  3. Log in to comment