[pypy-commit] lang-js default: wip
stepahn
noreply at buildbot.pypy.org
Fri Dec 28 11:33:42 CET 2012
Author: Stephan <stephan at stzal.com>
Branch:
Changeset: r202:085d0ac59e45
Date: 2012-05-22 15:20 +0200
http://bitbucket.org/pypy/lang-js/changeset/085d0ac59e45/
Log: wip
diff --git a/js/astbuilder.py b/js/astbuilder.py
--- a/js/astbuilder.py
+++ b/js/astbuilder.py
@@ -355,15 +355,18 @@
pos = self.get_pos(node)
self.funclists.append({})
nodes=[]
+
+ def isnotempty(node):
+ return node is not None and not isinstance(node, operations.Empty)
+
for child in node.children:
- node = self.dispatch(child)
- if node is not None:
- nodes.append(node)
- # XXX is this still needed or can it be dropped?
- #var_decl = self.scopes.declarations()
+ n = self.dispatch(child)
+ if isnotempty(n):
+ nodes.append(n)
+
var_decl = self.current_scope_variables()
func_decl = self.funclists.pop()
- #func_decl = self.scopes.functions.keys()
+
return operations.SourceElements(pos, var_decl, func_decl, nodes, self.sourcename)
def functioncommon(self, node, declaration=True):
@@ -583,14 +586,17 @@
right = self.dispatch(node.children[2])
body= self.dispatch(node.children[3])
assert isinstance(left, Identifier)
- return operations.ForIn(pos, left.name, right, body)
+ name = left.name
+ return operations.ForIn(pos, name, right, body)
def visit_invarfor(self, node):
pos = self.get_pos(node)
left = self.dispatch(node.children[1])
right = self.dispatch(node.children[2])
body= self.dispatch(node.children[3])
- return operations.ForVarIn(pos, left, right, body)
+ assert isinstance(left, operations.VariableDeclaration)# or isinstance(left, operations.LocalVariableDeclaration)
+ name = left.identifier
+ return operations.ForIn(pos, name, right, body)
def get_next_expr(self, node, i):
if isinstance(node.children[i], Symbol) and \
diff --git a/js/builtins_global.py b/js/builtins_global.py
--- a/js/builtins_global.py
+++ b/js/builtins_global.py
@@ -224,7 +224,7 @@
def pypy_repr(this, args):
o = args[0]
- return repr(o)
+ return str(o)
def inspect(this, args):
pass
@@ -269,6 +269,7 @@
symbol_map = ast.symbol_map
code = ast_to_bytecode(ast, symbol_map)
+ code.unpop()
f = JsEvalCode(code)
calling_context = ctx._calling_context_
diff --git a/js/execution.py b/js/execution.py
--- a/js/execution.py
+++ b/js/execution.py
@@ -34,8 +34,12 @@
class JsThrowException(JsException):
def __init__(self, value = None):
JsException.__init__(self)
+ from js.jsobj import _w
self.value = _w(value)
+ def _msg(self):
+ return self.value
+
class JsTypeError(JsException):
def __init__(self, value = None):
JsException.__init__(self)
@@ -50,7 +54,7 @@
self.identifier = identifier
def _msg(self):
- return 'ReferenceError: %s' % (self.identifier)
+ return 'ReferenceError: %s is not defined' % (self.identifier)
class JsRangeError(JsException):
def __init__(self, value = None):
diff --git a/js/execution_context.py b/js/execution_context.py
--- a/js/execution_context.py
+++ b/js/execution_context.py
@@ -190,16 +190,32 @@
def argv(self):
return self._argument_values_
-class WithExecutionContext(ExecutionContext):
- def __init__(self, code, expr_obj, calling_context):
+class SubExecutionContext(ExecutionContext):
+ def __init__(self, parent):
ExecutionContext.__init__(self)
+ self._parent_context_ = parent
+
+ def stack_append(self, value):
+ self._parent_context_.stack_append(value)
+
+ def stack_pop(self):
+ return self._parent_context_.stack_pop()
+
+ def stack_top(self):
+ return self._parent_context_.stack_top()
+
+ def stack_pop_n(self, n):
+ return self._parent_context_.stack_pop_n(n)
+
+class WithExecutionContext(SubExecutionContext):
+ def __init__(self, code, expr_obj, parent_context):
+ SubExecutionContext.__init__(self, parent_context)
self._code_ = code
self._strict_ = code.strict
- self._calling_context_ = calling_context
self._expr_obj_ = expr_obj
from js.lexical_environment import ObjectEnvironment
- parent_environment = calling_context.lexical_environment()
+ parent_environment = parent_context.lexical_environment()
local_env = ObjectEnvironment(expr_obj, outer_environment = parent_environment)
local_env.environment_record.provide_this = True
@@ -209,15 +225,22 @@
self.declaration_binding_initialization()
- def stack_append(self, value):
- self._calling_context_.stack_append(value)
+class CatchExecutionContext(SubExecutionContext):
+ def __init__(self, code, catchparam, exception_value, parent_context):
+ SubExecutionContext.__init__(self, parent_context)
+ self._code_ = code
+ self._strict_ = code.strict
- def stack_pop(self):
- return self._calling_context_.stack_pop()
+ parent_env = parent_context.lexical_environment()
- def stack_top(self):
- return self._calling_context_.stack_top()
+ from js.lexical_environment import DeclarativeEnvironment
+ local_env = DeclarativeEnvironment(parent_env)
+ local_env_rec = local_env.environment_record
+ local_env_rec.create_mutuable_binding(catchparam, True)
+ local_env_rec.set_mutable_binding(catchparam, exception_value, False)
- def stack_pop_n(self, n):
- return self._calling_context_.stack_pop_n(n)
+ self._lexical_environment_ = local_env
+ self._variable_environment_ = local_env
+ self._this_binding_ = parent_context.this_binding()
+ self.declaration_binding_initialization()
diff --git a/js/functions.py b/js/functions.py
--- a/js/functions.py
+++ b/js/functions.py
@@ -90,14 +90,18 @@
return self.opcodes[pc]
def run(self, ctx):
+ if len(self.opcodes) == 0:
+ from js.jsobj import w_Undefined
+ return w_Undefined
+
pc = 0
while True:
if pc >= len(self.opcodes):
break
opcode = self._get_opcode(pc)
result = opcode.eval(ctx)
+ #print("%3d %25s %s" % (pc, str(opcode), str([str(s) for s in ctx._stack_])))
assert result is None
- #print('pc:%d, opcode:%s, stack:%s'%(pc, repr(opcode), str(ctx._stack_)))
from js.opcodes import RETURN
if isinstance(opcode, BaseJump):
diff --git a/js/jscode.py b/js/jscode.py
--- a/js/jscode.py
+++ b/js/jscode.py
@@ -161,23 +161,24 @@
def to_function_opcodes(self):
self.unlabel()
- #self.unpop_or_undefined()
- self.emit('LOAD_UNDEFINED')
+ #self.unpop()
+ #self.unpop#_or_undefined()
+ #self.emit('LOAD_UNDEFINED')
return self.opcodes
def to_eval_opcodes(self):
self.unlabel()
- self.unpop_or_undefined()
+ #self.unpop#_or_undefined()
return self.opcodes
def to_global_opcodes(self):
self.unlabel()
- self.unpop_or_undefined()
+ #self.unpop#_or_undefined()
return self.opcodes
def to_executable_opcodes(self):
self.unlabel()
- self.unpop()
+ #self.unpop#_or_undefined()
return self.opcodes
def remove_labels(self):
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -298,7 +298,7 @@
desc = proto_desc
W_BasicObject.define_own_property(self, '__proto__', desc)
- def __repr__(self):
+ def __str__(self):
return "%s: %s" % (object.__repr__(self), self.klass())
@@ -1109,7 +1109,7 @@
W_Primitive.__init__(self)
self._boolval_ = bool(boolval)
- def __repr__(self):
+ def __str__(self):
return 'W_Bool(%s)' % (str(self._boolval_), )
def ToObject(self):
@@ -1140,8 +1140,8 @@
other_string = other.to_string()
return self.to_string() == other_string
- def __repr__(self):
- return 'W_String(%s)' % (repr(self._strval_),)
+ def __str__(self):
+ return 'W_String("%s")' % (repr(self._strval_),)
def ToObject(self):
return W_StringObject(self)
@@ -1206,7 +1206,7 @@
W_Number.__init__(self)
self._intval_ = intmask(intval)
- def __repr__(self):
+ def __str__(self):
return 'W_IntNumber(%s)' % (self._intval_,)
def ToInteger(self):
@@ -1234,7 +1234,7 @@
W_Number.__init__(self)
self._floatval_ = float(floatval)
- def __repr__(self):
+ def __str__(self):
return 'W_FloatNumber(%s)' % (self._floatval_,)
def to_string(self):
@@ -1302,6 +1302,9 @@
def empty(self):
return len(self.elements_w) == 0
+ def to_string(self):
+ return '<Iterator>'
+
def _w(value):
if isinstance(value, W_Root):
return value
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -66,8 +66,8 @@
def eval(self, ctx):
ctx.stack_append(self.w_intvalue)
- #def __repr__(self):
- #return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.ToInteger(),)
+ def __str__(self):
+ return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.ToInteger(),)
class LOAD_BOOLCONSTANT(Opcode):
def __init__(self, value):
@@ -76,6 +76,11 @@
def eval(self, ctx):
ctx.stack_append(newbool(self.boolval))
+ def __str__(self):
+ if self.boolval:
+ return 'LOAD_BOOLCONSTANT true'
+ return 'LOAD_BOOLCONSTANT false'
+
class LOAD_FLOATCONSTANT(Opcode):
def __init__(self, value):
self.w_floatvalue = W_FloatNumber(float(value))
@@ -83,8 +88,8 @@
def eval(self, ctx):
ctx.stack_append(self.w_floatvalue)
- #def __repr__(self):
- #return 'LOAD_FLOATCONSTANT %s' % (self.w_floatvalue.ToNumber(),)
+ def __str__(self):
+ return 'LOAD_FLOATCONSTANT %s' % (self.w_floatvalue.ToNumber(),)
class LOAD_STRINGCONSTANT(Opcode):
_immutable_fields_ = ['w_stringvalue']
@@ -94,8 +99,8 @@
def eval(self, ctx):
ctx.stack_append(self.w_stringvalue)
- #def __repr__(self):
- #return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.to_string(),)
+ def __str__(self):
+ return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.to_string())
class LOAD_UNDEFINED(Opcode):
def eval(self, ctx):
@@ -119,6 +124,9 @@
value = ref.get_value()
ctx.stack_append(value)
+ def __str__(self):
+ return 'LOAD_VARIABLE "%s"' %(self.identifier)
+
class LOAD_THIS(Opcode):
# 11.1.1
def eval(self, ctx):
@@ -243,6 +251,9 @@
var_type = var.type()
ctx.stack_append(W_String(var_type))
+ def __str__(self):
+ return 'TYPEOF_VARIABLE %s' % (self.name)
+
class ADD(BaseBinaryOperation):
def operation(self, ctx, left, right):
return plus(ctx, left, right)
@@ -390,12 +401,17 @@
ref = ctx.get_ref(self.identifier)
ref.put_value(value)
+ def __str__(self):
+ return 'STORE "%s"' %(self.identifier)
+
class LABEL(Opcode):
_stack_change = 0
def __init__(self, num):
self.num = num
+ def __str__(self):
+ return 'LABEL %d' %( self.num)
#def __repr__(self):
#return 'LABEL %d' % (self.num,)
@@ -419,6 +435,9 @@
def do_jump(self, ctx, pos):
return self.where
+ def __str__(self):
+ return 'JUMP %d' % (self.where)
+
class BaseIfJump(BaseJump):
def eval(self, ctx):
value = ctx.stack_pop()
@@ -435,6 +454,9 @@
return pos + 1
return self.where
+ def __str__(self):
+ return 'JUMP_IF_FALSE %d' % (self.where)
+
class JUMP_IF_FALSE_NOPOP(BaseIfNopopJump):
def do_jump(self, ctx, pos):
if self.decision:
@@ -442,12 +464,18 @@
return pos + 1
return self.where
+ def __str__(self):
+ return 'JUMP_IF_FALSE_NOPOP %d' % (self.where)
+
class JUMP_IF_TRUE(BaseIfJump):
def do_jump(self, ctx, pos):
if self.decision:
return self.where
return pos + 1
+ def __str__(self):
+ return 'JUMP_IF_TRUE %d' % (self.where)
+
class JUMP_IF_TRUE_NOPOP(BaseIfNopopJump):
def do_jump(self, ctx, pos):
if self.decision:
@@ -455,6 +483,9 @@
ctx.stack_pop()
return pos + 1
+ def __str__(self):
+ return 'JUMP_IF_TRUE_NOPOP %d' % (self.where)
+
class DECLARE_FUNCTION(Opcode):
_stack_change = 0
def __init__(self, funcobj):
@@ -576,17 +607,10 @@
b = self.tryexec.run(ctx)
except JsException, e:
if self.catchexec is not None:
- old_env = ctx.lexical_environment()
-
- 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)
+ from js.execution_context import CatchExecutionContext
+ b = e.msg()
+ catch_ctx = CatchExecutionContext(self.catchexec, self.catchparam, b, ctx)
+ c = self.catchexec.run(catch_ctx)
else:
c = b
@@ -659,6 +683,9 @@
return self.where
return pos + 1
+ def __str__(self):
+ return 'JUMP_IF_ITERATOR_EMPTY %d' %(self.where)
+
class NEXT_ITERATOR(Opcode):
_stack_change = 0
def __init__(self, name):
@@ -676,14 +703,13 @@
# ---------------- with support ---------------------
class WITH(Opcode):
- def __init__(self, expr, body):
- self.expr = expr
+ def __init__(self, body):
self.body = body
def eval(self, ctx):
from execution_context import WithExecutionContext
# 12.10
- expr = self.expr.run(ctx)
+ expr = ctx.stack_pop()
expr_obj = expr.ToObject()
with_ctx = WithExecutionContext(self.body, expr_obj, ctx)
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -59,7 +59,6 @@
def emit(self, bytecode):
self.expr.emit(bytecode)
- bytecode.emit('POP')
class Expression(Statement):
pass
@@ -121,17 +120,19 @@
OPERANDS = {
- '+=' : 'ADD',
- '-=' : 'SUB',
- '*=' : 'MUL',
- '/=' : 'DIV',
- '++' : 'INCR',
- '--' : 'DECR',
- '%=' : 'MOD',
- '&=' : 'BITAND',
- '|=' : 'BITOR',
- '^=' : 'BITXOR',
- '>>=' : 'RSH'
+ '+=' : 'ADD',
+ '-=' : 'SUB',
+ '*=' : 'MUL',
+ '/=' : 'DIV',
+ '++' : 'INCR',
+ '--' : 'DECR',
+ '%=' : 'MOD',
+ '&=' : 'BITAND',
+ '|=' : 'BITOR',
+ '^=' : 'BITXOR',
+ '>>=' : 'RSH',
+ '<<=' : 'LSH',
+ '>>>=' : 'URSH'
}
OPERATIONS = unrolling_iterable(OPERANDS.items())
@@ -227,7 +228,12 @@
self.nodes = nodes
def emit(self, bytecode):
- for node in self.nodes:
+ if len(self.nodes) > 1:
+ for node in self.nodes[:-1]:
+ node.emit(bytecode)
+ bytecode.emit('POP')
+ if len(self.nodes) > 0:
+ node = self.nodes[-1]
node.emit(bytecode)
BitwiseAnd = create_binary_op('BITAND')
@@ -244,11 +250,13 @@
class Break(Unconditional):
def emit(self, bytecode):
assert self.target is None
+ bytecode.emit('LOAD_UNDEFINED')
bytecode.emit_break()
class Continue(Unconditional):
def emit(self, bytecode):
assert self.target is None
+ bytecode.emit('LOAD_UNDEFINED')
bytecode.emit_continue()
class Call(Expression):
@@ -322,6 +330,7 @@
def emit(self, bytecode):
from jscode import ast_to_bytecode
body_code = ast_to_bytecode(self.body_ast, self.symbol_map)
+ body_code.emit('LOAD_UNDEFINED')
from js.functions import JsFunction
name = self.name
@@ -333,7 +342,6 @@
bytecode.emit('LOAD_FUNCTION', jsfunc)
if index is not None:
bytecode.emit('STORE', index, name)
- bytecode.emit('POP')
class Identifier(Expression):
def __init__(self, pos, name, index):
@@ -364,17 +372,19 @@
def emit(self, bytecode):
self.condition.emit(bytecode)
- one = bytecode.prealocate_label()
- bytecode.emit('JUMP_IF_FALSE', one)
+ endif = bytecode.prealocate_label()
+ endthen = bytecode.prealocate_label()
+ bytecode.emit('JUMP_IF_FALSE', endthen)
self.thenPart.emit(bytecode)
+ bytecode.emit('JUMP', endif)
+ bytecode.emit('LABEL', endthen)
+
if self.elsePart is not None:
- two = bytecode.prealocate_label()
- bytecode.emit('JUMP', two)
- bytecode.emit('LABEL', one)
self.elsePart.emit(bytecode)
- bytecode.emit('LABEL', two)
else:
- bytecode.emit('LABEL', one)
+ bytecode.emit('LOAD_UNDEFINED')
+
+ bytecode.emit('LABEL', endif)
class Switch(Statement):
def __init__(self, pos, expression, clauses, default_clause):
@@ -390,7 +400,6 @@
clause_code = bytecode.prealocate_label()
next_clause = bytecode.prealocate_label()
for expression in clause.expressions:
-
expression.emit(bytecode)
self.expression.emit(bytecode)
bytecode.emit('EQ')
@@ -403,7 +412,6 @@
bytecode.emit('LABEL', next_clause)
self.default_clause.emit(bytecode)
bytecode.emit('LABEL', end_of_switch)
- bytecode.emit('POP')
class CaseBlock(Statement):
def __init__(self, pos, clauses, default_clause):
@@ -429,7 +437,6 @@
def emit(self, bytecode):
self.block.emit(bytecode)
- bytecode.unpop_or_undefined()
class DefaultClause(Statement):
def __init__(self, pos, block):
@@ -664,13 +671,23 @@
self.sourcename = sourcename
def emit(self, bytecode):
- #for varname in self.var_decl:
- #bytecode.emit('DECLARE_VAR', varname)
- for funcname, funccode in self.func_decl.items():
+ functions = self.func_decl.values()
+ nodes = self.nodes
+
+ for funccode in functions:
funccode.emit(bytecode)
+ bytecode.emit('POP')
- for node in self.nodes:
+ if len(nodes) > 1:
+ for node in nodes[:-1]:
+ node.emit(bytecode)
+ bytecode.emit('POP')
+
+ if len(nodes) > 0:
+ node = nodes[-1]
node.emit(bytecode)
+ else:
+ bytecode.emit('LOAD_UNDEFINED')
class Program(Statement):
def __init__(self, pos, body, symbol_map):
@@ -747,6 +764,9 @@
if self.expr is not None:
self.expr.emit(bytecode)
bytecode.emit('STORE', self.index, self.identifier)
+ else:
+ # variable declaration actualy does nothing
+ bytecode.emit('LOAD_UNDEFINED')
def __str__(self):
return "VariableDeclaration %s:%s" % (self.identifier, self.expr)
@@ -803,10 +823,17 @@
self.nodes = nodes
def emit(self, bytecode):
- for node in self.nodes:
+ nodes = self.nodes
+ if len(nodes) > 1:
+ for node in nodes[:-1]:
+ node.emit(bytecode)
+ bytecode.emit('POP')
+
+ if len(nodes) > 0:
+ node = nodes[-1]
node.emit(bytecode)
- if (isinstance(node, VariableDeclaration) or isinstance(node, LocalVariableDeclaration)) and node.expr is not None:
- bytecode.emit('POP')
+ else:
+ bytecode.emit('LOAD_UNDEFINED')
class Variable(Statement):
def __init__(self, pos, body):
@@ -835,7 +862,8 @@
class EmptyExpression(Expression):
def emit(self, bytecode):
- bytecode.unpop_or_undefined()
+ #bytecode.unpop_or_undefined()
+ bytecode.emit('LOAD_UNDEFINED')
class With(Statement):
def __init__(self, pos, expr, body):
@@ -847,15 +875,13 @@
from js.jscode import JsCode
from js.functions import JsExecutableCode
- expr_code = JsCode()
- self.expr.emit(expr_code)
- expr_exec = JsExecutableCode(expr_code)
+ self.expr.emit(bytecode)
body_code = JsCode()
self.body.emit(body_code)
body_exec = JsExecutableCode(body_code)
- bytecode.emit('WITH', expr_exec, body_exec)
+ bytecode.emit('WITH', body_exec)
class WhileBase(Statement):
def __init__(self, pos, condition, body):
@@ -864,69 +890,52 @@
self.body = body
class Do(WhileBase):
- opcode = 'DO'
-
def emit(self, bytecode):
startlabel = bytecode.emit_startloop_label()
end = bytecode.prealocate_endloop_label()
self.body.emit(bytecode)
self.condition.emit(bytecode)
- bytecode.emit('JUMP_IF_TRUE', startlabel)
+ bytecode.emit('JUMP_IF_FALSE', end)
+ bytecode.emit('POP')
+ bytecode.emit('JUMP', startlabel)
bytecode.emit_endloop_label(end)
class While(WhileBase):
def emit(self, bytecode):
+ bytecode.emit('LOAD_UNDEFINED')
startlabel = bytecode.emit_startloop_label()
bytecode.continue_at_label(startlabel)
self.condition.emit(bytecode)
endlabel = bytecode.prealocate_endloop_label()
bytecode.emit('JUMP_IF_FALSE', endlabel)
+ bytecode.emit('POP')
self.body.emit(bytecode)
bytecode.emit('JUMP', startlabel)
bytecode.emit_endloop_label(endlabel)
bytecode.done_continue()
-class ForVarIn(Statement):
- def __init__(self, pos, vardecl, lobject, body):
+class ForIn(Statement):
+ def __init__(self, pos, name, lobject, body):
self.pos = pos
- assert isinstance(vardecl, VariableDeclaration) or isinstance(vardecl, LocalVariableDeclaration)
- self.iteratorname = vardecl.identifier
- self.object = lobject
+ self.iteratorname = name
+ self.w_object = lobject
self.body = body
-
def emit(self, bytecode):
- #bytecode.emit('DECLARE_VAR', self.iteratorname)
- self.object.emit(bytecode)
+ self.w_object.emit(bytecode)
bytecode.emit('LOAD_ITERATOR')
precond = bytecode.emit_startloop_label()
finish = bytecode.prealocate_endloop_label()
bytecode.emit('JUMP_IF_ITERATOR_EMPTY', finish)
bytecode.emit('NEXT_ITERATOR', self.iteratorname)
self.body.emit(bytecode)
+ # remove last body statement from stack
+ bytecode.emit('POP')
bytecode.emit('JUMP', precond)
bytecode.emit_endloop_label(finish)
+ # remove the iterrator from stack
bytecode.emit('POP')
-
-class ForIn(Statement):
- def __init__(self, pos, name, lobject, body):
- self.pos = pos
- #assert isinstance(iterator, Node)
- self.iteratorname = name
- self.object = lobject
- self.body = body
-
- def emit(self, bytecode):
- self.object.emit(bytecode)
- bytecode.emit('LOAD_ITERATOR')
- precond = bytecode.emit_startloop_label()
- finish = bytecode.prealocate_endloop_label()
- bytecode.emit('JUMP_IF_ITERATOR_EMPTY', finish)
- bytecode.emit('NEXT_ITERATOR', self.iteratorname)
- self.body.emit(bytecode)
- bytecode.emit('JUMP', precond)
- bytecode.emit_endloop_label(finish)
- bytecode.emit('POP')
+ bytecode.emit('LOAD_UNDEFINED')
class For(Statement):
def __init__(self, pos, setup, condition, update, body):
@@ -940,11 +949,13 @@
self.setup.emit(bytecode)
if isinstance(self.setup, Expression):
bytecode.emit('POP')
+ bytecode.emit('LOAD_UNDEFINED')
precond = bytecode.emit_startloop_label()
finish = bytecode.prealocate_endloop_label()
update = bytecode.prealocate_updateloop_label()
self.condition.emit(bytecode)
bytecode.emit('JUMP_IF_FALSE', finish)
+ bytecode.emit('POP')
self.body.emit(bytecode)
bytecode.emit_updateloop_label(update)
self.update.emit(bytecode)
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
@@ -14,7 +14,6 @@
bytecode.emit('LOAD_FLOATCONSTANT', 2)
bytecode.emit('LOAD_FLOATCONSTANT', 4)
bytecode.emit('ADD')
- bytecode.emit('POP')
from js.execution_context import ExecutionContext
@@ -197,6 +196,7 @@
x[1];
""", 'test')
+ at xfail
def test_print_object(capsys):
assertp("""
x = {1:"test"};
@@ -534,7 +534,7 @@
for(y in x){
print(y);
}
- """, '5', capsys)
+ """, 'a', capsys)
def test_forinvar(capsys):
assertp("""
@@ -542,7 +542,7 @@
for(var y in x){
print(y);
}
- """, '5', capsys)
+ """, 'a', capsys)
def test_stricteq():
assertv("2 === 2;", True)
More information about the pypy-commit
mailing list