123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251 |
- class Instruction(object):
- """A base class for instructions. An instruction is essentially a syntax
- node that must first be defined, and can only then be used."""
- def __init__(self):
- pass
- def has_result(self):
- """Tells if this instruction computes a result."""
- 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."""
- raise NotImplementedError
- 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_result():
- return code_generator.get_result_name(self)
- else:
- return 'None'
- def simplify(self):
- """Applies basic simplification to this instruction and its children."""
- return self
- def __str__(self):
- cg = PythonGenerator()
- self.generate_python_def(cg)
- return cg.code
- class PythonGenerator(object):
- """Generates Python code from instructions."""
- def __init__(self):
- self.code = ''
- self.indentation_string = ' ' * 4
- self.indentation = 0
- self.result_value_dict = {}
- def append(self, text):
- """Appends the given string to this code generator."""
- self.code += text
- def append_indentation(self):
- """Appends indentation to the code generator."""
- self.append(self.indentation_string * self.indentation)
- def append_line(self, line = None):
- """Appends the indentation string followed by the given string (if any)
- and a newline to the code generator."""
- self.append_indentation()
- if line is not None:
- self.append(line)
- self.append('\n')
- def increase_indentation(self):
- """Increases the code generator's indentation by one indent."""
- self.indentation += 1
- def decrease_indentation(self):
- """Decreases the code generator's indentation by one indent."""
- self.indentation -= 1
- def get_result_name(self, instruction):
- """Gets the name of the given instruction's result variable."""
- if instruction not in self.result_value_dict:
- self.result_value_dict[instruction] = \
- 'tmp' + str(len(self.result_value_dict))
- return self.result_value_dict[instruction]
- def append_definition(self, lhs, rhs):
- """Defines the first instruction's result variable as the second
- instruction's result."""
- self.append_line(
- self.get_result_name(lhs) + ' = ' + rhs.generate_python_use(self))
- class VoidInstruction(Instruction):
- """A base class for instructions that do not return a value."""
- def has_result(self):
- """Tells if this instruction computes a result."""
- return False
- class EmptyInstruction(VoidInstruction):
- """Represents the empty instruction, which does nothing."""
- def generate_python_def(self, code_generator):
- code_generator.append_line('pass')
- class SelectInstruction(Instruction):
- """Represents a select-instruction: an instruction that defines one of two
- child instructions, and sets its result to the defined child's result."""
- def __init__(self, condition, if_clause, else_clause):
- Instruction.__init__(self)
- self.condition = condition
- self.if_clause = if_clause
- self.else_clause = else_clause
- def has_result(self):
- """Tells if this instruction computes a result."""
- return self.if_clause.has_result() or self.else_clause.has_result()
- def simplify(self):
- """Applies basic simplification to this instruction and its children."""
- simple_cond = self.condition.simplify()
- simple_if = self.if_clause.simplify()
- simple_else = self.else_clause.simplify()
- return SelectInstruction(simple_cond, simple_if, simple_else)
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- if_has_result = self.has_result()
- if not isinstance(self.condition, EmptyInstruction):
- self.condition.generate_python_def(code_generator)
- code_generator.append_line(
- 'if ' + self.condition.generate_python_use(code_generator) + ':')
- code_generator.increase_indentation()
- self.if_clause.generate_python_def(code_generator)
- if if_has_result:
- code_generator.append_definition(self, self.if_clause)
- code_generator.decrease_indentation()
- if not isinstance(self.else_clause, EmptyInstruction) or if_has_result:
- code_generator.append_line('else:')
- code_generator.increase_indentation()
- self.else_clause.generate_python_def(code_generator)
- if if_has_result:
- code_generator.append_definition(self, self.else_clause)
- code_generator.decrease_indentation()
- class ReturnInstruction(VoidInstruction):
- """Represents a return-instruction."""
- def __init__(self, value):
- Instruction.__init__(self)
- self.value = value
- def simplify(self):
- """Applies basic simplification to this instruction and its children."""
- return LoopInstruction(self.value.simplify())
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- code_generator.append_line(
- 'raise PrimitiveFinished(' +
- self.value.generate_python_use(code_generator) +
- ')')
- class LoopInstruction(VoidInstruction):
- """Represents a loop-instruction, which loops until broken."""
- def __init__(self, body):
- Instruction.__init__(self)
- self.body = body
- def simplify(self):
- """Applies basic simplification to this instruction and its children."""
- return LoopInstruction(self.body.simplify())
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- code_generator.append_line('while True:')
- code_generator.increase_indentation()
- self.body.generate_python_def(code_generator)
- code_generator.decrease_indentation()
- class BreakInstruction(VoidInstruction):
- """Represents a break-instruction."""
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- code_generator.append_line('break')
- class ContinueInstruction(VoidInstruction):
- """Represents a continue-instruction."""
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- code_generator.append_line('continue')
- class CompoundInstruction(VoidInstruction):
- """Represents an instruction that evaluates two other instructions
- in order."""
- def __init__(self, first, second):
- Instruction.__init__(self)
- self.first = first
- self.second = second
- def simplify(self):
- """Applies basic simplification to this instruction and its children."""
- simple_fst, simple_snd = self.first.simplify(), self.second.simplify()
- if isinstance(simple_snd, EmptyInstruction):
- return simple_fst
- elif isinstance(simple_snd, EmptyInstruction):
- return simple_snd
- else:
- return CompoundInstruction(simple_fst, simple_snd)
- def generate_python_def(self, code_generator):
- """Generates Python code for this instruction."""
- if isinstance(self.second, EmptyInstruction):
- self.first.generate_python_def(code_generator)
- elif isinstance(self.first, EmptyInstruction):
- self.second.generate_python_def(code_generator)
- else:
- self.first.generate_python_def(code_generator)
- self.second.generate_python_def(code_generator)
- if __name__ == "__main__":
- exampleTree = SelectInstruction(
- EmptyInstruction(),
- LoopInstruction(
- CompoundInstruction(
- BreakInstruction(),
- ContinueInstruction()
- )
- ),
- ReturnInstruction(
- EmptyInstruction()))
- print(exampleTree)
|