|
@@ -108,6 +108,10 @@ class Instruction(object):
|
|
|
instruction if it is not None."""
|
|
|
return None
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return True
|
|
|
+
|
|
|
def generate_python_def(self, code_generator):
|
|
|
"""Generates a Python statement that executes this instruction.
|
|
|
The statement is appended immediately to the code generator."""
|
|
@@ -225,7 +229,7 @@ class PythonGenerator(object):
|
|
|
# Generate the rhs' definition.
|
|
|
rhs.generate_python_def(self)
|
|
|
# Only perform an assignment if it's truly necessary.
|
|
|
- if lhs_result_name != rhs_result_name:
|
|
|
+ if lhs_result_name != rhs_result_name or not rhs.has_result_temporary():
|
|
|
self.append_definition(lhs, rhs)
|
|
|
else:
|
|
|
self.append_definition(lhs, rhs)
|
|
@@ -523,6 +527,10 @@ class BinaryInstruction(Instruction):
|
|
|
else:
|
|
|
return self
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def generate_python_use(self, code_generator):
|
|
|
"""Generates a Python expression that retrieves this instruction's
|
|
|
result. The expression is returned as a string."""
|
|
@@ -534,11 +542,12 @@ class BinaryInstruction(Instruction):
|
|
|
def generate_python_def(self, code_generator):
|
|
|
"""Generates a Python statement that executes this instruction.
|
|
|
The statement is appended immediately to the code generator."""
|
|
|
- if self.lhs.has_definition():
|
|
|
+ lhs_has_def, rhs_has_def = self.lhs.has_definition(), self.rhs.has_definition()
|
|
|
+ if lhs_has_def:
|
|
|
self.lhs.generate_python_def(code_generator)
|
|
|
- if self.rhs.has_definition():
|
|
|
+ if rhs_has_def:
|
|
|
self.rhs.generate_python_def(code_generator)
|
|
|
- elif self.rhs.has_definition():
|
|
|
+ elif rhs_has_def:
|
|
|
self.rhs.generate_python_def(code_generator)
|
|
|
else:
|
|
|
code_generator.append_line('pass')
|
|
@@ -561,6 +570,10 @@ class UnaryInstruction(Instruction):
|
|
|
"""Gets this instruction's sequence of child instructions."""
|
|
|
return [self.operand]
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def create(self, new_children):
|
|
|
"""Creates a new instruction of this type from the given sequence of child instructions."""
|
|
|
operand, = new_children
|
|
@@ -595,7 +608,6 @@ class UnaryInstruction(Instruction):
|
|
|
|
|
|
class LoopInstruction(VoidInstruction):
|
|
|
"""Represents a loop-instruction, which loops until broken."""
|
|
|
-
|
|
|
def __init__(self, body):
|
|
|
VoidInstruction.__init__(self)
|
|
|
self.body = body
|
|
@@ -730,6 +742,10 @@ class LiteralInstruction(Instruction):
|
|
|
"""Tells if this instruction requires a definition."""
|
|
|
return False
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def get_children(self):
|
|
|
"""Gets this instruction's sequence of child instructions."""
|
|
|
return []
|
|
@@ -767,42 +783,32 @@ class DictionaryLiteralInstruction(Instruction):
|
|
|
[key.has_definition() or val.has_definition()
|
|
|
for key, val in self.key_value_pairs])
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def simplify(self):
|
|
|
"""Applies basic simplification to this instruction and its children."""
|
|
|
return DictionaryLiteralInstruction(
|
|
|
[(key.simplify(), val.simplify()) for key, val in self.key_value_pairs])
|
|
|
|
|
|
- def generate_dictionary_expr(self, code_generator):
|
|
|
- """Generates an expression that creates this dictionary."""
|
|
|
- return '{%s}' % ', '.join(
|
|
|
- ['%s : %s' % (
|
|
|
- key.generate_python_use(code_generator),
|
|
|
- val.generate_python_use(code_generator))
|
|
|
- for key, val in self.key_value_pairs])
|
|
|
-
|
|
|
def generate_python_def(self, code_generator):
|
|
|
"""Generates a Python statement that executes this instruction.
|
|
|
The statement is appended immediately to the code generator."""
|
|
|
- if self.has_definition():
|
|
|
- for key, val in self.key_value_pairs:
|
|
|
- if key.has_definition():
|
|
|
- key.generate_python_def(code_generator)
|
|
|
- if val.has_definition():
|
|
|
- val.generate_python_def(code_generator)
|
|
|
-
|
|
|
- code_generator.append_line('%s = %s' % (
|
|
|
- code_generator.get_result_name(self),
|
|
|
- self.generate_dictionary_expr(code_generator)))
|
|
|
- else:
|
|
|
- code_generator.append_line('pass')
|
|
|
+ for key, val in self.key_value_pairs:
|
|
|
+ if key.has_definition():
|
|
|
+ key.generate_python_def(code_generator)
|
|
|
+ if val.has_definition():
|
|
|
+ val.generate_python_def(code_generator)
|
|
|
|
|
|
def generate_python_use(self, code_generator):
|
|
|
"""Generates a Python expression that retrieves this instruction's
|
|
|
result. The expression is returned as a string."""
|
|
|
- if self.has_definition():
|
|
|
- return code_generator.get_result_name(self)
|
|
|
- else:
|
|
|
- return self.generate_dictionary_expr(code_generator)
|
|
|
+ return '{%s}' % ', '.join(
|
|
|
+ ['%s : %s' % (
|
|
|
+ key.generate_python_use(code_generator),
|
|
|
+ val.generate_python_use(code_generator))
|
|
|
+ for key, val in self.key_value_pairs])
|
|
|
|
|
|
def __repr__(self):
|
|
|
return "DictionaryLiteralInstruction(%r)" % self.key_value_pairs
|
|
@@ -1057,12 +1063,16 @@ class LoadIndexInstruction(Instruction):
|
|
|
|
|
|
def has_definition_impl(self):
|
|
|
"""Tells if this instruction requires a definition."""
|
|
|
- return False
|
|
|
+ return self.indexed.has_definition() or self.key.has_definition()
|
|
|
|
|
|
def get_children(self):
|
|
|
"""Gets this instruction's sequence of child instructions."""
|
|
|
return [self.indexed, self.key]
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def create(self, new_children):
|
|
|
"""Creates a new instruction of this type from the given sequence of child instructions."""
|
|
|
indexed, key = new_children
|
|
@@ -1071,15 +1081,22 @@ class LoadIndexInstruction(Instruction):
|
|
|
def generate_python_use(self, code_generator):
|
|
|
"""Generates a Python expression that retrieves this instruction's
|
|
|
result. The expression is returned as a string."""
|
|
|
- if self.indexed.has_definition():
|
|
|
+ return "%s[%s]" % (
|
|
|
+ self.indexed.generate_python_use(code_generator),
|
|
|
+ self.key.generate_python_use(code_generator))
|
|
|
+
|
|
|
+ def generate_python_def(self, code_generator):
|
|
|
+ """Generates a Python statement that executes this instruction.
|
|
|
+ The statement is appended immediately to the code generator."""
|
|
|
+ indexed_has_def, key_has_def = self.indexed.has_definition(), self.key.has_definition()
|
|
|
+ if indexed_has_def:
|
|
|
self.indexed.generate_python_def(code_generator)
|
|
|
|
|
|
- if self.key.has_definition():
|
|
|
+ if key_has_def:
|
|
|
self.key.generate_python_def(code_generator)
|
|
|
|
|
|
- return "%s[%s]" % (
|
|
|
- self.indexed.generate_python_use(code_generator),
|
|
|
- self.key.generate_python_use(code_generator))
|
|
|
+ if not indexed_has_def and not key_has_def:
|
|
|
+ code_generator.append_line('pass')
|
|
|
|
|
|
def __repr__(self):
|
|
|
return 'LoadIndexInstruction(%r, %r)' % (self.indexed, self.key)
|
|
@@ -1099,6 +1116,10 @@ class LoadMemberInstruction(Instruction):
|
|
|
"""Gets this instruction's sequence of child instructions."""
|
|
|
return [self.container]
|
|
|
|
|
|
+ def has_result_temporary(self):
|
|
|
+ """Tells if this instruction stores its result in a temporary."""
|
|
|
+ return False
|
|
|
+
|
|
|
def create(self, new_children):
|
|
|
"""Creates a new instruction of this type from the given sequence of child instructions."""
|
|
|
container, = new_children
|
|
@@ -1412,21 +1433,6 @@ def create_new_local_node(local_variable, connected_node, edge_variable=None):
|
|
|
|
|
|
return create_block(local_store, create_edge)
|
|
|
|
|
|
-def with_debug_info_trace(instruction, debug_info, function_name):
|
|
|
- """Prepends the given instruction with a tracing instruction that prints
|
|
|
- the given debug information and function name."""
|
|
|
- if debug_info is None and function_name is None:
|
|
|
- return instruction
|
|
|
- else:
|
|
|
- if debug_info is None:
|
|
|
- debug_info = 'unknown location '
|
|
|
- if function_name is None:
|
|
|
- function_name = 'unknown function'
|
|
|
- return create_block(
|
|
|
- PrintInstruction(
|
|
|
- LiteralInstruction('TRACE: %s(%s, JIT)' % (debug_info, function_name))),
|
|
|
- instruction)
|
|
|
-
|
|
|
def map_instruction_tree_top_down(function, instruction):
|
|
|
"""Applies the given mapping function to every instruction in the tree
|
|
|
that has the given instruction as root. The map is applied in a top-down
|