Author: Stephan <step...@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 _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit