Commit 36e460fc authored by Yuki Shiino's avatar Yuki Shiino Committed by Commit Bot

bind-gen: Separate SymbolScopeNode from SequenceNode

Bug: 839389
Change-Id: I935953fc0afa563c2bcb453ac4ae1e53fd755905
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1864749Reviewed-by: default avatarHitoshi Yoshida <peria@chromium.org>
Commit-Queue: Yuki Shiino <yukishiino@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706513}
parent 84fcc8ea
......@@ -46,7 +46,7 @@ class CodeNode(object):
if key in kwargs:
return kwargs[key]
else:
return '{' + key + '}'
return "{" + key + "}"
_template_formatter = _LooseFormatter()
_gensym_seq_id = 0
......@@ -93,7 +93,7 @@ class CodeNode(object):
will be "abc ${gensym1} xyz" when |sym| is 'gensym1'.
"""
cls._gensym_seq_id += 1
return 'gensym{}'.format(cls._gensym_seq_id)
return "gensym{}".format(cls._gensym_seq_id)
def __init__(self,
outer=None,
......@@ -281,22 +281,25 @@ class SimpleNode(CodeNode):
class SequenceNode(CodeNode):
"""
Represents a sequence of nodes.
If SymbolNodes are used inside this node, this node will attempt to insert
corresponding SymbolDefinitionNodes appropriately.
"""
def __init__(self, renderer=None):
element_nodes_symbol = CodeNode.gensym()
def __init__(self, code_nodes=None, separator="\n", renderer=None):
assert isinstance(separator, str)
element_nodes_gensym = CodeNode.gensym()
element_nodes = []
template_text = CodeNode.format_template(
"""\
% for node in {element_nodes}:
${node}
% endfor\
${node}\\
% if not loop.last:
{separator}\\
% endif
% endfor
""",
element_nodes=element_nodes_symbol)
template_vars = {element_nodes_symbol: element_nodes}
element_nodes=element_nodes_gensym,
separator=separator)
template_vars = {element_nodes_gensym: element_nodes}
CodeNode.__init__(
self,
......@@ -306,6 +309,9 @@ ${node}
self._element_nodes = element_nodes
if code_nodes is not None:
self.extend(code_nodes)
def __getitem__(self, index):
return self._element_nodes[index]
......@@ -315,20 +321,6 @@ ${node}
def __len__(self):
return len(self._element_nodes)
def _render(self, renderer, last_render_state):
# Sort nodes in order to generate reproducible code.
symbol_nodes = sorted(
last_render_state.code_symbols_used.itervalues(),
key=lambda node: node.name)
for symbol_node in symbol_nodes:
self._insert_symbol_definition(symbol_node)
return super(SequenceNode, self)._render(
renderer=renderer, last_render_state=last_render_state)
def _insert_symbol_definition(self, symbol_node):
self.insert(0, symbol_node.create_definition_node())
def append(self, node):
assert isinstance(node, CodeNode)
assert node.outer is None and node.prev is None
......@@ -369,8 +361,8 @@ class SymbolNode(CodeNode):
"""
Represents a code symbol such as a local variable of generated code.
Used combined with SequenceNode, SymbolDefinitionNode(s) will be
automatically inserted iff this symbol is referenced.
Using a SymbolNode combined with SymbolScopeNode, SymbolDefinitionNode(s)
will be automatically inserted iff this symbol is referenced.
"""
def __init__(self, name, definition_node_constructor):
......@@ -426,7 +418,7 @@ class SymbolDefinitionNode(CodeNode):
def _render(self, renderer, last_render_state):
if (self.upstream
and self.upstream.is_code_symbol_defined(self._symbol_node)):
return ''
return ""
return super(SymbolDefinitionNode, self)._render(
renderer=renderer, last_render_state=last_render_state)
......@@ -436,3 +428,35 @@ class SymbolDefinitionNode(CodeNode):
return True
return super(SymbolDefinitionNode,
self).is_code_symbol_defined(symbol_node)
class SymbolScopeNode(SequenceNode):
"""
Represents a sequence of nodes.
If SymbolNodes are rendered inside this node, this node will attempt to
insert corresponding SymbolDefinitionNodes appropriately.
"""
def _render(self, renderer, last_render_state):
# Sort nodes in order to generate reproducible code.
symbol_nodes = sorted(
last_render_state.code_symbols_used.itervalues(),
key=lambda symbol_node: symbol_node.name)
for symbol_node in symbol_nodes:
self._insert_symbol_definition(symbol_node)
return super(SymbolScopeNode, self)._render(
renderer=renderer, last_render_state=last_render_state)
def _insert_symbol_definition(self, symbol_node):
self.insert(0, symbol_node.create_definition_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)
def register_code_symbols(self, symbol_nodes):
for symbol_node in symbol_nodes:
self.register_code_symbol(symbol_node)
......@@ -8,12 +8,13 @@ from .code_node import SequenceNode
from .code_node import SimpleNode
from .code_node import SymbolDefinitionNode
from .code_node import SymbolNode
from .code_node import SymbolScopeNode
from .mako_renderer import MakoRenderer
class CodeNodeTest(unittest.TestCase):
def render(self, node):
prev = ''
prev = ""
current = str(node)
while current != prev:
prev = current
......@@ -22,7 +23,7 @@ class CodeNodeTest(unittest.TestCase):
def assertRenderResult(self, node, expected):
def simplify(s):
return ' '.join(s.split())
return " ".join(s.split())
actual = simplify(self.render(node))
expected = simplify(expected)
......@@ -60,7 +61,7 @@ class CodeNodeTest(unittest.TestCase):
def test_symbol_definition_chains(self):
renderer = MakoRenderer()
root = SequenceNode(renderer=renderer)
root = SymbolScopeNode(renderer=renderer)
def make_symbol(name, template_text):
def constructor(symbol_node):
......@@ -70,18 +71,13 @@ class CodeNodeTest(unittest.TestCase):
return SymbolNode(
name=name, definition_node_constructor=constructor)
root.add_template_vars({
'var1':
make_symbol('var1', "int var1 = ${var2} + ${var3};"),
'var2':
make_symbol('var2', "int var2 = ${var5};"),
'var3':
make_symbol('var3', "int var3 = ${var4};"),
'var4':
make_symbol('var4', "int var4 = 1;"),
'var5':
make_symbol('var5', "int var5 = 2;"),
})
root.register_code_symbols([
make_symbol("var1", "int var1 = ${var2} + ${var3};"),
make_symbol("var2", "int var2 = ${var5};"),
make_symbol("var3", "int var3 = ${var4};"),
make_symbol("var4", "int var4 = 1;"),
make_symbol("var5", "int var5 = 2;"),
])
root.append(SimpleNode(template_text="(void)${var1};"))
......
......@@ -15,7 +15,7 @@ def run_example(web_idl_database, output_dirs):
filename = 'v8_example.cc'
filepath = os.path.join(output_dirs['core'], filename)
root_node = code_node.SequenceNode(renderer=renderer)
root_node = code_node.SymbolScopeNode(renderer=renderer)
root_node.extend([
code_node.SimpleNode(template_text="${z} = ${x} + ${y};"),
code_node.SimpleNode(template_text="print ${z};"),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment