瀏覽代碼

Start working on an IR prototype

jonathanvdc 8 年之前
父節點
當前提交
92b334db19
共有 1 個文件被更改,包括 240 次插入0 次删除
  1. 240 0
      kernel/modelverse_jit/ir.py

+ 240 - 0
kernel/modelverse_jit/ir.py

@@ -0,0 +1,240 @@
+
+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 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 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)