[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