11cb0ef41Sopenharmony_ci# -*- coding: utf-8 -*-
21cb0ef41Sopenharmony_ci"""
31cb0ef41Sopenharmony_ci    jinja2.compiler
41cb0ef41Sopenharmony_ci    ~~~~~~~~~~~~~~~
51cb0ef41Sopenharmony_ci
61cb0ef41Sopenharmony_ci    Compiles nodes into python code.
71cb0ef41Sopenharmony_ci
81cb0ef41Sopenharmony_ci    :copyright: (c) 2017 by the Jinja Team.
91cb0ef41Sopenharmony_ci    :license: BSD, see LICENSE for more details.
101cb0ef41Sopenharmony_ci"""
111cb0ef41Sopenharmony_cifrom itertools import chain
121cb0ef41Sopenharmony_cifrom copy import deepcopy
131cb0ef41Sopenharmony_cifrom keyword import iskeyword as is_python_keyword
141cb0ef41Sopenharmony_cifrom functools import update_wrapper
151cb0ef41Sopenharmony_cifrom jinja2 import nodes
161cb0ef41Sopenharmony_cifrom jinja2.nodes import EvalContext
171cb0ef41Sopenharmony_cifrom jinja2.visitor import NodeVisitor
181cb0ef41Sopenharmony_cifrom jinja2.optimizer import Optimizer
191cb0ef41Sopenharmony_cifrom jinja2.exceptions import TemplateAssertionError
201cb0ef41Sopenharmony_cifrom jinja2.utils import Markup, concat, escape
211cb0ef41Sopenharmony_cifrom jinja2._compat import range_type, text_type, string_types, \
221cb0ef41Sopenharmony_ci     iteritems, NativeStringIO, imap, izip
231cb0ef41Sopenharmony_cifrom jinja2.idtracking import Symbols, VAR_LOAD_PARAMETER, \
241cb0ef41Sopenharmony_ci     VAR_LOAD_RESOLVE, VAR_LOAD_ALIAS, VAR_LOAD_UNDEFINED
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cioperators = {
281cb0ef41Sopenharmony_ci    'eq':       '==',
291cb0ef41Sopenharmony_ci    'ne':       '!=',
301cb0ef41Sopenharmony_ci    'gt':       '>',
311cb0ef41Sopenharmony_ci    'gteq':     '>=',
321cb0ef41Sopenharmony_ci    'lt':       '<',
331cb0ef41Sopenharmony_ci    'lteq':     '<=',
341cb0ef41Sopenharmony_ci    'in':       'in',
351cb0ef41Sopenharmony_ci    'notin':    'not in'
361cb0ef41Sopenharmony_ci}
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci# what method to iterate over items do we want to use for dict iteration
391cb0ef41Sopenharmony_ci# in generated code?  on 2.x let's go with iteritems, on 3.x with items
401cb0ef41Sopenharmony_ciif hasattr(dict, 'iteritems'):
411cb0ef41Sopenharmony_ci    dict_item_iter = 'iteritems'
421cb0ef41Sopenharmony_cielse:
431cb0ef41Sopenharmony_ci    dict_item_iter = 'items'
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_cicode_features = ['division']
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci# does this python version support generator stops? (PEP 0479)
481cb0ef41Sopenharmony_citry:
491cb0ef41Sopenharmony_ci    exec('from __future__ import generator_stop')
501cb0ef41Sopenharmony_ci    code_features.append('generator_stop')
511cb0ef41Sopenharmony_ciexcept SyntaxError:
521cb0ef41Sopenharmony_ci    pass
531cb0ef41Sopenharmony_ci
541cb0ef41Sopenharmony_ci# does this python version support yield from?
551cb0ef41Sopenharmony_citry:
561cb0ef41Sopenharmony_ci    exec('def f(): yield from x()')
571cb0ef41Sopenharmony_ciexcept SyntaxError:
581cb0ef41Sopenharmony_ci    supports_yield_from = False
591cb0ef41Sopenharmony_cielse:
601cb0ef41Sopenharmony_ci    supports_yield_from = True
611cb0ef41Sopenharmony_ci
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_cidef optimizeconst(f):
641cb0ef41Sopenharmony_ci    def new_func(self, node, frame, **kwargs):
651cb0ef41Sopenharmony_ci        # Only optimize if the frame is not volatile
661cb0ef41Sopenharmony_ci        if self.optimized and not frame.eval_ctx.volatile:
671cb0ef41Sopenharmony_ci            new_node = self.optimizer.visit(node, frame.eval_ctx)
681cb0ef41Sopenharmony_ci            if new_node != node:
691cb0ef41Sopenharmony_ci                return self.visit(new_node, frame)
701cb0ef41Sopenharmony_ci        return f(self, node, frame, **kwargs)
711cb0ef41Sopenharmony_ci    return update_wrapper(new_func, f)
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci
741cb0ef41Sopenharmony_cidef generate(node, environment, name, filename, stream=None,
751cb0ef41Sopenharmony_ci             defer_init=False, optimized=True):
761cb0ef41Sopenharmony_ci    """Generate the python source for a node tree."""
771cb0ef41Sopenharmony_ci    if not isinstance(node, nodes.Template):
781cb0ef41Sopenharmony_ci        raise TypeError('Can\'t compile non template nodes')
791cb0ef41Sopenharmony_ci    generator = environment.code_generator_class(environment, name, filename,
801cb0ef41Sopenharmony_ci                                                 stream, defer_init,
811cb0ef41Sopenharmony_ci                                                 optimized)
821cb0ef41Sopenharmony_ci    generator.visit(node)
831cb0ef41Sopenharmony_ci    if stream is None:
841cb0ef41Sopenharmony_ci        return generator.stream.getvalue()
851cb0ef41Sopenharmony_ci
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_cidef has_safe_repr(value):
881cb0ef41Sopenharmony_ci    """Does the node have a safe representation?"""
891cb0ef41Sopenharmony_ci    if value is None or value is NotImplemented or value is Ellipsis:
901cb0ef41Sopenharmony_ci        return True
911cb0ef41Sopenharmony_ci    if type(value) in (bool, int, float, complex, range_type, Markup) + string_types:
921cb0ef41Sopenharmony_ci        return True
931cb0ef41Sopenharmony_ci    if type(value) in (tuple, list, set, frozenset):
941cb0ef41Sopenharmony_ci        for item in value:
951cb0ef41Sopenharmony_ci            if not has_safe_repr(item):
961cb0ef41Sopenharmony_ci                return False
971cb0ef41Sopenharmony_ci        return True
981cb0ef41Sopenharmony_ci    elif type(value) is dict:
991cb0ef41Sopenharmony_ci        for key, value in iteritems(value):
1001cb0ef41Sopenharmony_ci            if not has_safe_repr(key):
1011cb0ef41Sopenharmony_ci                return False
1021cb0ef41Sopenharmony_ci            if not has_safe_repr(value):
1031cb0ef41Sopenharmony_ci                return False
1041cb0ef41Sopenharmony_ci        return True
1051cb0ef41Sopenharmony_ci    return False
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci
1081cb0ef41Sopenharmony_cidef find_undeclared(nodes, names):
1091cb0ef41Sopenharmony_ci    """Check if the names passed are accessed undeclared.  The return value
1101cb0ef41Sopenharmony_ci    is a set of all the undeclared names from the sequence of names found.
1111cb0ef41Sopenharmony_ci    """
1121cb0ef41Sopenharmony_ci    visitor = UndeclaredNameVisitor(names)
1131cb0ef41Sopenharmony_ci    try:
1141cb0ef41Sopenharmony_ci        for node in nodes:
1151cb0ef41Sopenharmony_ci            visitor.visit(node)
1161cb0ef41Sopenharmony_ci    except VisitorExit:
1171cb0ef41Sopenharmony_ci        pass
1181cb0ef41Sopenharmony_ci    return visitor.undeclared
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci
1211cb0ef41Sopenharmony_ciclass MacroRef(object):
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ci    def __init__(self, node):
1241cb0ef41Sopenharmony_ci        self.node = node
1251cb0ef41Sopenharmony_ci        self.accesses_caller = False
1261cb0ef41Sopenharmony_ci        self.accesses_kwargs = False
1271cb0ef41Sopenharmony_ci        self.accesses_varargs = False
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci
1301cb0ef41Sopenharmony_ciclass Frame(object):
1311cb0ef41Sopenharmony_ci    """Holds compile time information for us."""
1321cb0ef41Sopenharmony_ci
1331cb0ef41Sopenharmony_ci    def __init__(self, eval_ctx, parent=None, level=None):
1341cb0ef41Sopenharmony_ci        self.eval_ctx = eval_ctx
1351cb0ef41Sopenharmony_ci        self.symbols = Symbols(parent and parent.symbols or None,
1361cb0ef41Sopenharmony_ci                               level=level)
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci        # a toplevel frame is the root + soft frames such as if conditions.
1391cb0ef41Sopenharmony_ci        self.toplevel = False
1401cb0ef41Sopenharmony_ci
1411cb0ef41Sopenharmony_ci        # the root frame is basically just the outermost frame, so no if
1421cb0ef41Sopenharmony_ci        # conditions.  This information is used to optimize inheritance
1431cb0ef41Sopenharmony_ci        # situations.
1441cb0ef41Sopenharmony_ci        self.rootlevel = False
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci        # in some dynamic inheritance situations the compiler needs to add
1471cb0ef41Sopenharmony_ci        # write tests around output statements.
1481cb0ef41Sopenharmony_ci        self.require_output_check = parent and parent.require_output_check
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci        # inside some tags we are using a buffer rather than yield statements.
1511cb0ef41Sopenharmony_ci        # this for example affects {% filter %} or {% macro %}.  If a frame
1521cb0ef41Sopenharmony_ci        # is buffered this variable points to the name of the list used as
1531cb0ef41Sopenharmony_ci        # buffer.
1541cb0ef41Sopenharmony_ci        self.buffer = None
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci        # the name of the block we're in, otherwise None.
1571cb0ef41Sopenharmony_ci        self.block = parent and parent.block or None
1581cb0ef41Sopenharmony_ci
1591cb0ef41Sopenharmony_ci        # the parent of this frame
1601cb0ef41Sopenharmony_ci        self.parent = parent
1611cb0ef41Sopenharmony_ci
1621cb0ef41Sopenharmony_ci        if parent is not None:
1631cb0ef41Sopenharmony_ci            self.buffer = parent.buffer
1641cb0ef41Sopenharmony_ci
1651cb0ef41Sopenharmony_ci    def copy(self):
1661cb0ef41Sopenharmony_ci        """Create a copy of the current one."""
1671cb0ef41Sopenharmony_ci        rv = object.__new__(self.__class__)
1681cb0ef41Sopenharmony_ci        rv.__dict__.update(self.__dict__)
1691cb0ef41Sopenharmony_ci        rv.symbols = self.symbols.copy()
1701cb0ef41Sopenharmony_ci        return rv
1711cb0ef41Sopenharmony_ci
1721cb0ef41Sopenharmony_ci    def inner(self, isolated=False):
1731cb0ef41Sopenharmony_ci        """Return an inner frame."""
1741cb0ef41Sopenharmony_ci        if isolated:
1751cb0ef41Sopenharmony_ci            return Frame(self.eval_ctx, level=self.symbols.level + 1)
1761cb0ef41Sopenharmony_ci        return Frame(self.eval_ctx, self)
1771cb0ef41Sopenharmony_ci
1781cb0ef41Sopenharmony_ci    def soft(self):
1791cb0ef41Sopenharmony_ci        """Return a soft frame.  A soft frame may not be modified as
1801cb0ef41Sopenharmony_ci        standalone thing as it shares the resources with the frame it
1811cb0ef41Sopenharmony_ci        was created of, but it's not a rootlevel frame any longer.
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci        This is only used to implement if-statements.
1841cb0ef41Sopenharmony_ci        """
1851cb0ef41Sopenharmony_ci        rv = self.copy()
1861cb0ef41Sopenharmony_ci        rv.rootlevel = False
1871cb0ef41Sopenharmony_ci        return rv
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci    __copy__ = copy
1901cb0ef41Sopenharmony_ci
1911cb0ef41Sopenharmony_ci
1921cb0ef41Sopenharmony_ciclass VisitorExit(RuntimeError):
1931cb0ef41Sopenharmony_ci    """Exception used by the `UndeclaredNameVisitor` to signal a stop."""
1941cb0ef41Sopenharmony_ci
1951cb0ef41Sopenharmony_ci
1961cb0ef41Sopenharmony_ciclass DependencyFinderVisitor(NodeVisitor):
1971cb0ef41Sopenharmony_ci    """A visitor that collects filter and test calls."""
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci    def __init__(self):
2001cb0ef41Sopenharmony_ci        self.filters = set()
2011cb0ef41Sopenharmony_ci        self.tests = set()
2021cb0ef41Sopenharmony_ci
2031cb0ef41Sopenharmony_ci    def visit_Filter(self, node):
2041cb0ef41Sopenharmony_ci        self.generic_visit(node)
2051cb0ef41Sopenharmony_ci        self.filters.add(node.name)
2061cb0ef41Sopenharmony_ci
2071cb0ef41Sopenharmony_ci    def visit_Test(self, node):
2081cb0ef41Sopenharmony_ci        self.generic_visit(node)
2091cb0ef41Sopenharmony_ci        self.tests.add(node.name)
2101cb0ef41Sopenharmony_ci
2111cb0ef41Sopenharmony_ci    def visit_Block(self, node):
2121cb0ef41Sopenharmony_ci        """Stop visiting at blocks."""
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci
2151cb0ef41Sopenharmony_ciclass UndeclaredNameVisitor(NodeVisitor):
2161cb0ef41Sopenharmony_ci    """A visitor that checks if a name is accessed without being
2171cb0ef41Sopenharmony_ci    declared.  This is different from the frame visitor as it will
2181cb0ef41Sopenharmony_ci    not stop at closure frames.
2191cb0ef41Sopenharmony_ci    """
2201cb0ef41Sopenharmony_ci
2211cb0ef41Sopenharmony_ci    def __init__(self, names):
2221cb0ef41Sopenharmony_ci        self.names = set(names)
2231cb0ef41Sopenharmony_ci        self.undeclared = set()
2241cb0ef41Sopenharmony_ci
2251cb0ef41Sopenharmony_ci    def visit_Name(self, node):
2261cb0ef41Sopenharmony_ci        if node.ctx == 'load' and node.name in self.names:
2271cb0ef41Sopenharmony_ci            self.undeclared.add(node.name)
2281cb0ef41Sopenharmony_ci            if self.undeclared == self.names:
2291cb0ef41Sopenharmony_ci                raise VisitorExit()
2301cb0ef41Sopenharmony_ci        else:
2311cb0ef41Sopenharmony_ci            self.names.discard(node.name)
2321cb0ef41Sopenharmony_ci
2331cb0ef41Sopenharmony_ci    def visit_Block(self, node):
2341cb0ef41Sopenharmony_ci        """Stop visiting a blocks."""
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci
2371cb0ef41Sopenharmony_ciclass CompilerExit(Exception):
2381cb0ef41Sopenharmony_ci    """Raised if the compiler encountered a situation where it just
2391cb0ef41Sopenharmony_ci    doesn't make sense to further process the code.  Any block that
2401cb0ef41Sopenharmony_ci    raises such an exception is not further processed.
2411cb0ef41Sopenharmony_ci    """
2421cb0ef41Sopenharmony_ci
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ciclass CodeGenerator(NodeVisitor):
2451cb0ef41Sopenharmony_ci
2461cb0ef41Sopenharmony_ci    def __init__(self, environment, name, filename, stream=None,
2471cb0ef41Sopenharmony_ci                 defer_init=False, optimized=True):
2481cb0ef41Sopenharmony_ci        if stream is None:
2491cb0ef41Sopenharmony_ci            stream = NativeStringIO()
2501cb0ef41Sopenharmony_ci        self.environment = environment
2511cb0ef41Sopenharmony_ci        self.name = name
2521cb0ef41Sopenharmony_ci        self.filename = filename
2531cb0ef41Sopenharmony_ci        self.stream = stream
2541cb0ef41Sopenharmony_ci        self.created_block_context = False
2551cb0ef41Sopenharmony_ci        self.defer_init = defer_init
2561cb0ef41Sopenharmony_ci        self.optimized = optimized
2571cb0ef41Sopenharmony_ci        if optimized:
2581cb0ef41Sopenharmony_ci            self.optimizer = Optimizer(environment)
2591cb0ef41Sopenharmony_ci
2601cb0ef41Sopenharmony_ci        # aliases for imports
2611cb0ef41Sopenharmony_ci        self.import_aliases = {}
2621cb0ef41Sopenharmony_ci
2631cb0ef41Sopenharmony_ci        # a registry for all blocks.  Because blocks are moved out
2641cb0ef41Sopenharmony_ci        # into the global python scope they are registered here
2651cb0ef41Sopenharmony_ci        self.blocks = {}
2661cb0ef41Sopenharmony_ci
2671cb0ef41Sopenharmony_ci        # the number of extends statements so far
2681cb0ef41Sopenharmony_ci        self.extends_so_far = 0
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci        # some templates have a rootlevel extends.  In this case we
2711cb0ef41Sopenharmony_ci        # can safely assume that we're a child template and do some
2721cb0ef41Sopenharmony_ci        # more optimizations.
2731cb0ef41Sopenharmony_ci        self.has_known_extends = False
2741cb0ef41Sopenharmony_ci
2751cb0ef41Sopenharmony_ci        # the current line number
2761cb0ef41Sopenharmony_ci        self.code_lineno = 1
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci        # registry of all filters and tests (global, not block local)
2791cb0ef41Sopenharmony_ci        self.tests = {}
2801cb0ef41Sopenharmony_ci        self.filters = {}
2811cb0ef41Sopenharmony_ci
2821cb0ef41Sopenharmony_ci        # the debug information
2831cb0ef41Sopenharmony_ci        self.debug_info = []
2841cb0ef41Sopenharmony_ci        self._write_debug_info = None
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci        # the number of new lines before the next write()
2871cb0ef41Sopenharmony_ci        self._new_lines = 0
2881cb0ef41Sopenharmony_ci
2891cb0ef41Sopenharmony_ci        # the line number of the last written statement
2901cb0ef41Sopenharmony_ci        self._last_line = 0
2911cb0ef41Sopenharmony_ci
2921cb0ef41Sopenharmony_ci        # true if nothing was written so far.
2931cb0ef41Sopenharmony_ci        self._first_write = True
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci        # used by the `temporary_identifier` method to get new
2961cb0ef41Sopenharmony_ci        # unique, temporary identifier
2971cb0ef41Sopenharmony_ci        self._last_identifier = 0
2981cb0ef41Sopenharmony_ci
2991cb0ef41Sopenharmony_ci        # the current indentation
3001cb0ef41Sopenharmony_ci        self._indentation = 0
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci        # Tracks toplevel assignments
3031cb0ef41Sopenharmony_ci        self._assign_stack = []
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci        # Tracks parameter definition blocks
3061cb0ef41Sopenharmony_ci        self._param_def_block = []
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci        # Tracks the current context.
3091cb0ef41Sopenharmony_ci        self._context_reference_stack = ['context']
3101cb0ef41Sopenharmony_ci
3111cb0ef41Sopenharmony_ci    # -- Various compilation helpers
3121cb0ef41Sopenharmony_ci
3131cb0ef41Sopenharmony_ci    def fail(self, msg, lineno):
3141cb0ef41Sopenharmony_ci        """Fail with a :exc:`TemplateAssertionError`."""
3151cb0ef41Sopenharmony_ci        raise TemplateAssertionError(msg, lineno, self.name, self.filename)
3161cb0ef41Sopenharmony_ci
3171cb0ef41Sopenharmony_ci    def temporary_identifier(self):
3181cb0ef41Sopenharmony_ci        """Get a new unique identifier."""
3191cb0ef41Sopenharmony_ci        self._last_identifier += 1
3201cb0ef41Sopenharmony_ci        return 't_%d' % self._last_identifier
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci    def buffer(self, frame):
3231cb0ef41Sopenharmony_ci        """Enable buffering for the frame from that point onwards."""
3241cb0ef41Sopenharmony_ci        frame.buffer = self.temporary_identifier()
3251cb0ef41Sopenharmony_ci        self.writeline('%s = []' % frame.buffer)
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci    def return_buffer_contents(self, frame, force_unescaped=False):
3281cb0ef41Sopenharmony_ci        """Return the buffer contents of the frame."""
3291cb0ef41Sopenharmony_ci        if not force_unescaped:
3301cb0ef41Sopenharmony_ci            if frame.eval_ctx.volatile:
3311cb0ef41Sopenharmony_ci                self.writeline('if context.eval_ctx.autoescape:')
3321cb0ef41Sopenharmony_ci                self.indent()
3331cb0ef41Sopenharmony_ci                self.writeline('return Markup(concat(%s))' % frame.buffer)
3341cb0ef41Sopenharmony_ci                self.outdent()
3351cb0ef41Sopenharmony_ci                self.writeline('else:')
3361cb0ef41Sopenharmony_ci                self.indent()
3371cb0ef41Sopenharmony_ci                self.writeline('return concat(%s)' % frame.buffer)
3381cb0ef41Sopenharmony_ci                self.outdent()
3391cb0ef41Sopenharmony_ci                return
3401cb0ef41Sopenharmony_ci            elif frame.eval_ctx.autoescape:
3411cb0ef41Sopenharmony_ci                self.writeline('return Markup(concat(%s))' % frame.buffer)
3421cb0ef41Sopenharmony_ci                return
3431cb0ef41Sopenharmony_ci        self.writeline('return concat(%s)' % frame.buffer)
3441cb0ef41Sopenharmony_ci
3451cb0ef41Sopenharmony_ci    def indent(self):
3461cb0ef41Sopenharmony_ci        """Indent by one."""
3471cb0ef41Sopenharmony_ci        self._indentation += 1
3481cb0ef41Sopenharmony_ci
3491cb0ef41Sopenharmony_ci    def outdent(self, step=1):
3501cb0ef41Sopenharmony_ci        """Outdent by step."""
3511cb0ef41Sopenharmony_ci        self._indentation -= step
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci    def start_write(self, frame, node=None):
3541cb0ef41Sopenharmony_ci        """Yield or write into the frame buffer."""
3551cb0ef41Sopenharmony_ci        if frame.buffer is None:
3561cb0ef41Sopenharmony_ci            self.writeline('yield ', node)
3571cb0ef41Sopenharmony_ci        else:
3581cb0ef41Sopenharmony_ci            self.writeline('%s.append(' % frame.buffer, node)
3591cb0ef41Sopenharmony_ci
3601cb0ef41Sopenharmony_ci    def end_write(self, frame):
3611cb0ef41Sopenharmony_ci        """End the writing process started by `start_write`."""
3621cb0ef41Sopenharmony_ci        if frame.buffer is not None:
3631cb0ef41Sopenharmony_ci            self.write(')')
3641cb0ef41Sopenharmony_ci
3651cb0ef41Sopenharmony_ci    def simple_write(self, s, frame, node=None):
3661cb0ef41Sopenharmony_ci        """Simple shortcut for start_write + write + end_write."""
3671cb0ef41Sopenharmony_ci        self.start_write(frame, node)
3681cb0ef41Sopenharmony_ci        self.write(s)
3691cb0ef41Sopenharmony_ci        self.end_write(frame)
3701cb0ef41Sopenharmony_ci
3711cb0ef41Sopenharmony_ci    def blockvisit(self, nodes, frame):
3721cb0ef41Sopenharmony_ci        """Visit a list of nodes as block in a frame.  If the current frame
3731cb0ef41Sopenharmony_ci        is no buffer a dummy ``if 0: yield None`` is written automatically.
3741cb0ef41Sopenharmony_ci        """
3751cb0ef41Sopenharmony_ci        try:
3761cb0ef41Sopenharmony_ci            self.writeline('pass')
3771cb0ef41Sopenharmony_ci            for node in nodes:
3781cb0ef41Sopenharmony_ci                self.visit(node, frame)
3791cb0ef41Sopenharmony_ci        except CompilerExit:
3801cb0ef41Sopenharmony_ci            pass
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci    def write(self, x):
3831cb0ef41Sopenharmony_ci        """Write a string into the output stream."""
3841cb0ef41Sopenharmony_ci        if self._new_lines:
3851cb0ef41Sopenharmony_ci            if not self._first_write:
3861cb0ef41Sopenharmony_ci                self.stream.write('\n' * self._new_lines)
3871cb0ef41Sopenharmony_ci                self.code_lineno += self._new_lines
3881cb0ef41Sopenharmony_ci                if self._write_debug_info is not None:
3891cb0ef41Sopenharmony_ci                    self.debug_info.append((self._write_debug_info,
3901cb0ef41Sopenharmony_ci                                            self.code_lineno))
3911cb0ef41Sopenharmony_ci                    self._write_debug_info = None
3921cb0ef41Sopenharmony_ci            self._first_write = False
3931cb0ef41Sopenharmony_ci            self.stream.write('    ' * self._indentation)
3941cb0ef41Sopenharmony_ci            self._new_lines = 0
3951cb0ef41Sopenharmony_ci        self.stream.write(x)
3961cb0ef41Sopenharmony_ci
3971cb0ef41Sopenharmony_ci    def writeline(self, x, node=None, extra=0):
3981cb0ef41Sopenharmony_ci        """Combination of newline and write."""
3991cb0ef41Sopenharmony_ci        self.newline(node, extra)
4001cb0ef41Sopenharmony_ci        self.write(x)
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci    def newline(self, node=None, extra=0):
4031cb0ef41Sopenharmony_ci        """Add one or more newlines before the next write."""
4041cb0ef41Sopenharmony_ci        self._new_lines = max(self._new_lines, 1 + extra)
4051cb0ef41Sopenharmony_ci        if node is not None and node.lineno != self._last_line:
4061cb0ef41Sopenharmony_ci            self._write_debug_info = node.lineno
4071cb0ef41Sopenharmony_ci            self._last_line = node.lineno
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci    def signature(self, node, frame, extra_kwargs=None):
4101cb0ef41Sopenharmony_ci        """Writes a function call to the stream for the current node.
4111cb0ef41Sopenharmony_ci        A leading comma is added automatically.  The extra keyword
4121cb0ef41Sopenharmony_ci        arguments may not include python keywords otherwise a syntax
4131cb0ef41Sopenharmony_ci        error could occour.  The extra keyword arguments should be given
4141cb0ef41Sopenharmony_ci        as python dict.
4151cb0ef41Sopenharmony_ci        """
4161cb0ef41Sopenharmony_ci        # if any of the given keyword arguments is a python keyword
4171cb0ef41Sopenharmony_ci        # we have to make sure that no invalid call is created.
4181cb0ef41Sopenharmony_ci        kwarg_workaround = False
4191cb0ef41Sopenharmony_ci        for kwarg in chain((x.key for x in node.kwargs), extra_kwargs or ()):
4201cb0ef41Sopenharmony_ci            if is_python_keyword(kwarg):
4211cb0ef41Sopenharmony_ci                kwarg_workaround = True
4221cb0ef41Sopenharmony_ci                break
4231cb0ef41Sopenharmony_ci
4241cb0ef41Sopenharmony_ci        for arg in node.args:
4251cb0ef41Sopenharmony_ci            self.write(', ')
4261cb0ef41Sopenharmony_ci            self.visit(arg, frame)
4271cb0ef41Sopenharmony_ci
4281cb0ef41Sopenharmony_ci        if not kwarg_workaround:
4291cb0ef41Sopenharmony_ci            for kwarg in node.kwargs:
4301cb0ef41Sopenharmony_ci                self.write(', ')
4311cb0ef41Sopenharmony_ci                self.visit(kwarg, frame)
4321cb0ef41Sopenharmony_ci            if extra_kwargs is not None:
4331cb0ef41Sopenharmony_ci                for key, value in iteritems(extra_kwargs):
4341cb0ef41Sopenharmony_ci                    self.write(', %s=%s' % (key, value))
4351cb0ef41Sopenharmony_ci        if node.dyn_args:
4361cb0ef41Sopenharmony_ci            self.write(', *')
4371cb0ef41Sopenharmony_ci            self.visit(node.dyn_args, frame)
4381cb0ef41Sopenharmony_ci
4391cb0ef41Sopenharmony_ci        if kwarg_workaround:
4401cb0ef41Sopenharmony_ci            if node.dyn_kwargs is not None:
4411cb0ef41Sopenharmony_ci                self.write(', **dict({')
4421cb0ef41Sopenharmony_ci            else:
4431cb0ef41Sopenharmony_ci                self.write(', **{')
4441cb0ef41Sopenharmony_ci            for kwarg in node.kwargs:
4451cb0ef41Sopenharmony_ci                self.write('%r: ' % kwarg.key)
4461cb0ef41Sopenharmony_ci                self.visit(kwarg.value, frame)
4471cb0ef41Sopenharmony_ci                self.write(', ')
4481cb0ef41Sopenharmony_ci            if extra_kwargs is not None:
4491cb0ef41Sopenharmony_ci                for key, value in iteritems(extra_kwargs):
4501cb0ef41Sopenharmony_ci                    self.write('%r: %s, ' % (key, value))
4511cb0ef41Sopenharmony_ci            if node.dyn_kwargs is not None:
4521cb0ef41Sopenharmony_ci                self.write('}, **')
4531cb0ef41Sopenharmony_ci                self.visit(node.dyn_kwargs, frame)
4541cb0ef41Sopenharmony_ci                self.write(')')
4551cb0ef41Sopenharmony_ci            else:
4561cb0ef41Sopenharmony_ci                self.write('}')
4571cb0ef41Sopenharmony_ci
4581cb0ef41Sopenharmony_ci        elif node.dyn_kwargs is not None:
4591cb0ef41Sopenharmony_ci            self.write(', **')
4601cb0ef41Sopenharmony_ci            self.visit(node.dyn_kwargs, frame)
4611cb0ef41Sopenharmony_ci
4621cb0ef41Sopenharmony_ci    def pull_dependencies(self, nodes):
4631cb0ef41Sopenharmony_ci        """Pull all the dependencies."""
4641cb0ef41Sopenharmony_ci        visitor = DependencyFinderVisitor()
4651cb0ef41Sopenharmony_ci        for node in nodes:
4661cb0ef41Sopenharmony_ci            visitor.visit(node)
4671cb0ef41Sopenharmony_ci        for dependency in 'filters', 'tests':
4681cb0ef41Sopenharmony_ci            mapping = getattr(self, dependency)
4691cb0ef41Sopenharmony_ci            for name in getattr(visitor, dependency):
4701cb0ef41Sopenharmony_ci                if name not in mapping:
4711cb0ef41Sopenharmony_ci                    mapping[name] = self.temporary_identifier()
4721cb0ef41Sopenharmony_ci                self.writeline('%s = environment.%s[%r]' %
4731cb0ef41Sopenharmony_ci                               (mapping[name], dependency, name))
4741cb0ef41Sopenharmony_ci
4751cb0ef41Sopenharmony_ci    def enter_frame(self, frame):
4761cb0ef41Sopenharmony_ci        undefs = []
4771cb0ef41Sopenharmony_ci        for target, (action, param) in iteritems(frame.symbols.loads):
4781cb0ef41Sopenharmony_ci            if action == VAR_LOAD_PARAMETER:
4791cb0ef41Sopenharmony_ci                pass
4801cb0ef41Sopenharmony_ci            elif action == VAR_LOAD_RESOLVE:
4811cb0ef41Sopenharmony_ci                self.writeline('%s = %s(%r)' %
4821cb0ef41Sopenharmony_ci                               (target, self.get_resolve_func(), param))
4831cb0ef41Sopenharmony_ci            elif action == VAR_LOAD_ALIAS:
4841cb0ef41Sopenharmony_ci                self.writeline('%s = %s' % (target, param))
4851cb0ef41Sopenharmony_ci            elif action == VAR_LOAD_UNDEFINED:
4861cb0ef41Sopenharmony_ci                undefs.append(target)
4871cb0ef41Sopenharmony_ci            else:
4881cb0ef41Sopenharmony_ci                raise NotImplementedError('unknown load instruction')
4891cb0ef41Sopenharmony_ci        if undefs:
4901cb0ef41Sopenharmony_ci            self.writeline('%s = missing' % ' = '.join(undefs))
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci    def leave_frame(self, frame, with_python_scope=False):
4931cb0ef41Sopenharmony_ci        if not with_python_scope:
4941cb0ef41Sopenharmony_ci            undefs = []
4951cb0ef41Sopenharmony_ci            for target, _ in iteritems(frame.symbols.loads):
4961cb0ef41Sopenharmony_ci                undefs.append(target)
4971cb0ef41Sopenharmony_ci            if undefs:
4981cb0ef41Sopenharmony_ci                self.writeline('%s = missing' % ' = '.join(undefs))
4991cb0ef41Sopenharmony_ci
5001cb0ef41Sopenharmony_ci    def func(self, name):
5011cb0ef41Sopenharmony_ci        if self.environment.is_async:
5021cb0ef41Sopenharmony_ci            return 'async def %s' % name
5031cb0ef41Sopenharmony_ci        return 'def %s' % name
5041cb0ef41Sopenharmony_ci
5051cb0ef41Sopenharmony_ci    def macro_body(self, node, frame):
5061cb0ef41Sopenharmony_ci        """Dump the function def of a macro or call block."""
5071cb0ef41Sopenharmony_ci        frame = frame.inner()
5081cb0ef41Sopenharmony_ci        frame.symbols.analyze_node(node)
5091cb0ef41Sopenharmony_ci        macro_ref = MacroRef(node)
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci        explicit_caller = None
5121cb0ef41Sopenharmony_ci        skip_special_params = set()
5131cb0ef41Sopenharmony_ci        args = []
5141cb0ef41Sopenharmony_ci        for idx, arg in enumerate(node.args):
5151cb0ef41Sopenharmony_ci            if arg.name == 'caller':
5161cb0ef41Sopenharmony_ci                explicit_caller = idx
5171cb0ef41Sopenharmony_ci            if arg.name in ('kwargs', 'varargs'):
5181cb0ef41Sopenharmony_ci                skip_special_params.add(arg.name)
5191cb0ef41Sopenharmony_ci            args.append(frame.symbols.ref(arg.name))
5201cb0ef41Sopenharmony_ci
5211cb0ef41Sopenharmony_ci        undeclared = find_undeclared(node.body, ('caller', 'kwargs', 'varargs'))
5221cb0ef41Sopenharmony_ci
5231cb0ef41Sopenharmony_ci        if 'caller' in undeclared:
5241cb0ef41Sopenharmony_ci            # In older Jinja2 versions there was a bug that allowed caller
5251cb0ef41Sopenharmony_ci            # to retain the special behavior even if it was mentioned in
5261cb0ef41Sopenharmony_ci            # the argument list.  However thankfully this was only really
5271cb0ef41Sopenharmony_ci            # working if it was the last argument.  So we are explicitly
5281cb0ef41Sopenharmony_ci            # checking this now and error out if it is anywhere else in
5291cb0ef41Sopenharmony_ci            # the argument list.
5301cb0ef41Sopenharmony_ci            if explicit_caller is not None:
5311cb0ef41Sopenharmony_ci                try:
5321cb0ef41Sopenharmony_ci                    node.defaults[explicit_caller - len(node.args)]
5331cb0ef41Sopenharmony_ci                except IndexError:
5341cb0ef41Sopenharmony_ci                    self.fail('When defining macros or call blocks the '
5351cb0ef41Sopenharmony_ci                              'special "caller" argument must be omitted '
5361cb0ef41Sopenharmony_ci                              'or be given a default.', node.lineno)
5371cb0ef41Sopenharmony_ci            else:
5381cb0ef41Sopenharmony_ci                args.append(frame.symbols.declare_parameter('caller'))
5391cb0ef41Sopenharmony_ci            macro_ref.accesses_caller = True
5401cb0ef41Sopenharmony_ci        if 'kwargs' in undeclared and not 'kwargs' in skip_special_params:
5411cb0ef41Sopenharmony_ci            args.append(frame.symbols.declare_parameter('kwargs'))
5421cb0ef41Sopenharmony_ci            macro_ref.accesses_kwargs = True
5431cb0ef41Sopenharmony_ci        if 'varargs' in undeclared and not 'varargs' in skip_special_params:
5441cb0ef41Sopenharmony_ci            args.append(frame.symbols.declare_parameter('varargs'))
5451cb0ef41Sopenharmony_ci            macro_ref.accesses_varargs = True
5461cb0ef41Sopenharmony_ci
5471cb0ef41Sopenharmony_ci        # macros are delayed, they never require output checks
5481cb0ef41Sopenharmony_ci        frame.require_output_check = False
5491cb0ef41Sopenharmony_ci        frame.symbols.analyze_node(node)
5501cb0ef41Sopenharmony_ci        self.writeline('%s(%s):' % (self.func('macro'), ', '.join(args)), node)
5511cb0ef41Sopenharmony_ci        self.indent()
5521cb0ef41Sopenharmony_ci
5531cb0ef41Sopenharmony_ci        self.buffer(frame)
5541cb0ef41Sopenharmony_ci        self.enter_frame(frame)
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci        self.push_parameter_definitions(frame)
5571cb0ef41Sopenharmony_ci        for idx, arg in enumerate(node.args):
5581cb0ef41Sopenharmony_ci            ref = frame.symbols.ref(arg.name)
5591cb0ef41Sopenharmony_ci            self.writeline('if %s is missing:' % ref)
5601cb0ef41Sopenharmony_ci            self.indent()
5611cb0ef41Sopenharmony_ci            try:
5621cb0ef41Sopenharmony_ci                default = node.defaults[idx - len(node.args)]
5631cb0ef41Sopenharmony_ci            except IndexError:
5641cb0ef41Sopenharmony_ci                self.writeline('%s = undefined(%r, name=%r)' % (
5651cb0ef41Sopenharmony_ci                    ref,
5661cb0ef41Sopenharmony_ci                    'parameter %r was not provided' % arg.name,
5671cb0ef41Sopenharmony_ci                    arg.name))
5681cb0ef41Sopenharmony_ci            else:
5691cb0ef41Sopenharmony_ci                self.writeline('%s = ' % ref)
5701cb0ef41Sopenharmony_ci                self.visit(default, frame)
5711cb0ef41Sopenharmony_ci            self.mark_parameter_stored(ref)
5721cb0ef41Sopenharmony_ci            self.outdent()
5731cb0ef41Sopenharmony_ci        self.pop_parameter_definitions()
5741cb0ef41Sopenharmony_ci
5751cb0ef41Sopenharmony_ci        self.blockvisit(node.body, frame)
5761cb0ef41Sopenharmony_ci        self.return_buffer_contents(frame, force_unescaped=True)
5771cb0ef41Sopenharmony_ci        self.leave_frame(frame, with_python_scope=True)
5781cb0ef41Sopenharmony_ci        self.outdent()
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci        return frame, macro_ref
5811cb0ef41Sopenharmony_ci
5821cb0ef41Sopenharmony_ci    def macro_def(self, macro_ref, frame):
5831cb0ef41Sopenharmony_ci        """Dump the macro definition for the def created by macro_body."""
5841cb0ef41Sopenharmony_ci        arg_tuple = ', '.join(repr(x.name) for x in macro_ref.node.args)
5851cb0ef41Sopenharmony_ci        name = getattr(macro_ref.node, 'name', None)
5861cb0ef41Sopenharmony_ci        if len(macro_ref.node.args) == 1:
5871cb0ef41Sopenharmony_ci            arg_tuple += ','
5881cb0ef41Sopenharmony_ci        self.write('Macro(environment, macro, %r, (%s), %r, %r, %r, '
5891cb0ef41Sopenharmony_ci                   'context.eval_ctx.autoescape)' %
5901cb0ef41Sopenharmony_ci                   (name, arg_tuple, macro_ref.accesses_kwargs,
5911cb0ef41Sopenharmony_ci                    macro_ref.accesses_varargs, macro_ref.accesses_caller))
5921cb0ef41Sopenharmony_ci
5931cb0ef41Sopenharmony_ci    def position(self, node):
5941cb0ef41Sopenharmony_ci        """Return a human readable position for the node."""
5951cb0ef41Sopenharmony_ci        rv = 'line %d' % node.lineno
5961cb0ef41Sopenharmony_ci        if self.name is not None:
5971cb0ef41Sopenharmony_ci            rv += ' in ' + repr(self.name)
5981cb0ef41Sopenharmony_ci        return rv
5991cb0ef41Sopenharmony_ci
6001cb0ef41Sopenharmony_ci    def dump_local_context(self, frame):
6011cb0ef41Sopenharmony_ci        return '{%s}' % ', '.join(
6021cb0ef41Sopenharmony_ci            '%r: %s' % (name, target) for name, target
6031cb0ef41Sopenharmony_ci            in iteritems(frame.symbols.dump_stores()))
6041cb0ef41Sopenharmony_ci
6051cb0ef41Sopenharmony_ci    def write_commons(self):
6061cb0ef41Sopenharmony_ci        """Writes a common preamble that is used by root and block functions.
6071cb0ef41Sopenharmony_ci        Primarily this sets up common local helpers and enforces a generator
6081cb0ef41Sopenharmony_ci        through a dead branch.
6091cb0ef41Sopenharmony_ci        """
6101cb0ef41Sopenharmony_ci        self.writeline('resolve = context.resolve_or_missing')
6111cb0ef41Sopenharmony_ci        self.writeline('undefined = environment.undefined')
6121cb0ef41Sopenharmony_ci        self.writeline('if 0: yield None')
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci    def push_parameter_definitions(self, frame):
6151cb0ef41Sopenharmony_ci        """Pushes all parameter targets from the given frame into a local
6161cb0ef41Sopenharmony_ci        stack that permits tracking of yet to be assigned parameters.  In
6171cb0ef41Sopenharmony_ci        particular this enables the optimization from `visit_Name` to skip
6181cb0ef41Sopenharmony_ci        undefined expressions for parameters in macros as macros can reference
6191cb0ef41Sopenharmony_ci        otherwise unbound parameters.
6201cb0ef41Sopenharmony_ci        """
6211cb0ef41Sopenharmony_ci        self._param_def_block.append(frame.symbols.dump_param_targets())
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci    def pop_parameter_definitions(self):
6241cb0ef41Sopenharmony_ci        """Pops the current parameter definitions set."""
6251cb0ef41Sopenharmony_ci        self._param_def_block.pop()
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci    def mark_parameter_stored(self, target):
6281cb0ef41Sopenharmony_ci        """Marks a parameter in the current parameter definitions as stored.
6291cb0ef41Sopenharmony_ci        This will skip the enforced undefined checks.
6301cb0ef41Sopenharmony_ci        """
6311cb0ef41Sopenharmony_ci        if self._param_def_block:
6321cb0ef41Sopenharmony_ci            self._param_def_block[-1].discard(target)
6331cb0ef41Sopenharmony_ci
6341cb0ef41Sopenharmony_ci    def push_context_reference(self, target):
6351cb0ef41Sopenharmony_ci        self._context_reference_stack.append(target)
6361cb0ef41Sopenharmony_ci
6371cb0ef41Sopenharmony_ci    def pop_context_reference(self):
6381cb0ef41Sopenharmony_ci        self._context_reference_stack.pop()
6391cb0ef41Sopenharmony_ci
6401cb0ef41Sopenharmony_ci    def get_context_ref(self):
6411cb0ef41Sopenharmony_ci        return self._context_reference_stack[-1]
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci    def get_resolve_func(self):
6441cb0ef41Sopenharmony_ci        target = self._context_reference_stack[-1]
6451cb0ef41Sopenharmony_ci        if target == 'context':
6461cb0ef41Sopenharmony_ci            return 'resolve'
6471cb0ef41Sopenharmony_ci        return '%s.resolve' % target
6481cb0ef41Sopenharmony_ci
6491cb0ef41Sopenharmony_ci    def derive_context(self, frame):
6501cb0ef41Sopenharmony_ci        return '%s.derived(%s)' % (
6511cb0ef41Sopenharmony_ci            self.get_context_ref(),
6521cb0ef41Sopenharmony_ci            self.dump_local_context(frame),
6531cb0ef41Sopenharmony_ci        )
6541cb0ef41Sopenharmony_ci
6551cb0ef41Sopenharmony_ci    def parameter_is_undeclared(self, target):
6561cb0ef41Sopenharmony_ci        """Checks if a given target is an undeclared parameter."""
6571cb0ef41Sopenharmony_ci        if not self._param_def_block:
6581cb0ef41Sopenharmony_ci            return False
6591cb0ef41Sopenharmony_ci        return target in self._param_def_block[-1]
6601cb0ef41Sopenharmony_ci
6611cb0ef41Sopenharmony_ci    def push_assign_tracking(self):
6621cb0ef41Sopenharmony_ci        """Pushes a new layer for assignment tracking."""
6631cb0ef41Sopenharmony_ci        self._assign_stack.append(set())
6641cb0ef41Sopenharmony_ci
6651cb0ef41Sopenharmony_ci    def pop_assign_tracking(self, frame):
6661cb0ef41Sopenharmony_ci        """Pops the topmost level for assignment tracking and updates the
6671cb0ef41Sopenharmony_ci        context variables if necessary.
6681cb0ef41Sopenharmony_ci        """
6691cb0ef41Sopenharmony_ci        vars = self._assign_stack.pop()
6701cb0ef41Sopenharmony_ci        if not frame.toplevel or not vars:
6711cb0ef41Sopenharmony_ci            return
6721cb0ef41Sopenharmony_ci        public_names = [x for x in vars if x[:1] != '_']
6731cb0ef41Sopenharmony_ci        if len(vars) == 1:
6741cb0ef41Sopenharmony_ci            name = next(iter(vars))
6751cb0ef41Sopenharmony_ci            ref = frame.symbols.ref(name)
6761cb0ef41Sopenharmony_ci            self.writeline('context.vars[%r] = %s' % (name, ref))
6771cb0ef41Sopenharmony_ci        else:
6781cb0ef41Sopenharmony_ci            self.writeline('context.vars.update({')
6791cb0ef41Sopenharmony_ci            for idx, name in enumerate(vars):
6801cb0ef41Sopenharmony_ci                if idx:
6811cb0ef41Sopenharmony_ci                    self.write(', ')
6821cb0ef41Sopenharmony_ci                ref = frame.symbols.ref(name)
6831cb0ef41Sopenharmony_ci                self.write('%r: %s' % (name, ref))
6841cb0ef41Sopenharmony_ci            self.write('})')
6851cb0ef41Sopenharmony_ci        if public_names:
6861cb0ef41Sopenharmony_ci            if len(public_names) == 1:
6871cb0ef41Sopenharmony_ci                self.writeline('context.exported_vars.add(%r)' %
6881cb0ef41Sopenharmony_ci                               public_names[0])
6891cb0ef41Sopenharmony_ci            else:
6901cb0ef41Sopenharmony_ci                self.writeline('context.exported_vars.update((%s))' %
6911cb0ef41Sopenharmony_ci                               ', '.join(imap(repr, public_names)))
6921cb0ef41Sopenharmony_ci
6931cb0ef41Sopenharmony_ci    # -- Statement Visitors
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci    def visit_Template(self, node, frame=None):
6961cb0ef41Sopenharmony_ci        assert frame is None, 'no root frame allowed'
6971cb0ef41Sopenharmony_ci        eval_ctx = EvalContext(self.environment, self.name)
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci        from jinja2.runtime import __all__ as exported
7001cb0ef41Sopenharmony_ci        self.writeline('from __future__ import %s' % ', '.join(code_features))
7011cb0ef41Sopenharmony_ci        self.writeline('from jinja2.runtime import ' + ', '.join(exported))
7021cb0ef41Sopenharmony_ci
7031cb0ef41Sopenharmony_ci        if self.environment.is_async:
7041cb0ef41Sopenharmony_ci            self.writeline('from jinja2.asyncsupport import auto_await, '
7051cb0ef41Sopenharmony_ci                           'auto_aiter, make_async_loop_context')
7061cb0ef41Sopenharmony_ci
7071cb0ef41Sopenharmony_ci        # if we want a deferred initialization we cannot move the
7081cb0ef41Sopenharmony_ci        # environment into a local name
7091cb0ef41Sopenharmony_ci        envenv = not self.defer_init and ', environment=environment' or ''
7101cb0ef41Sopenharmony_ci
7111cb0ef41Sopenharmony_ci        # do we have an extends tag at all?  If not, we can save some
7121cb0ef41Sopenharmony_ci        # overhead by just not processing any inheritance code.
7131cb0ef41Sopenharmony_ci        have_extends = node.find(nodes.Extends) is not None
7141cb0ef41Sopenharmony_ci
7151cb0ef41Sopenharmony_ci        # find all blocks
7161cb0ef41Sopenharmony_ci        for block in node.find_all(nodes.Block):
7171cb0ef41Sopenharmony_ci            if block.name in self.blocks:
7181cb0ef41Sopenharmony_ci                self.fail('block %r defined twice' % block.name, block.lineno)
7191cb0ef41Sopenharmony_ci            self.blocks[block.name] = block
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci        # find all imports and import them
7221cb0ef41Sopenharmony_ci        for import_ in node.find_all(nodes.ImportedName):
7231cb0ef41Sopenharmony_ci            if import_.importname not in self.import_aliases:
7241cb0ef41Sopenharmony_ci                imp = import_.importname
7251cb0ef41Sopenharmony_ci                self.import_aliases[imp] = alias = self.temporary_identifier()
7261cb0ef41Sopenharmony_ci                if '.' in imp:
7271cb0ef41Sopenharmony_ci                    module, obj = imp.rsplit('.', 1)
7281cb0ef41Sopenharmony_ci                    self.writeline('from %s import %s as %s' %
7291cb0ef41Sopenharmony_ci                                   (module, obj, alias))
7301cb0ef41Sopenharmony_ci                else:
7311cb0ef41Sopenharmony_ci                    self.writeline('import %s as %s' % (imp, alias))
7321cb0ef41Sopenharmony_ci
7331cb0ef41Sopenharmony_ci        # add the load name
7341cb0ef41Sopenharmony_ci        self.writeline('name = %r' % self.name)
7351cb0ef41Sopenharmony_ci
7361cb0ef41Sopenharmony_ci        # generate the root render function.
7371cb0ef41Sopenharmony_ci        self.writeline('%s(context, missing=missing%s):' %
7381cb0ef41Sopenharmony_ci                       (self.func('root'), envenv), extra=1)
7391cb0ef41Sopenharmony_ci        self.indent()
7401cb0ef41Sopenharmony_ci        self.write_commons()
7411cb0ef41Sopenharmony_ci
7421cb0ef41Sopenharmony_ci        # process the root
7431cb0ef41Sopenharmony_ci        frame = Frame(eval_ctx)
7441cb0ef41Sopenharmony_ci        if 'self' in find_undeclared(node.body, ('self',)):
7451cb0ef41Sopenharmony_ci            ref = frame.symbols.declare_parameter('self')
7461cb0ef41Sopenharmony_ci            self.writeline('%s = TemplateReference(context)' % ref)
7471cb0ef41Sopenharmony_ci        frame.symbols.analyze_node(node)
7481cb0ef41Sopenharmony_ci        frame.toplevel = frame.rootlevel = True
7491cb0ef41Sopenharmony_ci        frame.require_output_check = have_extends and not self.has_known_extends
7501cb0ef41Sopenharmony_ci        if have_extends:
7511cb0ef41Sopenharmony_ci            self.writeline('parent_template = None')
7521cb0ef41Sopenharmony_ci        self.enter_frame(frame)
7531cb0ef41Sopenharmony_ci        self.pull_dependencies(node.body)
7541cb0ef41Sopenharmony_ci        self.blockvisit(node.body, frame)
7551cb0ef41Sopenharmony_ci        self.leave_frame(frame, with_python_scope=True)
7561cb0ef41Sopenharmony_ci        self.outdent()
7571cb0ef41Sopenharmony_ci
7581cb0ef41Sopenharmony_ci        # make sure that the parent root is called.
7591cb0ef41Sopenharmony_ci        if have_extends:
7601cb0ef41Sopenharmony_ci            if not self.has_known_extends:
7611cb0ef41Sopenharmony_ci                self.indent()
7621cb0ef41Sopenharmony_ci                self.writeline('if parent_template is not None:')
7631cb0ef41Sopenharmony_ci            self.indent()
7641cb0ef41Sopenharmony_ci            if supports_yield_from and not self.environment.is_async:
7651cb0ef41Sopenharmony_ci                self.writeline('yield from parent_template.'
7661cb0ef41Sopenharmony_ci                               'root_render_func(context)')
7671cb0ef41Sopenharmony_ci            else:
7681cb0ef41Sopenharmony_ci                self.writeline('%sfor event in parent_template.'
7691cb0ef41Sopenharmony_ci                               'root_render_func(context):' %
7701cb0ef41Sopenharmony_ci                               (self.environment.is_async and 'async ' or ''))
7711cb0ef41Sopenharmony_ci                self.indent()
7721cb0ef41Sopenharmony_ci                self.writeline('yield event')
7731cb0ef41Sopenharmony_ci                self.outdent()
7741cb0ef41Sopenharmony_ci            self.outdent(1 + (not self.has_known_extends))
7751cb0ef41Sopenharmony_ci
7761cb0ef41Sopenharmony_ci        # at this point we now have the blocks collected and can visit them too.
7771cb0ef41Sopenharmony_ci        for name, block in iteritems(self.blocks):
7781cb0ef41Sopenharmony_ci            self.writeline('%s(context, missing=missing%s):' %
7791cb0ef41Sopenharmony_ci                           (self.func('block_' + name), envenv),
7801cb0ef41Sopenharmony_ci                           block, 1)
7811cb0ef41Sopenharmony_ci            self.indent()
7821cb0ef41Sopenharmony_ci            self.write_commons()
7831cb0ef41Sopenharmony_ci            # It's important that we do not make this frame a child of the
7841cb0ef41Sopenharmony_ci            # toplevel template.  This would cause a variety of
7851cb0ef41Sopenharmony_ci            # interesting issues with identifier tracking.
7861cb0ef41Sopenharmony_ci            block_frame = Frame(eval_ctx)
7871cb0ef41Sopenharmony_ci            undeclared = find_undeclared(block.body, ('self', 'super'))
7881cb0ef41Sopenharmony_ci            if 'self' in undeclared:
7891cb0ef41Sopenharmony_ci                ref = block_frame.symbols.declare_parameter('self')
7901cb0ef41Sopenharmony_ci                self.writeline('%s = TemplateReference(context)' % ref)
7911cb0ef41Sopenharmony_ci            if 'super' in undeclared:
7921cb0ef41Sopenharmony_ci                ref = block_frame.symbols.declare_parameter('super')
7931cb0ef41Sopenharmony_ci                self.writeline('%s = context.super(%r, '
7941cb0ef41Sopenharmony_ci                               'block_%s)' % (ref, name, name))
7951cb0ef41Sopenharmony_ci            block_frame.symbols.analyze_node(block)
7961cb0ef41Sopenharmony_ci            block_frame.block = name
7971cb0ef41Sopenharmony_ci            self.enter_frame(block_frame)
7981cb0ef41Sopenharmony_ci            self.pull_dependencies(block.body)
7991cb0ef41Sopenharmony_ci            self.blockvisit(block.body, block_frame)
8001cb0ef41Sopenharmony_ci            self.leave_frame(block_frame, with_python_scope=True)
8011cb0ef41Sopenharmony_ci            self.outdent()
8021cb0ef41Sopenharmony_ci
8031cb0ef41Sopenharmony_ci        self.writeline('blocks = {%s}' % ', '.join('%r: block_%s' % (x, x)
8041cb0ef41Sopenharmony_ci                                                   for x in self.blocks),
8051cb0ef41Sopenharmony_ci                       extra=1)
8061cb0ef41Sopenharmony_ci
8071cb0ef41Sopenharmony_ci        # add a function that returns the debug info
8081cb0ef41Sopenharmony_ci        self.writeline('debug_info = %r' % '&'.join('%s=%s' % x for x
8091cb0ef41Sopenharmony_ci                                                    in self.debug_info))
8101cb0ef41Sopenharmony_ci
8111cb0ef41Sopenharmony_ci    def visit_Block(self, node, frame):
8121cb0ef41Sopenharmony_ci        """Call a block and register it for the template."""
8131cb0ef41Sopenharmony_ci        level = 0
8141cb0ef41Sopenharmony_ci        if frame.toplevel:
8151cb0ef41Sopenharmony_ci            # if we know that we are a child template, there is no need to
8161cb0ef41Sopenharmony_ci            # check if we are one
8171cb0ef41Sopenharmony_ci            if self.has_known_extends:
8181cb0ef41Sopenharmony_ci                return
8191cb0ef41Sopenharmony_ci            if self.extends_so_far > 0:
8201cb0ef41Sopenharmony_ci                self.writeline('if parent_template is None:')
8211cb0ef41Sopenharmony_ci                self.indent()
8221cb0ef41Sopenharmony_ci                level += 1
8231cb0ef41Sopenharmony_ci
8241cb0ef41Sopenharmony_ci        if node.scoped:
8251cb0ef41Sopenharmony_ci            context = self.derive_context(frame)
8261cb0ef41Sopenharmony_ci        else:
8271cb0ef41Sopenharmony_ci            context = self.get_context_ref()
8281cb0ef41Sopenharmony_ci
8291cb0ef41Sopenharmony_ci        if supports_yield_from and not self.environment.is_async and \
8301cb0ef41Sopenharmony_ci           frame.buffer is None:
8311cb0ef41Sopenharmony_ci            self.writeline('yield from context.blocks[%r][0](%s)' % (
8321cb0ef41Sopenharmony_ci                           node.name, context), node)
8331cb0ef41Sopenharmony_ci        else:
8341cb0ef41Sopenharmony_ci            loop = self.environment.is_async and 'async for' or 'for'
8351cb0ef41Sopenharmony_ci            self.writeline('%s event in context.blocks[%r][0](%s):' % (
8361cb0ef41Sopenharmony_ci                           loop, node.name, context), node)
8371cb0ef41Sopenharmony_ci            self.indent()
8381cb0ef41Sopenharmony_ci            self.simple_write('event', frame)
8391cb0ef41Sopenharmony_ci            self.outdent()
8401cb0ef41Sopenharmony_ci
8411cb0ef41Sopenharmony_ci        self.outdent(level)
8421cb0ef41Sopenharmony_ci
8431cb0ef41Sopenharmony_ci    def visit_Extends(self, node, frame):
8441cb0ef41Sopenharmony_ci        """Calls the extender."""
8451cb0ef41Sopenharmony_ci        if not frame.toplevel:
8461cb0ef41Sopenharmony_ci            self.fail('cannot use extend from a non top-level scope',
8471cb0ef41Sopenharmony_ci                      node.lineno)
8481cb0ef41Sopenharmony_ci
8491cb0ef41Sopenharmony_ci        # if the number of extends statements in general is zero so
8501cb0ef41Sopenharmony_ci        # far, we don't have to add a check if something extended
8511cb0ef41Sopenharmony_ci        # the template before this one.
8521cb0ef41Sopenharmony_ci        if self.extends_so_far > 0:
8531cb0ef41Sopenharmony_ci
8541cb0ef41Sopenharmony_ci            # if we have a known extends we just add a template runtime
8551cb0ef41Sopenharmony_ci            # error into the generated code.  We could catch that at compile
8561cb0ef41Sopenharmony_ci            # time too, but i welcome it not to confuse users by throwing the
8571cb0ef41Sopenharmony_ci            # same error at different times just "because we can".
8581cb0ef41Sopenharmony_ci            if not self.has_known_extends:
8591cb0ef41Sopenharmony_ci                self.writeline('if parent_template is not None:')
8601cb0ef41Sopenharmony_ci                self.indent()
8611cb0ef41Sopenharmony_ci            self.writeline('raise TemplateRuntimeError(%r)' %
8621cb0ef41Sopenharmony_ci                           'extended multiple times')
8631cb0ef41Sopenharmony_ci
8641cb0ef41Sopenharmony_ci            # if we have a known extends already we don't need that code here
8651cb0ef41Sopenharmony_ci            # as we know that the template execution will end here.
8661cb0ef41Sopenharmony_ci            if self.has_known_extends:
8671cb0ef41Sopenharmony_ci                raise CompilerExit()
8681cb0ef41Sopenharmony_ci            else:
8691cb0ef41Sopenharmony_ci                self.outdent()
8701cb0ef41Sopenharmony_ci
8711cb0ef41Sopenharmony_ci        self.writeline('parent_template = environment.get_template(', node)
8721cb0ef41Sopenharmony_ci        self.visit(node.template, frame)
8731cb0ef41Sopenharmony_ci        self.write(', %r)' % self.name)
8741cb0ef41Sopenharmony_ci        self.writeline('for name, parent_block in parent_template.'
8751cb0ef41Sopenharmony_ci                       'blocks.%s():' % dict_item_iter)
8761cb0ef41Sopenharmony_ci        self.indent()
8771cb0ef41Sopenharmony_ci        self.writeline('context.blocks.setdefault(name, []).'
8781cb0ef41Sopenharmony_ci                       'append(parent_block)')
8791cb0ef41Sopenharmony_ci        self.outdent()
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ci        # if this extends statement was in the root level we can take
8821cb0ef41Sopenharmony_ci        # advantage of that information and simplify the generated code
8831cb0ef41Sopenharmony_ci        # in the top level from this point onwards
8841cb0ef41Sopenharmony_ci        if frame.rootlevel:
8851cb0ef41Sopenharmony_ci            self.has_known_extends = True
8861cb0ef41Sopenharmony_ci
8871cb0ef41Sopenharmony_ci        # and now we have one more
8881cb0ef41Sopenharmony_ci        self.extends_so_far += 1
8891cb0ef41Sopenharmony_ci
8901cb0ef41Sopenharmony_ci    def visit_Include(self, node, frame):
8911cb0ef41Sopenharmony_ci        """Handles includes."""
8921cb0ef41Sopenharmony_ci        if node.ignore_missing:
8931cb0ef41Sopenharmony_ci            self.writeline('try:')
8941cb0ef41Sopenharmony_ci            self.indent()
8951cb0ef41Sopenharmony_ci
8961cb0ef41Sopenharmony_ci        func_name = 'get_or_select_template'
8971cb0ef41Sopenharmony_ci        if isinstance(node.template, nodes.Const):
8981cb0ef41Sopenharmony_ci            if isinstance(node.template.value, string_types):
8991cb0ef41Sopenharmony_ci                func_name = 'get_template'
9001cb0ef41Sopenharmony_ci            elif isinstance(node.template.value, (tuple, list)):
9011cb0ef41Sopenharmony_ci                func_name = 'select_template'
9021cb0ef41Sopenharmony_ci        elif isinstance(node.template, (nodes.Tuple, nodes.List)):
9031cb0ef41Sopenharmony_ci            func_name = 'select_template'
9041cb0ef41Sopenharmony_ci
9051cb0ef41Sopenharmony_ci        self.writeline('template = environment.%s(' % func_name, node)
9061cb0ef41Sopenharmony_ci        self.visit(node.template, frame)
9071cb0ef41Sopenharmony_ci        self.write(', %r)' % self.name)
9081cb0ef41Sopenharmony_ci        if node.ignore_missing:
9091cb0ef41Sopenharmony_ci            self.outdent()
9101cb0ef41Sopenharmony_ci            self.writeline('except TemplateNotFound:')
9111cb0ef41Sopenharmony_ci            self.indent()
9121cb0ef41Sopenharmony_ci            self.writeline('pass')
9131cb0ef41Sopenharmony_ci            self.outdent()
9141cb0ef41Sopenharmony_ci            self.writeline('else:')
9151cb0ef41Sopenharmony_ci            self.indent()
9161cb0ef41Sopenharmony_ci
9171cb0ef41Sopenharmony_ci        skip_event_yield = False
9181cb0ef41Sopenharmony_ci        if node.with_context:
9191cb0ef41Sopenharmony_ci            loop = self.environment.is_async and 'async for' or 'for'
9201cb0ef41Sopenharmony_ci            self.writeline('%s event in template.root_render_func('
9211cb0ef41Sopenharmony_ci                           'template.new_context(context.get_all(), True, '
9221cb0ef41Sopenharmony_ci                           '%s)):' % (loop, self.dump_local_context(frame)))
9231cb0ef41Sopenharmony_ci        elif self.environment.is_async:
9241cb0ef41Sopenharmony_ci            self.writeline('for event in (await '
9251cb0ef41Sopenharmony_ci                           'template._get_default_module_async())'
9261cb0ef41Sopenharmony_ci                           '._body_stream:')
9271cb0ef41Sopenharmony_ci        else:
9281cb0ef41Sopenharmony_ci            if supports_yield_from:
9291cb0ef41Sopenharmony_ci                self.writeline('yield from template._get_default_module()'
9301cb0ef41Sopenharmony_ci                               '._body_stream')
9311cb0ef41Sopenharmony_ci                skip_event_yield = True
9321cb0ef41Sopenharmony_ci            else:
9331cb0ef41Sopenharmony_ci                self.writeline('for event in template._get_default_module()'
9341cb0ef41Sopenharmony_ci                               '._body_stream:')
9351cb0ef41Sopenharmony_ci
9361cb0ef41Sopenharmony_ci        if not skip_event_yield:
9371cb0ef41Sopenharmony_ci            self.indent()
9381cb0ef41Sopenharmony_ci            self.simple_write('event', frame)
9391cb0ef41Sopenharmony_ci            self.outdent()
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_ci        if node.ignore_missing:
9421cb0ef41Sopenharmony_ci            self.outdent()
9431cb0ef41Sopenharmony_ci
9441cb0ef41Sopenharmony_ci    def visit_Import(self, node, frame):
9451cb0ef41Sopenharmony_ci        """Visit regular imports."""
9461cb0ef41Sopenharmony_ci        self.writeline('%s = ' % frame.symbols.ref(node.target), node)
9471cb0ef41Sopenharmony_ci        if frame.toplevel:
9481cb0ef41Sopenharmony_ci            self.write('context.vars[%r] = ' % node.target)
9491cb0ef41Sopenharmony_ci        if self.environment.is_async:
9501cb0ef41Sopenharmony_ci            self.write('await ')
9511cb0ef41Sopenharmony_ci        self.write('environment.get_template(')
9521cb0ef41Sopenharmony_ci        self.visit(node.template, frame)
9531cb0ef41Sopenharmony_ci        self.write(', %r).' % self.name)
9541cb0ef41Sopenharmony_ci        if node.with_context:
9551cb0ef41Sopenharmony_ci            self.write('make_module%s(context.get_all(), True, %s)'
9561cb0ef41Sopenharmony_ci                       % (self.environment.is_async and '_async' or '',
9571cb0ef41Sopenharmony_ci                          self.dump_local_context(frame)))
9581cb0ef41Sopenharmony_ci        elif self.environment.is_async:
9591cb0ef41Sopenharmony_ci            self.write('_get_default_module_async()')
9601cb0ef41Sopenharmony_ci        else:
9611cb0ef41Sopenharmony_ci            self.write('_get_default_module()')
9621cb0ef41Sopenharmony_ci        if frame.toplevel and not node.target.startswith('_'):
9631cb0ef41Sopenharmony_ci            self.writeline('context.exported_vars.discard(%r)' % node.target)
9641cb0ef41Sopenharmony_ci
9651cb0ef41Sopenharmony_ci    def visit_FromImport(self, node, frame):
9661cb0ef41Sopenharmony_ci        """Visit named imports."""
9671cb0ef41Sopenharmony_ci        self.newline(node)
9681cb0ef41Sopenharmony_ci        self.write('included_template = %senvironment.get_template('
9691cb0ef41Sopenharmony_ci                   % (self.environment.is_async and 'await ' or ''))
9701cb0ef41Sopenharmony_ci        self.visit(node.template, frame)
9711cb0ef41Sopenharmony_ci        self.write(', %r).' % self.name)
9721cb0ef41Sopenharmony_ci        if node.with_context:
9731cb0ef41Sopenharmony_ci            self.write('make_module%s(context.get_all(), True, %s)'
9741cb0ef41Sopenharmony_ci                       % (self.environment.is_async and '_async' or '',
9751cb0ef41Sopenharmony_ci                          self.dump_local_context(frame)))
9761cb0ef41Sopenharmony_ci        elif self.environment.is_async:
9771cb0ef41Sopenharmony_ci            self.write('_get_default_module_async()')
9781cb0ef41Sopenharmony_ci        else:
9791cb0ef41Sopenharmony_ci            self.write('_get_default_module()')
9801cb0ef41Sopenharmony_ci
9811cb0ef41Sopenharmony_ci        var_names = []
9821cb0ef41Sopenharmony_ci        discarded_names = []
9831cb0ef41Sopenharmony_ci        for name in node.names:
9841cb0ef41Sopenharmony_ci            if isinstance(name, tuple):
9851cb0ef41Sopenharmony_ci                name, alias = name
9861cb0ef41Sopenharmony_ci            else:
9871cb0ef41Sopenharmony_ci                alias = name
9881cb0ef41Sopenharmony_ci            self.writeline('%s = getattr(included_template, '
9891cb0ef41Sopenharmony_ci                           '%r, missing)' % (frame.symbols.ref(alias), name))
9901cb0ef41Sopenharmony_ci            self.writeline('if %s is missing:' % frame.symbols.ref(alias))
9911cb0ef41Sopenharmony_ci            self.indent()
9921cb0ef41Sopenharmony_ci            self.writeline('%s = undefined(%r %% '
9931cb0ef41Sopenharmony_ci                           'included_template.__name__, '
9941cb0ef41Sopenharmony_ci                           'name=%r)' %
9951cb0ef41Sopenharmony_ci                           (frame.symbols.ref(alias),
9961cb0ef41Sopenharmony_ci                            'the template %%r (imported on %s) does '
9971cb0ef41Sopenharmony_ci                            'not export the requested name %s' % (
9981cb0ef41Sopenharmony_ci                                self.position(node),
9991cb0ef41Sopenharmony_ci                                repr(name)
10001cb0ef41Sopenharmony_ci                           ), name))
10011cb0ef41Sopenharmony_ci            self.outdent()
10021cb0ef41Sopenharmony_ci            if frame.toplevel:
10031cb0ef41Sopenharmony_ci                var_names.append(alias)
10041cb0ef41Sopenharmony_ci                if not alias.startswith('_'):
10051cb0ef41Sopenharmony_ci                    discarded_names.append(alias)
10061cb0ef41Sopenharmony_ci
10071cb0ef41Sopenharmony_ci        if var_names:
10081cb0ef41Sopenharmony_ci            if len(var_names) == 1:
10091cb0ef41Sopenharmony_ci                name = var_names[0]
10101cb0ef41Sopenharmony_ci                self.writeline('context.vars[%r] = %s' %
10111cb0ef41Sopenharmony_ci                               (name, frame.symbols.ref(name)))
10121cb0ef41Sopenharmony_ci            else:
10131cb0ef41Sopenharmony_ci                self.writeline('context.vars.update({%s})' % ', '.join(
10141cb0ef41Sopenharmony_ci                    '%r: %s' % (name, frame.symbols.ref(name)) for name in var_names
10151cb0ef41Sopenharmony_ci                ))
10161cb0ef41Sopenharmony_ci        if discarded_names:
10171cb0ef41Sopenharmony_ci            if len(discarded_names) == 1:
10181cb0ef41Sopenharmony_ci                self.writeline('context.exported_vars.discard(%r)' %
10191cb0ef41Sopenharmony_ci                               discarded_names[0])
10201cb0ef41Sopenharmony_ci            else:
10211cb0ef41Sopenharmony_ci                self.writeline('context.exported_vars.difference_'
10221cb0ef41Sopenharmony_ci                               'update((%s))' % ', '.join(imap(repr, discarded_names)))
10231cb0ef41Sopenharmony_ci
10241cb0ef41Sopenharmony_ci    def visit_For(self, node, frame):
10251cb0ef41Sopenharmony_ci        loop_frame = frame.inner()
10261cb0ef41Sopenharmony_ci        test_frame = frame.inner()
10271cb0ef41Sopenharmony_ci        else_frame = frame.inner()
10281cb0ef41Sopenharmony_ci
10291cb0ef41Sopenharmony_ci        # try to figure out if we have an extended loop.  An extended loop
10301cb0ef41Sopenharmony_ci        # is necessary if the loop is in recursive mode if the special loop
10311cb0ef41Sopenharmony_ci        # variable is accessed in the body.
10321cb0ef41Sopenharmony_ci        extended_loop = node.recursive or 'loop' in \
10331cb0ef41Sopenharmony_ci                        find_undeclared(node.iter_child_nodes(
10341cb0ef41Sopenharmony_ci                            only=('body',)), ('loop',))
10351cb0ef41Sopenharmony_ci
10361cb0ef41Sopenharmony_ci        loop_ref = None
10371cb0ef41Sopenharmony_ci        if extended_loop:
10381cb0ef41Sopenharmony_ci            loop_ref = loop_frame.symbols.declare_parameter('loop')
10391cb0ef41Sopenharmony_ci
10401cb0ef41Sopenharmony_ci        loop_frame.symbols.analyze_node(node, for_branch='body')
10411cb0ef41Sopenharmony_ci        if node.else_:
10421cb0ef41Sopenharmony_ci            else_frame.symbols.analyze_node(node, for_branch='else')
10431cb0ef41Sopenharmony_ci
10441cb0ef41Sopenharmony_ci        if node.test:
10451cb0ef41Sopenharmony_ci            loop_filter_func = self.temporary_identifier()
10461cb0ef41Sopenharmony_ci            test_frame.symbols.analyze_node(node, for_branch='test')
10471cb0ef41Sopenharmony_ci            self.writeline('%s(fiter):' % self.func(loop_filter_func), node.test)
10481cb0ef41Sopenharmony_ci            self.indent()
10491cb0ef41Sopenharmony_ci            self.enter_frame(test_frame)
10501cb0ef41Sopenharmony_ci            self.writeline(self.environment.is_async and 'async for ' or 'for ')
10511cb0ef41Sopenharmony_ci            self.visit(node.target, loop_frame)
10521cb0ef41Sopenharmony_ci            self.write(' in ')
10531cb0ef41Sopenharmony_ci            self.write(self.environment.is_async and 'auto_aiter(fiter)' or 'fiter')
10541cb0ef41Sopenharmony_ci            self.write(':')
10551cb0ef41Sopenharmony_ci            self.indent()
10561cb0ef41Sopenharmony_ci            self.writeline('if ', node.test)
10571cb0ef41Sopenharmony_ci            self.visit(node.test, test_frame)
10581cb0ef41Sopenharmony_ci            self.write(':')
10591cb0ef41Sopenharmony_ci            self.indent()
10601cb0ef41Sopenharmony_ci            self.writeline('yield ')
10611cb0ef41Sopenharmony_ci            self.visit(node.target, loop_frame)
10621cb0ef41Sopenharmony_ci            self.outdent(3)
10631cb0ef41Sopenharmony_ci            self.leave_frame(test_frame, with_python_scope=True)
10641cb0ef41Sopenharmony_ci
10651cb0ef41Sopenharmony_ci        # if we don't have an recursive loop we have to find the shadowed
10661cb0ef41Sopenharmony_ci        # variables at that point.  Because loops can be nested but the loop
10671cb0ef41Sopenharmony_ci        # variable is a special one we have to enforce aliasing for it.
10681cb0ef41Sopenharmony_ci        if node.recursive:
10691cb0ef41Sopenharmony_ci            self.writeline('%s(reciter, loop_render_func, depth=0):' %
10701cb0ef41Sopenharmony_ci                           self.func('loop'), node)
10711cb0ef41Sopenharmony_ci            self.indent()
10721cb0ef41Sopenharmony_ci            self.buffer(loop_frame)
10731cb0ef41Sopenharmony_ci
10741cb0ef41Sopenharmony_ci            # Use the same buffer for the else frame
10751cb0ef41Sopenharmony_ci            else_frame.buffer = loop_frame.buffer
10761cb0ef41Sopenharmony_ci
10771cb0ef41Sopenharmony_ci        # make sure the loop variable is a special one and raise a template
10781cb0ef41Sopenharmony_ci        # assertion error if a loop tries to write to loop
10791cb0ef41Sopenharmony_ci        if extended_loop:
10801cb0ef41Sopenharmony_ci            self.writeline('%s = missing' % loop_ref)
10811cb0ef41Sopenharmony_ci
10821cb0ef41Sopenharmony_ci        for name in node.find_all(nodes.Name):
10831cb0ef41Sopenharmony_ci            if name.ctx == 'store' and name.name == 'loop':
10841cb0ef41Sopenharmony_ci                self.fail('Can\'t assign to special loop variable '
10851cb0ef41Sopenharmony_ci                          'in for-loop target', name.lineno)
10861cb0ef41Sopenharmony_ci
10871cb0ef41Sopenharmony_ci        if node.else_:
10881cb0ef41Sopenharmony_ci            iteration_indicator = self.temporary_identifier()
10891cb0ef41Sopenharmony_ci            self.writeline('%s = 1' % iteration_indicator)
10901cb0ef41Sopenharmony_ci
10911cb0ef41Sopenharmony_ci        self.writeline(self.environment.is_async and 'async for ' or 'for ', node)
10921cb0ef41Sopenharmony_ci        self.visit(node.target, loop_frame)
10931cb0ef41Sopenharmony_ci        if extended_loop:
10941cb0ef41Sopenharmony_ci            if self.environment.is_async:
10951cb0ef41Sopenharmony_ci                self.write(', %s in await make_async_loop_context(' % loop_ref)
10961cb0ef41Sopenharmony_ci            else:
10971cb0ef41Sopenharmony_ci                self.write(', %s in LoopContext(' % loop_ref)
10981cb0ef41Sopenharmony_ci        else:
10991cb0ef41Sopenharmony_ci            self.write(' in ')
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_ci        if node.test:
11021cb0ef41Sopenharmony_ci            self.write('%s(' % loop_filter_func)
11031cb0ef41Sopenharmony_ci        if node.recursive:
11041cb0ef41Sopenharmony_ci            self.write('reciter')
11051cb0ef41Sopenharmony_ci        else:
11061cb0ef41Sopenharmony_ci            if self.environment.is_async and not extended_loop:
11071cb0ef41Sopenharmony_ci                self.write('auto_aiter(')
11081cb0ef41Sopenharmony_ci            self.visit(node.iter, frame)
11091cb0ef41Sopenharmony_ci            if self.environment.is_async and not extended_loop:
11101cb0ef41Sopenharmony_ci                self.write(')')
11111cb0ef41Sopenharmony_ci        if node.test:
11121cb0ef41Sopenharmony_ci            self.write(')')
11131cb0ef41Sopenharmony_ci
11141cb0ef41Sopenharmony_ci        if node.recursive:
11151cb0ef41Sopenharmony_ci            self.write(', undefined, loop_render_func, depth):')
11161cb0ef41Sopenharmony_ci        else:
11171cb0ef41Sopenharmony_ci            self.write(extended_loop and ', undefined):' or ':')
11181cb0ef41Sopenharmony_ci
11191cb0ef41Sopenharmony_ci        self.indent()
11201cb0ef41Sopenharmony_ci        self.enter_frame(loop_frame)
11211cb0ef41Sopenharmony_ci
11221cb0ef41Sopenharmony_ci        self.blockvisit(node.body, loop_frame)
11231cb0ef41Sopenharmony_ci        if node.else_:
11241cb0ef41Sopenharmony_ci            self.writeline('%s = 0' % iteration_indicator)
11251cb0ef41Sopenharmony_ci        self.outdent()
11261cb0ef41Sopenharmony_ci        self.leave_frame(loop_frame, with_python_scope=node.recursive
11271cb0ef41Sopenharmony_ci                         and not node.else_)
11281cb0ef41Sopenharmony_ci
11291cb0ef41Sopenharmony_ci        if node.else_:
11301cb0ef41Sopenharmony_ci            self.writeline('if %s:' % iteration_indicator)
11311cb0ef41Sopenharmony_ci            self.indent()
11321cb0ef41Sopenharmony_ci            self.enter_frame(else_frame)
11331cb0ef41Sopenharmony_ci            self.blockvisit(node.else_, else_frame)
11341cb0ef41Sopenharmony_ci            self.leave_frame(else_frame)
11351cb0ef41Sopenharmony_ci            self.outdent()
11361cb0ef41Sopenharmony_ci
11371cb0ef41Sopenharmony_ci        # if the node was recursive we have to return the buffer contents
11381cb0ef41Sopenharmony_ci        # and start the iteration code
11391cb0ef41Sopenharmony_ci        if node.recursive:
11401cb0ef41Sopenharmony_ci            self.return_buffer_contents(loop_frame)
11411cb0ef41Sopenharmony_ci            self.outdent()
11421cb0ef41Sopenharmony_ci            self.start_write(frame, node)
11431cb0ef41Sopenharmony_ci            if self.environment.is_async:
11441cb0ef41Sopenharmony_ci                self.write('await ')
11451cb0ef41Sopenharmony_ci            self.write('loop(')
11461cb0ef41Sopenharmony_ci            if self.environment.is_async:
11471cb0ef41Sopenharmony_ci                self.write('auto_aiter(')
11481cb0ef41Sopenharmony_ci            self.visit(node.iter, frame)
11491cb0ef41Sopenharmony_ci            if self.environment.is_async:
11501cb0ef41Sopenharmony_ci                self.write(')')
11511cb0ef41Sopenharmony_ci            self.write(', loop)')
11521cb0ef41Sopenharmony_ci            self.end_write(frame)
11531cb0ef41Sopenharmony_ci
11541cb0ef41Sopenharmony_ci    def visit_If(self, node, frame):
11551cb0ef41Sopenharmony_ci        if_frame = frame.soft()
11561cb0ef41Sopenharmony_ci        self.writeline('if ', node)
11571cb0ef41Sopenharmony_ci        self.visit(node.test, if_frame)
11581cb0ef41Sopenharmony_ci        self.write(':')
11591cb0ef41Sopenharmony_ci        self.indent()
11601cb0ef41Sopenharmony_ci        self.blockvisit(node.body, if_frame)
11611cb0ef41Sopenharmony_ci        self.outdent()
11621cb0ef41Sopenharmony_ci        for elif_ in node.elif_:
11631cb0ef41Sopenharmony_ci            self.writeline('elif ', elif_)
11641cb0ef41Sopenharmony_ci            self.visit(elif_.test, if_frame)
11651cb0ef41Sopenharmony_ci            self.write(':')
11661cb0ef41Sopenharmony_ci            self.indent()
11671cb0ef41Sopenharmony_ci            self.blockvisit(elif_.body, if_frame)
11681cb0ef41Sopenharmony_ci            self.outdent()
11691cb0ef41Sopenharmony_ci        if node.else_:
11701cb0ef41Sopenharmony_ci            self.writeline('else:')
11711cb0ef41Sopenharmony_ci            self.indent()
11721cb0ef41Sopenharmony_ci            self.blockvisit(node.else_, if_frame)
11731cb0ef41Sopenharmony_ci            self.outdent()
11741cb0ef41Sopenharmony_ci
11751cb0ef41Sopenharmony_ci    def visit_Macro(self, node, frame):
11761cb0ef41Sopenharmony_ci        macro_frame, macro_ref = self.macro_body(node, frame)
11771cb0ef41Sopenharmony_ci        self.newline()
11781cb0ef41Sopenharmony_ci        if frame.toplevel:
11791cb0ef41Sopenharmony_ci            if not node.name.startswith('_'):
11801cb0ef41Sopenharmony_ci                self.write('context.exported_vars.add(%r)' % node.name)
11811cb0ef41Sopenharmony_ci            ref = frame.symbols.ref(node.name)
11821cb0ef41Sopenharmony_ci            self.writeline('context.vars[%r] = ' % node.name)
11831cb0ef41Sopenharmony_ci        self.write('%s = ' % frame.symbols.ref(node.name))
11841cb0ef41Sopenharmony_ci        self.macro_def(macro_ref, macro_frame)
11851cb0ef41Sopenharmony_ci
11861cb0ef41Sopenharmony_ci    def visit_CallBlock(self, node, frame):
11871cb0ef41Sopenharmony_ci        call_frame, macro_ref = self.macro_body(node, frame)
11881cb0ef41Sopenharmony_ci        self.writeline('caller = ')
11891cb0ef41Sopenharmony_ci        self.macro_def(macro_ref, call_frame)
11901cb0ef41Sopenharmony_ci        self.start_write(frame, node)
11911cb0ef41Sopenharmony_ci        self.visit_Call(node.call, frame, forward_caller=True)
11921cb0ef41Sopenharmony_ci        self.end_write(frame)
11931cb0ef41Sopenharmony_ci
11941cb0ef41Sopenharmony_ci    def visit_FilterBlock(self, node, frame):
11951cb0ef41Sopenharmony_ci        filter_frame = frame.inner()
11961cb0ef41Sopenharmony_ci        filter_frame.symbols.analyze_node(node)
11971cb0ef41Sopenharmony_ci        self.enter_frame(filter_frame)
11981cb0ef41Sopenharmony_ci        self.buffer(filter_frame)
11991cb0ef41Sopenharmony_ci        self.blockvisit(node.body, filter_frame)
12001cb0ef41Sopenharmony_ci        self.start_write(frame, node)
12011cb0ef41Sopenharmony_ci        self.visit_Filter(node.filter, filter_frame)
12021cb0ef41Sopenharmony_ci        self.end_write(frame)
12031cb0ef41Sopenharmony_ci        self.leave_frame(filter_frame)
12041cb0ef41Sopenharmony_ci
12051cb0ef41Sopenharmony_ci    def visit_With(self, node, frame):
12061cb0ef41Sopenharmony_ci        with_frame = frame.inner()
12071cb0ef41Sopenharmony_ci        with_frame.symbols.analyze_node(node)
12081cb0ef41Sopenharmony_ci        self.enter_frame(with_frame)
12091cb0ef41Sopenharmony_ci        for idx, (target, expr) in enumerate(izip(node.targets, node.values)):
12101cb0ef41Sopenharmony_ci            self.newline()
12111cb0ef41Sopenharmony_ci            self.visit(target, with_frame)
12121cb0ef41Sopenharmony_ci            self.write(' = ')
12131cb0ef41Sopenharmony_ci            self.visit(expr, frame)
12141cb0ef41Sopenharmony_ci        self.blockvisit(node.body, with_frame)
12151cb0ef41Sopenharmony_ci        self.leave_frame(with_frame)
12161cb0ef41Sopenharmony_ci
12171cb0ef41Sopenharmony_ci    def visit_ExprStmt(self, node, frame):
12181cb0ef41Sopenharmony_ci        self.newline(node)
12191cb0ef41Sopenharmony_ci        self.visit(node.node, frame)
12201cb0ef41Sopenharmony_ci
12211cb0ef41Sopenharmony_ci    def visit_Output(self, node, frame):
12221cb0ef41Sopenharmony_ci        # if we have a known extends statement, we don't output anything
12231cb0ef41Sopenharmony_ci        # if we are in a require_output_check section
12241cb0ef41Sopenharmony_ci        if self.has_known_extends and frame.require_output_check:
12251cb0ef41Sopenharmony_ci            return
12261cb0ef41Sopenharmony_ci
12271cb0ef41Sopenharmony_ci        allow_constant_finalize = True
12281cb0ef41Sopenharmony_ci        if self.environment.finalize:
12291cb0ef41Sopenharmony_ci            func = self.environment.finalize
12301cb0ef41Sopenharmony_ci            if getattr(func, 'contextfunction', False) or \
12311cb0ef41Sopenharmony_ci               getattr(func, 'evalcontextfunction', False):
12321cb0ef41Sopenharmony_ci                allow_constant_finalize = False
12331cb0ef41Sopenharmony_ci            elif getattr(func, 'environmentfunction', False):
12341cb0ef41Sopenharmony_ci                finalize = lambda x: text_type(
12351cb0ef41Sopenharmony_ci                    self.environment.finalize(self.environment, x))
12361cb0ef41Sopenharmony_ci            else:
12371cb0ef41Sopenharmony_ci                finalize = lambda x: text_type(self.environment.finalize(x))
12381cb0ef41Sopenharmony_ci        else:
12391cb0ef41Sopenharmony_ci            finalize = text_type
12401cb0ef41Sopenharmony_ci
12411cb0ef41Sopenharmony_ci        # if we are inside a frame that requires output checking, we do so
12421cb0ef41Sopenharmony_ci        outdent_later = False
12431cb0ef41Sopenharmony_ci        if frame.require_output_check:
12441cb0ef41Sopenharmony_ci            self.writeline('if parent_template is None:')
12451cb0ef41Sopenharmony_ci            self.indent()
12461cb0ef41Sopenharmony_ci            outdent_later = True
12471cb0ef41Sopenharmony_ci
12481cb0ef41Sopenharmony_ci        # try to evaluate as many chunks as possible into a static
12491cb0ef41Sopenharmony_ci        # string at compile time.
12501cb0ef41Sopenharmony_ci        body = []
12511cb0ef41Sopenharmony_ci        for child in node.nodes:
12521cb0ef41Sopenharmony_ci            try:
12531cb0ef41Sopenharmony_ci                if not allow_constant_finalize:
12541cb0ef41Sopenharmony_ci                    raise nodes.Impossible()
12551cb0ef41Sopenharmony_ci                const = child.as_const(frame.eval_ctx)
12561cb0ef41Sopenharmony_ci            except nodes.Impossible:
12571cb0ef41Sopenharmony_ci                body.append(child)
12581cb0ef41Sopenharmony_ci                continue
12591cb0ef41Sopenharmony_ci            # the frame can't be volatile here, becaus otherwise the
12601cb0ef41Sopenharmony_ci            # as_const() function would raise an Impossible exception
12611cb0ef41Sopenharmony_ci            # at that point.
12621cb0ef41Sopenharmony_ci            try:
12631cb0ef41Sopenharmony_ci                if frame.eval_ctx.autoescape:
12641cb0ef41Sopenharmony_ci                    if hasattr(const, '__html__'):
12651cb0ef41Sopenharmony_ci                        const = const.__html__()
12661cb0ef41Sopenharmony_ci                    else:
12671cb0ef41Sopenharmony_ci                        const = escape(const)
12681cb0ef41Sopenharmony_ci                const = finalize(const)
12691cb0ef41Sopenharmony_ci            except Exception:
12701cb0ef41Sopenharmony_ci                # if something goes wrong here we evaluate the node
12711cb0ef41Sopenharmony_ci                # at runtime for easier debugging
12721cb0ef41Sopenharmony_ci                body.append(child)
12731cb0ef41Sopenharmony_ci                continue
12741cb0ef41Sopenharmony_ci            if body and isinstance(body[-1], list):
12751cb0ef41Sopenharmony_ci                body[-1].append(const)
12761cb0ef41Sopenharmony_ci            else:
12771cb0ef41Sopenharmony_ci                body.append([const])
12781cb0ef41Sopenharmony_ci
12791cb0ef41Sopenharmony_ci        # if we have less than 3 nodes or a buffer we yield or extend/append
12801cb0ef41Sopenharmony_ci        if len(body) < 3 or frame.buffer is not None:
12811cb0ef41Sopenharmony_ci            if frame.buffer is not None:
12821cb0ef41Sopenharmony_ci                # for one item we append, for more we extend
12831cb0ef41Sopenharmony_ci                if len(body) == 1:
12841cb0ef41Sopenharmony_ci                    self.writeline('%s.append(' % frame.buffer)
12851cb0ef41Sopenharmony_ci                else:
12861cb0ef41Sopenharmony_ci                    self.writeline('%s.extend((' % frame.buffer)
12871cb0ef41Sopenharmony_ci                self.indent()
12881cb0ef41Sopenharmony_ci            for item in body:
12891cb0ef41Sopenharmony_ci                if isinstance(item, list):
12901cb0ef41Sopenharmony_ci                    val = repr(concat(item))
12911cb0ef41Sopenharmony_ci                    if frame.buffer is None:
12921cb0ef41Sopenharmony_ci                        self.writeline('yield ' + val)
12931cb0ef41Sopenharmony_ci                    else:
12941cb0ef41Sopenharmony_ci                        self.writeline(val + ',')
12951cb0ef41Sopenharmony_ci                else:
12961cb0ef41Sopenharmony_ci                    if frame.buffer is None:
12971cb0ef41Sopenharmony_ci                        self.writeline('yield ', item)
12981cb0ef41Sopenharmony_ci                    else:
12991cb0ef41Sopenharmony_ci                        self.newline(item)
13001cb0ef41Sopenharmony_ci                    close = 1
13011cb0ef41Sopenharmony_ci                    if frame.eval_ctx.volatile:
13021cb0ef41Sopenharmony_ci                        self.write('(escape if context.eval_ctx.autoescape'
13031cb0ef41Sopenharmony_ci                                   ' else to_string)(')
13041cb0ef41Sopenharmony_ci                    elif frame.eval_ctx.autoescape:
13051cb0ef41Sopenharmony_ci                        self.write('escape(')
13061cb0ef41Sopenharmony_ci                    else:
13071cb0ef41Sopenharmony_ci                        self.write('to_string(')
13081cb0ef41Sopenharmony_ci                    if self.environment.finalize is not None:
13091cb0ef41Sopenharmony_ci                        self.write('environment.finalize(')
13101cb0ef41Sopenharmony_ci                        if getattr(self.environment.finalize,
13111cb0ef41Sopenharmony_ci                                   "contextfunction", False):
13121cb0ef41Sopenharmony_ci                            self.write('context, ')
13131cb0ef41Sopenharmony_ci                        close += 1
13141cb0ef41Sopenharmony_ci                    self.visit(item, frame)
13151cb0ef41Sopenharmony_ci                    self.write(')' * close)
13161cb0ef41Sopenharmony_ci                    if frame.buffer is not None:
13171cb0ef41Sopenharmony_ci                        self.write(',')
13181cb0ef41Sopenharmony_ci            if frame.buffer is not None:
13191cb0ef41Sopenharmony_ci                # close the open parentheses
13201cb0ef41Sopenharmony_ci                self.outdent()
13211cb0ef41Sopenharmony_ci                self.writeline(len(body) == 1 and ')' or '))')
13221cb0ef41Sopenharmony_ci
13231cb0ef41Sopenharmony_ci        # otherwise we create a format string as this is faster in that case
13241cb0ef41Sopenharmony_ci        else:
13251cb0ef41Sopenharmony_ci            format = []
13261cb0ef41Sopenharmony_ci            arguments = []
13271cb0ef41Sopenharmony_ci            for item in body:
13281cb0ef41Sopenharmony_ci                if isinstance(item, list):
13291cb0ef41Sopenharmony_ci                    format.append(concat(item).replace('%', '%%'))
13301cb0ef41Sopenharmony_ci                else:
13311cb0ef41Sopenharmony_ci                    format.append('%s')
13321cb0ef41Sopenharmony_ci                    arguments.append(item)
13331cb0ef41Sopenharmony_ci            self.writeline('yield ')
13341cb0ef41Sopenharmony_ci            self.write(repr(concat(format)) + ' % (')
13351cb0ef41Sopenharmony_ci            self.indent()
13361cb0ef41Sopenharmony_ci            for argument in arguments:
13371cb0ef41Sopenharmony_ci                self.newline(argument)
13381cb0ef41Sopenharmony_ci                close = 0
13391cb0ef41Sopenharmony_ci                if frame.eval_ctx.volatile:
13401cb0ef41Sopenharmony_ci                    self.write('(escape if context.eval_ctx.autoescape else'
13411cb0ef41Sopenharmony_ci                               ' to_string)(')
13421cb0ef41Sopenharmony_ci                    close += 1
13431cb0ef41Sopenharmony_ci                elif frame.eval_ctx.autoescape:
13441cb0ef41Sopenharmony_ci                    self.write('escape(')
13451cb0ef41Sopenharmony_ci                    close += 1
13461cb0ef41Sopenharmony_ci                if self.environment.finalize is not None:
13471cb0ef41Sopenharmony_ci                    self.write('environment.finalize(')
13481cb0ef41Sopenharmony_ci                    if getattr(self.environment.finalize,
13491cb0ef41Sopenharmony_ci                               'contextfunction', False):
13501cb0ef41Sopenharmony_ci                        self.write('context, ')
13511cb0ef41Sopenharmony_ci                    elif getattr(self.environment.finalize,
13521cb0ef41Sopenharmony_ci                               'evalcontextfunction', False):
13531cb0ef41Sopenharmony_ci                        self.write('context.eval_ctx, ')
13541cb0ef41Sopenharmony_ci                    elif getattr(self.environment.finalize,
13551cb0ef41Sopenharmony_ci                               'environmentfunction', False):
13561cb0ef41Sopenharmony_ci                        self.write('environment, ')
13571cb0ef41Sopenharmony_ci                    close += 1
13581cb0ef41Sopenharmony_ci                self.visit(argument, frame)
13591cb0ef41Sopenharmony_ci                self.write(')' * close + ', ')
13601cb0ef41Sopenharmony_ci            self.outdent()
13611cb0ef41Sopenharmony_ci            self.writeline(')')
13621cb0ef41Sopenharmony_ci
13631cb0ef41Sopenharmony_ci        if outdent_later:
13641cb0ef41Sopenharmony_ci            self.outdent()
13651cb0ef41Sopenharmony_ci
13661cb0ef41Sopenharmony_ci    def visit_Assign(self, node, frame):
13671cb0ef41Sopenharmony_ci        self.push_assign_tracking()
13681cb0ef41Sopenharmony_ci        self.newline(node)
13691cb0ef41Sopenharmony_ci        self.visit(node.target, frame)
13701cb0ef41Sopenharmony_ci        self.write(' = ')
13711cb0ef41Sopenharmony_ci        self.visit(node.node, frame)
13721cb0ef41Sopenharmony_ci        self.pop_assign_tracking(frame)
13731cb0ef41Sopenharmony_ci
13741cb0ef41Sopenharmony_ci    def visit_AssignBlock(self, node, frame):
13751cb0ef41Sopenharmony_ci        self.push_assign_tracking()
13761cb0ef41Sopenharmony_ci        block_frame = frame.inner()
13771cb0ef41Sopenharmony_ci        # This is a special case.  Since a set block always captures we
13781cb0ef41Sopenharmony_ci        # will disable output checks.  This way one can use set blocks
13791cb0ef41Sopenharmony_ci        # toplevel even in extended templates.
13801cb0ef41Sopenharmony_ci        block_frame.require_output_check = False
13811cb0ef41Sopenharmony_ci        block_frame.symbols.analyze_node(node)
13821cb0ef41Sopenharmony_ci        self.enter_frame(block_frame)
13831cb0ef41Sopenharmony_ci        self.buffer(block_frame)
13841cb0ef41Sopenharmony_ci        self.blockvisit(node.body, block_frame)
13851cb0ef41Sopenharmony_ci        self.newline(node)
13861cb0ef41Sopenharmony_ci        self.visit(node.target, frame)
13871cb0ef41Sopenharmony_ci        self.write(' = (Markup if context.eval_ctx.autoescape '
13881cb0ef41Sopenharmony_ci                   'else identity)(')
13891cb0ef41Sopenharmony_ci        if node.filter is not None:
13901cb0ef41Sopenharmony_ci            self.visit_Filter(node.filter, block_frame)
13911cb0ef41Sopenharmony_ci        else:
13921cb0ef41Sopenharmony_ci            self.write('concat(%s)' % block_frame.buffer)
13931cb0ef41Sopenharmony_ci        self.write(')')
13941cb0ef41Sopenharmony_ci        self.pop_assign_tracking(frame)
13951cb0ef41Sopenharmony_ci        self.leave_frame(block_frame)
13961cb0ef41Sopenharmony_ci
13971cb0ef41Sopenharmony_ci    # -- Expression Visitors
13981cb0ef41Sopenharmony_ci
13991cb0ef41Sopenharmony_ci    def visit_Name(self, node, frame):
14001cb0ef41Sopenharmony_ci        if node.ctx == 'store' and frame.toplevel:
14011cb0ef41Sopenharmony_ci            if self._assign_stack:
14021cb0ef41Sopenharmony_ci                self._assign_stack[-1].add(node.name)
14031cb0ef41Sopenharmony_ci        ref = frame.symbols.ref(node.name)
14041cb0ef41Sopenharmony_ci
14051cb0ef41Sopenharmony_ci        # If we are looking up a variable we might have to deal with the
14061cb0ef41Sopenharmony_ci        # case where it's undefined.  We can skip that case if the load
14071cb0ef41Sopenharmony_ci        # instruction indicates a parameter which are always defined.
14081cb0ef41Sopenharmony_ci        if node.ctx == 'load':
14091cb0ef41Sopenharmony_ci            load = frame.symbols.find_load(ref)
14101cb0ef41Sopenharmony_ci            if not (load is not None and load[0] == VAR_LOAD_PARAMETER and \
14111cb0ef41Sopenharmony_ci                    not self.parameter_is_undeclared(ref)):
14121cb0ef41Sopenharmony_ci                self.write('(undefined(name=%r) if %s is missing else %s)' %
14131cb0ef41Sopenharmony_ci                           (node.name, ref, ref))
14141cb0ef41Sopenharmony_ci                return
14151cb0ef41Sopenharmony_ci
14161cb0ef41Sopenharmony_ci        self.write(ref)
14171cb0ef41Sopenharmony_ci
14181cb0ef41Sopenharmony_ci    def visit_NSRef(self, node, frame):
14191cb0ef41Sopenharmony_ci        # NSRefs can only be used to store values; since they use the normal
14201cb0ef41Sopenharmony_ci        # `foo.bar` notation they will be parsed as a normal attribute access
14211cb0ef41Sopenharmony_ci        # when used anywhere but in a `set` context
14221cb0ef41Sopenharmony_ci        ref = frame.symbols.ref(node.name)
14231cb0ef41Sopenharmony_ci        self.writeline('if not isinstance(%s, Namespace):' % ref)
14241cb0ef41Sopenharmony_ci        self.indent()
14251cb0ef41Sopenharmony_ci        self.writeline('raise TemplateRuntimeError(%r)' %
14261cb0ef41Sopenharmony_ci                       'cannot assign attribute on non-namespace object')
14271cb0ef41Sopenharmony_ci        self.outdent()
14281cb0ef41Sopenharmony_ci        self.writeline('%s[%r]' % (ref, node.attr))
14291cb0ef41Sopenharmony_ci
14301cb0ef41Sopenharmony_ci    def visit_Const(self, node, frame):
14311cb0ef41Sopenharmony_ci        val = node.as_const(frame.eval_ctx)
14321cb0ef41Sopenharmony_ci        if isinstance(val, float):
14331cb0ef41Sopenharmony_ci            self.write(str(val))
14341cb0ef41Sopenharmony_ci        else:
14351cb0ef41Sopenharmony_ci            self.write(repr(val))
14361cb0ef41Sopenharmony_ci
14371cb0ef41Sopenharmony_ci    def visit_TemplateData(self, node, frame):
14381cb0ef41Sopenharmony_ci        try:
14391cb0ef41Sopenharmony_ci            self.write(repr(node.as_const(frame.eval_ctx)))
14401cb0ef41Sopenharmony_ci        except nodes.Impossible:
14411cb0ef41Sopenharmony_ci            self.write('(Markup if context.eval_ctx.autoescape else identity)(%r)'
14421cb0ef41Sopenharmony_ci                       % node.data)
14431cb0ef41Sopenharmony_ci
14441cb0ef41Sopenharmony_ci    def visit_Tuple(self, node, frame):
14451cb0ef41Sopenharmony_ci        self.write('(')
14461cb0ef41Sopenharmony_ci        idx = -1
14471cb0ef41Sopenharmony_ci        for idx, item in enumerate(node.items):
14481cb0ef41Sopenharmony_ci            if idx:
14491cb0ef41Sopenharmony_ci                self.write(', ')
14501cb0ef41Sopenharmony_ci            self.visit(item, frame)
14511cb0ef41Sopenharmony_ci        self.write(idx == 0 and ',)' or ')')
14521cb0ef41Sopenharmony_ci
14531cb0ef41Sopenharmony_ci    def visit_List(self, node, frame):
14541cb0ef41Sopenharmony_ci        self.write('[')
14551cb0ef41Sopenharmony_ci        for idx, item in enumerate(node.items):
14561cb0ef41Sopenharmony_ci            if idx:
14571cb0ef41Sopenharmony_ci                self.write(', ')
14581cb0ef41Sopenharmony_ci            self.visit(item, frame)
14591cb0ef41Sopenharmony_ci        self.write(']')
14601cb0ef41Sopenharmony_ci
14611cb0ef41Sopenharmony_ci    def visit_Dict(self, node, frame):
14621cb0ef41Sopenharmony_ci        self.write('{')
14631cb0ef41Sopenharmony_ci        for idx, item in enumerate(node.items):
14641cb0ef41Sopenharmony_ci            if idx:
14651cb0ef41Sopenharmony_ci                self.write(', ')
14661cb0ef41Sopenharmony_ci            self.visit(item.key, frame)
14671cb0ef41Sopenharmony_ci            self.write(': ')
14681cb0ef41Sopenharmony_ci            self.visit(item.value, frame)
14691cb0ef41Sopenharmony_ci        self.write('}')
14701cb0ef41Sopenharmony_ci
14711cb0ef41Sopenharmony_ci    def binop(operator, interceptable=True):
14721cb0ef41Sopenharmony_ci        @optimizeconst
14731cb0ef41Sopenharmony_ci        def visitor(self, node, frame):
14741cb0ef41Sopenharmony_ci            if self.environment.sandboxed and \
14751cb0ef41Sopenharmony_ci               operator in self.environment.intercepted_binops:
14761cb0ef41Sopenharmony_ci                self.write('environment.call_binop(context, %r, ' % operator)
14771cb0ef41Sopenharmony_ci                self.visit(node.left, frame)
14781cb0ef41Sopenharmony_ci                self.write(', ')
14791cb0ef41Sopenharmony_ci                self.visit(node.right, frame)
14801cb0ef41Sopenharmony_ci            else:
14811cb0ef41Sopenharmony_ci                self.write('(')
14821cb0ef41Sopenharmony_ci                self.visit(node.left, frame)
14831cb0ef41Sopenharmony_ci                self.write(' %s ' % operator)
14841cb0ef41Sopenharmony_ci                self.visit(node.right, frame)
14851cb0ef41Sopenharmony_ci            self.write(')')
14861cb0ef41Sopenharmony_ci        return visitor
14871cb0ef41Sopenharmony_ci
14881cb0ef41Sopenharmony_ci    def uaop(operator, interceptable=True):
14891cb0ef41Sopenharmony_ci        @optimizeconst
14901cb0ef41Sopenharmony_ci        def visitor(self, node, frame):
14911cb0ef41Sopenharmony_ci            if self.environment.sandboxed and \
14921cb0ef41Sopenharmony_ci               operator in self.environment.intercepted_unops:
14931cb0ef41Sopenharmony_ci                self.write('environment.call_unop(context, %r, ' % operator)
14941cb0ef41Sopenharmony_ci                self.visit(node.node, frame)
14951cb0ef41Sopenharmony_ci            else:
14961cb0ef41Sopenharmony_ci                self.write('(' + operator)
14971cb0ef41Sopenharmony_ci                self.visit(node.node, frame)
14981cb0ef41Sopenharmony_ci            self.write(')')
14991cb0ef41Sopenharmony_ci        return visitor
15001cb0ef41Sopenharmony_ci
15011cb0ef41Sopenharmony_ci    visit_Add = binop('+')
15021cb0ef41Sopenharmony_ci    visit_Sub = binop('-')
15031cb0ef41Sopenharmony_ci    visit_Mul = binop('*')
15041cb0ef41Sopenharmony_ci    visit_Div = binop('/')
15051cb0ef41Sopenharmony_ci    visit_FloorDiv = binop('//')
15061cb0ef41Sopenharmony_ci    visit_Pow = binop('**')
15071cb0ef41Sopenharmony_ci    visit_Mod = binop('%')
15081cb0ef41Sopenharmony_ci    visit_And = binop('and', interceptable=False)
15091cb0ef41Sopenharmony_ci    visit_Or = binop('or', interceptable=False)
15101cb0ef41Sopenharmony_ci    visit_Pos = uaop('+')
15111cb0ef41Sopenharmony_ci    visit_Neg = uaop('-')
15121cb0ef41Sopenharmony_ci    visit_Not = uaop('not ', interceptable=False)
15131cb0ef41Sopenharmony_ci    del binop, uaop
15141cb0ef41Sopenharmony_ci
15151cb0ef41Sopenharmony_ci    @optimizeconst
15161cb0ef41Sopenharmony_ci    def visit_Concat(self, node, frame):
15171cb0ef41Sopenharmony_ci        if frame.eval_ctx.volatile:
15181cb0ef41Sopenharmony_ci            func_name = '(context.eval_ctx.volatile and' \
15191cb0ef41Sopenharmony_ci                        ' markup_join or unicode_join)'
15201cb0ef41Sopenharmony_ci        elif frame.eval_ctx.autoescape:
15211cb0ef41Sopenharmony_ci            func_name = 'markup_join'
15221cb0ef41Sopenharmony_ci        else:
15231cb0ef41Sopenharmony_ci            func_name = 'unicode_join'
15241cb0ef41Sopenharmony_ci        self.write('%s((' % func_name)
15251cb0ef41Sopenharmony_ci        for arg in node.nodes:
15261cb0ef41Sopenharmony_ci            self.visit(arg, frame)
15271cb0ef41Sopenharmony_ci            self.write(', ')
15281cb0ef41Sopenharmony_ci        self.write('))')
15291cb0ef41Sopenharmony_ci
15301cb0ef41Sopenharmony_ci    @optimizeconst
15311cb0ef41Sopenharmony_ci    def visit_Compare(self, node, frame):
15321cb0ef41Sopenharmony_ci        self.visit(node.expr, frame)
15331cb0ef41Sopenharmony_ci        for op in node.ops:
15341cb0ef41Sopenharmony_ci            self.visit(op, frame)
15351cb0ef41Sopenharmony_ci
15361cb0ef41Sopenharmony_ci    def visit_Operand(self, node, frame):
15371cb0ef41Sopenharmony_ci        self.write(' %s ' % operators[node.op])
15381cb0ef41Sopenharmony_ci        self.visit(node.expr, frame)
15391cb0ef41Sopenharmony_ci
15401cb0ef41Sopenharmony_ci    @optimizeconst
15411cb0ef41Sopenharmony_ci    def visit_Getattr(self, node, frame):
15421cb0ef41Sopenharmony_ci        self.write('environment.getattr(')
15431cb0ef41Sopenharmony_ci        self.visit(node.node, frame)
15441cb0ef41Sopenharmony_ci        self.write(', %r)' % node.attr)
15451cb0ef41Sopenharmony_ci
15461cb0ef41Sopenharmony_ci    @optimizeconst
15471cb0ef41Sopenharmony_ci    def visit_Getitem(self, node, frame):
15481cb0ef41Sopenharmony_ci        # slices bypass the environment getitem method.
15491cb0ef41Sopenharmony_ci        if isinstance(node.arg, nodes.Slice):
15501cb0ef41Sopenharmony_ci            self.visit(node.node, frame)
15511cb0ef41Sopenharmony_ci            self.write('[')
15521cb0ef41Sopenharmony_ci            self.visit(node.arg, frame)
15531cb0ef41Sopenharmony_ci            self.write(']')
15541cb0ef41Sopenharmony_ci        else:
15551cb0ef41Sopenharmony_ci            self.write('environment.getitem(')
15561cb0ef41Sopenharmony_ci            self.visit(node.node, frame)
15571cb0ef41Sopenharmony_ci            self.write(', ')
15581cb0ef41Sopenharmony_ci            self.visit(node.arg, frame)
15591cb0ef41Sopenharmony_ci            self.write(')')
15601cb0ef41Sopenharmony_ci
15611cb0ef41Sopenharmony_ci    def visit_Slice(self, node, frame):
15621cb0ef41Sopenharmony_ci        if node.start is not None:
15631cb0ef41Sopenharmony_ci            self.visit(node.start, frame)
15641cb0ef41Sopenharmony_ci        self.write(':')
15651cb0ef41Sopenharmony_ci        if node.stop is not None:
15661cb0ef41Sopenharmony_ci            self.visit(node.stop, frame)
15671cb0ef41Sopenharmony_ci        if node.step is not None:
15681cb0ef41Sopenharmony_ci            self.write(':')
15691cb0ef41Sopenharmony_ci            self.visit(node.step, frame)
15701cb0ef41Sopenharmony_ci
15711cb0ef41Sopenharmony_ci    @optimizeconst
15721cb0ef41Sopenharmony_ci    def visit_Filter(self, node, frame):
15731cb0ef41Sopenharmony_ci        if self.environment.is_async:
15741cb0ef41Sopenharmony_ci            self.write('await auto_await(')
15751cb0ef41Sopenharmony_ci        self.write(self.filters[node.name] + '(')
15761cb0ef41Sopenharmony_ci        func = self.environment.filters.get(node.name)
15771cb0ef41Sopenharmony_ci        if func is None:
15781cb0ef41Sopenharmony_ci            self.fail('no filter named %r' % node.name, node.lineno)
15791cb0ef41Sopenharmony_ci        if getattr(func, 'contextfilter', False):
15801cb0ef41Sopenharmony_ci            self.write('context, ')
15811cb0ef41Sopenharmony_ci        elif getattr(func, 'evalcontextfilter', False):
15821cb0ef41Sopenharmony_ci            self.write('context.eval_ctx, ')
15831cb0ef41Sopenharmony_ci        elif getattr(func, 'environmentfilter', False):
15841cb0ef41Sopenharmony_ci            self.write('environment, ')
15851cb0ef41Sopenharmony_ci
15861cb0ef41Sopenharmony_ci        # if the filter node is None we are inside a filter block
15871cb0ef41Sopenharmony_ci        # and want to write to the current buffer
15881cb0ef41Sopenharmony_ci        if node.node is not None:
15891cb0ef41Sopenharmony_ci            self.visit(node.node, frame)
15901cb0ef41Sopenharmony_ci        elif frame.eval_ctx.volatile:
15911cb0ef41Sopenharmony_ci            self.write('(context.eval_ctx.autoescape and'
15921cb0ef41Sopenharmony_ci                       ' Markup(concat(%s)) or concat(%s))' %
15931cb0ef41Sopenharmony_ci                       (frame.buffer, frame.buffer))
15941cb0ef41Sopenharmony_ci        elif frame.eval_ctx.autoescape:
15951cb0ef41Sopenharmony_ci            self.write('Markup(concat(%s))' % frame.buffer)
15961cb0ef41Sopenharmony_ci        else:
15971cb0ef41Sopenharmony_ci            self.write('concat(%s)' % frame.buffer)
15981cb0ef41Sopenharmony_ci        self.signature(node, frame)
15991cb0ef41Sopenharmony_ci        self.write(')')
16001cb0ef41Sopenharmony_ci        if self.environment.is_async:
16011cb0ef41Sopenharmony_ci            self.write(')')
16021cb0ef41Sopenharmony_ci
16031cb0ef41Sopenharmony_ci    @optimizeconst
16041cb0ef41Sopenharmony_ci    def visit_Test(self, node, frame):
16051cb0ef41Sopenharmony_ci        self.write(self.tests[node.name] + '(')
16061cb0ef41Sopenharmony_ci        if node.name not in self.environment.tests:
16071cb0ef41Sopenharmony_ci            self.fail('no test named %r' % node.name, node.lineno)
16081cb0ef41Sopenharmony_ci        self.visit(node.node, frame)
16091cb0ef41Sopenharmony_ci        self.signature(node, frame)
16101cb0ef41Sopenharmony_ci        self.write(')')
16111cb0ef41Sopenharmony_ci
16121cb0ef41Sopenharmony_ci    @optimizeconst
16131cb0ef41Sopenharmony_ci    def visit_CondExpr(self, node, frame):
16141cb0ef41Sopenharmony_ci        def write_expr2():
16151cb0ef41Sopenharmony_ci            if node.expr2 is not None:
16161cb0ef41Sopenharmony_ci                return self.visit(node.expr2, frame)
16171cb0ef41Sopenharmony_ci            self.write('undefined(%r)' % ('the inline if-'
16181cb0ef41Sopenharmony_ci                       'expression on %s evaluated to false and '
16191cb0ef41Sopenharmony_ci                       'no else section was defined.' % self.position(node)))
16201cb0ef41Sopenharmony_ci
16211cb0ef41Sopenharmony_ci        self.write('(')
16221cb0ef41Sopenharmony_ci        self.visit(node.expr1, frame)
16231cb0ef41Sopenharmony_ci        self.write(' if ')
16241cb0ef41Sopenharmony_ci        self.visit(node.test, frame)
16251cb0ef41Sopenharmony_ci        self.write(' else ')
16261cb0ef41Sopenharmony_ci        write_expr2()
16271cb0ef41Sopenharmony_ci        self.write(')')
16281cb0ef41Sopenharmony_ci
16291cb0ef41Sopenharmony_ci    @optimizeconst
16301cb0ef41Sopenharmony_ci    def visit_Call(self, node, frame, forward_caller=False):
16311cb0ef41Sopenharmony_ci        if self.environment.is_async:
16321cb0ef41Sopenharmony_ci            self.write('await auto_await(')
16331cb0ef41Sopenharmony_ci        if self.environment.sandboxed:
16341cb0ef41Sopenharmony_ci            self.write('environment.call(context, ')
16351cb0ef41Sopenharmony_ci        else:
16361cb0ef41Sopenharmony_ci            self.write('context.call(')
16371cb0ef41Sopenharmony_ci        self.visit(node.node, frame)
16381cb0ef41Sopenharmony_ci        extra_kwargs = forward_caller and {'caller': 'caller'} or None
16391cb0ef41Sopenharmony_ci        self.signature(node, frame, extra_kwargs)
16401cb0ef41Sopenharmony_ci        self.write(')')
16411cb0ef41Sopenharmony_ci        if self.environment.is_async:
16421cb0ef41Sopenharmony_ci            self.write(')')
16431cb0ef41Sopenharmony_ci
16441cb0ef41Sopenharmony_ci    def visit_Keyword(self, node, frame):
16451cb0ef41Sopenharmony_ci        self.write(node.key + '=')
16461cb0ef41Sopenharmony_ci        self.visit(node.value, frame)
16471cb0ef41Sopenharmony_ci
16481cb0ef41Sopenharmony_ci    # -- Unused nodes for extensions
16491cb0ef41Sopenharmony_ci
16501cb0ef41Sopenharmony_ci    def visit_MarkSafe(self, node, frame):
16511cb0ef41Sopenharmony_ci        self.write('Markup(')
16521cb0ef41Sopenharmony_ci        self.visit(node.expr, frame)
16531cb0ef41Sopenharmony_ci        self.write(')')
16541cb0ef41Sopenharmony_ci
16551cb0ef41Sopenharmony_ci    def visit_MarkSafeIfAutoescape(self, node, frame):
16561cb0ef41Sopenharmony_ci        self.write('(context.eval_ctx.autoescape and Markup or identity)(')
16571cb0ef41Sopenharmony_ci        self.visit(node.expr, frame)
16581cb0ef41Sopenharmony_ci        self.write(')')
16591cb0ef41Sopenharmony_ci
16601cb0ef41Sopenharmony_ci    def visit_EnvironmentAttribute(self, node, frame):
16611cb0ef41Sopenharmony_ci        self.write('environment.' + node.name)
16621cb0ef41Sopenharmony_ci
16631cb0ef41Sopenharmony_ci    def visit_ExtensionAttribute(self, node, frame):
16641cb0ef41Sopenharmony_ci        self.write('environment.extensions[%r].%s' % (node.identifier, node.name))
16651cb0ef41Sopenharmony_ci
16661cb0ef41Sopenharmony_ci    def visit_ImportedName(self, node, frame):
16671cb0ef41Sopenharmony_ci        self.write(self.import_aliases[node.importname])
16681cb0ef41Sopenharmony_ci
16691cb0ef41Sopenharmony_ci    def visit_InternalName(self, node, frame):
16701cb0ef41Sopenharmony_ci        self.write(node.name)
16711cb0ef41Sopenharmony_ci
16721cb0ef41Sopenharmony_ci    def visit_ContextReference(self, node, frame):
16731cb0ef41Sopenharmony_ci        self.write('context')
16741cb0ef41Sopenharmony_ci
16751cb0ef41Sopenharmony_ci    def visit_Continue(self, node, frame):
16761cb0ef41Sopenharmony_ci        self.writeline('continue', node)
16771cb0ef41Sopenharmony_ci
16781cb0ef41Sopenharmony_ci    def visit_Break(self, node, frame):
16791cb0ef41Sopenharmony_ci        self.writeline('break', node)
16801cb0ef41Sopenharmony_ci
16811cb0ef41Sopenharmony_ci    def visit_Scope(self, node, frame):
16821cb0ef41Sopenharmony_ci        scope_frame = frame.inner()
16831cb0ef41Sopenharmony_ci        scope_frame.symbols.analyze_node(node)
16841cb0ef41Sopenharmony_ci        self.enter_frame(scope_frame)
16851cb0ef41Sopenharmony_ci        self.blockvisit(node.body, scope_frame)
16861cb0ef41Sopenharmony_ci        self.leave_frame(scope_frame)
16871cb0ef41Sopenharmony_ci
16881cb0ef41Sopenharmony_ci    def visit_OverlayScope(self, node, frame):
16891cb0ef41Sopenharmony_ci        ctx = self.temporary_identifier()
16901cb0ef41Sopenharmony_ci        self.writeline('%s = %s' % (ctx, self.derive_context(frame)))
16911cb0ef41Sopenharmony_ci        self.writeline('%s.vars = ' % ctx)
16921cb0ef41Sopenharmony_ci        self.visit(node.context, frame)
16931cb0ef41Sopenharmony_ci        self.push_context_reference(ctx)
16941cb0ef41Sopenharmony_ci
16951cb0ef41Sopenharmony_ci        scope_frame = frame.inner(isolated=True)
16961cb0ef41Sopenharmony_ci        scope_frame.symbols.analyze_node(node)
16971cb0ef41Sopenharmony_ci        self.enter_frame(scope_frame)
16981cb0ef41Sopenharmony_ci        self.blockvisit(node.body, scope_frame)
16991cb0ef41Sopenharmony_ci        self.leave_frame(scope_frame)
17001cb0ef41Sopenharmony_ci        self.pop_context_reference()
17011cb0ef41Sopenharmony_ci
17021cb0ef41Sopenharmony_ci    def visit_EvalContextModifier(self, node, frame):
17031cb0ef41Sopenharmony_ci        for keyword in node.options:
17041cb0ef41Sopenharmony_ci            self.writeline('context.eval_ctx.%s = ' % keyword.key)
17051cb0ef41Sopenharmony_ci            self.visit(keyword.value, frame)
17061cb0ef41Sopenharmony_ci            try:
17071cb0ef41Sopenharmony_ci                val = keyword.value.as_const(frame.eval_ctx)
17081cb0ef41Sopenharmony_ci            except nodes.Impossible:
17091cb0ef41Sopenharmony_ci                frame.eval_ctx.volatile = True
17101cb0ef41Sopenharmony_ci            else:
17111cb0ef41Sopenharmony_ci                setattr(frame.eval_ctx, keyword.key, val)
17121cb0ef41Sopenharmony_ci
17131cb0ef41Sopenharmony_ci    def visit_ScopedEvalContextModifier(self, node, frame):
17141cb0ef41Sopenharmony_ci        old_ctx_name = self.temporary_identifier()
17151cb0ef41Sopenharmony_ci        saved_ctx = frame.eval_ctx.save()
17161cb0ef41Sopenharmony_ci        self.writeline('%s = context.eval_ctx.save()' % old_ctx_name)
17171cb0ef41Sopenharmony_ci        self.visit_EvalContextModifier(node, frame)
17181cb0ef41Sopenharmony_ci        for child in node.body:
17191cb0ef41Sopenharmony_ci            self.visit(child, frame)
17201cb0ef41Sopenharmony_ci        frame.eval_ctx.revert(saved_ctx)
17211cb0ef41Sopenharmony_ci        self.writeline('context.eval_ctx.revert(%s)' % old_ctx_name)
1722