# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
The code generator generates code based on a graph of code fragments.  Each node
of the graph is represented with CodeNode and its subclasses.  This module
provides a collection of the classes that represent code nodes independent from
specific bindings, such as ECMAScript bindings.
"""

from .codegen_accumulator import CodeGenAccumulator
from .codegen_format import format_template
from .mako_renderer import MakoRenderer
from .mako_renderer import MakoTemplate


def render_code_node(code_node):
    """
    Renders |code_node| and turns it into text letting |code_node| apply all
    necessary changes (side effects).  Returns the resulting text.
    """
    assert isinstance(code_node, CodeNode)
    assert code_node.outer is None

    renderer = code_node.renderer
    accumulator = code_node.accumulator

    accumulated_size = accumulator.total_size()
    while True:
        prev_accumulated_size = accumulated_size
        renderer.reset()
        code_node.render(renderer)
        accumulated_size = accumulator.total_size()
        if (renderer.is_rendering_complete()
                and accumulated_size == prev_accumulated_size):
            break

    return renderer.to_text()


class Likeliness(object):
    """
    Represents how much likely a code node will be executed.

    Used in SymbolScopeNode in order to determine where SymbolDefinitionNodes
    should be inserted.  Likeliness level can change only at SymbolScopeNode.

    Relational operators are supported, and it's guaranteed to be:
      NEVER < UNLIKELY < LIKELY < ALWAYS
    """

    class Level(int):
        pass

    NEVER = Level(0)
    UNLIKELY = Level(1)
    LIKELY = Level(2)
    ALWAYS = Level(3)


class CodeNode(object):
    """
    This is the base class of all code fragment nodes.

    - Graph structure
    CodeNode can be nested and |outer| points to the nesting CodeNode.  Also
    CodeNode can make a sequence and |prev| points to the previous CodeNode.
    See also |ListNode|.

    - Template rendering
    CodeNode has template text and template variable bindings.  Either of
    |__str__| or |render| returns a text of generated code.  However, these
    methods have side effects on rendering states, and repeated calls may return
    different results.
    """

    class _RenderState(object):
        """
        Represents a set of per-render states.  Every call to CodeNode.render
        resets all the per-render states.
        """

        def __init__(self):
            # List of SymbolNodes that are defined at this point of rendering.
            # Used to determine whether a certain symbol is already defined by
            # this point of rendering.
            self.defined_code_symbols = []

            # List of SymbolNodes that are not yet defined at this point of
            # rendering.  SymbolNodes are accumulated in order of their first
            # appearance.  The order affects the insertion order of
            # SymbolDefinitionNodes.
            self.undefined_code_symbols = []

            # Dict from a SymbolNode to a set of tuples of SymbolScopeNodes
            # where the symbol was used.
            #
            # For example, given a code symbol |x|, the following code
            # structure:
            #   {  // Scope1
            #     {  // Scope2A
            #       {  // Scope3
            #         x;          // [1]
            #       }
            #       x;            // [2]
            #     }
            #     x;              // [3]
            #     {  // Scope2B
            #       x;            // [4]
            #     }
            #     x;              // [5]
            #   }
            # is translated into an entry of the dict below:
            #   set([
            #     (Scope1),                   # [3], [5]
            #     (Scope1, Scope2A),          # [2]
            #     (Scope1, Scope2A, Scope3),  # [1]
            #     (Scope1, Scope2B),          # [4]
            #   ])
            self.symbol_to_scope_chains = {}

    _gensym_seq_id = 0

    @classmethod
    def gensym(cls):
        """
        Creates a new template variable that never conflicts with anything.

        The name 'gensym' came from 'gensym' (generated symbol) in Lisp that
        exists for exactly the same purpose.

        Note that |gensym| is used to produce a new Mako template variable while
        SymbolNode is used to represent a code symbol (such as a local variable)
        in generated code.

        Bad example:
            template_text = "abc ${tmp} xyz"
            a = CodeNodeA(template_text='123')
            b = CodeNodeB(template_text=template_text, {'tmp': a})
        |b| expects "abc 123 xyz" but what if 'tmp' were already bound to
        something else?

        Good example:
            sym = CodeNode.gensym()
            template_text = format_template(
                "abc ${{{node_a}}} xyz", node_a=sym)
            a = CodeNodeA(template_text='123')
            b = CodeNodeB(template_text=template_text, {sym: a})
        "{{" and "}}" are literal of "{" and "}" themselves, and the innermost
        "{node_a}" will be replaced with |sym|.  The resulting template text
        will be "abc ${gensym1} xyz" when |sym| is 'gensym1'.
        """
        cls._gensym_seq_id += 1
        return "gensym{}".format(cls._gensym_seq_id)

    def __init__(self, template_text=None, template_vars=None):
        assert template_text is None or isinstance(template_text, str)
        assert template_vars is None or isinstance(template_vars, dict)

        # The outer CodeNode or None iff this is a top-level node
        self._outer = None
        # The previous CodeNode if this is a Sequence or None
        self._prev = None

        # Mako's template text, bindings dict
        if template_text is None:
            self._template = None
        else:
            self._template = MakoTemplate(template_text)

        # Template variable bindings
        self._own_template_vars = None
        self._base_template_vars = None
        self._cached_template_vars = None

        self._accumulator = None  # CodeGenAccumulator
        self._accumulate_requests = None

        self._renderer = None  # MakoRenderer

        self._render_state = CodeNode._RenderState()
        self._is_rendering = False

        if template_vars:
            self.add_template_vars(template_vars)

    def __str__(self):
        """
        Renders this CodeNode object directly into the renderer's text buffer
        and always returns the empty string.  This is because it's faster to
        accumulate the rendering result directly in a single text buffer than
        making a lot of string pieces and concatenating them.

        This function is supposed to be used in a Mako template as ${code_node}.
        """
        renderer = self.renderer
        assert renderer

        self.render(renderer)
        return ""

    def render(self, renderer):
        """
        Renders this CodeNode object as a text string and also propagates
        updates to related CodeNode objects.  As this method has side-effects
        not only to this object but also other related objects, the resulting
        text may change on each invocation.
        """
        last_render_state = self._render_state
        self._render_state = CodeNode._RenderState()
        self._is_rendering = True

        try:
            self._render(
                renderer=renderer, last_render_state=last_render_state)
        finally:
            self._is_rendering = False

        if self._accumulate_requests:
            accumulator = self.accumulator
            assert accumulator
            for request in self._accumulate_requests:
                request(accumulator)
            self._accumulate_requests = None

    def _render(self, renderer, last_render_state):
        """
        Renders this CodeNode object as a text string and also propagates
        updates to related CodeNode objects.

        Only limited subclasses may override this method.
        """
        renderer.render(
            caller=self,
            template=self._template,
            template_vars=self.template_vars)

    @property
    def outer(self):
        """Returns the outer CodeNode or None iff this is a top-level node."""
        return self._outer

    def set_outer(self, outer):
        assert isinstance(outer, CodeNode)
        assert self._outer is None
        self._outer = outer

    def reset_outer(self, outer):
        assert isinstance(outer, CodeNode) or outer is None
        self._outer = outer

    @property
    def prev(self):
        """Returns the previous CodeNode if this is a Sequence or None."""
        return self._prev

    def set_prev(self, prev):
        assert isinstance(prev, CodeNode)
        assert self._prev is None
        self._prev = prev

    def reset_prev(self, prev):
        assert isinstance(prev, CodeNode) or prev is None
        self._prev = prev

    def outer_scope(self):
        """Returns the outer scope closest to this scope or None."""
        node = self.outer
        while node is not None:
            if isinstance(node, SymbolScopeNode):
                return node
            node = node.outer
        return None

    def outermost(self):
        """Returns the outermost node, i.e. the node whose |outer| is None."""
        node = self
        while node.outer is not None:
            node = node.outer
        return node

    def inclusive_outers(self):
        """
        Returns a list of outer nodes including this node in order from this
        node to the outermost node.
        """
        outers = []
        node = self
        while node is not None:
            outers.append(node)
            node = node.outer
        return outers

    @property
    def template_vars(self):
        """
        Returns the template variable bindings available at this point, i.e.
        bound at this node or outer nodes.

        CAUTION: This accessor caches the result.  This accessor must not be
        called during construction of a code node tree.
        """
        if self._cached_template_vars is not None:
            return self._cached_template_vars

        outers = self.inclusive_outers()
        bindings = None

        for node in outers:
            if node.base_template_vars is not None:
                bindings = dict(node.base_template_vars)
                break
        if bindings is None:
            bindings = {}

        for node in outers:
            if node.own_template_vars is None:
                continue
            for name, value in node.own_template_vars.items():
                assert name not in bindings, (
                    "Duplicated template variable binding: {}".format(name))
                bindings[name] = value

        self._cached_template_vars = bindings
        return self._cached_template_vars

    @property
    def own_template_vars(self):
        """Returns the template variables bound at this code node."""
        return self._own_template_vars

    def add_template_var(self, name, value):
        if self._own_template_vars is None:
            self._own_template_vars = {}
        assert isinstance(name, str)
        assert name not in self._own_template_vars, (
            "Duplicated template variable binding: {}".format(name))
        if isinstance(value, CodeNode):
            value.set_outer(self)
        self._own_template_vars[name] = value

    def add_template_vars(self, template_vars):
        assert isinstance(template_vars, dict)
        for name, value in template_vars.items():
            self.add_template_var(name, value)

    @property
    def base_template_vars(self):
        """
        Returns the base template variables if it's set at this code node.

        The base template variables are a set of template variables that of
        the innermost code node takes effect.  It means that the base template
        variables are layered and shadowable.
        """
        return self._base_template_vars

    def set_base_template_vars(self, template_vars):
        assert isinstance(template_vars, dict)
        for name, value in template_vars.items():
            assert isinstance(name, str)
            assert not isinstance(value, CodeNode)
        assert self._base_template_vars is None
        self._base_template_vars = template_vars

    @property
    def accumulator(self):
        # Always consistently use the accumulator of the root node.
        if self.outer is None:
            return self._accumulator
        return self.outermost().accumulator

    def set_accumulator(self, accumulator):
        assert isinstance(accumulator, CodeGenAccumulator)
        assert self._accumulator is None
        self._accumulator = accumulator

    def accumulate(self, request):
        """
        While rendering the code node, |request| will be called with the
        argument of self.accumulator.
        """
        assert callable(request)
        if self._accumulate_requests is None:
            self._accumulate_requests = []
        self._accumulate_requests.append(request)

    @property
    def renderer(self):
        # Always consistently use the renderer of the root node.
        if self.outer is None:
            return self._renderer
        return self.outermost().renderer

    def set_renderer(self, renderer):
        assert isinstance(renderer, MakoRenderer)
        assert self._renderer is None
        self._renderer = renderer

    @property
    def current_render_state(self):
        assert self._is_rendering
        return self._render_state

    @property
    def last_render_state(self):
        assert not self._is_rendering
        return self._render_state

    def on_code_symbol_referenced(self, symbol_node, symbol_scope_chain):
        """Receives a report of use of a symbol node."""
        assert isinstance(symbol_node, SymbolNode)
        assert isinstance(symbol_scope_chain, tuple)
        assert all(
            isinstance(scope, SymbolScopeNode) for scope in symbol_scope_chain)
        self.current_render_state.symbol_to_scope_chains.setdefault(
            symbol_node, set()).add(symbol_scope_chain)


class EmptyNode(CodeNode):
    """Represents the zero-length text and renders nothing."""

    def __init__(self):
        CodeNode.__init__(self)

    def _render(self, renderer, last_render_state):
        pass


class LiteralNode(CodeNode):
    """
    Represents a literal text, which will be rendered as is without any template
    magic applied.  The given literal text object will be stringified on each
    rendering.
    """

    def __init__(self, literal_text):
        CodeNode.__init__(self)

        self._literal_text = literal_text

    def _render(self, renderer, last_render_state):
        renderer.push_caller(self)
        try:
            renderer.render_text(str(self._literal_text))
        finally:
            renderer.pop_caller()


def TextNode(template_text):
    """
    Represents a template text node.

    TextNode is designed to be a leaf node of a code node tree.  TextNode
    represents a template text while LiteralNode represents a literal text.
    All template magics will be applied to |template_text|.

    This function is pretending to be a CodeNode subclass and instantiates one
    of text-ish code node subclass depending on the content of |template_text|.
    """
    assert isinstance(template_text, str)

    if "$" in template_text or "%" in template_text:
        return _TextNode(template_text)
    elif template_text:
        return LiteralNode(template_text)
    else:
        return EmptyNode()


class _TextNode(CodeNode):
    """
    Represents a template text node.

    TextNode is designed to be a leaf node of a code node tree.  TextNode
    represents a template text while LiteralNode represents a literal text.
    All template magics will be applied to |template_text|.
    """

    def __init__(self, template_text):
        CodeNode.__init__(self, template_text=template_text)


class CompositeNode(CodeNode):
    """
    Represents a composition of multiple code nodes.  Composition will be done
    by using |CodeNode.gensym| so that it won't contaminate a namespace of the
    template variables.
    """

    def __init__(self, template_format_str, *args, **kwargs):
        """
        Args:
            template_format_str: A format string that is used to produce the
                template text.
            args:
            kwargs: Arguments to be passed to |format_template|.  Not
                necessarily be CodeNode, but also anything renderable can be
                passed in.
        """
        assert isinstance(template_format_str, str)
        gensym_args = []
        gensym_kwargs = {}
        template_vars = {}
        for arg in args:
            assert isinstance(arg, (CodeNode, int, str))
            gensym = CodeNode.gensym()
            gensym_args.append("${{{}}}".format(gensym))
            template_vars[gensym] = arg
        for key, value in kwargs.items():
            assert isinstance(key, (int, str))
            assert isinstance(value, (CodeNode, int, str))
            gensym = CodeNode.gensym()
            gensym_kwargs[key] = "${{{}}}".format(gensym)
            template_vars[gensym] = value
        template_text = format_template(template_format_str, *gensym_args,
                                        **gensym_kwargs)

        CodeNode.__init__(
            self, template_text=template_text, template_vars=template_vars)


class ListNode(CodeNode):
    """
    Represents a list of nodes.

    append, extend, insert, and remove work just like built-in list's methods
    except that addition and removal of None have no effect.
    """

    def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
        """
        Args:
            code_nodes: A list of CodeNode to be rendered.
            separator: A str inserted between code nodes.
            head:
            tail: The head and tail sections that will be rendered iff the
                content list is not empty.
        """
        assert isinstance(separator, str)
        assert isinstance(head, str)
        assert isinstance(tail, str)

        CodeNode.__init__(self)

        self._element_nodes = []
        self._separator = separator
        self._head = head
        self._tail = tail

        self._will_skip_separator = False

        if code_nodes is not None:
            self.extend(code_nodes)

    def __getitem__(self, index):
        return self._element_nodes[index]

    def __iter__(self):
        return iter(self._element_nodes)

    def __len__(self):
        return len(self._element_nodes)

    def _render(self, renderer, last_render_state):
        renderer.push_caller(self)
        try:
            if self._element_nodes:
                renderer.render_text(self._head)
            self._will_skip_separator = True
            for node in self._element_nodes:
                if self._will_skip_separator:
                    self._will_skip_separator = False
                else:
                    renderer.render_text(self._separator)
                node.render(renderer)
            if self._element_nodes:
                renderer.render_text(self._tail)
        finally:
            renderer.pop_caller()

    def skip_separator(self):
        self._will_skip_separator = True

    def append(self, node):
        if node is None:
            return
        assert isinstance(node, CodeNode)
        assert node.outer is None and node.prev is None

        if len(self._element_nodes) == 0:
            self._element_nodes.append(node)
        else:
            node.set_prev(self._element_nodes[-1])
            self._element_nodes.append(node)
        node.set_outer(self)

    def extend(self, nodes):
        for node in nodes:
            self.append(node)

    def insert(self, index, node):
        if node is None:
            return
        assert isinstance(index, int)
        assert isinstance(node, CodeNode)
        assert node.outer is None and node.prev is None

        if index < 0:
            index += len(self._element_nodes)
        index = max(0, min(index, len(self._element_nodes)))

        if (len(self._element_nodes) == 0
                or index == len(self._element_nodes)):
            return self.append(node)

        next_node = self._element_nodes[index]
        if next_node.prev:
            node.set_prev(next_node.prev)
        next_node.reset_prev(node)
        node.set_outer(self)
        self._element_nodes.insert(index, node)

    def remove(self, node):
        if node is None:
            return
        assert node in self

        index = self._element_nodes.index(node)
        if index + 1 < len(self._element_nodes):
            next_node = self._element_nodes[index + 1]
            prev_node = self._element_nodes[index - 1] if index != 0 else None
            next_node.reset_prev(prev_node)
        del self._element_nodes[index]
        node.reset_outer(None)
        node.reset_prev(None)


class SequenceNode(ListNode):
    """
    Represents a sequence of generated code without introducing any new scope,
    and provides the points where SymbolDefinitionNodes can be inserted.
    """

    def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
        ListNode.__init__(
            self,
            code_nodes=code_nodes,
            separator=separator,
            head=head,
            tail=tail)

        self._to_be_removed = []

    def _render(self, renderer, last_render_state):
        if self._to_be_removed:
            for node in self._to_be_removed:
                self.remove(node)
            self._to_be_removed = []

        super(SequenceNode, self)._render(
            renderer=renderer, last_render_state=last_render_state)

    def schedule_to_remove(self, node):
        """Schedules a task to remove the |node| in the next rendering cycle."""
        assert node in self
        self._to_be_removed.append(node)


class SymbolScopeNode(SequenceNode):
    """
    Represents a scope of generated code.

    If SymbolNodes are rendered inside this node, this node will attempt to
    insert corresponding SymbolDefinitionNodes appropriately.
    """

    def __init__(self, code_nodes=None, separator="\n", head="", tail=""):
        SequenceNode.__init__(
            self,
            code_nodes=code_nodes,
            separator=separator,
            head=head,
            tail=tail)

        self._likeliness = Likeliness.ALWAYS
        self._registered_code_symbols = set()
        self._referenced_code_symbols = set()

    def _render(self, renderer, last_render_state):
        for symbol_node in last_render_state.undefined_code_symbols:
            assert self.is_code_symbol_registered(symbol_node)
            self._referenced_code_symbols.add(symbol_node)
            if not self.is_code_symbol_defined(symbol_node):
                self._insert_symbol_definition(symbol_node, last_render_state)

        super(SymbolScopeNode, self)._render(
            renderer=renderer, last_render_state=last_render_state)

        if self.current_render_state.undefined_code_symbols:
            renderer.invalidate_rendering_result()

    def _insert_symbol_definition(self, symbol_node, last_render_state):
        DIRECT_USES = "u"
        DIRECT_CHILD_SCOPES = "s"
        ANALYSIS_RESULT_KEYS = (
            # Number of direct uses in this scope
            DIRECT_USES,
            # Number of direct child scopes
            DIRECT_CHILD_SCOPES,
            # Number of direct child scopes per likeliness
            Likeliness.ALWAYS,
            Likeliness.LIKELY,
            Likeliness.UNLIKELY,
        )

        def analyze_symbol_usage(render_state):
            counts = dict.fromkeys(ANALYSIS_RESULT_KEYS, 0)

            scope_chains = render_state.symbol_to_scope_chains.get(symbol_node)
            if not scope_chains:
                return counts

            self_index = next(iter(scope_chains)).index(self)
            scope_chains = map(
                lambda scope_chain: scope_chain[self_index + 1:], scope_chains)
            scope_to_likeliness = {}
            for scope_chain in scope_chains:
                if not scope_chain:
                    counts[DIRECT_USES] += 1
                else:
                    likeliness = min(
                        map(lambda scope: scope.likeliness, scope_chain))
                    scope = scope_chain[0]
                    scope_to_likeliness[scope] = max(
                        likeliness, scope_to_likeliness.get(scope, likeliness))
            for likeliness in scope_to_likeliness.values():
                counts[DIRECT_CHILD_SCOPES] += 1
                counts[likeliness] += 1
            return counts

        def likeliness_at(render_state):
            counts = analyze_symbol_usage(render_state)
            if counts[DIRECT_USES] >= 1:
                return Likeliness.ALWAYS
            for likeliness in (Likeliness.ALWAYS, Likeliness.LIKELY,
                               Likeliness.UNLIKELY):
                if counts[likeliness] > 0:
                    return likeliness
            return Likeliness.NEVER

        def insert_before_threshold(sequence_node, threshold):
            for index, node in enumerate(sequence_node):
                if (isinstance(node, SequenceNode)
                        and not isinstance(node, SymbolScopeNode)):
                    did_insert = insert_before_threshold(node, threshold)
                    if did_insert:
                        return True
                elif likeliness_at(node.last_render_state) >= threshold:
                    sequence_node.insert(index,
                                         symbol_node.create_definition_node())
                    return True
            return False

        counts = analyze_symbol_usage(last_render_state)
        if counts[DIRECT_USES] >= 1:
            did_insert = insert_before_threshold(self, Likeliness.UNLIKELY)
            assert did_insert
        elif counts[DIRECT_CHILD_SCOPES] == 1:
            pass  # Let the child SymbolScopeNode do the work.
        elif counts[Likeliness.ALWAYS] + counts[Likeliness.LIKELY] >= 2:
            did_insert = insert_before_threshold(self, Likeliness.LIKELY)
            assert did_insert
        else:
            pass  # Let descendant SymbolScopeNodes do the work.

    def is_code_symbol_registered(self, symbol_node):
        """
        Returns True if |symbol_node| is registered and available for use within
        this scope.
        """
        assert isinstance(symbol_node, SymbolNode)

        if symbol_node in self._registered_code_symbols:
            return True

        outer = self.outer_scope()
        if outer is None:
            return False
        return outer.is_code_symbol_registered(symbol_node)

    def register_code_symbol(self, symbol_node):
        """Registers a SymbolNode and makes it available in this scope."""
        assert isinstance(symbol_node, SymbolNode)
        self.add_template_var(symbol_node.name, symbol_node)
        self._registered_code_symbols.add(symbol_node)

    def register_code_symbols(self, symbol_nodes):
        for symbol_node in symbol_nodes:
            self.register_code_symbol(symbol_node)

    @property
    def referenced_code_symbols(self):
        """Returns SymbolNodes that have once been referenced in this scope."""
        return frozenset(self._referenced_code_symbols)

    @property
    def likeliness(self):
        """
        Returns how much likely that this SymbolScopeNode will be executed in
        runtime.  The likeliness is relative to the closest outer
        SymbolScopeNode.
        """
        return self._likeliness

    def set_likeliness(self, likeliness):
        assert isinstance(likeliness, Likeliness.Level)
        self._likeliness = likeliness

    def is_code_symbol_defined(self, symbol_node):
        """
        Returns True if |symbol_node| is defined in this scope by the moment
        when the method is called.
        """
        assert isinstance(symbol_node, SymbolNode)

        if symbol_node in self.current_render_state.defined_code_symbols:
            return True

        outer = self.outer_scope()
        if outer is None:
            return False
        return outer.is_code_symbol_defined(symbol_node)

    def on_code_symbol_defined(self, symbol_node):
        """Receives a report that a symbol gets defined."""
        assert isinstance(symbol_node, SymbolNode)
        self.current_render_state.defined_code_symbols.append(symbol_node)

    def on_undefined_code_symbol_found(self, symbol_node):
        """Receives a report of use of an undefined symbol node."""
        assert isinstance(symbol_node, SymbolNode)
        state = self.current_render_state
        if symbol_node not in state.undefined_code_symbols:
            state.undefined_code_symbols.append(symbol_node)


class SymbolNode(CodeNode):
    """
    Represents a code symbol such as a local variable of generated code.

    Using a SymbolNode combined with SymbolScopeNode, SymbolDefinitionNode(s)
    will be automatically inserted iff this symbol is referenced.
    """

    def __init__(self, name, template_text=None, definition_constructor=None):
        """
        Args:
            name: The name of this code symbol.
            template_text: Template text to be used to define the code symbol.
            definition_constructor: A callable that creates and returns a new
                definition node.  This SymbolNode will be passed as the
                argument.
                Either of |template_text| or |definition_constructor| must be
                given.
        """
        assert isinstance(name, str) and name

        CodeNode.__init__(self)

        self._name = name

        if template_text is not None:
            assert isinstance(template_text, str)
            assert definition_constructor is None

            def constructor(symbol_node):
                return SymbolDefinitionNode(
                    symbol_node=symbol_node,
                    code_nodes=[TextNode(template_text)])

            self._definition_constructor = constructor
        else:
            assert template_text is None
            assert callable(definition_constructor)

            self._definition_constructor = definition_constructor

    def _render(self, renderer, last_render_state):
        self._request_symbol_definition(renderer)

        renderer.render_text(self.name)

    def request_symbol_definition(self):
        self._request_symbol_definition(self.renderer)

    def _request_symbol_definition(self, renderer):
        symbol_scope_chain = tuple(
            filter(lambda node: isinstance(node, SymbolScopeNode),
                   renderer.callers_from_first_to_last))

        for caller in renderer.callers_from_last_to_first:
            caller.on_code_symbol_referenced(self, symbol_scope_chain)
            if caller is self.outer:
                break

        if not symbol_scope_chain[-1].is_code_symbol_defined(self):
            for scope in reversed(symbol_scope_chain):
                scope.on_undefined_code_symbol_found(self)
                if scope is self.outer:
                    break

    @property
    def name(self):
        return self._name

    def create_definition_node(self):
        """Creates a new definition node."""
        node = self._definition_constructor(self)
        assert isinstance(node, SymbolDefinitionNode)
        assert node.target_symbol is self
        return node


class SymbolDefinitionNode(SequenceNode):
    """
    Represents a definition of a code symbol.

    It's allowed to define the same code symbol multiple times, and most
    upstream definition(s) are effective.
    """

    def __init__(self, symbol_node, code_nodes=None):
        assert isinstance(symbol_node, SymbolNode)

        SequenceNode.__init__(self, code_nodes)

        self._symbol_node = symbol_node

    def _render(self, renderer, last_render_state):
        scope = self.outer_scope()
        if scope.is_code_symbol_defined(self._symbol_node):
            assert isinstance(self.outer, SequenceNode)
            self.outer.schedule_to_remove(self)
            self.outer.skip_separator()
            return

        scope.on_code_symbol_defined(self._symbol_node)

        super(SymbolDefinitionNode, self)._render(
            renderer=renderer, last_render_state=last_render_state)

    @property
    def target_symbol(self):
        return self._symbol_node


class WeakDependencyNode(CodeNode):
    """
    Represents weak dependencies to SymbolNodes, where "weak" means that this
    code node itself does not require any SymbolDefinitionNode of the target
    symbols, however, once any other code node within the closest outer scope
    requires a symbol definition, then this code node also requires the symbol
    definition, too.  This makes the symbol definition node be placed prior to
    this node iff such a definition is added.

    In short, you can control the position of SymbolDefinitionNode with using
    WeakDependencyNode without requiring the symbol definition node.
    """

    def __init__(self, dep_syms):
        """
        Args:
            dep_syms: A list of code symbol names on which this code node
                weakly depends.
        """
        assert isinstance(dep_syms, (list, tuple))
        assert all(isinstance(sym, str) for sym in dep_syms)

        CodeNode.__init__(self)

        # Registered weak dependencies to symbols.
        self._weak_dep_sym_names = list(dep_syms)
        # Symbol names that have not yet turned into strong references.
        self._weak_dep_sym_queue = list(self._weak_dep_sym_names)
        # SymbolNodes that already turned into strong references.
        self._strong_dep_symbol_nodes = []

    def _render(self, renderer, last_render_state):
        renderer.push_caller(self)
        try:
            self._render_internal()
        finally:
            renderer.pop_caller()

    def _render_internal(self):
        for symbol_node in self._strong_dep_symbol_nodes:
            symbol_node.request_symbol_definition()

        if not self._weak_dep_sym_queue:
            return

        referenced_code_symbols = self.outer_scope().referenced_code_symbols
        unprocessed_sym_names = []
        for weak_sym_name in self._weak_dep_sym_queue:
            for symbol_node in referenced_code_symbols:
                if symbol_node.name == weak_sym_name:
                    symbol_node.request_symbol_definition()
                    self._strong_dep_symbol_nodes.append(symbol_node)
                    break
            else:
                unprocessed_sym_names.append(weak_sym_name)
        self._weak_dep_sym_queue = unprocessed_sym_names
