[pypy-commit] lang-js default: wip

stepahn noreply at buildbot.pypy.org
Fri Dec 28 11:33:24 CET 2012


Author: Stephan <stephan at stzal.com>
Branch: 
Changeset: r184:ef92b18137ba
Date: 2012-05-09 23:15 +0200
http://bitbucket.org/pypy/lang-js/changeset/ef92b18137ba/

Log:	wip

diff --git a/js/execution.py b/js/execution.py
--- a/js/execution.py
+++ b/js/execution.py
@@ -23,17 +23,24 @@
         self.exception = exception
         self.args = [exception]
 
-class JsThrowException(ThrowException):
+class JsException(Exception):
+    def __init__(self, value = None):
+        from js.jsobj import _w
+        self.value = _w(value)
+
+class JsThrowException(JsException):
     pass
 
-class JsTypeError(JsBaseExcept):
+class JsTypeError(JsException):
     pass
 
-class JsReferenceError(JsBaseExcept):
+class JsReferenceError(JsException):
+    def __init__(self, identifier):
+        s = "ReferenceError: %s is not defined" % (identifier)
+        JsException.__init__(self, s)
+
+class JsRangeError(JsException):
     pass
 
-class JsRangeError(JsBaseExcept):
+class JsSyntaxError(JsException):
     pass
-
-class JsSyntaxError(JsBaseExcept):
-    pass
diff --git a/js/execution_context.py b/js/execution_context.py
--- a/js/execution_context.py
+++ b/js/execution_context.py
@@ -45,6 +45,9 @@
     def lexical_environment(self):
         return self._lexical_environment_
 
+    def set_lexical_environment(self, lex_env):
+        self._lexical_environment_ = lex_env
+
     def declaration_binding_initialization(self):
         env = self._variable_environment_.environment_record
         strict = self._strict_
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -3,7 +3,7 @@
 from pypy.rlib.jit import JitDriver, purefunction
 
 from js.execution import JsTypeError, ReturnException, ThrowException, JsReferenceError
-from js.opcodes import opcodes, LABEL, BaseJump, WITH_START, WITH_END
+from js.opcodes import opcodes, LABEL, BaseJump
 from js.jsobj import W_Root, W_String, _w, w_Null, w_Undefined
 
 from pypy.rlib import jit, debug
@@ -171,6 +171,11 @@
         #self.unpop()
         return self.opcodes
 
