def parse_logic(struct): lineno = struct.lineno kw = dict(lineno=lineno, col_offset=0) if isinstance(struct.right, LogicalOp): ast_right, insert_into = parse_logic(struct.right) assert insert_into is None else: ast_right = struct.right parent = struct.parent Logic = _ast.Or if struct.flag == 'OR' else _ast.And if isinstance(parent, LogicalOp): ast_parent, insert_into = parse_logic(struct.parent) new_insert_into = [ast_right] insert_into.insert(0, _ast.BoolOp(op=Logic(), values=new_insert_into, **kw)) return ast_parent, new_insert_into elif parent is None: insert_into = [ast_right] return _ast.BoolOp(op=Logic(), values=insert_into, **kw), insert_into else: bool_op = _ast.BoolOp(op=Logic(), values=[parent, ast_right], **kw) return bool_op, None
def test_compile_ast(self): fname = __file__ if fname.lower().endswith('pyc'): fname = fname[:-1] with open(fname, 'r') as f: fcontents = f.read() sample_code = [ ['<assign>', 'x = 5'], ['<ifblock>', """if True:\n pass\n"""], ['<forblock>', """for n in [1, 2, 3]:\n print(n)\n"""], ['<deffunc>', """def foo():\n pass\nfoo()\n"""], [fname, fcontents], ] for fname, code in sample_code: co1 = compile(code, '%s1' % fname, 'exec') ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST) self.assertTrue(type(ast) == _ast.Module) co2 = compile(ast, '%s3' % fname, 'exec') self.assertEqual(co1, co2) # the code object's filename comes from the second compilation step self.assertEqual(co2.co_filename, '%s3' % fname) # raise exception when node type doesn't match with compile mode co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST) self.assertRaises(TypeError, compile, co1, '<ast>', 'eval') # raise exception when node type is no start node self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec') # raise exception when node has invalid children ast = _ast.Module() ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
def parse_generator(nodes, ids): node = nodes[0] tempnode = _ast.For() tempnode.target = node.target tempnode.iter = _ast.Name(id=ids[0], ctx=_ast.Load()) if len(nodes) == 1: yield_node = _ast.Expr(value=_ast.Yield(value=elt)) body = [yield_node] else: body = [parse_generator(nodes[1:], ids[1:])] if len(node.ifs) == 1: ifnode = _ast.If(test=node.ifs[0], body=body, orelse=[]) tempnode.body = [ifnode] elif len(node.ifs) > 1: ifnode = _ast.If(test=_ast.BoolOp(op=_ast.And(), values=node.ifs), body=body, orelse=[]) tempnode.body = [ifnode] else: tempnode.body = body tempnode.orelse = None return tempnode
def parse_generator(nodes): """Transform the generator into a for loop. """ node = nodes[0] tempnode = ast.For() tempnode.target = node.target tempnode.iter = node.iter if len(nodes) == 1: append_node = ast.parse("%s.append(foo)" % iden).body[0] append_node.value.args[0] = elt body = [append_node] else: body = [parse_generator(nodes[1:])] if len(node.ifs) == 1: ifnode = _ast.If(test=node.ifs[0], body=body, orelse=[]) tempnode.body = [ifnode] elif len(node.ifs) > 1: ifnode = _ast.If(test=_ast.BoolOp(op=_ast.And(), values=node.ifs), body=body, orelse=[]) tempnode.body = [ifnode] else: tempnode.body = body tempnode.orelse = None return tempnode
def test_compile_ast(self): fname = __file__ if fname.lower().endswith('pyc'): fname = fname[:-1] with open(fname, 'r') as f: fcontents = f.read() sample_code = [['<assign>', 'x = 5'], ['<ifblock>', 'if True:\n pass\n'], ['<forblock>', """for n in [1, 2, 3]: print(n) """], ['<deffunc>', """def foo(): pass foo() """], [fname, fcontents]] for fname, code in sample_code: co1 = compile(code, '%s1' % fname, 'exec') ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST) self.assertTrue(type(ast) == _ast.Module) co2 = compile(ast, '%s3' % fname, 'exec') self.assertEqual(co1, co2) self.assertEqual(co2.co_filename, '%s3' % fname) co1 = compile('print(1)', '<string>', 'exec', _ast.PyCF_ONLY_AST) self.assertRaises(TypeError, compile, co1, '<ast>', 'eval') self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec') ast = _ast.Module() ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
def BoolOp(left, *alternating_ops_values): """Creates an _ast.BoolOp node. Args: left: The node on the left side of the equal sign. *alternating_ops_values: An alternating list of ops and expressions. Note that _ast.Not is not a valid boolean operator, it is considered a unary operator. For example: (_ast.Or, _ast.Name('a')) Returns: An _ast.BoolOp node. """ values = [left] op = None op_next = True alternating_ops_values = list(alternating_ops_values) while alternating_ops_values: op_or_value = alternating_ops_values.pop(0) if op_next: if not isinstance(op_or_value, _ast.AST): op_or_value = BoolOpMap(op_or_value) if not op: op = op_or_value elif op and op == op_or_value: continue else: # Or's take priority over And's if isinstance(op, _ast.And): return BoolOp(_ast.BoolOp(op=op, values=values), op_or_value, *alternating_ops_values) else: last_value = values.pop() values.append( BoolOp(last_value, op_or_value, *alternating_ops_values)) return _ast.BoolOp(op=_ast.Or(), values=values) else: values.append(op_or_value) op_next = not op_next return _ast.BoolOp(op=op, values=values)
def visit_BoolOp(self, node): if self.randomize(): if self.randomize(): op = ast.And() else: op = ast.Or() values = [] for value in node.values: values.append(self.visit(value)) return ast.copy_location(_ast.BoolOp(op=op, values=values), node) else: return node
def test_compile_ast(self): if test_support.due_to_ironpython_bug( "http://www.codeplex.com/IronPython/WorkItem/View.aspx?WorkItemId=21088" ): return fname = __file__ if fname.lower().endswith(('pyc', 'pyo')): fname = fname[:-1] with open(fname, 'r') as f: fcontents = f.read() sample_code = [ ['<assign>', 'x = 5'], ['<print1>', 'print 1'], ['<printv>', 'print v'], ['<printTrue>', 'print True'], ['<printList>', 'print []'], ['<ifblock>', """if True:\n pass\n"""], ['<forblock>', """for n in [1, 2, 3]:\n print n\n"""], ['<deffunc>', """def foo():\n pass\nfoo()\n"""], [fname, fcontents], ] for fname, code in sample_code: co1 = compile(code, '%s1' % fname, 'exec') ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST) self.assertTrue(type(ast) == _ast.Module) co2 = compile(ast, '%s3' % fname, 'exec') self.assertEqual(co1, co2) # the code object's filename comes from the second compilation step self.assertEqual(co2.co_filename, '%s3' % fname) # raise exception when node type doesn't match with compile mode co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST) self.assertRaises(TypeError, compile, co1, '<ast>', 'eval') # raise exception when node type is no start node self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec') # raise exception when node has invalid children ast = _ast.Module() ast.body = [_ast.BoolOp()] self.assertRaises(TypeError, compile, ast, '<ast>', 'exec')
def test_compile_ast(self): fname = __file__ if fname.lower().endswith(('pyc', 'pyo')): fname = fname[:-1] with open(fname, 'r') as f: fcontents = f.read() sample_code = [ ['<assign>', 'x = 5'], ['<print1>', 'print 1'], ['<printv>', 'print v'], ['<printTrue>', 'print True'], ['<printList>', 'print []'], ['<ifblock>', """if True:\n pass\n"""], ['<forblock>', """for n in [1, 2, 3]:\n print n\n"""], ['<deffunc>', """def foo():\n pass\nfoo()\n"""], #FIXME: Next one not working in Jython: #[fname, fcontents], ] for fname, code in sample_code: co1 = compile(code, '%s1' % fname, 'exec') ast = compile(code, '%s2' % fname, 'exec', _ast.PyCF_ONLY_AST) self.assert_(type(ast) == _ast.Module) co2 = compile(ast, '%s3' % fname, 'exec') if not test_support.is_jython: self.assertEqual(co1, co2) # the code object's filename comes from the second compilation step self.assertEqual(co2.co_filename, '%s3' % fname) # raise exception when node type doesn't match with compile mode co1 = compile('print 1', '<string>', 'exec', _ast.PyCF_ONLY_AST) #FIXME: raises wrong error in Jython. #self.assertRaises(TypeError, compile, co1, '<ast>', 'eval') # raise exception when node type is no start node self.assertRaises(TypeError, compile, _ast.If(), '<ast>', 'exec') # raise exception when node has invalid children ast = _ast.Module() ast.body = [_ast.BoolOp()]
def JUMP_IF_Y_OR_POP(self, instr): left = self.pop_ast_item() and_block = self.gather_jumps(instr) hi = self.process_logic([instr] + and_block) # Compress (a > b) and (b > c) into (a > b > c) hi.right = reduce_cmp(hi.right) if isinstance(hi.right, _ast.Compare): if isinstance(left, _ast.Compare) and left.comparators[-1] is hi.right.left: left.ops.extend(hi.right.ops) left.comparators.extend(hi.right.comparators) else: left = _ast.BoolOp(op=operand(), values=[left, hi.right], lineno=instr.lineno, col_offset=0) else: bool_op, insert_into = parse_logic(hi) insert_into.insert(0, left) left = bool_op self.push_ast_item(left) if len(self.ilst) >= 2 and [ii.opname for ii in self.ilst[:2]] == ['ROT_TWO', 'POP_TOP']: self.ilst.pop(0) self.ilst.pop(0)
def bool_op_expr(op: _ast.boolop, values: List[_ast.expr]) -> _ast.BoolOp: return _ast.BoolOp(op=op, values=values)