def test_parse_arithmetic(): result = parser.parse('x * (y + z);') assert result == Block([Stmt(BinOp('*', Variable('x'), BinOp('+', Variable('y'), Variable('z'))))]) result = parser.parse('z + x * y;') assert result == Block([Stmt(BinOp('+', Variable('z'), BinOp('*', Variable('x'), Variable('y'))))]) result = parser.parse('z * x + y;') assert result == Block([Stmt(BinOp('+', BinOp('*', Variable('z'), Variable('x')), Variable('y')))]) result = parser.parse('x > z + x * y;') assert result == Block([Stmt(BinOp('>', Variable('x'), BinOp('+', Variable('z'), BinOp('*', Variable('x'), Variable('y')))))]) result = parser.parse('(x + y) / x + 3;') assert result == Block([Stmt(BinOp('+', BinOp( '/', BinOp( '+', Variable('x'), Variable('y')), Variable('x')), ConstantNum(3.0)))])
def test_parse_return(): result = parser.parse('function foo(x, y, z) { return; };') assert result == Block([Stmt(FnDef('foo', ['x', 'y', 'z'], Block([Return()]), None, 0))]) result = parser.parse('function foo(x, y, z) { return x + y; };') assert result == Block([Stmt(FnDef('foo', ['x', 'y', 'z'], Block([Return(BinOp('+', Variable('x'), Variable('y')))]), None, 0))])
def test_parse_if(): result = parser.parse('if (y) { x = 10; }') assert result == Block([If(Variable('y'), Block([Assignment('x', ConstantNum(10.0))]))]) result = parser.parse('if (y) { x = 10; } else { x = 12; }') assert result == Block([If(Variable('y'), Block([Assignment('x', ConstantNum(10.0))]), Block([Assignment('x', ConstantNum(12.0))]))])
def test_paser_assignment(): result = parser.parse('x_y = x;') assert result == \ Block([Assignment('x_y', Variable('x'))]) result = parser.parse('PI = 3.14;') assert result == \ Block([Assignment('PI', ConstantNum(3.14))]) with pytest.raises(parser.ParseError): parser.parse('1.0 = x;')
def test_parse_variable(): for var_name in ('x', 'X', '_', 'foo', 'Fo', '_123'): result = parser.parse('%s;' % var_name) assert result == Block([Stmt(Variable(var_name))]) for invalid_var_name in ('0x', '123ss'): with pytest.raises(parser.ParseError): parser.parse('%s;' % invalid_var_name) for invalid_var_name in ('%',): with pytest.raises(parser.ParseError): parser.parse('%s;' % invalid_var_name) for not_var_name in ('123',): assert result != Block([Stmt(Variable(not_var_name))])
def test_parse_fn_def(): result = parser.parse('function foo() { };') assert result == Block([Stmt(FnDef('foo', [], Block([]), None, 0))]) result = parser.parse(''' function foo(x) { x + y; }; ''', filename='foo.js') assert result == Block([Stmt(FnDef('foo', ['x'], Block( [Stmt(BinOp('+', Variable('x'), Variable('y')))]), 'foo.js', 2))]) result = parser.parse('function foo(x){};') assert result == Block([Stmt(FnDef('foo', ['x'], Block([]), None, 0))]) result = parser.parse('function foo(){x;};') assert result == Block([Stmt(FnDef('foo', [], Block([ Stmt(Variable('x'))]), None, 0))]) result = parser.parse('function foo(x, y, z) { x + y; };') assert result == Block([Stmt(FnDef('foo', ['x', 'y', 'z'], Block([Stmt(BinOp('+', Variable('x'), Variable('y')))]), None, 0))])
def test_parse_fn_call(): result = parser.parse('foo();') assert result == Block([Stmt(Call(Variable('foo'), []))]) result = parser.parse('print(x);') assert result == Block([Stmt(Call(Variable('print'), [Variable('x')]))]) result = parser.parse('foo(1);') assert result == Block([Stmt(Call(Variable('foo'), [ConstantNum(1.0)]))]) result = parser.parse('foo(1 + 2);') assert result == Block([Stmt(Call(Variable('foo'), [BinOp('+', ConstantNum(1.0), ConstantNum(2.0))]))]) result = parser.parse('foo(x + y);') assert result == Block([Stmt(Call(Variable('foo'), [BinOp('+', Variable('x'), Variable('y'))]))]) result = parser.parse('foo(f(x) + y);') assert result == Block([Stmt(Call(Variable('foo'), [BinOp('+', Call(Variable('f'), [Variable('x')]), Variable('y'))]))]) result = parser.parse('foo(f(x), y);') assert result == Block([Stmt(Call(Variable('foo'), [Call(Variable('f'), [Variable('x')]), Variable('y')]))]) result = parser.parse('foo(1, f(x), y);') assert result == Block([Stmt(Call(Variable('foo'), [ ConstantNum(1.0), Call(Variable('f'), [Variable('x')]), Variable('y')]))]) result = parser.parse('foo(1, f(x), y, z, y);') assert result == Block([Stmt(Call(Variable('foo'), [ ConstantNum(1.0), Call(Variable('f'), [Variable('x')]), Variable('y'), Variable('z'), Variable('y'), ]))])
def test_get_location(): filename = '_for_test_jit.js' source = ''' function foo(x, y) { return x + y; }; x = 3; foo(1, x); ''' ast = parser.parse(source, filename=filename) bc = CompilerContext.compile_ast(ast, co_filename=filename) assert bc.code == to_code([ LOAD_CONSTANT_FN, 0, ASSIGN, 0, LOAD_CONSTANT_FN, 0, DISCARD_TOP, 0, LOAD_CONSTANT_FLOAT, 0, ASSIGN, 1, LOAD_VAR, 0, LOAD_CONSTANT_FLOAT, 1, LOAD_VAR, 1, CALL, 2, DISCARD_TOP, 0, RETURN, 0]) assert bc.co_name == '__main__' assert bc.co_filename == '_for_test_jit.js' assert bc.co_firstlineno == 0 inner_bc = bc.constants_fn[0] assert inner_bc.code == to_code([ LOAD_VAR, 0, LOAD_VAR, 1, BINARY_ADD, 0, RETURN, 1]) assert inner_bc.co_name == 'foo' assert inner_bc.co_filename == '_for_test_jit.js' assert inner_bc.co_firstlineno == 1 assert get_printable_location(0, bc.code, bc) == \ "<code object __main__, file '_for_test_jit.js', line 1> #0 LOAD_CONSTANT_FN" assert get_printable_location(2, bc.code, bc) == \ "<code object __main__, file '_for_test_jit.js', line 1> #2 ASSIGN" assert get_printable_location(0, inner_bc.code, inner_bc) == \ "<code object foo, file '_for_test_jit.js', line 2> #0 LOAD_VAR" assert get_printable_location(4, inner_bc.code, inner_bc) == \ "<code object foo, file '_for_test_jit.js', line 2> #4 BINARY_ADD"
def test_parse_binop(): result = parser.parse('x = 1 + 2;') assert result == Block([Assignment('x', BinOp('+', ConstantNum(1.0), ConstantNum(2.0)))]) result = parser.parse('x = x - 2;') assert result == Block([Assignment('x', BinOp('-', Variable('x'), ConstantNum(2.0)))]) result = parser.parse('x = 1+2;') assert result == Block([Assignment('x', BinOp('+', ConstantNum(1.0), ConstantNum(2.0)))]) result = parser.parse('x = x-2;') assert result == Block([Assignment('x', BinOp('-', Variable('x'), ConstantNum(2.0)))]) result = parser.parse('x = y % 2;') assert result == Block([Assignment('x', BinOp('%', Variable('y'), ConstantNum(2.0)))]) result = parser.parse('while (x == y) { }') assert result == Block([While( BinOp('==', Variable('x'), Variable('y')), Block([]))])
def interpret_source(source, filename=None): ast = parser.parse(source, filename=filename) bc = bytecode.CompilerContext.compile_ast(ast) return interpret(bc)
def test_parse_while(): result = parser.parse('while (1) { a = 3; }') assert result == Block([While(ConstantNum(1.0), Block([Assignment('a', ConstantNum(3))]))]) result = parser.parse('while (1) { }') assert result == Block([While(ConstantNum(1.0), Block([]))])
def test_parse_number(): for num, value in [ ('0', 0.0), ('1', 1.0), ('.123', .123), ('123.123', 123.123), ('+12', 12.0), ('-.12', -0.12)]: result = parser.parse('%s;' % num) assert result == Block([Stmt(ConstantNum(value))])