[pypy-commit] lang-js default: moved opceode execution into jscode

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


Author: Stephan <stephan at stzal.com>
Branch: 
Changeset: r247:b8540e257db0
Date: 2012-06-03 18:10 +0200
http://bitbucket.org/pypy/lang-js/changeset/b8540e257db0/

Log:	moved opceode execution into jscode use js.completion for return
	values

diff --git a/js/builtins_global.py b/js/builtins_global.py
--- a/js/builtins_global.py
+++ b/js/builtins_global.py
@@ -274,7 +274,7 @@
     calling_context = ctx._calling_context_
     ctx = EvalExecutionContext(f, calling_context = calling_context)
     res = f.run(ctx)
-    return _w(res)
+    return res
 
 def js_load(ctx):
     from js.interpreter import load_file
diff --git a/js/completion.py b/js/completion.py
new file mode 100644
--- /dev/null
+++ b/js/completion.py
@@ -0,0 +1,23 @@
+# 8.9
+class Completion(object):
+    def __init__(self, value = None, target = None):
+        self.value = value
+        self.target = target
+
+class NormalCompletion(Completion):
+    pass
+
+class ReturnCompletion(Completion):
+    pass
+
+class BreakCompletion(Completion):
+    pass
+
+class ContinueCompletion(Completion):
+    pass
+
+class ThrowCompletion(Completion):
+    pass
+
+def is_return_completion(c):
+    return isinstance(c, ReturnCompletion)
diff --git a/js/functions.py b/js/functions.py
--- a/js/functions.py
+++ b/js/functions.py
@@ -1,4 +1,3 @@
-from js.opcodes import BaseJump
 from js.jsobj import _w
 
 class JsBaseFunction(object):
@@ -56,10 +55,12 @@
         return self._name_
 
     def run(self, ctx):
+        from js.completion import ReturnCompletion
         args = ctx.argv()
         this = ctx.this_binding()
         res = self._function_(this, args)
-        return _w(res)
+        compl = ReturnCompletion(value = _w(res))
+        return compl
 
     def to_string(self):
         name = self.name()
@@ -85,40 +86,9 @@
     #def estimated_stack_size(self):
         #return self.stack_size
 
-    def _get_opcode(self, pc):
-        assert pc >= 0
-        return self.opcodes[pc]
-
     def run(self, ctx):
-        from js.globals import DEBUG
-        if len(self.opcodes) == 0:
-            from js.jsobj import w_Undefined
-            return w_Undefined
-
-        if DEBUG:
-            print('start running %s' % (str(self)))
-
-        pc = 0
-        while True:
-            if pc >= len(self.opcodes):
-                break
-            opcode = self._get_opcode(pc)
-            result = opcode.eval(ctx)
-            if DEBUG:
-                print(u'%3d %25s %s' % (pc, str(opcode), unicode([unicode(s) for s in ctx._stack_])))
-            assert result is None
-
-            from js.opcodes import RETURN
-            if isinstance(opcode, BaseJump):
-                new_pc = opcode.do_jump(ctx, pc)
-                pc = new_pc
-                continue
-            elif isinstance(opcode, RETURN):
-                break
-            else:
-                pc += 1
-
-        return ctx.stack_top()
+        result = self._js_code_.run(ctx)
+        return result
 
     def variables(self):
         return self._js_code_.variables()
diff --git a/js/interpreter.py b/js/interpreter.py
--- a/js/interpreter.py
+++ b/js/interpreter.py
@@ -68,7 +68,8 @@
         from js.execution_context import GlobalExecutionContext
         ctx = GlobalExecutionContext(c, self.global_object)
 
-        return c.run(ctx)
+        result = c.run(ctx)
+        return result.value
 
         #"""run the interpreter"""
         #bytecode = JsCode()
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -201,6 +201,49 @@
                 op.where = labels[op.where]
         self.has_labels = False
 
+    def _get_opcode(self, pc):
+        assert pc >= 0
+        return self.opcodes[pc]
+
+    def run(self, ctx):
+        from js.globals import DEBUG
+        from js.completion import ReturnCompletion, NormalCompletion
+        from js.opcodes import RETURN, BaseJump
+        from js.jsobj import w_Undefined
+
+        if len(self.opcodes) == 0:
+            return w_Undefined
+
+        if DEBUG:
+            print('start running %s' % (str(self)))
+
+        pc = 0
+        result = None
+        while True:
+            if pc >= len(self.opcodes):
+                break
+            opcode = self._get_opcode(pc)
+            result = opcode.eval(ctx)
+
+            if DEBUG:
+                print(u'%3d %25s %s %s' % (pc, str(opcode), unicode([unicode(s) for s in ctx._stack_]), str(result)))
+
+            if isinstance(result, ReturnCompletion):
+                break;
+
+            if isinstance(opcode, BaseJump):
+                new_pc = opcode.do_jump(ctx, pc)
+                pc = new_pc
+                continue
+            else:
+                pc += 1
+
+        if result is None:
+            result = NormalCompletion(value = ctx.stack_top())
+
+        return result
+
+
     #def __repr__(self):
         #return "\n".join([repr(i) for i in self.opcodes])
 
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -851,7 +851,7 @@
         ctx._calling_context_ = calling_context
 
         res = code.run(ctx)
-        return res
+        return res.value
 
     # 15.3.5.4
     def get(self, p):
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -554,8 +554,9 @@
 class RETURN(Opcode):
     _stack_change = 0
     def eval(self, ctx):
-        pass
-        #raise ReturnException(ctx.stack_pop())
+        from js.completion import ReturnCompletion
+        value = ctx.stack_top()
+        return ReturnCompletion(value)
 
 class POP(Opcode):
     _stack_change = -1
@@ -612,6 +613,7 @@
         self.finallyexec = finallyfunc
 
     def eval(self, ctx):
+        from js.completion import is_return_completion
         from js.execution import JsException
         try:
             b = self.tryexec.run(ctx)
@@ -631,7 +633,10 @@
         else:
             f = c
 
-        ctx.stack_append(f)
+        if is_return_completion(f):
+            return f
+        else:
+            ctx.stack_append(f.value)
 
 def commonnew(ctx, obj, args):
     from js.jsobj import W_BasicFunction
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
@@ -23,8 +23,8 @@
     from js.execution_context import ExecutionContext
     ctx = ExecutionContext()
     res = f.run(ctx)
-
-    assert res.ToNumber() == 6.0
+    value = res.value
+    assert value.ToNumber() == 6.0
 
 def assertp(code, prints, captured):
     out, err = captured.readouterr()
@@ -968,3 +968,8 @@
 def test_boolean_constructor():
     assertv("typeof Boolean(true)", 'boolean')
     assertv("typeof new Boolean(true)", 'object')
+
+def test_return_trycatch():
+    assertv("function f() { try { return 1; } catch(e) { return -1; } }; f()", 1)
+    assertv("function f() { try { throw('foo'); return 1; } catch(e) { return -1; } }; f()", -1)
+    assertv("function f() { try { throw('foo'); return 1; } catch(e) { return -1; } finally { return 0; } }; f()", 0)


More information about the pypy-commit mailing list