+    def to_executable_opcodes(self):
+        self.unlabel()
+        self.unpop()
+        return self.opcodes
+
     def remove_labels(self):
         """ Basic optimization to remove all labels and change
         jumps to addresses. Necessary to run code at all
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem import rffi
 from pypy.rlib.rarithmetic import r_uint, intmask, ovfcheck_float_to_int
 from pypy.rlib.rfloat import isnan, isinf, NAN, formatd
-from js.execution import ThrowException, JsTypeError, JsRangeError, ReturnException
+from js.execution import JsTypeError, JsRangeError, ReturnException
 
 from pypy.rlib.jit import hint
 from pypy.rlib import jit, debug
diff --git a/js/lexical_environment.py b/js/lexical_environment.py
--- a/js/lexical_environment.py
+++ b/js/lexical_environment.py
@@ -81,7 +81,8 @@
     base = v.get_base()
 
     if v.is_unresolvable_reference():
-        raise JsReferenceError()
+        referenced = v.get_referenced_name()
+        raise JsReferenceError(referenced)
 
     if v.is_property_reference():
         raise NotImplementedError('8.7.1 4.')
@@ -100,7 +101,8 @@
     base = v.get_base()
     if v.is_unresolvable_reference():
         if v.is_strict_reference():
-            raise JsReferenceError()
+            referenced = v.get_referenced_name()
+            raise JsReferenceError(referenced)
         else:
             name = v.get_referenced_name()
             # TODO how to solve this ????
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -233,7 +233,7 @@
 
 class TYPEOF(BaseUnaryOperation):
     def eval(self, ctx):
-        one = ctx.stack_pop()
+        var = ctx.stack_pop()
         ctx.stack_append(W_String(one.type()))
 
 class TYPEOF_VARIABLE(Opcode):
@@ -242,20 +242,13 @@
         self.name = name
 
     def eval(self, ctx):
-        try:
-            ref = ctx.get_ref(self.name)
+        ref = ctx.get_ref(self.name)
+        if ref.is_unresolvable_reference():
+            var_type = 'undefined'
+        else:
             var = ref.get_value()
             var_type = var.type()
-            ctx.stack_append(W_String(var_type))
-        except ThrowException:
-            ctx.stack_append(W_String('undefined'))
-
-#class Typeof(UnaryOp):
-#    def eval(self, ctx):
-#        val = self.expr.eval(ctx)
-#        if isinstance(val, W_Reference) and val.GetBase() is None:
-#            return W_String("undefined")
-#        return W_String(val.GetValue().type())
+        ctx.stack_append(W_String(var_type))
 
 class ADD(BaseBinaryOperation):
     def operation(self, ctx, left, right):
@@ -568,33 +561,39 @@
 class TRYCATCHBLOCK(Opcode):
     _stack_change = 0
     def __init__(self, tryfunc, catchparam, catchfunc, finallyfunc):
-        self.tryfunc     = tryfunc
-        self.catchfunc   = catchfunc
+        self.tryexec     = tryfunc
+        self.catchexec   = catchfunc
         self.catchparam  = catchparam
-        self.finallyfunc = finallyfunc
+        self.finallyexec = finallyfunc
 
     def eval(self, ctx):
+        from js.execution import JsException
         try:
-            try:
-                self.tryfunc.run(ctx)
-            except ThrowException, e:
-                if self.catchfunc is not None:
-                    # XXX just copied, I don't know if it's right
-                    from js.jsexecution_context import make_catch_context
-                    newctx = make_catch_context(ctx, self.catchparam, e.exception)
-                    self.catchfunc.run(newctx)
-                if self.finallyfunc is not None:
-                    self.finallyfunc.run(ctx)
-                if not self.catchfunc:
-                    raise
-        except ReturnException:
-            # we run finally block here and re-raise the exception
-            if self.finallyfunc is not None:
-                self.finallyfunc.run(ctx)
-            raise
+            b = self.tryexec.run(ctx)
+        except JsException, e:
+            if self.catchexec is not None:
+                old_env = ctx.lexical_environment()
 
-    #def __repr__(self):
-        #return "TRYCATCHBLOCK" # XXX shall we add stuff here???
+                from js.lexical_environment import DeclarativeEnvironment
+                catch_env = DeclarativeEnvironment(old_env)
+                catch_env_rec = catch_env.environment_record
+                catch_env_rec.create_mutuable_binding(self.catchparam, True)
+                b = e.value
+                catch_env_rec.set_mutable_binding(self.catchparam, b, False)
+                ctx.set_lexical_environment(catch_env)
+                c = self.catchexec.run(ctx)
+                ctx.set_lexical_environment(old_env)
+        else:
+            c = b
+
+        if self.finallyexec is not None:
+            f = self.finallyexec.run(ctx)
+            if f is None:
+                f = c
+        else:
+            f = c
+
+        ctx.stack_append(f)
 
 class NEW(Opcode):
     _stack_change = 0
@@ -651,23 +650,27 @@
 
 # ---------------- with support ---------------------
 
-class WITH_START(Opcode):
-    _stack_change = 0
-    def __init__(self):
-        self.newctx = None
+class WITH(Opcode):
+    def __init__(self, expr, body):
+        self.expr = expr
+        self.body = body
 
     def eval(self, ctx):
-        from js.lexical_environment import ObjectEnvironment
-        obj = ctx.stack_pop().ToObject()
+        from lexical_environment import ObjectEnvironment
+        # 12.10
+        expr = self.expr.run(ctx)
+        expr_obj = expr.ToObject()
+
         old_env = ctx.lexical_environment()
-        new_env = ObjectEnvironment(obj, outer_environment = old_env)
+        new_env = ObjectEnvironment(expr_obj, outer_environment = old_env)
         new_env.environment_record.provide_this = True
-        ctx._lexical_environment_ = new_env
+        ctx.set_lexical_environment(new_env)
 
-class WITH_END(Opcode):
-    _stack_change = 0
-    def eval(self, ctx):
-        ctx._lexical_environment_ = ctx.lexical_environment().outer_environment
+        try:
+            c = self.body.run(ctx)
+            ctx.stack_append(c)
+        finally:
+            ctx.set_lexical_environment(old_env)
 
 # ------------------ delete -------------------------
 
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -730,25 +730,27 @@
 
     def emit(self, bytecode):
         from js.jscode import JsCode
-        # a bit naive operator for now
+        from js.functions import JsExecutableCode
+
         trycode = JsCode()
         self.tryblock.emit(trycode)
+        tryexec = JsExecutableCode(trycode)
 
-        #tryfunc = trycode.make_js_function()
         if self.catchblock:
             catchcode = JsCode()
             self.catchblock.emit(catchcode)
-        #    catchfunc = catchcode.make_js_function()
+            catchexec = JsExecutableCode(catchcode)
         else:
             catchfunc = None
+
         if self.finallyblock:
             finallycode = JsCode()
             self.finallyblock.emit(finallycode)
-        #    finallyfunc = finallycode.make_js_function()
+            finallyexec = JsExecutableCode(finallycode)
         else:
-            finallyfunc = None
-        raise NotImplementedError()
-        bytecode.emit('TRYCATCHBLOCK', tryfunc, self.catchparam.get_literal(), catchfunc, finallyfunc)
+            finallyexec = None
+        catchparam = self.catchparam.get_literal()
+        bytecode.emit('TRYCATCHBLOCK', tryexec, catchparam, catchexec, finallyexec)
 
 class VariableDeclaration(Expression):
     def __init__(self, pos, identifier, index, expr=None):
@@ -860,10 +862,18 @@
         self.body = body
 
     def emit(self, bytecode):
-        self.expr.emit(bytecode)
-        bytecode.emit('WITH_START')
-        self.body.emit(bytecode)
-        bytecode.emit('WITH_END')
+        from js.jscode import JsCode
+        from js.functions import JsExecutableCode
+
+        expr_code = JsCode()
+        self.expr.emit(expr_code)
+        expr_exec = JsExecutableCode(expr_code)
+
+        body_code = JsCode()
+        self.body.emit(body_code)
+        body_exec = JsExecutableCode(body_code)
+
+        bytecode.emit('WITH', expr_exec, body_exec)
 
 class WhileBase(Statement):
     def __init__(self, pos, condition, body):
diff --git a/js/test/test_interp.py b/js/test/test_interp.py
--- a/js/test/test_interp.py
+++ b/js/test/test_interp.py
@@ -216,9 +216,9 @@
     print(x.length)
     """, '\n0', capsys)
 
- at xfail
 def test_throw(capsys):
-    assertp("throw(3);", "uncaught exception: 3", capsys)
+    from js.execution import JsThrowException
+    asserte("throw(3);", JsThrowException)
 
 def test_group():
     assertv("(2+1);", 3)
@@ -230,7 +230,6 @@
     assertp("{print(5);}", '5', capsys)
     assertp("{3; print(5);}", '5', capsys)
 
- at xfail
 def test_try_catch_finally(capsys):
     assertp("""
     try {
@@ -321,14 +320,13 @@
     o;
     """, "[object Object]")
 
- at xfail
 def test_var_decl(capsys):
     assertp("print(x); var x;", "undefined", capsys)
     assertp("""
     try {
         print(z);
     }
-    catch (e) {
+    catch(e){
         print(e);
     }
     """, "ReferenceError: z is not defined", capsys)
@@ -395,7 +393,6 @@
     }
     print('out');""", "out", capsys)
 
- at xfail
 def test_typeof():
     assertv("""
     var x = 3;
@@ -555,7 +552,6 @@
     assertv("2 !== 3;", True)
     assertv("2 !== 2;", False)
 
- at xfail
 def test_with(capsys):
     assertp("""
     var mock = {x:2};


More information about the pypy-commit mailing list