def visit_Name(self, name): # Display the repr of the name if it's a local variable or # _should_repr_global_name() thinks it's acceptable. locs = ast_Call(self.builtin("locals"), [], []) inlocs = ast.Compare(ast.Str(name.id), [ast.In()], [locs]) dorepr = self.helper("_should_repr_global_name", name) test = ast.BoolOp(ast.Or(), [inlocs, dorepr]) expr = ast.IfExp(test, self.display(name), ast.Str(name.id)) return name, self.explanation_param(expr)
def visit_TryExcept(self, node): if node.orelse: raise NotImplementedError('Try-except else handler not implemented') self.indent() self.output('try') self.block(node.body, context=BlockContext(self.stack[-1])) self.output(' catch($e) ') self.push(BlockContext(self.stack[-1])) if_start = None if_end = None for handler in node.handlers: if handler.type is not None: if handler.name is not None: body = handler.body[:] body.insert(0, ast.Assign( [handler.name], ast_call(ast_load('JS'), ast.Str('$e')) )) else: body = handler.body types = [handler.type] if isinstance(handler.type, _ast.Name) else handler.type conditions = [ ast_call( ast_load('isinstance'), ast_call(ast_load('JS'), ast.Str('$e')), type_, ) for type_ in types ] _if = ast.If( ast.BoolOp(ast.Or(), conditions), body, [] ) if if_start is None: if_start = if_end = _if else: if_end.orelse, if_end = [_if], _if else: if handler is not node.handlers[-1]: raise SyntaxError("default 'except:' must be last") if if_start is None: self.block(handler.body) else: if_end.orelse = handler.body if if_start is not None: self.visit(if_start) self.pop() self.output('\n')
def setup(self): self.modulename = 'somename' self.node = ast.BoolOp(values=[ ast.Name(id='a'), ast.Name(id='b'), ast.Name(id='c'), ], lineno=6, col_offset=4) self.label = '6.1'
def __and__(self, other) -> Column: ''' Bitwise and becomes a logical and. ''' self._test_for_extension('operator and') from .utils import _term_to_ast return Column( type(bool), ast.BoolOp( op=ast.And(), values=[_term_to_ast(self, None), _term_to_ast(other, None)]))
def compile_logical_or_and_and_operator(self, expression): ops = {"and": ast.And, "or": ast.Or} operator = expression.pop(0) values = [] for child in expression: values.append(self.compile(child)) return ast.BoolOp(op=ops[operator](), lineno=operator.start_line, col_offset=operator.start_column, values=values)
def missingCheck(check: ast.Compare, el: ast.Subscript, default: bool) -> ast.BoolOp: """Creates AST nodes corresponding to check whether the `el` is None, if it is returns `default`""" return ast.BoolOp(op=(ast.Or() if default else ast.And()), values=[ ast.Compare( left=el, ops=[(ast.Is() if default else ast.IsNot())], comparators=[noneCnst]), check ])
def visit_BoolOp(self, node): 'Check if BoolOp is exaclty matching or contain pattern' if isinstance(self.patt_ast, ast.BoolOp): if len(node.values) == len(self.patt_ast.values): pat = PatternMatcher(node, self.nbits) matched = pat.visit(node, self.patt_ast) if matched: new_node = EvalPattern(pat.wildcards).visit(self.rep_ast) return new_node else: return self.generic_visit(node) elif len(node.values) > len(self.patt_ast.values): # associativity n to m for combi in itertools.combinations(node.values, len(self.patt_ast.values)): rest = [elem for elem in node.values if elem not in combi] testnode = ast.BoolOp(node.op, list(combi)) pat = PatternMatcher(testnode, self.nbits) matched = pat.visit(testnode, self.patt_ast) if matched: new = EvalPattern(pat.wildcards).visit(self.rep_ast) new = ast.BoolOp(node.op, [new] + rest) new = asttools.Unleveling().visit(new) return new return self.generic_visit(node) if isinstance(self.patt_ast, ast.BinOp): if type(node.op) != type(self.patt_ast.op): return self.generic_visit(node) op = node.op for combi in itertools.combinations(node.values, 2): rest = [elem for elem in node.values if elem not in combi] testnode = ast.BinOp(combi[0], op, combi[1]) pat = PatternMatcher(testnode, self.nbits) matched = pat.visit(testnode, self.patt_ast) if matched: new_node = EvalPattern(pat.wildcards).visit(self.rep_ast) new_node = ast.BoolOp(op, [new_node] + rest) new_node = asttools.Unleveling().visit(new_node) return new_node return self.generic_visit(node)
def test_astform(self): 'Tests with different types of ast' t1 = ast.parse("1 + 2 + 3", mode="eval").body t1_ref = ast.BoolOp(ast.Add(), [ast.Num(1), ast.Num(2), ast.Num(3)]) t2 = ast.parse("1 + 2 + 3", mode="eval") t3 = ast.parse("1 + 2 + 3").body[0] tests = [(t1, t1_ref), (t2, ast.Expression(t1_ref)), (t3, ast.Expr(t1_ref))] for test, ref in tests: ltest = Flattening().visit(test) self.assertTrue(Comparator().visit(ltest, ref))
def make_Iterator(self, gen): if gen.ifs: ldFilter = ast.Lambda( ast.arguments([ast.Name(gen.target.id, ast.Param())], None, None, []), ast.BoolOp(ast.And(), gen.ifs)) ifilterName = ast.Attribute( value=ast.Name(id='itertools', ctx=ast.Load()), attr='ifilter', ctx=ast.Load()) return ast.Call(ifilterName, [ldFilter, gen.iter], [], None, None) else: return gen.iter
def __or__(self, other) -> Column: ''' Bitwise and becomes a logical and. ''' self._test_for_extension('operator or') from .utils import _term_to_ast return Column( type(bool), ast.BoolOp(op=ast.Or(), values=[ ast.Name('p', ctx=ast.Load()), _term_to_ast(other, self) ]))
def stop_iteration(node): cmp_break = ast.Compare(left=mk_name(self.flag_id), ops=[ast.Eq()], comparators=[mk_str(self.BREAK)]) cmp_return = ast.Compare(left=mk_name(self.flag_id), ops=[ast.Eq()], comparators=[mk_str(self.RETURN)]) test = ast.BoolOp(op=ast.Or(), values=[cmp_break, cmp_return]) break_stmt = ast.Break() ifstmt = ast.If(test=test, body=[break_stmt], orelse=[]) node.body.append(ifstmt)
def _dnf(self, node): if type(node) != ast.BoolOp: return node values = [self._dnf(child) for child in node.values] if type(node.op) == ast.Or: return ast.BoolOp(op=ast.Or(), values=values) for index, value in enumerate(values): if (type(value) == ast.BoolOp) and (type(value.op) == ast.Or): maxterm = values[index] values = values[:index] + values[index + 1:] values = [ ast.BoolOp(op=ast.And(), values=[v] + values) for v in maxterm.values ] return self._dnf(ast.BoolOp(op=ast.Or(), values=values)) return node
def gen_attr_check(self, node, attr_name): """Check if 'attr_name' is allowed on the object in node. It generates (_getattr_(node, attr_name) and node). """ call_getattr = ast.Call(func=ast.Name('_getattr_', ast.Load()), args=[node, ast.Str(attr_name)], keywords=[]) return ast.BoolOp(op=ast.And(), values=[call_getattr, node])
def ast(self): op = self.keyword_aliases[self.op_token] if isinstance(op, ast.boolop): # and and or use one type of AST node value = ast.BoolOp(op=op, values=[e.ast() for e in self.comparators]) else: # remaining operators use another value = ast.Compare(left=self.comparators[0].ast(), ops=[op], comparators=[e.ast() for e in self.comparators[1:]]) return value
def parse_bool_op(self, node, operator): values = [] for child in node: rule = self.parse_rule_node(child) if rule: values.append(rule) num_values = len(values) if num_values > 1: return ast.BoolOp(operator, values) elif num_values == 1: return values[0] return None
def __parseBoolOp(node, operator): values = [] for child in _iter_children(node): rule = __parseRuleNode(child) if rule: values.append(rule) num_values = len(values) if num_values > 1: return ast.BoolOp(operator, values) elif num_values == 1: return values[0] return None
def mutate(self, node, idx): """Replace AND with OR.""" # replace all occurences of And() # A and B and C -> A or B or C node.op = ast.Or() # or replace an operator somewhere in the middle # of the expression if idx and len(node.values) > 2: left = node.values[:idx] if len(left) > 1: left = [ast.BoolOp(op=ast.And(), values=left)] right = node.values[idx:] if len(right) > 1: right = [ast.BoolOp(op=ast.And(), values=right)] node.values = [] node.values.extend(left) node.values.extend(right) return node
def visit_BoolOp(self, node): 'A custom BoolOp can be used in leveled AST' if type(node.op) not in (ast.Add, ast.Mult, ast.BitXor, ast.BitAnd, ast.BitOr): return self.generic_visit(node) # get constant parts of node: list_cste = [child for child in node.values if isinstance(child, ast.Num)] if len(list_cste) < 2: return self.generic_visit(node) rest_values = [n for n in node.values if n not in list_cste] fake_node = Unleveling().visit(ast.BoolOp(node.op, list_cste)) fake_node = ast.Expression(fake_node) ast.fix_missing_locations(fake_node) code = compile(fake_node, '<constant folding>', 'eval') obj_env = globals().copy() exec code in obj_env value = eval(code, obj_env) new_node = ast.Num(value) rest_values.append(new_node) return ast.BoolOp(node.op, rest_values)
def visit_Where_of_Where(self, parent, filter): ''' seq.Where(x: f(x)).Where(x: g(x)) => Where(Where(seq, x: f(x)), y: g(y)) is turned into seq.Where(x: f(x) and g(y)) => Where(seq, x: f(x) and g(y)) ''' func_f = parent.filter func_g = filter arg = arg_name() return self.visit(Where(parent.source, lambda_build(arg, ast.BoolOp(ast.And(), [lambda_call(arg, func_f), lambda_call(arg, func_g)]))))
def test_withUnaryOp(self): 'Test with UnaryOp involved' tests = [("5 + (-(6 + 2)) + 3", ast.BoolOp(ast.Add(), [ast.Num(5), ast.UnaryOp(ast.USub(), ast.BinOp(ast.Num(6), ast.Add(), ast.Num(2))), ast.Num(3)]))] for teststring, ref_ast in tests: test_ast = ast.parse(teststring, mode="eval").body test_ast = asttools.LevelOperators(ast.Add).visit(test_ast) self.assertTrue(asttools.Comparator().visit(test_ast, ref_ast))
def visit_ListComp(self, node): """ Rewrite list comprehensions to the equivalent for loops. AST syntax: ListComp(expr elt, comprehension* generators) comprehension = (expr target, expr iter, expr* ifs) 'ifs' represent a chain of ANDs """ assert len(node.generators) > 0 # Create innermost body, i.e. list.append(expr) # TODO: size hint for PyList_New list_create = ast.List(elts=[], ctx=ast.Load()) list_create.type = typesystem.object_ # typesystem.list_() list_create = nodes.CloneableNode(list_create) list_value = nodes.CloneNode(list_create) list_append = ast.Attribute(list_value, "append", ast.Load()) append_call = ast.Call(func=list_append, args=[node.elt], keywords=[], starargs=None, kwargs=None) # Build up the loops from inwards to outwards body = append_call for comprehension in reversed(node.generators): # Hanlde the 'if' clause ifs = comprehension.ifs if len(ifs) > 1: make_boolop = lambda op1_op2: ast.BoolOp(op=ast.And(), values=op1_op2) if_test = reduce(make_boolop, ifs) elif len(ifs) == 1: if_test, = ifs else: if_test = None if if_test is not None: body = ast.If(test=if_test, body=[body], orelse=[]) # Wrap list.append() call or inner loops body = ast.For(target=comprehension.target, iter=comprehension.iter, body=[body], orelse=[]) expr = nodes.ExpressionNode(stmts=[list_create, body], expr=list_value) return self.visit(expr)
def single_compare(self, node): rhs = node.comparators[0] if is_obj(node.left.type): node = self.single_compare_objects(node) elif node.left.type.is_pointer and rhs.type.is_pointer: # Coerce pointers to integer values before comparing node.left = nodes.CoercionNode(node.left, Py_uintptr_t) node.comparators = [nodes.CoercionNode(rhs, Py_uintptr_t)] elif node.left.type.is_complex and rhs.type.is_complex: real1, imag1 = extract(node.left) real2, imag2 = extract(rhs) op = type(node.ops[0]) if op == ast.Eq: lhs = compare(real1, ast.Eq(), real2) rhs = compare(imag1, ast.Eq(), imag2) result = ast.BoolOp(ast.And(), [lhs, rhs]) elif op == ast.NotEq: lhs = compare(real1, ast.NotEq(), real2) rhs = compare(imag1, ast.NotEq(), imag2) result = ast.BoolOp(ast.Or(), [lhs, rhs]) else: raise NotImplementedError("ordered comparisons are not " "implemented for complex numbers") node = nodes.typednode(result, bool_) elif node.left.type.is_string and rhs.type.is_string: node.left = nodes.CoercionNode(node.left, object_) node.comparators = [nodes.CoercionNode(rhs, object_)] return self.single_compare(node) elif node.left.type.is_complex and rhs.type.is_datetime: raise error.NumbaError(node, "datetime comparisons not yet implemented") return node
def invert(self, node: Type[ast.AST]) -> Type[ast.AST]: if type(node) == ast.Compare: if len(node.ops) == 1: return ast.Compare( left=node.left, ops=[self.invertComparators[type(node.ops[0])]()], comparators=node.comparators) else: tmpNode = ast.BoolOp(op=ast.And(), values=[ ast.Compare( left=node.left, ops=[node.ops[0]], comparators=[node.comparators[0]]) ]) for i in range(0, len(node.ops) - 1): tmpNode.values.append( ast.Compare(left=node.comparators[i], ops=[node.ops[i + 1]], comparators=[node.comparators[i + 1]])) return self.invert(tmpNode) elif isinstance(node, ast.BinOp) and type( node.op) in self.invertComparators: return ast.BinOp(node.left, self.invertComparators[type(node.op)](), node.right) elif type(node) == ast.NameConstant and type(node.value) == bool: return ast.NameConstant(value=not node.value) elif type(node) == ast.BoolOp: return ast.BoolOp(values=[self.invert(x) for x in node.values], op={ ast.And: ast.Or(), ast.Or: ast.And() }.get(type(node.op))) elif type(node) == ast.UnaryOp: return self.UnaryopInvert(node) else: return ast.UnaryOp(op=ast.Not(), operand=node)
def test_differentops(self): 'Test with other types of operators' tests = [ ("(3 & 5 & 6)", ast.BoolOp( ast.BitAnd(), [ast.Num(3), ast.Num(5), ast.Num(6)])), ("(1 ^ 2 ^ 3) - 4", ast.BinOp( ast.BoolOp(ast.BitXor(), [ast.Num(1), ast.Num(2), ast.Num(3)]), ast.Add(), ast.BinOp(ast.Num(-1), ast.Mult(), ast.Num(4)))), ("((1 + 2 + 3) & (4 + 5))", ast.BinOp( ast.BoolOp(ast.Add(), [ast.Num(1), ast.Num(2), ast.Num(3)]), ast.BitAnd(), ast.BinOp(ast.Num(4), ast.Add(), ast.Num(5)))), ("(1 & 2 & 3) - (4 & 5)", ast.BinOp( ast.BoolOp(ast.BitAnd(), [ast.Num(1), ast.Num(2), ast.Num(3)]), ast.Add(), ast.BinOp(ast.Num(-1), ast.Mult(), ast.BinOp(ast.Num(4), ast.BitAnd(), ast.Num(5))))), ("(1 & 2 & 3) << (4 & 5)", ast.BinOp( ast.BoolOp(ast.BitAnd(), [ast.Num(1), ast.Num(2), ast.Num(3)]), ast.LShift(), ast.BinOp(ast.Num(4), ast.BitAnd(), ast.Num(5)))) ] for teststring, ref_ast in tests: test_ast = ast.parse(teststring, mode="eval").body test_ast = pre_processing.all_preprocessings(test_ast) test_ast = Flattening().visit(test_ast) self.assertTrue(Comparator().visit(test_ast, ref_ast))
def p_or_test(p): '''or_test : and_test | or_test TAG_OR and_test''' if len(p) == 2: p[0] = p[1] else: p[0] = ast.BoolOp(op=ast.Or(), values=[p[1], p[3]], lineno=p[1].lineno, col_offset=p[1].col_offset) return
def visit_While(self, node): if not self.is_body_covered(node.body): test = ast.BoolOp(op=ast.Or(), values=[node.test, ast.Name(id='True')]) body = [ast.copy_location(ast.Pass(), node.body[0])] if_ = ast.If(test=test, body=body, orelse=[]) # This is a workaround on a pasta bug # TODO remove when is is fixed if_.__pasta__ = {'prefix': node.__pasta__['prefix']} return if_ elif node.orelse and not self.is_body_covered(node.orelse): node.orelse = [] return super(LoopRemover, self).generic_visit(node)
def visit_Compare(self, node): self.generic_visit(node) if len(node.ops) == 1: return node else: list_compare = [] left = node.left for op, comparator in zip(node.ops, node.comparators): compare = ast.Compare(left=left, ops=[op], comparators=[comparator]) list_compare.append(compare) left = comparator return ast.BoolOp(op=ast.And(), values=list_compare)
def p_and_test(p): '''and_test : not_test | and_test TAG_AND not_test''' if len(p) == 2: p[0] = p[1] else: p[0] = ast.BoolOp(op=ast.And(), values=[p[1], p[3]], lineno=p[1].lineno, col_offset=p[1].col_offset) return
def merge_exitcases(exit1, exit2): """ Merge the exitcases of two Links. Args: exit1: The exitcase of a Link object. exit2: Another exitcase to merge with exit1. Returns: The merged exitcases. """ if exit1: if exit2: return ast.BoolOp(ast.And(), values=[exit1, exit2]) return exit1 return exit2
def visit_ListComp(self, node): """Generate a curried lambda function [x + y for x, y in [[1, 4], [2, 5], [3, 6]]] becomes [[1, 4], [2, 5], [3, 6]]].map(([x, y]) => x + y) """ try: generator, = node.generators except ValueError: raise NotImplementedError( 'Only single loop comprehensions are allowed' ) names = find_names(generator.target) argslist = [ast.arg(arg=name.id, annotation=None) for name in names] if len(names) <= 1: signature = ast.arguments( args=argslist, vararg=None, kwonlyargs=[], kw_defaults=[], kwarg=None, defaults=[], ) else: signature = ast.List(elts=argslist, ctx=ast.Load()) array = generator.iter lam_sig = functools.partial(ast.Lambda, args=signature) filters = generator.ifs if filters: filt = ast.BoolOp(op=ast.And(), values=filters) # array.filter method = ast.Attribute(value=array, attr='filter', ctx=ast.Load()) # array.filter(func) array = ast.Call( func=method, args=[lam_sig(body=filt)], keywords=[] ) method = ast.Attribute(value=array, attr='map', ctx=ast.Load()) mapped = ast.Call( func=method, args=[lam_sig(body=node.elt)], keywords=[] ) result = self.visit(mapped) return result