[pypy-svn] r28199 - in pypy/dist/pypy/translator/js2: . jssrc test

fijal at codespeak.net fijal at codespeak.net
Sat Jun 3 20:21:25 CEST 2006


Author: fijal
Date: Sat Jun  3 20:21:24 2006
New Revision: 28199

Modified:
   pypy/dist/pypy/translator/js2/asmgen.py
   pypy/dist/pypy/translator/js2/function.py
   pypy/dist/pypy/translator/js2/jssrc/misc.js
   pypy/dist/pypy/translator/js2/opcodes.py
   pypy/dist/pypy/translator/js2/test/test_class.py
   pypy/dist/pypy/translator/js2/test/test_exception.py
Log:
Added exception handling and isinstanceof. Works by terrible hack of exception value.


Modified: pypy/dist/pypy/translator/js2/asmgen.py
==============================================================================
--- pypy/dist/pypy/translator/js2/asmgen.py	(original)
+++ pypy/dist/pypy/translator/js2/asmgen.py	Sat Jun  3 20:21:24 2006
@@ -113,13 +113,38 @@
         self.right_hand.append("%s ( %s )" % (func_name, real_args))
 
     def branch_if(self, arg, exitcase):
-        arg_name = self.subst_table.get(arg.name, arg.name)
-        self.codegenerator.write("if ( %s == %s )"%(arg_name, str(exitcase).lower()))
+        def mapping(exitc):
+            if exitc in ['True', 'False']:
+                return exitc.lower()
+            return exitc
+        
+        if hasattr(arg,'name'):
+            arg_name = self.subst_table.get(arg.name, arg.name)
+        else:
+            arg_name = arg
+        self.branch_if_string("%s == %s"%(arg_name, mapping(str(exitcase))))
+        
+    def branch_if_string(self, arg):
+        self.codegenerator.writeline("if (%s)"%arg)
+        self.codegenerator.openblock()
+    
+    def branch_elsif_string(self, arg):
+        self.codegenerator.closeblock()
+        self.codegenerator.writeline("else if (%s)"%arg)
         self.codegenerator.openblock()
     
+    def branch_elsif(self, arg, exitcase):
+        self.codegenerator.closeblock()
+        self.branch_if(arg, exitcase, "else if")
+    
     def branch_while(self, arg, exitcase):
+        def mapping(exitc):
+            if exitc in ['True', 'False']:
+                return exitc.lower()
+            return exitc
+        
         arg_name = self.subst_table.get(arg.name, arg.name)
-        self.codegenerator.write("while ( %s == %s )"%(arg_name, str(exitcase).lower()))
+        self.codegenerator.write("while ( %s == %s )"%(arg_name, mapping(str(exitcase))))
         self.codegenerator.openblock()
     
     def branch_while_true(self):
@@ -229,8 +254,10 @@
         self.codegenerator.write("try ")
         self.codegenerator.openblock()
     
-    def end_try(self):
+    def catch(self):
         self.codegenerator.closeblock()
+        self.codegenerator.write("catch (exc)")
+        self.codegenerator.openblock()
     
     def begin_for(self):
         self.codegenerator.writeline("var block = 0;")
@@ -251,7 +278,10 @@
         self.codegenerator.closeblock()
     
     def inherits(self, subclass_name, parent_name):
-        self.codegenerator.writeline("%s.inherits(%s);"%(subclass_name, parent_name))
+        self.codegenerator.writeline("inherits(%s,%s);"%(subclass_name, parent_name))
+    
+    def throw(self, var):
+        self.codegenerator.writeline("throw(%s);"%var.name)
     
     #def finish ( self ):
     #    self . outfile . write ( "%r" % self . right_hand )

Modified: pypy/dist/pypy/translator/js2/function.py
==============================================================================
--- pypy/dist/pypy/translator/js2/function.py	(original)
+++ pypy/dist/pypy/translator/js2/function.py	Sat Jun  3 20:21:24 2006
@@ -16,6 +16,8 @@
 
 from pypy.translator.js2.log import log
 
+import re
+
 class LoopFinder(object):
 
     def __init__(self, startblock):
@@ -163,6 +165,9 @@
     def render_block(self, startblock):
         """ Block rendering routine using for variable trick
         """
+        def basename(x):
+            return str(x).split('.')[-1]
+        
         self.ilasm.begin_for()
         
         block_map = {}
@@ -176,16 +181,41 @@
         
         for block in graph.iterblocks():
             self.ilasm.write_case(block_map[block])
+            
+            is_exc_block = (block.exitswitch is flowmodel.c_last_exception)
+            
+            if is_exc_block:
+                self.ilasm.begin_try()
+                
             self.render_block_operations(block)
             if self._is_return_block(block):
                 return_var = block.inputargs[0]
                 #if return_var.concretetype is not Void:
                 self.load(return_var)
                 self.ilasm.ret()
+            elif self._is_raise_block(block):
+                self.ilasm.throw(block.inputargs[1])
             elif block.exitswitch is None:
                 self._setup_link(block.exits[0])
                 self.ilasm.jump_block(block_map[block.exits[0].target])
-            elif block.exitswitch.concretetype is Bool:
+            elif block.exitswitch is flowmodel.c_last_exception:
+                link = [i for i in block.exits if i.exitcase is None][0]
+                self._setup_link(link)
+                self.ilasm.jump_block(block_map[link.target])
+                self.ilasm.catch()
+                first = False
+                for link in [i for i in block.exits if i.exitcase is not None]:
+                    s = "isinstanceof(exc, %s)"%basename(link.exitcase)
+                    if not first:
+                        first = True
+                        self.ilasm.branch_if_string(s)
+                    else:
+                        self.ilasm.branch_elsif_string(s)
+                    self._setup_link(link, True)
+                    self.ilasm.jump_block(block_map[link.target])
+                self.ilasm.close_branch()
+                self.ilasm.close_branch()
+            elif len(block.exits) == 2:
                 self.ilasm.branch_if(block.exitswitch, True)
                 self._setup_link(block.exits[True])
                 self.ilasm.jump_block(block_map[block.exits[True].target])
