class_docstr: Gathers inter-procedural effects on function arguments.
class_docstr_tok: ["Gathers","inter-procedural","effects","on","function","arguments","."]
code: def visit_Call(self, node):
      for i, arg in enumerate(node.args):
          n = self.argument_index(arg)
          if n >= 0:
              func_aliases = self.aliases[node.func]
  
              # pessimistic case: no alias found
              if func_aliases is None:
                  self.current_function.update_effects[n] = True
                  continue
  
              # expand argument if any
              func_aliases = reduce(
                  lambda x, y: x
                  + (
                      # all functions
                      list(self.node_to_functioneffect.keys())
                      if (
                          isinstance(y, ast.Name)
                          and self.argument_index(y) >= 0
                      )
                      else [y]
                  ),
                  func_aliases,
                  list(),
              )
  
              for func_alias in func_aliases:
                  # special hook for binded functions
                  if isinstance(func_alias, ast.Call):
                      bound_name = func_alias.args[0].id
                      func_alias = self.global_declarations[bound_name]
                  if func_alias is intrinsic.UnboundValue:
                      continue
  
                  if func_alias not in self.node_to_functioneffect:
                      continue
  
                  if func_alias is MODULES["functools"]["partial"]:
                      base_func_aliases = self.aliases[node.args[0]]
                      fe = self.node_to_functioneffect[func_alias]
                      if len(base_func_aliases) == 1:
                          base_func_alias = next(
                              iter(base_func_aliases)
                          )
                          fe = self.node_to_functioneffect.get(
                              base_func_alias, fe
                          )
                  else:
                      fe = self.node_to_functioneffect[func_alias]
  
                  if not self.result.has_edge(
                      fe, self.current_function
                  ):
                      self.result.add_edge(
                          fe,
                          self.current_function,
                          effective_parameters=[],
                          formal_parameters=[],
                      )
                  edge = self.result.edges[fe, self.current_function]
                  edge["effective_parameters"].append(n)
                  edge["formal_parameters"].append(i)
      self.generic_visit(node)
  
imports: from pythran.analyses.aliases import Aliases
  from pythran.analyses.intrinsics import Intrinsics
  from pythran.analyses.global_declarations import GlobalDeclarations
  from pythran.passmanager import ModuleAnalysis
  from pythran.tables import MODULES
  from pythran.graph import DiGraph
  from pythran import intrinsic
  import gast
  from functools import reduce
label_desc: Use image node_id 9 for calling the ArgumentEffects obj's underlying member method code with example usage: obj.visit_Call(node) without return types