# Tracks parameter definition blocks
self._param_def_block = []
+ # Tracks the current context.
+ self._context_reference_stack = ['context']
+
# -- Various compilation helpers
def fail(self, msg, lineno):
if action == VAR_LOAD_PARAMETER:
pass
elif action == VAR_LOAD_RESOLVE:
- self.writeline('%s = resolve(%r)' %
- (target, param))
+ self.writeline('%s = %s(%r)' %
+ (target, self.get_resolve_func(), param))
elif action == VAR_LOAD_ALIAS:
self.writeline('%s = %s' % (target, param))
elif action == VAR_LOAD_UNDEFINED:
if self._param_def_block:
self._param_def_block[-1].discard(target)
+ def push_context_reference(self, target):
+ self._context_reference_stack.append(target)
+
+ def pop_context_reference(self):
+ self._context_reference_stack.pop()
+
+ def get_context_ref(self):
+ return self._context_reference_stack[-1]
+
+ def get_resolve_func(self):
+ target = self._context_reference_stack[-1]
+ if target == 'context':
+ return 'resolve'
+ return '%s.resolve' % target
+
+ def derive_context(self, frame):
+ return '%s.derived(%s)' % (
+ self.get_context_ref(),
+ self.dump_local_context(frame),
+ )
+
def parameter_is_undeclared(self, target):
"""Checks if a given target is an undeclared parameter."""
if not self._param_def_block:
self.writeline('if parent_template is None:')
self.indent()
level += 1
- context = node.scoped and (
- 'context.derived(%s)' % self.dump_local_context(frame)) or 'context'
+
+ if node.scoped:
+ context = self.derive_context(frame)
+ else:
+ context = self.get_context_ref()
if supports_yield_from and not self.environment.is_async and \
frame.buffer is None:
self.blockvisit(node.body, scope_frame)
self.leave_frame(scope_frame)
+ def visit_OverlayScope(self, node, frame):
+ ctx = self.temporary_identifier()
+ self.writeline('%s = %s' % (ctx, self.derive_context(frame)))
+ self.writeline('%s.vars = ' % ctx)
+ self.visit(node.context, frame)
+ self.push_context_reference(ctx)
+
+ scope_frame = Frame(frame.eval_ctx)
+ scope_frame.symbols.analyze_node(node)
+ self.enter_frame(scope_frame)
+ self.blockvisit(node.body, scope_frame)
+ self.leave_frame(scope_frame)
+ self.pop_context_reference()
+
def visit_EvalContextModifier(self, node, frame):
for keyword in node.options:
self.writeline('context.eval_ctx.%s = ' % keyword.key)
for child in node.iter_child_nodes(exclude=('call',)):
self.sym_visitor.visit(child)
+ def visit_OverlayScope(self, node, **kwargs):
+ for child in node.body:
+ self.sym_visitor.visit(child)
+
def visit_For(self, node, for_branch='body', **kwargs):
if node.test is not None:
self.sym_visitor.visit(node.test)
def visit_Block(self, node, **kwargs):
"""Stop visiting at blocks."""
+
+ def visit_OverlayScope(self, node, **kwargs):
+ """Do not visit into overlay scopes."""