@@ -193,8 +223,6 @@
                 self._setup_link(block.exits[False])
                 self.ilasm.jump_block(block_map[block.exits[False].target])
                 self.ilasm.close_branch()
-            elif block.exitswitch is flowmodel.c_last_exception:
-                raise NotImplementedError("Exception work in progress")
             else:
                 raise TypeError("Unknow block.exitswitch type %r"%block.exitswitch)
         
@@ -231,11 +259,14 @@
         else:
             self.db.record_function(self.graph, self.name)
 
-    def _setup_link(self, link):
+    def _setup_link(self, link, is_exc_link = False):
         target = link.target
         for to_load, to_store in zip(link.args, target.inputargs):
             if to_load.concretetype is not Void:
-                self.load(to_load)
+                if is_exc_link and isinstance(to_load, flowmodel.Variable) and re.match("last_exc_value", to_load.name):
+                    self.ilasm.load_str("exc")
+                else:
+                    self.load(to_load)
                 self.store(to_store)
 
 

Modified: pypy/dist/pypy/translator/js2/jssrc/misc.js
==============================================================================
--- pypy/dist/pypy/translator/js2/jssrc/misc.js	(original)
+++ pypy/dist/pypy/translator/js2/jssrc/misc.js	Sat Jun  3 20:21:24 2006
@@ -3,8 +3,28 @@
     return this;
 };
 
-Function.method('inherits', function (parent) {
+function inherits(child, parent) {
+    child.parent = parent;
+    for (i in parent.prototype) {
+        child.prototype[i] = parent.prototype[i];
+    }
+}
+
+function isinstanceof(self, what) {
+    t = self.constructor;
+    while ( t ) {
+        if (t == what) {
+            return (true);
+        }
+        t = t.parent;
+    }
+    return (false);
+}
+
+Function.method('old_inherits', function (parent) {
     var d = 0, p = (this.prototype = new parent());
+    //var p = new parent();
+    //var d = 0;
     this.method('uber', function uber(name) {
         var f, r, t = d, v = parent.prototype;
         if (t) {

Modified: pypy/dist/pypy/translator/js2/opcodes.py
==============================================================================
--- pypy/dist/pypy/translator/js2/opcodes.py	(original)
+++ pypy/dist/pypy/translator/js2/opcodes.py	Sat Jun  3 20:21:24 2006
@@ -19,13 +19,14 @@
 class _SameAs(MicroInstruction):
     def render(self, generator, op):
         generator.change_name(op.result, op.args[0])
-        
+
 class _CastFun(MicroInstruction):
     def __init__(self, name, num):
         self.name = name
         self.num = num
 
     def render(self, generator, op):
+        log("Args: %r"%op.args)
         generator.cast_function(self.name, self.num)
 
 class _Prefix(MicroInstruction):
@@ -41,6 +42,10 @@
     
     def render(self, generator, op):
         raise NotImplementedError(self.reason)
+        
+class _New(MicroInstruction):
+    def render(self, generator, op):
+        generator.new(op.args[0].value)
 
 class _CastString(MicroInstruction):
     def render(self, generator, op):
@@ -121,6 +126,14 @@
         method = op.args[0]
         self._render_method(generator, method.value, op.args[1:])
 
+class _IsInstance(MicroInstruction):
+    def render(self, generator, op):
+        # FIXME: just temporary hack
+        generator.load(op.args[0])
+        generator.ilasm.load_const(op.args[1].value._name.split('.')[-1])
+        generator.cast_function("isinstanceof", 2)
+
+IsInstance = _IsInstance()
 Call = _Call()
 CallMethod = _CallMethod()
 CopyName = [PushAllArgs, _SameAs ()]
@@ -207,6 +220,7 @@
     'indirect_call' : [_NotImplemented("Indirect call not implemented")],
     'same_as' : SameAs,
     'new' : [New],
+    'instanceof' : [IsInstance],
     
     # objects
     

Modified: pypy/dist/pypy/translator/js2/test/test_class.py
==============================================================================
--- pypy/dist/pypy/translator/js2/test/test_class.py	(original)
+++ pypy/dist/pypy/translator/js2/test/test_class.py	Sat Jun  3 20:21:24 2006
@@ -51,7 +51,7 @@
         assert f() == 14
 
     def test_flow_type(self):
-        py.test.skip("isinstanceof not implemented")
+        #py.test.skip("isinstanceof not implemented")
         f = compile_function(llvmsnippet.flow_type, [])
         assert f() == 16
 
@@ -81,7 +81,7 @@
         assert f(15) == 25
 
     def test_call_degrading_func(self):
-        py.test.skip("isinstanceof not implemented")
+        #py.test.skip("isinstanceof not implemented")
         f = compile_function(llvmsnippet.call_degrading_func, [bool])
         assert f(True) == llvmsnippet.call_degrading_func(True)
         assert f(False) == llvmsnippet.call_degrading_func(False)

Modified: pypy/dist/pypy/translator/js2/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/translator/js2/test/test_exception.py	(original)
+++ pypy/dist/pypy/translator/js2/test/test_exception.py	Sat Jun  3 20:21:24 2006
@@ -6,7 +6,7 @@
 
 import sys
 
-py.test.skip("Exception work in progress")
+#py.test.skip("Exception work in progress")
 
 class TestException(Exception):
     pass



More information about the Pypy-commit mailing list