def func_super(self, type_, inst): self.visit( ast_call( ast.FunctionDef( '', ast.arguments( [ast_store('p'), ast_store('i')], None, None, []), [ ast.FunctionDef('tmp', ast.arguments( [], None, None, []), [ ast.Expr( ast_call(ast_load('this.__bind__'), ast_load('i'))), ], []), ast.Assign([ast_load('tmp.prototype')], ast_load('p')), ast.Return(ast_call( ast_load('new'), ast_load('tmp'), )) ], []), ast.Attribute( ast.Subscript( ast_load('self.__mro__'), ast.Index( ast.BinOp( ast_call( ast_load('self.__mro__.indexOf'), type_, ), ast.Sub(), ast.Num(1))), ast.Load()), 'prototype', ast.Load()), inst, ))
def visit_ImportFrom(self, node): if node.level: raise NotImplementedError('Relative imports are not supported') module_path = node.module.split('.') import_module = self.init_module(module_path) if len(node.names) > 1 or node.names[0].name == '*': self.visit(ast.Assign( [ast_store('$t1')], import_module )) import_from = ast_load('$t1') else: import_from = import_module if node.names[0].name == '*': name = node.names[0] if name.name == '*': if self.stack[-1].scope.prefix != ['__module__']: raise NotImplementedError('from x import * only implemented at module level') self.visit(ast.For( ast_store('$t2'), import_from, [ ast.Assign( [ ast.Subscript( ast_call(ast_load('JS'), ast.Str('__module__')), ast.Index(ast_load('$t2')), ast.Load() ) ], ast.Subscript( import_from, ast.Index(ast_load('$t2')), ast.Load(), ) ), ], [] )) else: for name in node.names: asname = name.asname if name.asname else name.name self.visit( ast.Assign( [ast_store(asname)], ast.Attribute( import_from, name.name, ast.Load() ) ) )
def test_starargs_context(self): assert self.run( [ ast.Assign( [ast_store('o')], ast.Dict( [ast.Str('a'), ], [ast.Num(6), ] ) ), ast.Assign( [ast_store('o.f')], ast.FunctionDef( '', ast.arguments( [ ast_store('a'), ], None, None, [] ), [ ast.Return( ast.BinOp( ast_load('this.a'), ast.Mult(), ast_load('a') ) ) ], [] ), ), ast.Assign( [ast_store('a')], ast.List( [ ast.Num(7), ], ast.Load() ) ), ast.Expr( ast.Call( ast_load('o.f'), [], {}, ast_load('a'), None ) ) ], None, int ) == 42
def func_super(self, type_, inst): self.visit( ast_call( ast.FunctionDef( '', ast.arguments([ast_store('p'), ast_store('i')], None, None, []), [ ast.FunctionDef( 'tmp', ast.arguments([], None, None, []), [ ast.Expr( ast_call( ast_load('this.__bind__'), ast_load('i') ) ), ], [] ), ast.Assign( [ast_load('tmp.prototype')], ast_load('p') ), ast.Return( ast_call( ast_load('new'), ast_load('tmp'), ) ) ], [] ), ast.Attribute( ast.Subscript( ast_load('self.__mro__'), ast.Index( ast.BinOp( ast_call( ast_load('self.__mro__.indexOf'), type_, ), ast.Sub(), ast.Num(1) ) ), ast.Load() ), 'prototype', ast.Load() ), inst, ) )
def test_multi_assign(self): assert self.run( [ ast.Assign( [ ast_store('test1'), ast_store('test2') ], ast.Str('test') ) ], 'test1 + "+" + test2' ) == 'test+test'
def visit_Import(self, node): for name in node.names: module_path = name.name.split('.') import_module = self.init_module(module_path) if not name.asname: self.visit(ast.Expr(import_module)) self.visit( ast.Assign([ast_store(module_path[0])], self.init_module(module_path[:1]))) else: self.visit(ast.Assign([ast_store(name.asname)], import_module))
def test_args_starargs(self): assert self.run( [ ast.FunctionDef( 'test', ast.arguments( [ ast_store('a'), ast_store('b'), ], None, None, [] ), [ ast.Return( ast.BinOp( ast_load('a'), ast.Mult(), ast_load('b') ) ) ], [] ), ast.Assign( [ast_store('a')], ast.List( [ ast.Num(7), ], ast.Load() ) ), ast.Expr( ast.Call( ast_load('test'), [ ast.Num(6), ], {}, ast_load('a'), None ) ) ], None, int ) == 42
def _bool_op(self, v_type, op, v, r): assert self.run([ ast.Assign( [ast_store('test')], ast.BoolOp(op(), [v_type(i) for i in v]), ), ], 'test', type(r)) == r
def test_kwargs(self): assert self.run( [ ast.Assign( [ast_store('a')], ast.Dict( [ ast.Str('a'), ], [ ast.Num(0), ] ) ), ast.Expr( ast.Call( ast_load('alert'), [], {}, None, ast_load('a') ) ) ], None, int ) == 0
def test_starargs_no_context(self): assert self.run([ ast.FunctionDef('test', ast.arguments([ ast_store('a'), ], None, None, []), [ ast.Return( ast.BinOp(ast_load('this.o'), ast.Mult(), ast_load('a'))) ], []), ast.Assign([ast_store('o')], ast.Num(6)), ast.Assign([ast_store('a')], ast.List([ ast.Num(7), ], ast.Load())), ast.Expr(ast.Call(ast_load('test'), [], {}, ast_load('a'), None)) ], None, int) == 42
def _aug_assign(self, v_type, v1, op, v2, r): assert self.run( [ ast.Assign( [ast_store('test')], v_type(v1), ), ast.AugAssign( ast_store('test'), op(), v_type(v2), ) ], 'test', type(r) ) == r
def _bin_op(self, v_type, v1, op, v2, r): assert self.run([ ast.Assign( [ast_store('test')], ast.BinOp(v_type(v1), op(), v_type(v2)), ), ], 'test', type(r)) == r
def build_Assign_Destructuring(self, targets, value): scope = self.stack[-1].scope global_scope = scope.get_global_scope() assignments = [] for target, i in zip(targets.elts, range(len(targets.elts))): if isinstance(target, _ast.Name): if scope.is_global(target.id): global_scope.declare(target.id) else: scope.declare(target.id) target = ast.Name(target.id, ast.Load()) assignments.append( ast.Assign( [target], ast.Subscript( ast_load('v'), ast.Index(ast.Num(i)), ast.Load() ) ) ) return ast_call( ast.FunctionDef( '', ast.arguments([ast_store('v')], None, None, []), assignments + [ ast.Return(ast_load('v')) ], [] ), value )
def test_assign_expr_slice(self): assert self.run( [ ast.Assign( [ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load()) ), ast.FunctionDef( 'f_test', ast.arguments([], None, None, []), [ ast.Return(ast_load('test')), ], [] ), ast.Assign( [ ast.Subscript( ast_call(ast_load('f_test')), ast.Slice(ast.Num(2), ast.Num(8), None), ast.Store() ), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load()) ), ], 'test', list ) == [0, 1, 42, 43, 8, 9]
def test_call(self): assert self.run([ ast.FunctionDef( 'test', ast.arguments([ ast_store('a'), ast_store('b'), ], None, None, []), [ ast.Return( ast.BinOp(ast_load('a'), ast.Mult(), ast_load('b'))) ], []), ast.Expr( ast.Call(ast_load('test'), [ ast.Num(6), ast.Num(7), ], {}, None, None)) ], None, int) == 42
def test_single_assign(self): assert self.run( [ ast.Assign( [ast_store('test')], ast.Str('test')) ], 'test' ) == 'test'
def test_kwargs(self): assert self.run([ ast.Assign([ast_store('a')], ast.Dict([ ast.Str('a'), ], [ ast.Num(0), ])), ast.Expr(ast.Call(ast_load('alert'), [], {}, None, ast_load('a'))) ], None, int) == 0
def test_break(self): assert self.run([ ast.Assign( [ast_store('i')], ast.Num(0), ), ast.While(ast.Compare(ast_load('i'), [ast.Lt()], [ast.Num(10)]), [ ast.Break(), ], []) ], 'i', int) == 0
def visit_ImportFrom(self, node): if node.level: raise NotImplementedError('Relative imports are not supported') module_path = node.module.split('.') import_module = self.init_module(module_path) if len(node.names) > 1 or node.names[0].name == '*': self.visit(ast.Assign([ast_store('$t1')], import_module)) import_from = ast_load('$t1') else: import_from = import_module if node.names[0].name == '*': name = node.names[0] if name.name == '*': if self.stack[-1].scope.prefix != ['__module__']: raise NotImplementedError( 'from x import * only implemented at module level') self.visit( ast.For(ast_store('$t2'), import_from, [ ast.Assign([ ast.Subscript( ast_call(ast_load('JS'), ast.Str('__module__')), ast.Index(ast_load('$t2')), ast.Load()) ], ast.Subscript( import_from, ast.Index(ast_load('$t2')), ast.Load(), )), ], [])) else: for name in node.names: asname = name.asname if name.asname else name.name self.visit( ast.Assign([ast_store(asname)], ast.Attribute(import_from, name.name, ast.Load())))
def _bin_op(self, v_type, v1, op, v2, r): assert self.run( [ ast.Assign( [ast_store('test')], ast.BinOp(v_type(v1), op(), v_type(v2)), ), ], 'test', type(r) ) == r
def test_destructure(self): assert self.run([ ast.Assign([ast_store('test2')], ast_call( ast.FunctionDef('', ast.arguments( [], None, None, []), [ ast.Global(['test1']), ast.Assign([ ast.List([ ast_store('test1'), ast_store('test2'), ], ast.Store()) ], ast.List([ ast.Str('test1'), ast.Str('test2'), ], ast.Load())), ast.Return(ast_load('test2')) ], []))) ], 'test1 + "+" + test2') == 'test1+test2'
def visit_ListComp(self, node): body = [ast.Expr(ast_call(ast_load('$$.push'), node.elt))] for i, generator in reversed( zip(range(len(node.generators)), node.generators)): if not isinstance(generator.target, ast.Name): raise TypeError('dereferencing assignment not supported') if generator.ifs: if len(generator.ifs) > 1: cond = ast.BoolOp(ast.And(), generator.ifs) else: cond = generator.ifs[0] body = [ast.If(cond, body, [])] body = [ ast.Assign([ast_store('$$' + generator.target.id)], generator.iter), ast.For( ast_store('$' + generator.target.id), ast_call( ast_load('range'), ast.Num(0), ast.Attribute(ast_load('$$' + generator.target.id), 'length', ast.Load())), [ ast.Assign( [generator.target], ast.Subscript( ast_load('$$' + generator.target.id), ast.Index(ast_load('$' + generator.target.id)), ast.Load())), ] + body, []) ] self.visit( ast_call( ast.FunctionDef('', ast.arguments([], None, None, []), [ ast.Assign([ast_store('$$')], ast.List([], ast.Load())), ] + body + [ ast.Return(ast_load('$$')), ], []), ))
def visit_Import(self, node): for name in node.names: module_path = name.name.split('.') import_module = self.init_module(module_path) if not name.asname: self.visit(ast.Expr(import_module)) self.visit( ast.Assign( [ast_store(module_path[0])], self.init_module(module_path[:1]) ) ) else: self.visit( ast.Assign( [ast_store(name.asname)], import_module ) )
def _slice_assign(self, start, end): result = self.run([ ast.Assign([ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load())), ast.Assign([ ast.Subscript( ast_load('test'), ast.Slice(start and ast.Num(start), end and ast.Num(end), None), ast.Store()), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load())), ], 'test', list) return result
def test_assign_expr_slice(self): assert self.run([ ast.Assign([ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load())), ast.FunctionDef('f_test', ast.arguments([], None, None, []), [ ast.Return(ast_load('test')), ], []), ast.Assign([ ast.Subscript(ast_call(ast_load('f_test')), ast.Slice(ast.Num(2), ast.Num(8), None), ast.Store()), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load())), ], 'test', list) == [0, 1, 42, 43, 8, 9]
def _bool_op(self, v_type, op, v, r): assert self.run( [ ast.Assign( [ast_store('test')], ast.BoolOp(op(), [ v_type(i) for i in v ]), ), ], 'test', type(r) ) == r
def test_destructure(self): assert self.run( [ ast.Assign( [ast_store('test2')], ast_call( ast.FunctionDef( '', ast.arguments([], None, None, []), [ ast.Global(['test1']), ast.Assign( [ ast.List( [ ast_store('test1'), ast_store('test2'), ], ast.Store() ) ], ast.List( [ ast.Str('test1'), ast.Str('test2'), ], ast.Load() ) ), ast.Return(ast_load('test2')) ], [] ) ) ) ], 'test1 + "+" + test2' ) == 'test1+test2'
def test_assign_multiple_slice(self): self.v.visit( ast.Assign( [ ast.Subscript( ast_load('foo'), ast.Slice(), ast.Store() ), ast_store('bar'), ], ast.Str('test') ) )
def test_break(self): assert self.run( [ ast.Assign( [ast_store('i')], ast.Num(0), ), ast.While( ast.Compare( ast_load('i'), [ast.Lt()], [ast.Num(10)] ), [ ast.Break(), ], [] ) ], 'i', int ) == 0
def _slice_assign(self, start, end): result = self.run( [ ast.Assign( [ast_store('test')], ast.List([ast.Num(x) for x in range(10)], ast.Load()) ), ast.Assign( [ ast.Subscript( ast_load('test'), ast.Slice(start and ast.Num(start), end and ast.Num(end), None), ast.Store() ), ], ast.List([ast.Num(42), ast.Num(43)], ast.Load()) ), ], 'test', list ) return result
def setUp(self): self.o = ast_store('foo')
def visit_ListComp(self, node): body = [ ast.Expr( ast_call( ast_load('$$.push'), node.elt ) ) ] for i, generator in reversed(zip(range(len(node.generators)), node.generators)): if not isinstance(generator.target, ast.Name): raise TypeError('dereferencing assignment not supported') if generator.ifs: if len(generator.ifs) > 1: cond = ast.BoolOp(ast.And(), generator.ifs) else: cond = generator.ifs[0] body = [ ast.If( cond, body, [] ) ] body = [ ast.Assign( [ast_store('$$' + generator.target.id)], generator.iter ), ast.For( ast_store('$' + generator.target.id), ast_call( ast_load('range'), ast.Num(0), ast.Attribute( ast_load('$$' + generator.target.id), 'length', ast.Load() ) ), [ ast.Assign( [generator.target], ast.Subscript( ast_load('$$' + generator.target.id), ast.Index(ast_load('$' + generator.target.id)), ast.Load() ) ), ] + body, [] ) ] self.visit( ast_call( ast.FunctionDef( '', ast.arguments( [ ], None, None, [] ), [ ast.Assign( [ ast_store('$$') ], ast.List( [], ast.Load() ) ), ] + body + [ ast.Return(ast_load('$$')), ], [] ), ) )
def setUp(self): self.o = ast_store('foo.bar', 'baz')
def visit_ClassDef(self, node): if len(node.bases) > 1: raise Exception('Multiple inheritance not supported') self.visit(FunctionDef( node.name, arguments([], None, None, []), [ ast.If( ast.UnaryOp( ast.Not(), ast_call( ast_load('isinstance'), ast_load('this'), ast_load('arguments.callee'), ) ), [ ast.Return( ast_call( ast_load('new'), ast_load('arguments.callee'), ast_load('arguments'), ) ) ], [] ), ast.Assign( [ast_store('this.__class__')], ast_load('arguments.callee') ), ast.Expr( ast_call( ast_load('this.__bind__'), ast_load('this'), ), ), ast.If( ast.Compare( ast_call( ast_load('type'), ast_load('this.__init__'), ), [ast.IsNot()], [ast.Str('undefined')], ), [ ast.Expr( ast_call( ast_load('this.__init__.apply'), ast_load('this'), ast.Subscript( ast_load('arguments'), ast.Index(ast.Num(0)), ast.Load() ) ) ), ], [] ) ], [] )) self.push(ClassContext(self.stack[-1], node.name)) scope = self.stack[-1].scope if not node.bases: scope.prefix.pop() self.visit( ast.Assign( [ast_store('prototype')], ast.Dict( [ ast.Str('constructor'), ast.Str('__mro__') ], [ ast_load(node.name), ast.List([ast_load(node.name)], ast.Load()) ] ) ) ) scope.prefix.append('prototype') self.visit( ast.Assign( [ast_store('__bind__')], FunctionDef( '', arguments([ast_load('self')], None, None, []), [ ast.For( ast_store('i'), ast_load('this'), [ ast.If( ast.Compare( ast_call( ast_load('type'), ast.Subscript( ast_load('this'), ast.Index(ast_load('i')), ast.Load(), ) ), [ast.Is()], [ast.Str('function')] ), [ ast.Assign( [ast.Subscript( ast_load('this'), ast.Index(ast_load('i')), ast.Store(), )], ast_call( ast.Attribute( ast.Subscript( ast_load('this'), ast.Index(ast_load('i')), ast.Load(), ), 'bind', ast.Load(), ), ast_load('self'), ast_load('self'), ) ), ], [] ) ], [] ), ], [] ) ) ) else: base = node.bases[0] self.visit( ast.Assign( [ast_store(node.name, 'prototype')], ast_call( FunctionDef( '', arguments([], None, None, []), [ ast.Assign( [ast_store('tmp')], FunctionDef( '', arguments([], None, None, []), [], [] ) ), ast.Assign( [ast_store('tmp', 'prototype')], ast.Attribute(base, 'prototype', ast.Load()), ), ast.Return( ast_call( ast_load('new'), ast_load('tmp'), ) ) ], [] ), ) ) ) self.visit( ast.Assign( [ast_store(node.name, 'prototype.constructor')], ast_load(node.name) ) ) self.visit( ast.Assign( [ast_store(node.name, 'prototype.__base__')], base, ) ) self.visit( ast.Assign( [ast_store(node.name, 'prototype.__mro__')], ast_call( ast_load(node.name, 'prototype.__mro__.concat'), ast_load(node.name), ) ) ) for stmt in node.body: self.visit(stmt) self.pop() if node.decorator_list: arg = ast_load(node.name) for decorator in node.decorator_list: arg = ast_call(decorator, arg) self.visit( ast.Assign( [ast_store(node.name)], arg ) )
def test_single_assign(self): assert self.run([ast.Assign([ast_store('test')], ast.Str('test'))], 'test') == 'test'
def test_assign_multiple_slice(self): self.v.visit( ast.Assign([ ast.Subscript(ast_load('foo'), ast.Slice(), ast.Store()), ast_store('bar'), ], ast.Str('test')))
def build_Assign_Slice(self, target, value): args = [] if target.slice.lower or target.slice.upper: args.append(target.slice.lower or ast.Num(0)) if target.slice.upper: args.append(target.slice.upper) return ast_call( ast.FunctionDef( '', ast.arguments( [ ast_store('t'), ast_store('v'), ast_store('s'), ast_store('e'), ], None, None, [] ), [ ast.Assign( [ast_store('s')], ast.IfExp( ast.Compare( ast_call( ast_load('type'), ast_load('s') ), [ast.Eq()], [ast.Str('undefined')], ), ast.Num(0), ast.IfExp( ast.Compare( ast_load('s'), [ast.Lt()], [ast.Num(0)], ), ast.BinOp( ast_load('s'), ast.Add(), ast_load('t.length') ), ast_load('s') ) ) ), ast.Assign( [ast_store('e')], ast.IfExp( ast.Compare( ast_call( ast_load('type'), ast_load('e') ), [ast.Eq()], [ast.Str('undefined')], ), ast_load('t.length'), ast.IfExp( ast.Compare( ast_load('e'), [ast.Lt()], [ast.Num(0)], ), ast.BinOp( ast_load('e'), ast.Add(), ast_load('t.length') ), ast_load('e') ) ) ), ast.Expr( ast_call( ast_load('Array.prototype.splice.apply'), ast_load('t'), ast_call( ast.Attribute( ast.List([ ast_load('s'), ast.BinOp( ast_load('e'), ast.Sub(), ast_load('s') ), ], ast.Load()), 'concat', ast.Load(), ), ast_load('v'), ) ) ), ast.Return(ast_load('v')), ], [] ), target.value, value, *args )
def test_multi_assign(self): assert self.run([ ast.Assign( [ast_store('test1'), ast_store('test2')], ast.Str('test')) ], 'test1 + "+" + test2') == 'test+test'