[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