[pypy-commit] lang-js default: implemented switch statement
stepahn
noreply at buildbot.pypy.org
Wed May 18 11:14:52 CEST 2011
Author: Stephan <stephan at stzal.com>
Branch:
Changeset: r61:90412ea44556
Date: 2011-05-17 18:04 +0200
http://bitbucket.org/pypy/lang-js/changeset/90412ea44556/
Log: implemented switch statement
diff --git a/js/astbuilder.py b/js/astbuilder.py
--- a/js/astbuilder.py
+++ b/js/astbuilder.py
@@ -382,6 +382,41 @@
def visit_iterationstatement(self, node):
return self.dispatch(node.children[0])
+ def visit_switchstatement(self, node):
+ pos = self.get_pos(node)
+ expression = self.dispatch(node.children[0])
+ caseblock = self.dispatch(node.children[1])
+ return operations.Switch(pos, expression, caseblock.clauses, caseblock.default_clause)
+
+ def visit_caseblock(self, node):
+ pos = self.get_pos(node)
+ caseclauses = self.dispatch(node.children[0])
+ defaultblock = self.dispatch(node.children[1])
+ return operations.Cases(pos, caseclauses, defaultblock)
+
+ def visit_caseclauses(self, node):
+ pos = self.get_pos(node)
+ expressions = []
+ clauses = []
+ for c in node.children:
+ if c.symbol == 'statementlist':
+ block = self.dispatch(c)
+ clauses.append(operations.CaseClause(pos, expressions, block))
+ expressions = []
+ else:
+ expressions.append(self.dispatch(c))
+ return clauses
+
+ def visit_defaultclause(self, node):
+ pos = self.get_pos(node)
+ block = self.dispatch(node.children[0])
+ return operations.DefaultClause(pos, block)
+
+ def visit_statementlist(self, node):
+ pos = self.get_pos(node)
+ block = self.dispatch(node.children[0])
+ return operations.StatementList(pos, block)
+
def visit_whiles(self, node):
pos = self.get_pos(node)
itertype = node.children[0].additional_info
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -359,6 +359,64 @@
else:
bytecode.emit('LABEL', one)
+class Switch(Statement):
+ def __init__(self, pos, expression, clauses, default_clause = None):
+ super(Switch, self).__init__(pos)
+ self.expression = expression
+ self.clauses = clauses
+ self.default_clause = default_clause
+
+ def emit(self, bytecode):
+ end_of_switch = bytecode.prealocate_label()
+
+ for clause in self.clauses:
+ 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')
+ bytecode.emit('JUMP_IF_TRUE', clause_code)
+
+ bytecode.emit('JUMP', next_clause)
+ bytecode.emit('LABEL', clause_code)
+ clause.block.emit(bytecode)
+ bytecode.emit('JUMP', end_of_switch)
+ bytecode.emit('LABEL', next_clause)
+ self.default_clause.emit(bytecode)
+ bytecode.emit('LABEL', end_of_switch)
+ bytecode.emit('POP')
+
+class Cases(Statement):
+ def __init__(self, pos, clauses, default_clause):
+ super(Cases, self).__init__(pos)
+ self.clauses = clauses
+ self.default_clause = default_clause
+
+class CaseClause(Statement):
+ def __init__(self, pos, expressions, block):
+ super(CaseClause, self).__init__(pos)
+ self.expressions = expressions
+ self.block = block
+
+class StatementList(Statement):
+ def __init__(self, pos, block):
+ super(StatementList, self).__init__(pos)
+ self.block = block
+
+ def emit(self, bytecode):
+ self.block.emit(bytecode)
+ bytecode.unpop_or_undefined()
+
+class DefaultClause(Statement):
+ def __init__(self, pos, block):
+ super(DefaultClause, self).__init__(pos)
+ self.block = block
+
+ def emit(self, bytecode):
+ self.block.emit(bytecode)
+
#class Group(UnaryOp):
# def eval(self, ctx):
# return self.expr.eval(ctx)
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
@@ -599,7 +599,6 @@
yield assertv, "0xF", 15
def test_switch():
- py.test.skip("not ready yet")
yield assertv, """
x = 1;
switch(x){
@@ -607,11 +606,11 @@
default: 30;
};""", 15
yield assertv, """
- x = 1;
+ x = 0;
switch(x){
case 1: 15; break;
default: 30;
- };""", 15
+ };""", 30
def test_autoboxing():
yield assertv, "'abc'.charAt(0)", 'a'
@@ -669,3 +668,30 @@
yield assertv, "var x = {y:1}; ++x.y; x.y;", 2
yield assertv, "var x = {y:1}; ++x.y;", 2
+def switch_test_code(x):
+ return """
+ function f(x) {
+ var y;
+ switch(x) {
+ case 1:
+ y = 1;
+ break;
+ case 2:
+ y = 2;
+ break;
+ case 3:
+ default:
+ return 42;
+ }
+ return y;
+ };
+
+ f(%(x)s);
+ """ % {'x': x}
+
+
+def test_more_switch():
+ yield assertv, switch_test_code(0), 42
+ yield assertv, switch_test_code(1), 1
+ yield assertv, switch_test_code(2), 2
+ yield assertv, switch_test_code(3), 42
More information about the pypy-commit
mailing list