%PDF- %PDF-
Direktori : /lib/python3/dist-packages/pythran/transformations/ |
Current File : //lib/python3/dist-packages/pythran/transformations/normalize_is_none.py |
""" NormalizeIsNone detects is None patterns. """ from pythran.passmanager import Transformation from pythran.analyses import Ancestors from pythran.syntax import PythranSyntaxError from functools import reduce import gast as ast def is_none(expr): # py3 if isinstance(expr, ast.Constant) and expr.value is None: return True # py2 if not isinstance(expr, ast.Attribute): return False return expr.attr == "None" def is_is_none(expr): if not isinstance(expr, ast.Compare): return None if len(expr.ops) != 1: exprs = [expr.left] + expr.comparators if any(is_none(expr) for expr in exprs): raise PythranSyntaxError("is None in complex condition", expr) return None if not isinstance(expr.ops[0], (ast.Eq, ast.Is)): return None if is_none(expr.left): return expr.comparators[0] if is_none(expr.comparators[0]): return expr.left return None def is_is_not_none(expr): if not isinstance(expr, ast.Compare): return None if len(expr.ops) != 1: exprs = [expr.left] + expr.comparators if any(is_none(expr) for expr in exprs): raise PythranSyntaxError("is None in complex condition", expr) return None if not isinstance(expr.ops[0], (ast.NotEq, ast.IsNot)): return None if is_none(expr.left): return expr.comparators[0] if is_none(expr.comparators[0]): return expr.left return None class NormalizeIsNone(Transformation): table = {ast.And: ast.BitAnd, ast.Or: ast.BitOr} def __init__(self): super(NormalizeIsNone, self).__init__(Ancestors) @staticmethod def match_is_none(node): noned_var = is_is_none(node) if noned_var is None: noned_var = is_is_not_none(node) negated = noned_var is not None else: negated = False return noned_var, negated def visit_BoolOp(self, node): values = list(node.values) self.generic_visit(node) if any(x != y for x, y in zip(values, node.values)): self.update = True expr = reduce(lambda x, y: ast.BinOp(x, NormalizeIsNone.table[type(node.op)](), y), node.values) return expr else: return node def visit_Compare(self, node): self.generic_visit(node) noned_var, negated = self.match_is_none(node) if noned_var is None: return node call = ast.Call( ast.Attribute( ast.Attribute( ast.Name('builtins', ast.Load(), None, None), 'pythran', ast.Load() ), 'is_none', ast.Load()), [noned_var], []) self.update = True if negated: return ast.UnaryOp(ast.Not(), call) else: return call