class_docstr: Gather aliasing informations across nodes
  
  As a result, each node from the module is associated to a set of node or
  Intrinsic to which it *may* alias to.
class_docstr_tok: ["Gather","aliasing","informations","across","nodes","As","a","result",",","each","node","from","the","module","is","associated","to","a","set","of","node","or","Intrinsic","to","which","it","*","may","*","alias","to","."]
docstr: Resulting node alias to the return_alias of called function,
  if the function is already known by Pythran (i.e. it's an Intrinsic)
  or if Pythran already computed it's ``return_alias`` behavior.
  
  >>> from pythran import passmanager
  >>> pm = passmanager.PassManager('demo')
  >>> fun = """
  ... def f(a): return a
  ... def foo(b): c = f(b)"""
  >>> module = ast.parse(fun)
  
  The ``f`` function create aliasing between
  the returned value and its first argument.
  
  >>> result = pm.gather(Aliases, module)
  >>> Aliases.dump(result, filter=ast.Call)
  f(b) => ['b']
  
  This also works with intrinsics, e.g ``dict.setdefault`` which
  may create alias between its third argument and the return value.
  
  >>> fun = 'def foo(a, d): builtins.dict.setdefault(d, 0, a)'
  >>> module = ast.parse(fun)
  >>> result = pm.gather(Aliases, module)
  >>> Aliases.dump(result, filter=ast.Call)
  builtins.dict.setdefault(d, 0, a) => ['<unbound-value>', 'a']
  
  Note that complex cases can arise, when one of the formal parameter
  is already known to alias to various values:
  
  >>> fun = """
  ... def f(a, b): return a and b
  ... def foo(A, B, C, D): return f(A or B, C or D)"""
  >>> module = ast.parse(fun)
  >>> result = pm.gather(Aliases, module)
  >>> Aliases.dump(result, filter=ast.Call)
  f((A or B), (C or D)) => ['A', 'B', 'C', 'D']
docstr_tok: ["Resulting","node","alias","to","the","return_alias","of","called","function",",","if","the","function","is","already","known","by","Pythran","(","i.e",".","it","'s","an","Intrinsic",")","or","if","Pythran","already","computed","it","'s","``","return_alias","``","behavior",".",">",">",">","from","pythran","import","passmanager",">",">",">","pm","=","passmanager.PassManager","(","'demo","'",")",">",">",">","fun","=","``","''","''","...","def","f","(","a",")",":","return","a","...","def","foo","(","b",")",":","c","=","f","(","b",")","''","''","''",">",">",">","module","=","ast.parse","(","fun",")","The","``","f","``","function","create","aliasing","between","the","returned","value","and","its","first","argument",".",">",">",">","result","=","pm.gather","(","Aliases",",","module",")",">",">",">","Aliases.dump","(","result",",","filter=ast.Call",")","f","(","b",")","=",">","[","'","b","'","]","This","also","works","with","intrinsics",",","e.g","``","dict.setdefault","``","which","may","create","alias","between","its","third","argument","and","the","return","value",".",">",">",">","fun","=","'def","foo","(","a",",","d",")",":","builtins.dict.setdefault","(","d",",","0",",","a",")","'",">",">",">","module","=","ast.parse","(","fun",")",">",">",">","result","=","pm.gather","(","Aliases",",","module",")",">",">",">","Aliases.dump","(","result",",","filter=ast.Call",")","builtins.dict.setdefault","(","d",",","0",",","a",")","=",">","[","'","<","unbound-value",">","'",",","'","a","'","]","Note","that","complex","cases","can","arise",",","when","one","of","the","formal","parameter","is","already","known","to","alias","to","various","values",":",">",">",">","fun","=","``","''","''","...","def","f","(","a",",","b",")",":","return","a","and","b","...","def","foo","(","A",",","B",",","C",",","D",")",":","return","f","(","A","or","B",",","C","or","D",")","''","''","''",">",">",">","module","=","ast.parse","(","fun",")",">",">",">","result","=","pm.gather","(","Aliases",",","module",")",">",">",">","Aliases.dump","(","result",",","filter=ast.Call",")","f","(","(","A","or","B",")",",","(","C","or","D",")",")","=",">","[","'","A","'",",","'","B","'",",","'","C","'",",","'D","'","]"]
code: def visit_Call(self, node):
      '''
      Resulting node alias to the return_alias of called function,
      if the function is already known by Pythran (i.e. it's an Intrinsic)
      or if Pythran already computed it's ``return_alias`` behavior.
  
      >>> from pythran import passmanager
      >>> pm = passmanager.PassManager('demo')
      >>> fun = """
      ... def f(a): return a
      ... def foo(b): c = f(b)"""
      >>> module = ast.parse(fun)
  
      The ``f`` function create aliasing between
      the returned value and its first argument.
  
      >>> result = pm.gather(Aliases, module)
      >>> Aliases.dump(result, filter=ast.Call)
      f(b) => ['b']
  
      This also works with intrinsics, e.g ``dict.setdefault`` which
      may create alias between its third argument and the return value.
  
      >>> fun = 'def foo(a, d): builtins.dict.setdefault(d, 0, a)'
      >>> module = ast.parse(fun)
      >>> result = pm.gather(Aliases, module)
      >>> Aliases.dump(result, filter=ast.Call)
      builtins.dict.setdefault(d, 0, a) => ['<unbound-value>', 'a']
  
      Note that complex cases can arise, when one of the formal parameter
      is already known to alias to various values:
  
      >>> fun = """
      ... def f(a, b): return a and b
      ... def foo(A, B, C, D): return f(A or B, C or D)"""
      >>> module = ast.parse(fun)
      >>> result = pm.gather(Aliases, module)
      >>> Aliases.dump(result, filter=ast.Call)
      f((A or B), (C or D)) => ['A', 'B', 'C', 'D']
      '''
      self.generic_visit(node)
      f = node.func
      # special handler for bind functions
      if isinstance(f, ast.Attribute) and f.attr == "partial":
          return self.add(node, {node})
      else:
          return_alias = self.call_return_alias(node)
          # expand collected aliases
          all_aliases = set()
          for value in return_alias:
              # no translation
              if isinstance(
                  value, (ContainerOf, ast.FunctionDef, Intrinsic)
              ):
                  all_aliases.add(value)
              elif value in self.result:
                  all_aliases.update(self.result[value])
              else:
                  try:
                      ap = Aliases.access_path(value)
                      all_aliases.update(self.aliases.get(ap, ()))
                  except NotImplementedError:
                      # should we do something better here?
                      all_aliases.add(value)
          return self.add(node, all_aliases)
  
imports: from pythran.analyses.global_declarations import GlobalDeclarations
  from pythran.intrinsic import Intrinsic, Class, UnboundValue
  from pythran.passmanager import ModuleAnalysis
  from pythran.tables import functions, methods, MODULES
  from pythran.unparse import Unparser
  from pythran.conversion import demangle
  import pythran.metadata
  from pythran.utils import isnum
  from pythran.syntax import PythranSyntaxError
  import gast
  from copy import deepcopy
  from itertools import product
  import io
label_desc: Use image node_id 13 for calling the Aliases obj's underlying member method code with example usage: obj.visit_Call(node) and returns: self, self