[pypy-svn] r52670 - in pypy/branch/jit-refactoring/pypy/lang/js: . doc test

fijal at codespeak.net fijal at codespeak.net
Mon Mar 17 22:21:33 CET 2008


Author: fijal
Date: Mon Mar 17 22:21:33 2008
New Revision: 52670

Modified:
   pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py
   pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt
   pypy/branch/jit-refactoring/pypy/lang/js/execution.py
   pypy/branch/jit-refactoring/pypy/lang/js/interpreter.py
   pypy/branch/jit-refactoring/pypy/lang/js/jscode.py
   pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py
   pypy/branch/jit-refactoring/pypy/lang/js/operations.py
   pypy/branch/jit-refactoring/pypy/lang/js/test/test_interp.py
   pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py
Log:
Some progress.


Modified: pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/astbuilder.py	Mon Mar 17 22:21:33 2008
@@ -283,17 +283,17 @@
         if isinstance(left, Identifier):
             return operations.SimpleAssignment(pos, left, right, atype)
         elif isinstance(left, Member):
-            return operations.MemberAssignment(pos, left.left, left.right,
+            return operations.MemberAssignment(pos, left.left, left.expr,
                                                right, atype)
         elif isinstance(left, MemberDot):
             return operations.MemberDotAssignment(pos, left.left, left.name,
                                                   right, atype)
         else:
-            raise ParseError(left.pos, "Invalid lefthand expression")
+            raise ParseError(pos, None)
     visit_assignmentexpressionnoin = visit_assignmentexpression
         
     def visit_emptystatement(self, node):
-        return operations.astundef
+        pass
     
     def visit_newexpression(self, node):
         if len(node.children) == 1:
@@ -376,7 +376,7 @@
         if len(node.children) > 0:
             value = self.dispatch(node.children[0])
         else:
-            value = operations.astundef
+            value = None
         return operations.Return(pos, value)
 
     def visit_conditionalexpression(self, node):

Modified: pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/doc/bytecode.txt	Mon Mar 17 22:21:33 2008
@@ -30,7 +30,7 @@
 
 object creation:
 
-LOAD_OBJECT <list of parameters>
+LOAD_OBJECT <num>
 
 Takes one element per one parameter from the stack and initializes
 object this way.
@@ -44,6 +44,15 @@
 loads function object (declared earlier) to a stack. used for
 function expressions.
 
+LOAD_MEMBER <name>
+
+Load a member name from the last element on a stack.
+
+LOAD_ELEMENT
+
+Take element and left side from the stack and load element
+from the left side onto the stack
+
 Arithmetic binary operations:
 (all pops two values and pushes on stack the result)
 

Modified: pypy/branch/jit-refactoring/pypy/lang/js/execution.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/execution.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/execution.py	Mon Mar 17 22:21:33 2008
@@ -9,11 +9,15 @@
         self.message = message
         self.exception_object = exception_object # JS Exception Object
 
-class ExecutionReturned(JsBaseExcept):
-    def __init__(self, type='normal', value=None, identifier=None):
-        self.type = type
+class ReturnException(Exception):
+    def __init__(self, value):
         self.value = value
-        self.identifier = identifier
+
+#class ExecutionReturned(JsBaseExcept):
+#    def __init__(self, type='normal', value=None, identifier=None):
+#        self.type = type
+#        self.value = value
+#        self.identifier = identifier
 
 class ThrowException(JsBaseExcept):
     def __init__(self, exception):

Modified: pypy/branch/jit-refactoring/pypy/lang/js/interpreter.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/interpreter.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/interpreter.py	Mon Mar 17 22:21:33 2008
@@ -259,7 +259,11 @@
             functioncode = "function () {}"
         #remove program and sourcelements node
         funcnode = parse(functioncode).children[0].children[0]
-        return ASTBUILDER.dispatch(funcnode).execute(ctx)
+        ast = ASTBUILDER.dispatch(funcnode)
+        bytecode = JsCode()
+        ast.emit(bytecode)
+        bytecode.run(ctx, check_stack=False)
+        return bytecode.stack[-1]
     
     def Construct(self, ctx, args=[]):
         return self.Call(ctx, args, this=None)

Modified: pypy/branch/jit-refactoring/pypy/lang/js/jscode.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/jscode.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/jscode.py	Mon Mar 17 22:21:33 2008
@@ -1,8 +1,8 @@
 
 from pypy.lang.js.jsobj import W_IntNumber, W_FloatNumber, W_String,\
      W_Array, W_PrimitiveObject, W_Reference, ActivationObject,\
-     create_object
-from pypy.lang.js.execution import JsTypeError
+     create_object, W_Object, w_Undefined
+from pypy.lang.js.execution import JsTypeError, ReturnException
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.lang.js.baseop import plus, sub
 
@@ -81,6 +81,13 @@
         self.params = params
         self.code = code
 
+    def run(self, ctx):
+        try:
+            self.code.run(ctx)
+        except ReturnException, e:
+            return e.value
+        return w_Undefined
+
 class Opcode(object):
     def eval(self, ctx, stack):
         """ Execute in context ctx
@@ -160,6 +167,10 @@
     def __repr__(self):
         return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.strval,)
 
+class LOAD_UNDEFINED(Opcode):
+    def eval(self, ctx, stack):
+        stack.append(w_Undefined)
+
 class LOAD_VARIABLE(Opcode):
     def __init__(self, identifier):
         self.identifier = identifier
@@ -188,6 +199,16 @@
     def __init__(self, funcobj):
         self.funcobj = funcobj
 
+    def eval(self, ctx, stack):
+        proto = ctx.get_global().Get('Function').Get('prototype')
+        w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function',
+                          callfunc=self.funcobj)
+        w_func.Put('length', W_IntNumber(len(self.funcobj.params)))
+        w_obj = create_object(ctx, 'Object')
+        w_obj.Put('constructor', w_func, de=True)
+        w_func.Put('prototype', w_obj)
+        stack.append(w_func)
+
     def __repr__(self):
         return 'LOAD_FUNCTION' # XXX
 
@@ -208,18 +229,19 @@
         return 'STORE "%s"' % self.name
 
 class LOAD_OBJECT(Opcode):
-    def __init__(self, listofnames):
-        self.listofnames = reversed(listofnames)
-
+    def __init__(self, counter):
+        self.counter = counter
+    
     def eval(self, ctx, stack):
         w_obj = create_object(ctx, 'Object')
-        for name in self.listofnames:
+        for _ in range(self.counter):
+            name = stack.pop().GetValue().ToString()
             w_elem = stack.pop().GetValue()
             w_obj.Put(name, w_elem)
         stack.append(w_obj)
 
     def __repr__(self):
-        return 'LOAD_OBJECT %r' % (self.listofnames,)
+        return 'LOAD_OBJECT %d' % (self.counter,)
 
 class LOAD_MEMBER(Opcode):
     def __init__(self, name):
@@ -232,6 +254,12 @@
     def __repr__(self):
         return 'LOAD_MEMBER "%s"' % (self.name,)
 
+class LOAD_ELEMENT(Opcode):
+    def eval(self, ctx, stack):
+        name = stack.pop().GetValue().ToString(ctx)
+        w_obj = stack.pop().GetValue().ToObject(ctx)        
+        stack.append(W_Reference(name, w_obj))
+
 class SUB(BaseBinaryOperation):
     def operation(self, ctx, left, right):
         return sub(ctx, left, right)
@@ -306,6 +334,16 @@
     def __init__(self, funcobj):
         self.funcobj = funcobj
 
+    def eval(self, ctx, stack):
+        # function declaration actyally don't run anything
+        proto = ctx.get_global().Get('Function').Get('prototype')
+        w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self.funcobj)
+        w_func.Put('length', W_IntNumber(len(self.funcobj.params)))
+        w_obj = create_object(ctx, 'Object')
+        w_obj.Put('constructor', w_func, de=True)
+        w_func.Put('prototype', w_obj)
+        ctx.put(self.funcobj.name, w_func)
+
     def __repr__(self):
         funcobj = self.funcobj
         if funcobj.name is None:
@@ -319,11 +357,15 @@
     def __init__(self, name):
         self.name = name
 
+    def eval(self, ctx, stack):
+        ctx.put(self.name, w_Undefined)
+
     def __repr__(self):
         return 'DECLARE_VAR "%s"' % (self.name,)
 
 class RETURN(Opcode):
-    pass
+    def eval(self, ctx, stack):
+        raise ReturnException(stack.pop())
 
 class POP(Opcode):
     def eval(self, ctx, stack):

Modified: pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/jsobj.py	Mon Mar 17 22:21:33 2008
@@ -2,7 +2,7 @@
 from pypy.rlib.rarithmetic import r_uint, intmask, isnan, isinf,\
      ovfcheck_float_to_int
 from pypy.lang.js.execution import ThrowException, JsTypeError,\
-     ExecutionReturned, RangeError
+     RangeError
 
 class SeePage(NotImplementedError):
     pass
@@ -145,7 +145,7 @@
         w_Arguments = W_Arguments(self, args)
         act.Put('arguments', w_Arguments)
         newctx = function_context(self.Scope, act, this)
-        val = self.callfunc.body.execute(ctx=newctx)
+        val = self.callfunc.run(ctx=newctx)
         return val
     
     def Construct(self, ctx, args=[]):
@@ -517,7 +517,10 @@
                 obj.Put(name, value)
                 return
         # if not, we need to put this thing in current scope
-        self.scope[0].Put(name, value)
+        self.variable.Put(name, value)
+
+    def put(self, name, value):
+        self.variable.Put(name, value)
     
     def get_global(self):
         return self.scope[-1]

Modified: pypy/branch/jit-refactoring/pypy/lang/js/operations.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/operations.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/operations.py	Mon Mar 17 22:21:33 2008
@@ -9,8 +9,7 @@
      W_PrimitiveObject, W_Reference, ActivationObject, W_Array, W_Boolean,\
      w_Null, W_BaseNumber, isnull_or_undefined
 from pypy.rlib.parsing.ebnfparse import Symbol, Nonterminal
-from pypy.lang.js.execution import ExecutionReturned, JsTypeError,\
-     ThrowException
+from pypy.lang.js.execution import JsTypeError, ThrowException
 from pypy.lang.js.jscode import JsCode, JsFunction
 from constants import unescapedict, SLASH
 
@@ -87,13 +86,17 @@
         bytecode.emit('LOAD_UNDEFINED')
 
 class PropertyInit(Expression):
-    def __init__(self, pos, identifier, expr):
+    def __init__(self, pos, lefthand, expr):
         self.pos = pos
-        self.identifier = identifier.name
+        self.lefthand = lefthand
         self.expr = expr
     
     def emit(self, bytecode):
         self.expr.emit(bytecode)
+        if isinstance(self.lefthand, Identifier):
+            bytecode.emit('LOAD_STRINGCONSTANT', self.lefthand.name)
+        else:
+            self.lefthand.emit(bytecode)
 
 class Array(ListOp):
     def emit(self, bytecode):
@@ -290,13 +293,17 @@
             return self.falsepart.eval(ctx).GetValue()
     
 
-class Member(BinaryOp):
+class Member(Expression):
     "this is for object[name]"
-    def eval(self, ctx):
-        w_obj = self.left.eval(ctx).GetValue().ToObject(ctx)
-        name = self.right.eval(ctx).GetValue().ToString(ctx)
-        return W_Reference(name, w_obj)
-    
+    def __init__(self, pos, left, expr):
+        self.pos = pos
+        self.left = left
+        self.expr = expr
+
+    def emit(self, bytecode):
+        self.left.emit(bytecode)
+        self.expr.emit(bytecode)
+        bytecode.emit('LOAD_ELEMENT')
 
 class MemberDot(BinaryOp):
     "this is for object.name"
@@ -308,13 +315,7 @@
     
     def emit(self, bytecode):
         self.left.emit(bytecode)
-        bytecode.emit('LOAD_MEMBER', self.name)
-    
-    def eval(self, ctx):
-        w_obj = self.left.eval(ctx).GetValue().ToObject(ctx)
-        name = self.right.get_literal()
-        return W_Reference(name, w_obj)
-    
+        bytecode.emit('LOAD_MEMBER', self.name)    
 
 class FunctionStatement(Statement):
     def __init__(self, pos, name, params, body):
@@ -329,25 +330,16 @@
 
     def emit(self, bytecode):
         code = JsCode()
-        self.body.emit(code)
+        if self.body is not None:
+            self.body.emit(code)
         funcobj = JsFunction(self.name, self.params, code)
         bytecode.emit('DECLARE_FUNCTION', funcobj)
         if self.name is None:
-            # XXX looks awful
             bytecode.emit('LOAD_FUNCTION', funcobj)
-
-    def eval(self, ctx):
-        proto = ctx.get_global().Get('Function').Get('prototype')
-        w_func = W_Object(ctx=ctx, Prototype=proto, Class='Function', callfunc=self)
-        w_func.Put('length', W_IntNumber(len(self.params)))
-        w_obj = create_object(ctx, 'Object')
-        w_obj.Put('constructor', w_func, de=True)
-        w_func.Put('prototype', w_obj)
-        return w_func
-    
-    def execute(self, ctx):
-        return self.eval(ctx)
-    
+        #else:
+        #    bytecode.emit('LOAD_FUNCTION', funcobj)
+        #    bytecode.emit('STORE', self.name)
+        #    bytecode.emit('POP')
 
 class Identifier(Expression):
     def __init__(self, pos, name):
@@ -869,11 +861,9 @@
 
 class ObjectInit(ListOp):
     def emit(self, bytecode):
-        names = []
         for prop in self.nodes:
             prop.emit(bytecode)
-            names.append(prop.identifier)
-        bytecode.emit('LOAD_OBJECT', names)
+        bytecode.emit('LOAD_OBJECT', len(self.nodes))
 
 class SourceElements(Statement):
     """
@@ -934,15 +924,11 @@
         self.expr = expr
 
     def emit(self, bytecode):
-        self.expr.emit(bytecode)
-        bytecode.emit('RETURN')
-    
-    def execute(self, ctx):
-        if isinstance(self.expr, Undefined):
-            raise ExecutionReturned('return', None, None)
+        if self.expr is None:
+            bytecode.emit('LOAD_UNDEFINED')
         else:
-            raise ExecutionReturned('return', self.expr.eval(ctx), None)
-    
+            self.expr.emit(bytecode)
+        bytecode.emit('RETURN')
 
 class Throw(Statement):
     def __init__(self, pos, exp):
@@ -999,7 +985,10 @@
         self.expr = expr
 
     def emit(self, bytecode):
-        self.expr.emit(bytecode)
+        if self.expr is not None:
+            self.expr.emit(bytecode)
+        else:
+            bytecode.emit('LOAD_UNDEFINED')
         bytecode.emit('STORE', self.identifier)
     
     def eval(self, ctx):

Modified: pypy/branch/jit-refactoring/pypy/lang/js/test/test_interp.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/test/test_interp.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/test/test_interp.py	Mon Mar 17 22:21:33 2008
@@ -110,7 +110,8 @@
     function x () {
         var p;
         p = 1;
-        y = 3; return y + z;
+        y = 3;
+        return y + z;
     };
     var z = 2;
     print(x(), y, p);

Modified: pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py	(original)
+++ pypy/branch/jit-refactoring/pypy/lang/js/test/test_parser.py	Mon Mar 17 22:21:33 2008
@@ -331,9 +331,10 @@
         self.check('x = 3', [
             'LOAD_INTCONSTANT 3',
             'STORE "x"'])
-        self.check('{x:1}', [
+        self.check('{"x":1}', [
             'LOAD_INTCONSTANT 1',
-            "LOAD_OBJECT ['x']"])
+            'LOAD_STRINGCONSTANT "x"',
+            "LOAD_OBJECT 1"])
 
     def test_raising(self):
         py.test.raises(ParseError, self.check, '1=2', [])
@@ -367,6 +368,12 @@
                     'LOAD_STRINGCONSTANT "world"',
                     'ADD'])
 
+    def test_member(self):
+        self.check('a["b"]',
+                   ['LOAD_VARIABLE "a"',
+                    'LOAD_STRINGCONSTANT "b"',
+                    'LOAD_ELEMENT'])
+
 class TestToAstStatement(BaseTestToAST):
     def setup_class(cls):
         cls.parse = parse_func('statement')



More information about the Pypy-commit mailing list