[pypy-svn] r53222 - in pypy/branch/js-refactoring/pypy/lang/js: . test

fijal at codespeak.net fijal at codespeak.net
Tue Apr 1 01:26:22 CEST 2008


Author: fijal
Date: Tue Apr  1 01:26:21 2008
New Revision: 53222

Modified:
   pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py
   pypy/branch/js-refactoring/pypy/lang/js/jscode.py
   pypy/branch/js-refactoring/pypy/lang/js/operations.py
   pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py
Log:
some general progress in area of assignments.


Modified: pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py
==============================================================================
--- pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py	(original)
+++ pypy/branch/js-refactoring/pypy/lang/js/astbuilder.py	Tue Apr  1 01:26:21 2008
@@ -40,16 +40,10 @@
         #'!': operations.Not,
         '+': operations.UPlus,
         '-': operations.UMinus,
-        '++': operations.PreIncrement,
-        '--': operations.PreDecrement,
         #'typeof': operations.Typeof,
         #'void': operations.Void,
         #'delete': operations.Delete,
     }
-    POSTFIX_TO_CLS = {
-        '++': operations.PostIncrement,
-        '--': operations.PostDecrement,
-    }
     LISTOP_TO_CLS = {
         '[': operations.Array,
         '{': operations.ObjectInit,
@@ -161,14 +155,35 @@
         op = node.children[0]
         pos = self.get_pos(op)
         child = self.dispatch(node.children[1])
+        if op.additional_info in ['++', '--']:
+            return self._dispatch_assignment(pos, child, op.additional_info,
+                                             'pre')
         return self.UNOP_TO_CLS[op.additional_info](pos, child)
 
+    def _dispatch_assignment(self, pos, left, atype, prepost):
+        from pypy.lang.js.operations import Identifier, Member, MemberDot,\
+             VariableIdentifier
+
+        if isinstance(left, Identifier):
+            return operations.SimpleAssignment(pos, left, None, atype, prepost)
+        elif isinstance(left, VariableIdentifier):
+            return operations.VariableAssignment(pos, left, None, atype,
+                                                 prepost)
+        elif isinstance(left, Member):
+            return operations.MemberAssignment(pos, left.left, left.expr,
+                                               None, atype, prepost)
+        elif isinstance(left, MemberDot):
+            return operations.MemberDotAssignment(pos, left.left, left.name,
+                                                  None, atype, prepost)
+        else:
+            return operations.SimpleIncrement(pos, left, atype)
+
     def visit_postfixexpression(self, node):
         op = node.children[1]
         pos = self.get_pos(op)
         child = self.dispatch(node.children[0])
-        return self.POSTFIX_TO_CLS[op.additional_info](pos, child)
-
+        # all postfix expressions are assignments
+        return self._dispatch_assignment(pos, child, op.additional_info, 'post')
     
     def listop(self, node):
         op = node.children[0]

Modified: pypy/branch/js-refactoring/pypy/lang/js/jscode.py
==============================================================================
--- pypy/branch/js-refactoring/pypy/lang/js/jscode.py	(original)
+++ pypy/branch/js-refactoring/pypy/lang/js/jscode.py	Tue Apr  1 01:26:21 2008
@@ -241,21 +241,46 @@
     def __repr__(self):
         return 'LOAD_FUNCTION' # XXX
 
-class STORE_MEMBER(Opcode):
+class BaseStoreMember(Opcode):
     pass
     #def eval(self, ctx, ):
     #    XXX
 
-class STORE(Opcode):
+class STORE_MEMBER(Opcode):
+    pass
+
+class STORE_MEMBER_POSTINCR(Opcode):
+    pass
+
+class STORE_MEMBER_PREINCR(Opcode):
+    pass
+
+class STORE_MEMBER_SUB(Opcode):
+    pass
+
+class BaseStore(Opcode):
     def __init__(self, name):
         self.name = name
     
     def eval(self, ctx, stack):
         value = stack[-1]
+        value = self.process(ctx, self.name, value)
         ctx.assign(self.name, value)
 
     def __repr__(self):
-        return 'STORE "%s"' % self.name
+        return '%s "%s"' % (self.__class__.__name__, self.name)
+
+class STORE(BaseStore):
+    def process(self, ctx, name, value):
+        return value
+
+class STORE_ADD(BaseStore):
+    def process(self, ctx, name, value):
+        xxx
+
+class STORE_POSTINCR(BaseStore):
+    def process(self, ctx, name, value):
+        xxx
 
 class STORE_VAR(Opcode):
     def __init__(self, depth, name):
@@ -338,17 +363,11 @@
 class UMINUS(BaseUnaryOperation):
     pass
 
-#class PREINCR(BaseUnaryOperation):
-#    pass
-
-#class POSTINCR(BaseUnaryOperation):
-#    pass
- 
-#class PREDECR(BaseUnaryOperation):
-#    pass
+class INCR(BaseUnaryOperation):
+    pass
 
-#class POSTDECR(BaseUnaryOperation):
-#    pass
+class DECR(BaseUnaryOperation):
+    pass
 
 class GT(BaseBinaryComparison):
     def decision(self, ctx, op1, op2):

Modified: pypy/branch/js-refactoring/pypy/lang/js/operations.py
==============================================================================
--- pypy/branch/js-refactoring/pypy/lang/js/operations.py	(original)
+++ pypy/branch/js-refactoring/pypy/lang/js/operations.py	Tue Apr  1 01:26:21 2008
@@ -121,18 +121,48 @@
         bytecode.emit('LOAD_ARRAY', len(self.nodes))
 
 class Assignment(Expression):
-    pass
+    def _get_name(self):
+        addoper = OPERANDS[self.operand]
+        if addoper:
+            addoper = '_' + self.prefix.upper() + addoper
+        return addoper
+
+OPERANDS = {
+    '='  : '',
+    '+=' : 'ADD',
+    '-=' : 'SUB',
+    '*=' : 'MUL',
+    '/=' : 'DIV',
+    '++' : 'INCR',
+    '--' : 'DECR',
+    }
+
+class SimpleIncrement(Expression):
+    def __init__(self, pos, left, atype):
+        self.pos   = pos
+        self.left  = left
+        self.atype = atype
+
+    def emit(self, bytecode):
+        self.left.emit(bytecode)
+        if self.atype == '++':
+            bytecode.emit('INCR')
+        elif self.atype == '--':
+            bytecode.emit('DECR')
 
 class SimpleAssignment(Assignment):
-    def __init__(self, pos, left, right, operand):
+    def __init__(self, pos, left, right, operand, prefix=''):
         self.identifier = left.get_literal()
         self.right = right
         self.pos = pos
         self.operand = operand
+        self.prefix = prefix
 
     def emit(self, bytecode):
-        self.right.emit(bytecode)
-        bytecode.emit('STORE', self.identifier)
+        if self.right is not None:
+            self.right.emit(bytecode)
+        bytecode_name = 'STORE' + self._get_name()
+        bytecode.emit(bytecode_name, self.identifier)
 
 class VariableAssignment(Assignment):
     def __init__(self, pos, left, right, operand):
@@ -147,7 +177,7 @@
         bytecode.emit('STORE_VAR', self.depth, self.identifier)
 
 class MemberAssignment(Assignment):
-    def __init__(self, pos, what, item, right, operand):
+    def __init__(self, pos, what, item, right, operand, prefix=''):
         # XXX we can optimise here what happens if what is identifier,
         #     but let's leave it alone for now
         self.pos = pos
@@ -155,26 +185,30 @@
         self.item = item
         self.right = right
         self.operand = operand
+        self.prefix = prefix
 
     def emit(self, bytecode):
-        self.right.emit(bytecode)
+        if self.right is not None:
+            self.right.emit(bytecode)
         self.item.emit(bytecode)
         self.what.emit(bytecode)
-        bytecode.emit('STORE_MEMBER')
+        bytecode.emit('STORE_MEMBER' + self._get_name())
 
 class MemberDotAssignment(Assignment):
-    def __init__(self, pos, what, name, right, operand):
+    def __init__(self, pos, what, name, right, operand, prefix=''):
         self.pos = pos
         self.what = what
         self.itemname = name
         self.right = right
         self.operand = operand
+        self.prefix = prefix
 
     def emit(self, bytecode):
-        self.right.emit(bytecode)
+        if self.right is not None:
+            self.right.emit(bytecode)
         bytecode.emit('LOAD_STRINGCONSTANT', self.itemname)
         self.what.emit(bytecode)
-        bytecode.emit('STORE_MEMBER')
+        bytecode.emit('STORE_MEMBER' + self._get_name())
 
 class StuffAssignment(Expression):
     def __init__(self, pos, left, right, operand):
@@ -507,11 +541,6 @@
 #         r4 = r1.GetPropertyName()
 #         return W_Boolean(r3.Delete(r4))
 
-PreIncrement = create_unary_op('PREINCR')
-PostIncrement = create_unary_op('POSTINCR')
-PreDecrement = create_unary_op('PREDECRE')
-PostDecrement = create_unary_op('POSTDECR')
-
 #class Index(BinaryOp):
 #    def eval(self, ctx):
 #        w_obj = self.left.eval(ctx).GetValue().ToObject(ctx)

Modified: pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py
==============================================================================
--- pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py	(original)
+++ pypy/branch/js-refactoring/pypy/lang/js/test/test_parser.py	Tue Apr  1 01:26:21 2008
@@ -360,10 +360,10 @@
             'SUB'])
         self.check('++5', [
             'LOAD_INTCONSTANT 5',
-            'PREINCR'])
+            'INCR'])
         self.check('5--', [
             'LOAD_INTCONSTANT 5',
-            'POSTDECR'])
+            'DECR'])
         self.check('"hello " + \'world\'',
                    ['LOAD_STRINGCONSTANT "hello "',
                     'LOAD_STRINGCONSTANT "world"',
@@ -478,6 +478,25 @@
                                'STORE_MEMBER',
                                'POP'])
 
+    def test_different_assignments(self):
+        self.check('x += y', [
+            'LOAD_VARIABLE "y"',
+            'STORE_ADD "x"',
+            'POP'])
+        self.check('x++', ['STORE_POSTINCR "x"',
+                           'POP'])
+        self.check('++x[2]', [
+            'LOAD_INTCONSTANT 2',
+            'LOAD_VARIABLE "x"',
+            'STORE_MEMBER_PREINCR',
+            'POP'])
+        self.check('x.y -= 2',
+                   ['LOAD_INTCONSTANT 2',
+                    'LOAD_STRINGCONSTANT "y"',
+                    'LOAD_VARIABLE "x"',
+                    'STORE_MEMBER_SUB',
+                    'POP'])
+
 from pypy.lang.js.jsparser import parse
     
 def test_simplesemicolon():


More information about the pypy-svn mailing list