class_docstr: This analyse extract positive subscripts from code.
  
  It is flow sensitive and aliasing is not taken into account as integer
  doesn't create aliasing in Python.
  
  >>> import gast as ast
  >>> from pythran import passmanager, backend
  >>> node = ast.parse('''
  ... def foo(a):
  ...     for i in builtins.range(1, 10):
  ...         c = i // 2
  ...     return''')
  >>> pm = passmanager.PassManager("test")
  >>> res = pm.gather(RangeValues, node)
  >>> res['c'], res['i']
  (Interval(low=0, high=5), Interval(low=1, high=10))
class_docstr_tok: ["This","analyse","extract","positive","subscripts","from","code",".","It","is","flow","sensitive","and","aliasing","is","not","taken","into","account","as","integer","does","n't","create","aliasing","in","Python",".",">",">",">","import","gast","as","ast",">",">",">","from","pythran","import","passmanager",",","backend",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","for","i","in","builtins.range","(","1",",","10",")",":","...","c","=","i","\/\/","2","...","return","''","'",")",">",">",">","pm","=","passmanager.PassManager","(","``","test","''",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","c","'","]",",","res","[","'","i","'","]","(","Interval","(","low=0",",","high=5",")",",","Interval","(","low=1",",","high=10",")",")"]
docstr: Handle iterate variable across branches
  
  >>> import gast as ast
  >>> from pythran import passmanager, backend
  >>> pm = passmanager.PassManager("test")
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if a > 1: b = 1
  ...     else: b = 3
  ...     pass''')
  
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=1, high=3)
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if a > 1: b = a
  ...     else: b = 3
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=2, high=inf)
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if 0 < a < 4: b = a
  ...     else: b = 3
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=1, high=3)
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if (0 < a) and (a < 4): b = a
  ...     else: b = 3
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=1, high=3)
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if (a == 1) or (a == 2): b = a
  ...     else: b = 3
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=1, high=3)
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     b = 5
  ...     if a > 0: b = a
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['a'], res['b']
  (Interval(low=-inf, high=inf), Interval(low=1, high=inf))
  
  >>> node = ast.parse('''
  ... def foo(a):
  ...     if a > 3: b = 1
  ...     else: b = 2
  ...     if a > 1: b = 2
  ...     pass''')
  >>> res = pm.gather(RangeValues, node)
  >>> res['b']
  Interval(low=2, high=2)
docstr_tok: ["Handle","iterate","variable","across","branches",">",">",">","import","gast","as","ast",">",">",">","from","pythran","import","passmanager",",","backend",">",">",">","pm","=","passmanager.PassManager","(","``","test","''",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","a",">","1",":","b","=","1","...","else",":","b","=","3","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=1",",","high=3",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","a",">","1",":","b","=","a","...","else",":","b","=","3","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=2",",","high=inf",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","0","<","a","<","4",":","b","=","a","...","else",":","b","=","3","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=1",",","high=3",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","(","0","<","a",")","and","(","a","<","4",")",":","b","=","a","...","else",":","b","=","3","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=1",",","high=3",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","(","a","==","1",")","or","(","a","==","2",")",":","b","=","a","...","else",":","b","=","3","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=1",",","high=3",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","b","=","5","...","if","a",">","0",":","b","=","a","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","a","'","]",",","res","[","'","b","'","]","(","Interval","(","low=-inf",",","high=inf",")",",","Interval","(","low=1",",","high=inf",")",")",">",">",">","node","=","ast.parse","(","``","'","...","def","foo","(","a",")",":","...","if","a",">","3",":","b","=","1","...","else",":","b","=","2","...","if","a",">","1",":","b","=","2","...","pass","''","'",")",">",">",">","res","=","pm.gather","(","RangeValues",",","node",")",">",">",">","res","[","'","b","'","]","Interval","(","low=2",",","high=2",")"]
code: def visit_If(self, node):
      """Handle iterate variable across branches
  
      >>> import gast as ast
      >>> from pythran import passmanager, backend
      >>> pm = passmanager.PassManager("test")
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if a > 1: b = 1
      ...     else: b = 3
      ...     pass''')
  
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=1, high=3)
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if a > 1: b = a
      ...     else: b = 3
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=2, high=inf)
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if 0 < a < 4: b = a
      ...     else: b = 3
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=1, high=3)
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if (0 < a) and (a < 4): b = a
      ...     else: b = 3
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=1, high=3)
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if (a == 1) or (a == 2): b = a
      ...     else: b = 3
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=1, high=3)
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     b = 5
      ...     if a > 0: b = a
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['a'], res['b']
      (Interval(low=-inf, high=inf), Interval(low=1, high=inf))
  
      >>> node = ast.parse('''
      ... def foo(a):
      ...     if a > 3: b = 1
      ...     else: b = 2
      ...     if a > 1: b = 2
      ...     pass''')
      >>> res = pm.gather(RangeValues, node)
      >>> res['b']
      Interval(low=2, high=2)
      """
      # handling each branch becomes too costly, opt for a simpler,
      # less accurate algorithm.
      if self.no_if_split == 4:
          raise RangeValueTooCostly()
  
      self.no_if_split += 1
  
      test_range = self.visit(node.test)
      init_state = self.result.copy()
  
      if 1 in test_range:
          bound_range(self.result, self.aliases, node.test)
          self.cfg_visit(node.body[0])
  
      visited_successors = {node.body[0]}
  
      if node.orelse:
          if 0 in test_range:
              prev_state = self.result
              self.result = init_state.copy()
              bound_range(
                  self.result,
                  self.aliases,
                  ast.UnaryOp(ast.Not(), node.test),
              )
              self.cfg_visit(node.orelse[0])
              self.unionify(prev_state)
          visited_successors.add(node.orelse[0])
  
      elif 0 in test_range:
          successors = self.cfg.successors(node)
          for successor in list(successors):
              # no else branch
              if successor not in visited_successors:
                  self.result, prev_state = (
                      init_state.copy(),
                      self.result,
                  )
                  bound_range(
                      self.result,
                      self.aliases,
                      ast.UnaryOp(ast.Not(), node.test),
                  )
                  self.cfg_visit(successor)
                  self.unionify(prev_state)
  
      self.no_if_split -= 1
  
imports: import gast
  from collections import defaultdict
  from functools import reduce
  from pythran.analyses import Aliases, CFG
  from pythran.intrinsic import Intrinsic
  from pythran.passmanager import ModuleAnalysis
  from pythran.interval import Interval, IntervalTuple, UNKNOWN_RANGE
  from pythran.tables import MODULES, attributes
label_desc: Use image node_id 14 for calling the RangeValues obj's underlying member method code with example usage: obj.visit_If(node) without return types