[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