[pypy-svn] r73745 - in pypy/trunk/pypy/jit/tl: . test

fijal at codespeak.net fijal at codespeak.net
Wed Apr 14 21:46:43 CEST 2010


Author: fijal
Date: Wed Apr 14 21:46:41 2010
New Revision: 73745

Modified:
   pypy/trunk/pypy/jit/tl/test/test_tinyframe.py
   pypy/trunk/pypy/jit/tl/tinyframe.py
Log:
Add loops


Modified: pypy/trunk/pypy/jit/tl/test/test_tinyframe.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/test/test_tinyframe.py	(original)
+++ pypy/trunk/pypy/jit/tl/test/test_tinyframe.py	Wed Apr 14 21:46:41 2010
@@ -1,9 +1,11 @@
 
+import py
 from pypy.jit.tl.tinyframe import *
 
 class TestCompile(object):
     def test_simple(self):
         code = compile('''
+        main:
         LOAD 0 => r1
         LOAD 1 => r0 # comment
         # other comment
@@ -16,6 +18,7 @@
 
     def test_return(self):
         code = compile('''
+        main:
         LOAD 0 => r1
         LOAD 1 => r0 # comment
         # other comment
@@ -23,3 +26,31 @@
         RETURN r2
         ''')
         res = interpret(code)
+        assert isinstance(res, Int)
+        assert res.val == 1
+
+    def test_loop(self):
+        code = compile('''
+        main:
+        LOAD 1 => r1
+        LOAD 100 => r2
+        LOAD 0 => r0
+        @l1
+        ADD r0 r1 => r0
+        JUMP_IF_ABOVE r2 r0 @l1
+        RETURN r0
+        ''')
+        ret = interpret(code)
+        assert ret.val == 100
+
+    def test_function(self):
+        py.test.skip("not yet")
+        code = compile('''
+        func: # arg comes in r0
+        LOAD 1 => r1
+        ADD r0 r1 => r1
+        RETURN r1
+        main:
+        LOAD_FUNCTION name
+        CALL 
+        ''')

Modified: pypy/trunk/pypy/jit/tl/tinyframe.py
==============================================================================
--- pypy/trunk/pypy/jit/tl/tinyframe.py	(original)
+++ pypy/trunk/pypy/jit/tl/tinyframe.py	Wed Apr 14 21:46:41 2010
@@ -12,37 +12,70 @@
                     # pointed by r1 (must be int) to r2
 PRINT r # print a register
 CALL r1 r2 # call a function in register one with argument in r2
-LOAD <name> => r # load a function named name into register r
+LOAD_FUNCTION <name> => r # load a function named name into register r
 LOAD <int constant> => r # load an integer constant into register r
 RETURN r1
+JUMP @label # jump + or - by x opcodes
+JUMP_IF_ABOVE r1 r2 @label # jump if value in r1 is above
+# value in r2
 
 function argument always comes in r0
 """
 
-opcodes = ['ADD', 'INTROSPECT', 'PRINT', 'CALL', 'LOAD', 'RETURN']
+opcodes = ['ADD', 'INTROSPECT', 'PRINT', 'CALL', 'LOAD', 'LOAD_FUNCTION',
+           'RETURN', 'JUMP', 'JUMP_IF_ABOVE']
 for i, opcode in enumerate(opcodes):
     globals()[opcode] = i
 
 class Code(object):
-    def __init__(self, code, regno):
+    def __init__(self, code, regno, functions):
         self.code = code
         self.regno = regno
+        self.functions = functions
 
 class Parser(object):
+
+    name = None
     
     def compile(self, strrepr):
         self.code = []
         self.maxregno = 0
-        for line in strrepr.splitlines():
+        self.functions = {}
+        self.labels = {}
+        lines = strrepr.splitlines()
+        for line in lines:
             comment = line.find('#')
             if comment != -1:
                 line = line[:comment]
             line = line.strip()
             if not line:
                 continue
+            if line.endswith(':'):
+                # a name
+                self.finish_currect_code()
+                self.name = line[:-1]
+                continue
+            if line.startswith('@'):
+                self.labels[line[1:]] = len(self.code)
+                continue
             opcode, args = line.split(" ", 1)
             getattr(self, 'compile_' + opcode)(args)
-        return Code("".join([chr(i) for i in self.code]), self.maxregno + 1)
+        functions = [code for i, code in sorted(self.functions.values())]
+        assert self.name == 'main'
+        return Code("".join([chr(i) for i in self.code]), self.maxregno + 1,
+                    functions)
+
+    def finish_currect_code(self):
+        if self.name is None:
+            assert not self.code
+            return
+        code = Code("".join([chr(i) for i in self.code]), self.maxregno + 1,
+                    [])
+        self.functions[self.name] = (len(self.functions), code)
+        self.name = None
+        self.labels = {}
+        self.code = []
+        self.maxregno = 0
 
     def rint(self, arg):
         assert arg.startswith('r')
@@ -69,6 +102,11 @@
         arg = self.rint(args.strip())
         self.code += [RETURN, arg]
 
+    def compile_JUMP_IF_ABOVE(self, args):
+        arg0, arg1, label = args.split(" ")
+        self.code += [JUMP_IF_ABOVE, self.rint(arg0.strip()),
+                      self.rint(arg1.strip()), self.labels[label[1:]]]
+
 def compile(strrepr):
     parser = Parser()
     return parser.compile(strrepr)
@@ -83,6 +121,9 @@
     def add(self, other):
         raise NotImplementedError("abstract base class")
 
+    def gt(self, other):
+        raise NotImplementedError("abstract base class")
+
 class Int(Object):
     def __init__(self, val):
         self.val = val
@@ -90,6 +131,9 @@
     def add(self, other):
         return Int(self.val + other.val)
 
+    def gt(self, other):
+        return self.val > other.val
+
 class Frame(object):
     def __init__(self, code):
         self.code = code
@@ -110,6 +154,14 @@
                 i += 4
             elif opcode == RETURN:
                 return self.registers[ord(code[i + 1])]
+            elif opcode == JUMP_IF_ABOVE:
+                arg0 = self.registers[ord(code[i + 1])]
+                arg1 = self.registers[ord(code[i + 2])]
+                tgt = ord(code[i + 3])
+                if arg0.gt(arg1):
+                    i = tgt
+                else:
+                    i += 4
             else:
                 raise Exception("unimplemented opcode %s" % opcodes[opcode])
 



More information about the Pypy-commit mailing list