[pypy-svn] r36301 - in pypy/dist/pypy/lang/js: . test
antocuni at codespeak.net
antocuni at codespeak.net
Mon Jan 8 18:10:57 CET 2007
Author: antocuni
Date: Mon Jan 8 18:10:57 2007
New Revision: 36301
Modified:
pypy/dist/pypy/lang/js/interpreter.py
pypy/dist/pypy/lang/js/jsobj.py
pypy/dist/pypy/lang/js/test/test_interp.py
Log:
(antocuni, santagada around)
Make the js interpreter RPythonic: we can now successfully translate
an interpreter that runs a somewhat complex hard-coded snippet. :-)
Modified: pypy/dist/pypy/lang/js/interpreter.py
==============================================================================
--- pypy/dist/pypy/lang/js/interpreter.py (original)
+++ pypy/dist/pypy/lang/js/interpreter.py Mon Jan 8 18:10:57 2007
@@ -9,17 +9,28 @@
# self.lineno = lineno
pass
-class BinaryOp(Node):
+class Statement(Node):
+ def execute(self, ctx):
+ raise NotImplementedError
+
+class Expression(Statement):
+ def eval(self, ctx):
+ return W_Root()
+
+ def execute(self, ctx):
+ return self.eval(ctx)
+
+class BinaryOp(Expression):
def __init__(self, left, right):
self.left = left
self.right = right
class BinaryComparisonOp(BinaryOp):
"""super class for binary operators"""
- def call(self, ctx):
- s2 = self.left.call(ctx).GetValue()
- s4 = self.right.call(ctx).GetValue()
- return self.decision(s2, s4)
+ def eval(self, ctx):
+ s2 = self.left.eval(ctx).GetValue()
+ s4 = self.right.eval(ctx).GetValue()
+ return self.decision(ctx, s2, s4)
class BinaryLogicOp(BinaryOp):
@@ -35,7 +46,7 @@
self.w_Object = W_Object() #creating Object
self.w_Global = W_Object()
self.w_Global.Prototype = self.w_Object
- self.w_Global.Put('prototype', 'Object')
+ self.w_Global.Put('prototype', W_String('Object'))
self.w_Global.Put('Object', self.w_Object)
self.global_context = global_context(self.w_Global)
if script_source is not None:
@@ -53,7 +64,7 @@
def run(self):
"""run the interpreter"""
- return self.script.call(self.global_context)
+ return self.script.execute(self.global_context)
class PropertyInit(Node):
def __init__(self, name, value):
@@ -64,127 +75,126 @@
return "<%s : %s>"%(str(self.name), str(self.value))
-
-class Undefined(Node):
- def __init__(self):
- pass
-
-
-class Array(Node):
+class Array(Expression):
def __init__(self, items=()):
self.items = items
- def call(self, ctx):
- d = dict(enumerate(self.items))
+ def eval(self, ctx):
+ #d = dict(enumerate(self.items))
+ d = {}
+ for i in range(len(self.items)):
+ d[i] = self.items[i]
return W_Array(d)
-class Assign(Node):
+class Assign(Expression):
def __init__(self, LHSExp, AssignmentExp):
self.LHSExp = LHSExp
self.AssignmentExp = AssignmentExp
- def call(self, ctx):
- print "Assign LHS = ", self.LHSExp
- v1 = self.LHSExp.call(ctx)
- print "Assign Exp = ", self.AssignmentExp
- v3 = self.AssignmentExp.call(ctx).GetValue()
+ def eval(self, ctx):
+ #print "Assign LHS = ", self.LHSExp
+ v1 = self.LHSExp.eval(ctx)
+ #print "Assign Exp = ", self.AssignmentExp
+ v3 = self.AssignmentExp.eval(ctx).GetValue()
v1.PutValue(v3, ctx)
return v3
-class Block(Node):
+class Block(Statement):
def __init__(self, nodes):
self.nodes = nodes
- def call(self, ctx):
+ def execute(self, ctx):
try:
last = w_Undefined
for node in self.nodes:
- last = node.call(ctx)
+ last = node.execute(ctx)
return last
except ExecutionReturned, e:
return e.value
-class Call(Node):
+class Call(Expression):
def __init__(self, identifier, arglist):
self.identifier = identifier
self.arglist = arglist
- def call(self, ctx):
+ def eval(self, ctx):
name = self.identifier.get_literal()
if name == 'print':
- writer(",".join([i.GetValue().ToString() for i in self.arglist.call(ctx)]))
+ writer(",".join([i.GetValue().ToString() for i in self.arglist.get_args(ctx)]))
else:
w_obj = ctx.resolve_identifier(name).GetValue()
- print "arglist = ", self.arglist
- retval = w_obj.Call(ctx=ctx, args=[i for i in self.arglist.call(ctx)])
+ #print "arglist = ", self.arglist
+ retval = w_obj.Call(ctx=ctx, args=[i for i in self.arglist.get_args(ctx)])
return retval
class Comma(BinaryOp):
- def call(self, ctx):
- self.left.call(ctx)
- return self.right.call(ctx)
+ def eval(self, ctx):
+ self.left.eval(ctx)
+ return self.right.eval(ctx)
class Dot(BinaryOp):
- def call(self, ctx):
- w_obj = self.left.call(ctx).GetValue().ToObject()
+ def eval(self, ctx):
+ w_obj = self.left.eval(ctx).GetValue().ToObject()
name = self.right.get_literal()
- return Reference(name, w_obj)
+ return W_Reference(name, w_obj)
-class Function(Node):
+class Function(Expression):
def __init__(self, name, params, body):
self.name = name
self.params = params
self.body = body
- def call(self, ctx):
+ def eval(self, ctx):
w_obj = W_FunctionObject(self, ctx)
return w_obj
-class Identifier(Node):
+class Identifier(Expression):
def __init__(self, name, initialiser=None):
self.name = name
self.initialiser = initialiser
+
def __str__(self):
return "<id %s init: %s>"%(str(self.name), str(self.initialiser))
- def call(self, ctx):
+
+ def eval(self, ctx):
if self.initialiser is not None:
ref = ctx.resolve_identifier(self.name)
- ref.PutValue(self.initialiser.call(ctx), ctx)
+ ref.PutValue(self.initialiser.eval(ctx), ctx)
return ctx.resolve_identifier(self.name)
def get_literal(self):
return self.name
-class If(Node):
+class If(Statement):
def __init__(self, condition, thenPart=None, elsePart=None):
self.condition = condition
self.thenPart = thenPart
self.elsePart = elsePart
- def call(self, ctx=None):
- temp = self.condition.call(ctx)
- print "if condition = ", temp
+ def execute(self, ctx=None):
+ temp = self.condition.eval(ctx)
+ #print "if condition = ", temp
if temp.ToBoolean():
- return self.thenPart.call(ctx)
+ return self.thenPart.execute(ctx)
else:
- return self.elsePart.call(ctx)
+ return self.elsePart.execute(ctx)
-class Group(Node):
+class Group(Expression):
def __init__(self, expr):
self.expr = expr
- def call(self, ctx):
- return self.expr.call(ctx)
+ def eval(self, ctx):
+ return self.expr.eval(ctx)
-def ARC(x, y):
+def ARC(ctx, x, y):
"""
Implements the Abstract Relational Comparison x < y
Still not 100% to the spec
"""
# TODO complete the funcion with strings comparison
- s1 = x.ToPrimitive('Number')
- s2 = y.ToPrimitive('Number')
- print "ARC x = %s, y = %s"%(str(s1),str(s2))
+ s1 = x.ToPrimitive(ctx, 'Number')
+ s2 = y.ToPrimitive(ctx, 'Number')
+ #print "ARC x = %s, y = %s"%(str(s1),str(s2))
if not (isinstance(s1, W_String) and isinstance(s2, W_String)):
s4 = s1.ToNumber()
s5 = s2.ToNumber()
@@ -198,48 +208,48 @@
pass
class Or(BinaryLogicOp):
- def call(self, ctx):
- s2 = self.left.call(ctx).GetValue()
+ def eval(self, ctx):
+ s2 = self.left.eval(ctx).GetValue()
if s2.ToBoolean():
return s2
- s4 = self.right.call(ctx).GetValue()
+ s4 = self.right.eval(ctx).GetValue()
return s4
class And(BinaryLogicOp):
- def call(self, ctx):
- s2 = self.left.call(ctx).GetValue()
+ def eval(self, ctx):
+ s2 = self.left.eval(ctx).GetValue()
if not s2.ToBoolean():
return s2
- s4 = self.right.call(ctx).GetValue()
+ s4 = self.right.eval(ctx).GetValue()
return s4
class Ge(BinaryComparisonOp):
- def decision(self, op1, op2):
- s5 = ARC(op1, op2)
+ def decision(self, ctx, op1, op2):
+ s5 = ARC(ctx, op1, op2)
if s5 is None or s5:
return W_Boolean(False)
else:
return W_Boolean(True)
class Gt(BinaryComparisonOp):
- def decision(self, op1, op2):
- s5 = ARC(op2, op1)
+ def decision(self, ctx, op1, op2):
+ s5 = ARC(ctx, op2, op1)
if s5 is None:
return W_Boolean(False)
else:
return W_Boolean(s5)
class Le(BinaryComparisonOp):
- def decision(self, op1, op2):
- s5 = ARC(op2, op1)
+ def decision(self, ctx, op1, op2):
+ s5 = ARC(ctx, op2, op1)
if s5 is None or s5:
return W_Boolean(False)
else:
return W_Boolean(True)
class Lt(BinaryComparisonOp):
- def decision(self, op1, op2):
- s5 = ARC(op1, op2)
+ def decision(self, ctx, op1, op2):
+ s5 = ARC(ctx, op1, op2)
if s5 is None:
return W_Boolean(False)
else:
@@ -254,30 +264,30 @@
return r
class Eq(BinaryComparisonOp):
- def decision(self, op1, op2):
+ def decision(self, ctx, op1, op2):
return W_Boolean(AEC(op1, op2))
class Ne(BinaryComparisonOp):
- def decision(self, op1, op2):
+ def decision(self, ctx, op1, op2):
return W_Boolean(not AEC(op1, op2))
class In(BinaryComparisonOp):
- def decision(self, op1, op2):
+ def decision(self, ctx, op1, op2):
if not isinstance(op2, W_Object):
raise ThrowException("TypeError")
name = op1.ToString()
return W_Boolean(op2.HasProperty(name))
-class Index(Node):
+class Index(Expression):
def __init__(self, left, expr):
self.left = left
self.expr = expr
- def call(self, ctx):
- w_obj = self.left.call(ctx).GetValue()
- w_member = self.expr.call(ctx).GetValue()
+ def eval(self, ctx):
+ w_obj = self.left.eval(ctx).GetValue()
+ w_member = self.expr.eval(ctx).GetValue()
w_obj = w_obj.ToObject()
name = w_member.ToString()
return w_obj.Get(name)
@@ -285,21 +295,22 @@
class List(Node):
def __init__(self, nodes):
self.nodes = nodes
- def call(self, ctx):
- print "nodes = ", self.nodes
- return [node.call(ctx) for node in self.nodes]
+
+ def get_args(self, ctx):
+ #print "nodes = ", self.nodes
+ return [node.eval(ctx) for node in self.nodes]
class Minus(BinaryComparisonOp):
- def decision(self, op1, op2):
+ def decision(self, ctx, op1, op2):
x = op1.ToNumber()
y = op2.ToNumber()
return W_Number(x - y)
-class New(Node):
+class New(Expression):
def __init__(self, identifier):
self.identifier = identifier
- def call(self, ctx):
+ def eval(self, ctx):
obj = W_Object()
#it should be undefined... to be completed
constructor = ctx.resolve_identifier(self.identifier).GetValue()
@@ -307,34 +318,34 @@
constructor.Call(ctx, this = obj)
return obj
-class Number(Node):
+class Number(Expression):
def __init__(self, num):
self.num = num
- def call(self, ctx):
+ def eval(self, ctx):
return W_Number(self.num)
def get_literal(self):
return W_Number(self.num).ToString()
-class ObjectInit(Node):
+class ObjectInit(Expression):
def __init__(self, properties):
self.properties = properties
- def call(self, ctx):
+ def eval(self, ctx):
w_obj = W_Object()
- print "properties = ", self.properties
+ ##print "properties = ", self.properties
for property in self.properties:
name = property.name.get_literal()
- print "prop name = ", name
- w_expr = property.value.call(ctx).GetValue()
+ #print "prop name = ", name
+ w_expr = property.value.eval(ctx).GetValue()
w_obj.Put(name, w_expr)
return w_obj
class Plus(BinaryComparisonOp):
- def decision(self, op1, op2):
- prim_left = op1.ToPrimitive('Number')
- prim_right = op2.ToPrimitive('Number')
+ def decision(self, ctx, op1, op2):
+ prim_left = op1.ToPrimitive(ctx, 'Number')
+ prim_right = op2.ToPrimitive(ctx, 'Number')
if isinstance(prim_left, W_String) or isinstance(prim_right, W_String):
str_left = prim_left.ToString()
str_right = prim_right.ToString()
@@ -344,23 +355,22 @@
num_right = prim_right.ToNumber()
return W_Number(num_left + num_right)
-class Script(Node):
+class Script(Statement):
def __init__(self, nodes, var_decl, func_decl):
self.nodes = nodes
self.var_decl = var_decl
self.func_decl = func_decl
- def call(self, ctx):
+ def execute(self, ctx):
for var in self.var_decl:
ctx.variable.Put(var.name, w_Undefined)
for fun in self.func_decl:
- ctx.variable.Put(fun.name, fun.call(ctx))
-
-
+ ctx.variable.Put(fun.name, fun.eval(ctx))
+
try:
last = w_Undefined
for node in self.nodes:
- last = node.call(ctx)
+ last = node.execute(ctx)
return last
except ExecutionReturned, e:
return e.value
@@ -371,40 +381,40 @@
self.nodes.extend(newscript.nodes)
self.func_decl.extend(newscript.func_decl)
-class Semicolon(Node):
+class Semicolon(Statement):
def __init__(self, expr = None):
self.expr = expr
- def call(self, ctx):
+ def execute(self, ctx):
if self.expr is None:
return
- return self.expr.call(ctx)
+ return self.expr.execute(ctx)
-class String(Node):
+class String(Expression):
def __init__(self, strval):
self.strval = strval
- def call(self, ctx):
+ def eval(self, ctx):
return W_String(self.strval)
def get_literal(self):
return W_String(self.strval).ToString()
-class Return(Node):
+class Return(Statement):
def __init__(self, expr):
self.expr = expr
- def call(self, ctx):
- raise ExecutionReturned(self.expr.call(ctx))
+ def execute(self, ctx):
+ raise ExecutionReturned(self.expr.eval(ctx))
-class Throw(Node):
+class Throw(Statement):
def __init__(self, exception):
self.exception = exception
- def call(self, ctx):
- raise ThrowException(self.exception.call(ctx))
+ def execute(self, ctx):
+ raise ThrowException(self.exception.eval(ctx))
-class Try(Node):
+class Try(Statement):
# TODO: rewrite to use 'Undefined'
def __init__(self, tryblock, catchblock, finallyblock, catchparam):
self.tryblock = tryblock
@@ -412,21 +422,21 @@
self.finallyblock = finallyblock
self.catchparam = catchparam
- def call(self, ctx):
+ def execute(self, ctx):
e = None
try:
- tryresult = self.tryblock.call(ctx)
+ tryresult = self.tryblock.execute(ctx)
except ThrowException, excpt:
e = excpt
if self.catchblock is not None:
obj = W_Object()
obj.Put(self.catchparam, e.exception)
ctx.push_object(obj)
- tryresult = self.catchblock.call(ctx)
+ tryresult = self.catchblock.execute(ctx)
ctx.pop_object()
if self.finallyblock is not None:
- tryresult = self.finallyblock.call(ctx)
+ tryresult = self.finallyblock.execute(ctx)
#if there is no catchblock reraise the exception
if (e is not None) and (self.catchblock is None):
@@ -434,28 +444,28 @@
return tryresult
-class Undefined(Node):
- def call(self, ctx):
+class Undefined(Statement):
+ def execute(self, ctx):
return None
-class Vars(Node):
+class Vars(Statement):
def __init__(self, nodes):
self.nodes = nodes
- def call(self, ctx):
- print self.nodes
+ def execute(self, ctx):
+ #print self.nodes
for var in self.nodes:
- print var.name
- var.call(ctx)
+ #print var.name
+ var.execute(ctx)
-class While(Node):
+class While(Statement):
def __init__(self, condition, body):
self.condition = condition
self.body = body
- def call(self, ctx):
- while self.condition.call(ctx).ToBoolean():
- self.body.call(ctx)
+ def execute(self, ctx):
+ while self.condition.eval(ctx).ToBoolean():
+ self.body.execute(ctx)
def getlist(t):
item = gettreeitem(t, 'length')
@@ -470,7 +480,7 @@
if x.children[0].additional_info == name:
return x.children[1]
return
-
+
def from_tree(t):
if t is None:
return
Modified: pypy/dist/pypy/lang/js/jsobj.py
==============================================================================
--- pypy/dist/pypy/lang/js/jsobj.py (original)
+++ pypy/dist/pypy/lang/js/jsobj.py Mon Jan 8 18:10:57 2007
@@ -13,6 +13,8 @@
self.exception = exception
self.args = self.exception
+class JsTypeError(Exception):
+ pass
INFDEF = 1e300 * 1e300
NaN = INFDEF/INFDEF
@@ -41,7 +43,7 @@
def ToBoolean(self):
return False
- def ToPrimitive(self, hint=""):
+ def ToPrimitive(self, ctx, hint=""):
return self
def ToString(self):
@@ -63,7 +65,7 @@
class W_Primitive(W_Root):
"""unifying parent for primitives"""
- def ToPrimitive(self, PreferredType):
+ def ToPrimitive(self, ctx, PreferredType):
return self
class W_Object(W_Root):
@@ -81,8 +83,6 @@
return W_Object()
def Get(self, P):
- if not isinstance(P, str):
- P = P.ToString()
if P in self.propdict: return self.propdict[P].value
if self.Prototype is None: return w_Undefined
return self.Prototype.Get(P) # go down the prototype chain
@@ -93,11 +93,10 @@
return True
if self.Prototype is None: return True
return self.Prototype.CanPut(P)
-
+
def Put(self, P, V):
- if not isinstance(P, str):
- P = P.ToString()
- if not self.CanPut(P): return
+ if not self.CanPut(P):
+ return
if P in self.propdict:
self.propdict[P].value = V
else:
@@ -111,28 +110,28 @@
def Delete(P):
if P in self.propdict:
if self.propdict[P].DontDelete: return False
- self.propdict.pop(P)
+ del self.propdict[P]
return True
return True
-
- def DefaultValue(self, hint):
- def internal_def_value(tryone, trytwo):
- t1 = self.Get(tryone)
- if isinstance(t1, W_Object):
- val = t1.Call(this=self)
- if isinstance(val, W_Primitive):
- return val
- t2 = self.Get(trytwo)
- if isinstance(t2, W_Object):
- val = t2.Call(this=self)
- if isinstance(val, W_Primitive):
- return val
- raise jsTypeError
-
+
+ def internal_def_value(self, ctx, tryone, trytwo):
+ t1 = self.Get(tryone)
+ if isinstance(t1, W_Object):
+ val = t1.Call(ctx, this=self)
+ if isinstance(val, W_Primitive):
+ return val
+ t2 = self.Get(trytwo)
+ if isinstance(t2, W_Object):
+ val = t2.Call(ctx, this=self)
+ if isinstance(val, W_Primitive):
+ return val
+ raise JsTypeError
+
+ def DefaultValue(self, ctx, hint):
if hint == "String":
- internal_def_value("toString", "valueOf")
+ return self.internal_def_value(ctx, "toString", "valueOf")
else: #suppose hint is "Number" dunno what to do otherwise
- internal_def_value("valueOf", "toString")
+ return self.internal_def_value(ctx, "valueOf", "toString")
ToPrimitive = DefaultValue
@@ -140,27 +139,29 @@
return "[object %s]"%(self.Class,)
def __str__(self):
- return "<Object class: %s\nproperties: %s\nPrototype: %s>"%(self.Class,
- self.propdict, self.Prototype)
+ return "<Object class: %s>" % self.Class
+
class W_Arguments(W_Object):
def __init__(self, callee, args):
W_Object.__init__(self)
self.Class = "arguments"
- self.propdict.pop("toString")
- self.propdict.pop("prototype")
+ del self.propdict["toString"]
+ del self.propdict["prototype"]
self.Put('callee', callee)
- self.Put('length', len(args))
- for i, arg in enumerate(args):
- self.Put(str(i), arg)
+ self.Put('length', W_Number(len(args)))
+## for i, arg in enumerate(args):
+## self.Put(str(i), arg)
+ for i in range(len(args)):
+ self.Put(str(i), args[i])
class ActivationObject(W_Object):
"""The object used on function calls to hold arguments and this"""
def __init__(self):
W_Object.__init__(self)
self.Class = "Activation"
- self.propdict.pop("toString")
- self.propdict.pop("prototype")
+ del self.propdict["toString"]
+ del self.propdict["prototype"]
class W_FunctionObject(W_Object):
def __init__(self, function, ctx):
@@ -172,22 +173,24 @@
self.scope = ctx.scope[:]
def Call(self, ctx, args=[], this=None):
- print "* start of function call"
- print " args = ", args
+ #print "* start of function call"
+ #print " args = ", args
act = ActivationObject()
- for i, arg in enumerate(self.function.params):
+ #for i, arg in enumerate(self.function.params):
+ for i in range(len(self.function.params)):
+ arg = self.function.params[i]
try:
value = args[i]
except IndexError:
value = w_Undefined
act.Put(self.function.params[i], value)
act.Put('this', this)
- print " act.propdict = ", act.propdict
+ #print " act.propdict = ", act.propdict
w_Arguments = W_Arguments(self, args)
act.Put('arguments', w_Arguments)
newctx = function_context(self.scope, act, this)
- val = self.function.body.call(ctx=newctx)
- print "* end of function call return = ", val
+ val = self.function.body.execute(ctx=newctx)
+ #print "* end of function call return = ", val
return val
class W_Array(W_Object):
@@ -262,7 +265,7 @@
class W_Number(W_Primitive):
def __init__(self, floatval):
- print "w_number = ", floatval
+ #print "w_number = ", floatval
self.floatval = floatval
def ToString(self):
@@ -289,8 +292,9 @@
#W_Object.__init__(self)
self.builtinfunction = builtinfunction
- def Call(self, context, args=[], this = None):
- return self.builtinfunction(*args)
+ def Call(self, ctx, args=[], this = None):
+ assert len(args) == 0
+ return W_String(self.builtinfunction()) # ???
class W_List(W_Root):
def __init__(self, list_w):
@@ -338,9 +342,9 @@
def resolve_identifier(self, identifier):
for obj in self.scope:
if obj.HasProperty(identifier):
- return Reference(identifier, obj)
+ return W_Reference(identifier, obj)
- return Reference(identifier)
+ return W_Reference(identifier)
def global_context(w_global):
@@ -370,7 +374,7 @@
ctx.property = Property('', w_Undefined)
return ctx
-class Reference(object):
+class W_Reference(W_Root):
"""Reference Type"""
def __init__(self, property_name, base=None):
self.base = base
@@ -396,4 +400,4 @@
def __str__(self):
return "< " + str(self.base) + " -> " + str(self.property_name) + " >"
-
\ No newline at end of file
+
Modified: pypy/dist/pypy/lang/js/test/test_interp.py
==============================================================================
--- pypy/dist/pypy/lang/js/test/test_interp.py (original)
+++ pypy/dist/pypy/lang/js/test/test_interp.py Mon Jan 8 18:10:57 2007
@@ -18,11 +18,11 @@
class TestInterp(object):
def test_simple(self):
- assert Plus(Number(3), Number(4)).call(ExecutionContext()).floatval == 7
+ assert Plus(Number(3), Number(4)).eval(ExecutionContext()).floatval == 7
l = []
interpreter.writer = l.append
Script([Semicolon(Call(Identifier('print', None),
- List([Number(1), Number(2)])))],[],[]).call(ExecutionContext())
+ List([Number(1), Number(2)])))],[],[]).execute(ExecutionContext())
assert l == ['1,2']
def assert_prints(self, code, assval):
More information about the Pypy-commit
mailing list