[pypy-svn] r5153 - in pypy/trunk/src: Pyrex/Compiler pypy/translator pypy/translator/test

arigo at codespeak.net arigo at codespeak.net
Thu Jun 17 19:44:51 CEST 2004


Author: arigo
Date: Thu Jun 17 19:44:50 2004
New Revision: 5153

Modified:
   pypy/trunk/src/Pyrex/Compiler/ExprNodes.py
   pypy/trunk/src/Pyrex/Compiler/Lexicon.pickle
   pypy/trunk/src/Pyrex/Compiler/Lexicon.py
   pypy/trunk/src/Pyrex/Compiler/Parsing.py
   pypy/trunk/src/pypy/translator/genpyrex.py
   pypy/trunk/src/pypy/translator/test/test_pyrextrans.py
Log:
Implemented in-place operators in Pyrex, but only the 'name += expr' syntax.
For the more involved syntaxes like 'expr1[expr2] = expr3' we would have to
precompute expr1 and expr2 and store them in temporary variables.  Not sure
how to do this.  But 'v12 += v34' is probably all we need for PyPy.

Fixed genpyrex.py to use this extension.  Remember that in-place operators are
actually binary operators returning a result: an in-place operator
SpaceOperation() still has two args and a new result variable, and corresponds
to the C API call 'result = PyNumber_InPlaceXxx(arg1, arg2)'.  To emulate
this, genpyrex.py now generates code like 'result = arg1; result += arg2'.  


Modified: pypy/trunk/src/Pyrex/Compiler/ExprNodes.py
==============================================================================
--- pypy/trunk/src/Pyrex/Compiler/ExprNodes.py	(original)
+++ pypy/trunk/src/Pyrex/Compiler/ExprNodes.py	Thu Jun 17 19:44:50 2004
@@ -2268,7 +2268,7 @@
     def generate_result_code(self, code):
         if self.operand1.type.is_pyobject:
             function = self.py_operation_function()
-            if function == "PyNumber_Power":
+            if self.operator == "**":
                 extra_args = ", Py_None"
             else:
                 extra_args = ""
@@ -2296,6 +2296,7 @@
 
 class NumBinopNode(BinopNode):
     #  Binary operation taking numeric arguments.
+    inplace = 0
     
     def analyse_c_operation(self, env):
         type1 = self.operand1.type
@@ -2320,7 +2321,10 @@
             self.operand2.result)
     
     def py_operation_function(self):
-        return self.py_functions[self.operator]
+        function = self.py_functions[self.operator]
+        if self.inplace:
+            function = function.replace("PyNumber_", "PyNumber_InPlace")
+        return function
 
     py_functions = {
         "|":		"PyNumber_Or",

Modified: pypy/trunk/src/Pyrex/Compiler/Lexicon.pickle
==============================================================================
Binary files. No diff available.

Modified: pypy/trunk/src/Pyrex/Compiler/Lexicon.py
==============================================================================
--- pypy/trunk/src/Pyrex/Compiler/Lexicon.py	(original)
+++ pypy/trunk/src/Pyrex/Compiler/Lexicon.py	Thu Jun 17 19:44:50 2004
@@ -66,7 +66,9 @@
     bra = Any("([{")
     ket = Any(")]}")
     punct = Any(":,;+-*/|&<>=.%`~^?")
-    diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**")
+    diphthong = Str("==", "<>", "!=", "<=", ">=", "<<", ">>", "**",
+                    "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=",
+                    "<<=", ">>=", "**=")
     spaces = Rep1(Any(" \t\f"))
     comment = Str("#") + Rep(AnyBut("\n"))
     escaped_newline = Str("\\\n")

Modified: pypy/trunk/src/Pyrex/Compiler/Parsing.py
==============================================================================
--- pypy/trunk/src/Pyrex/Compiler/Parsing.py	(original)
+++ pypy/trunk/src/Pyrex/Compiler/Parsing.py	Thu Jun 17 19:44:50 2004
@@ -637,6 +637,23 @@
 
 def p_expression_or_assignment(s):
     expr_list = [p_expr(s)]
+    if s.sy in augassign_ops:
+        n1 = expr_list[0]
+        op = s.sy[:-1]
+        pos = s.position()
+        s.next()
+        n2 = p_expr(s)
+        # Parse a limited form of augmented assignment:
+        #    'name += expr'  -->  'name = name + y'
+        # with a specially marked binop node.
+        # Augmented assignment to more complex expressions isn't supported yet.
+        if isinstance(n1, ExprNodes.NameNode):
+            n1copy = ExprNodes.NameNode(n1.pos, name = n1.name)
+        else:
+            s.error("not implemented: augmented assignment to an expression more complex than a variable name")
+        binop = ExprNodes.binop_node(pos, op, n1, n2)
+        binop.inplace = 1
+        return Nodes.SingleAssignmentNode(pos, lhs = n1copy, rhs = binop)
     while s.sy == '=':
         s.next()
         expr_list.append(p_expr(s))
@@ -663,6 +680,11 @@
             #return Nodes.StatListNode(nodes[0].pos, stats = nodes)
             return Nodes.ParallelAssignmentNode(nodes[0].pos, stats = nodes)
 
+augassign_ops = (
+    '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=',
+    '<<=', '>>=', '**='
+)
+
 def flatten_parallel_assignments(input, output):
     #  The input is a list of expression nodes, representing 
     #  the LHSs and RHS of one (possibly cascaded) assignment 

Modified: pypy/trunk/src/pypy/translator/genpyrex.py
==============================================================================
--- pypy/trunk/src/pypy/translator/genpyrex.py	(original)
+++ pypy/trunk/src/pypy/translator/genpyrex.py	Thu Jun 17 19:44:50 2004
@@ -26,12 +26,11 @@
                 return "%s = %s %s" % (self.resultname, operator) + args
             elif len(args) == 2:
                 #Inplace operators
-                inp=['+=','-=','*=','/=','%=','^=','//=','div=','**=','<<=','>>=','!=','&=']
+                inp=['+=','-=','*=','/=','%=','&=','|=','^=','//=',
+                     '<<=','>>=','**=']
                 if operator in inp:
-                    temp_str="temp_xx12=%s %s %s\n"%(args[0], operator[:-1], args[1])
-                    temp_str+="%s=temp_xx12\n"%args[0]
-                    temp_str+="%s=temp_xx12"%self.resultname
-                    return temp_str
+                    return "%s = %s; %s %s %s" % (self.resultname, args[0],
+                                        self.resultname, operator, args[1])
                 else:
                     return "%s = %s %s %s" % (self.resultname, args[0], operator, args[1])
             elif len(args) == 3 and operator == "**": #special case, have to handle it manually

Modified: pypy/trunk/src/pypy/translator/test/test_pyrextrans.py
==============================================================================
--- pypy/trunk/src/pypy/translator/test/test_pyrextrans.py	(original)
+++ pypy/trunk/src/pypy/translator/test/test_pyrextrans.py	Thu Jun 17 19:44:50 2004
@@ -41,6 +41,10 @@
         poor_man_range = self.build_cfunc(snippet.poor_man_range)
         self.assertEquals(poor_man_range(10), range(10))
 
+    def poor_man_rev_range(self):
+        poor_man_rev_range = self.build_cfunc(snippet.poor_man_rev_range)
+        self.assertEquals(poor_man_rev_range(10), range(9,-1,-1))
+
     def test_simple_id(self):
         #we just want to see, if renaming of parameter works correctly
         #if the first branch is the end branch



More information about the Pypy-commit mailing list