def eval(self, context): if self.expression is None: return js.Completion(js.RETURN, js.UNDEFINED, js.EMPTY) else: return js.Completion(js.RETURN, js.get_value(self.expression.eval(context)), js.EMPTY)
def eval(self, context): if self.expression is None: return js.Completion(js.RETURN, js.UNDEFINED, js.EMPTY) else: item = self.expression.eval(context) if type(item) is js.Completion: item = item.value return js.Completion(js.RETURN, item, js.EMPTY)
def eval(self, context): result_value = js.EMPTY while True: condition_value = js.get_value(self.condition.eval(context)) if not condition_value: return js.Completion(js.NORMAL, result_value, js.EMPTY) stmt = self.statement.eval(context) if stmt.value is not js.EMPTY: result_value = stmt.value if stmt.type is js.BREAK: return js.Completion(js.NORMAL, result_value, js.EMPTY) elif js.is_abrupt(stmt) and stmt.type is not js.CONTINUE: return stmt
def test_closure(self): program = """var fibgen = function () { var a = 0, b = 1; return function () { var old = a; a = b; b = b + old; return old; }; }; var fib = fibgen(); var f1 = fib(); var f2 = fib(); fib(); fib(); fib(); fib(); var f7 = fib(); fib(); fib(); fib(); fib(); var fib2 = fibgen(); fib2(); fib2(); fib2(); fib2(); var f5 = fib2(); fib(); // f12 """ context = js.ExecutionContext({}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 89, js.EMPTY)) self.assertEqual(context['f1'], 0) self.assertEqual(context['f2'], 1) self.assertEqual(context['f5'], 3) self.assertEqual(context['f7'], 8)
def test_modify_global_variable(self): program = """var x = 1, incrementX = function () { x += 1; }; incrementX(); incrementX(); x;""" self.assertEqual(self.eval(program), js.Completion(js.NORMAL, 3, js.EMPTY))
def eval(self, context): cntx = js.ExecutionContext(dict(), parent=context) result_value = js.EMPTY firstst = self.first.eval(cntx) while True: condition_value = js.get_value(self.condition.eval(cntx)) #print("COND",condition_value) if not condition_value: return js.Completion(js.NORMAL, result_value, js.EMPTY) stmt = self.statement.eval(cntx) if stmt.value is not js.EMPTY: result_value = stmt.value if stmt.type is js.BREAK: return js.Completion(js.NORMAL, result_value, js.EMPTY) elif js.is_abrupt(stmt) and stmt.type is not js.CONTINUE: return stmt nextst = self.then.eval(cntx)
def test_shadowing(self): program = """var x = 1; var shadow = function () { var x = 3; x += 1; return x; }; shadow();""" context = js.ExecutionContext({}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 4, js.EMPTY)) self.assertEqual(context['x'], 1)
def test_dangling_else(self): stmt = """if (false) if (true) 3; else 5;""" self.assertEqual(self.eval(stmt), js.EMPTY_COMPLETION) stmt = """if (true) if (true) 3; else 5;""" self.assertEqual(self.eval(stmt), js.Completion(js.NORMAL, 3, js.EMPTY))
def test_continue_statement(self): stmt = """while (x < 10) { ++x; if (x % 2 == 0) continue; ++y; }""" context = js.ExecutionContext({'x': 0, 'y': 0}) self.assertEqual(self.eval(stmt, context), js.Completion(js.NORMAL, 5, js.EMPTY)) self.assertEqual(context['x'], 10) self.assertEqual(context['y'], 5)
def test_console_object(self): program = """var i = 0; while (i < 10) { console.log(i); i++; } """ out = StringIO() context = js.ExecutionContext({'console': js.Console(out=out)}) self.assertEqual(self.eval(program, context), js.Completion(js.NORMAL, 9, js.EMPTY)) self.assertEqual(out.getvalue(), "0.0\n1.0\n2.0\n3.0\n4.0\n5.0\n6.0\n7.0\n8.0\n9.0\n")
def test_break_statement(self): stmt = """while (x < 10) { ++x; if (x % 3 == 0) break; ++y; }""" context = js.ExecutionContext({'x': 0, 'y': 0}) self.assertEqual(self.eval(stmt, context), js.Completion(js.NORMAL, 2, js.EMPTY)) self.assertEqual(context['x'], 3) self.assertEqual(context['y'], 2)
def eval(self, context): return js.Completion(js.NORMAL, js.get_value(self.expression.eval(context)), js.EMPTY)
def eval(self, context): ref = self.identifier.eval(context) value = js.get_value(self.initialiser.eval(context)) js.put_value(ref, value) return js.Completion(js.NORMAL, ref.name, js.EMPTY)
def test_block(self): self.assertEqual(self.eval('{ 1; 3; }'), js.Completion(js.NORMAL, 3, js.EMPTY))
def test_expression_statement(self): self.assertEqual(self.eval('1 + 2 * 7;'), js.Completion(js.NORMAL, 15, js.EMPTY))
def test_if_statement(self): self.assertEqual(self.eval('if (2 + 2 == 4) 3;'), js.Completion(js.NORMAL, 3, js.EMPTY)) self.assertEqual(self.eval('if (false) 3;'), js.EMPTY_COMPLETION)
def eval(self, context): return js.Completion(js.BREAK, js.EMPTY, js.EMPTY)
def test_arguments(self): program = """var sqr = function (x) { return x * x; }; sqr(7);""" self.assertEqual(self.eval(program), js.Completion(js.NORMAL, 49, js.EMPTY))
def test_function_as_variable(self): program = """var f = function () { return 42; }; f();""" self.assertEqual(self.eval(program), js.Completion(js.NORMAL, 42, js.EMPTY))
def test_while_statement(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('while (x < 5) ++x;', context), js.Completion(js.NORMAL, 5, js.EMPTY)) self.assertEqual(context['x'], 5)
def test_do_while_statement(self): context = js.ExecutionContext({'x': 3}) self.assertEqual(self.eval('do ++x; while (x < 3);', context), js.Completion(js.NORMAL, 4, js.EMPTY)) self.assertEqual(context['x'], 4)
def test_if_else_statement(self): self.assertEqual(self.eval('if (false) 3; else 5;'), js.Completion(js.NORMAL, 5, js.EMPTY))
def test_function_as_argument(self): program = """var double = function (f, x) { return f(f(x)); }; double(function (x) { return x * x; }, 2);""" self.assertEqual(self.eval(program), js.Completion(js.NORMAL, 16, js.EMPTY))
def eval(self, context): return js.Completion(js.CONTINUE, js.EMPTY, js.EMPTY)
def test_nested_blocks(self): self.assertEqual(self.eval('{ 1; {3; 2;}}'), js.Completion(js.NORMAL, 2, js.EMPTY))
def test_return_statement(self): program = """function () { return 4; 7; } ();""" self.assertEqual(self.eval(program), js.Completion(js.NORMAL, 4, js.EMPTY))
def test_block_with_empty_statements(self): self.assertEqual(self.eval('{7;;}'), js.Completion(js.NORMAL, 7, js.EMPTY))