class_docstr: This node replaces a function with fused arguments. It deep-copies the
  function for every permutation of fused types, and allocates a new local
  scope for it. It keeps track of the original function in self.node, and
  the entry of the original function in the symbol table is given the
  'fused_cfunction' attribute which points back to us.
  Then when a function lookup occurs (to e.g. call it), the call can be
  dispatched to the right function.
  
  node    FuncDefNode    the original function
  nodes   [FuncDefNode]  list of copies of node with different specific types
  py_func DefNode        the fused python function subscriptable from
                         Python space
  __signatures__         A DictNode mapping signature specialization strings
                         to PyCFunction nodes
  resulting_fused_function  PyCFunction for the fused DefNode that delegates
                            to specializations
  fused_func_assignment   Assignment of the fused function to the function name
  defaults_tuple          TupleNode of defaults (letting PyCFunctionNode build
                          defaults would result in many different tuples)
  specialized_pycfuncs    List of synthesized pycfunction nodes for the
                          specializations
  code_object             CodeObjectNode shared by all specializations and the
                          fused function
  
  fused_compound_types    All fused (compound) types (e.g. floating[:])
class_docstr_tok: ["This","node","replaces","a","function","with","fused","arguments",".","It","deep-copies","the","function","for","every","permutation","of","fused","types",",","and","allocates","a","new","local","scope","for","it",".","It","keeps","track","of","the","original","function","in","self.node",",","and","the","entry","of","the","original","function","in","the","symbol","table","is","given","the","'fused_cfunction","'","attribute","which","points","back","to","us",".","Then","when","a","function","lookup","occurs","(","to","e.g",".","call","it",")",",","the","call","can","be","dispatched","to","the","right","function",".","node","FuncDefNode","the","original","function","nodes","[","FuncDefNode","]","list","of","copies","of","node","with","different","specific","types","py_func","DefNode","the","fused","python","function","subscriptable","from","Python","space","__signatures__","A","DictNode","mapping","signature","specialization","strings","to","PyCFunction","nodes","resulting_fused_function","PyCFunction","for","the","fused","DefNode","that","delegates","to","specializations","fused_func_assignment","Assignment","of","the","fused","function","to","the","function","name","defaults_tuple","TupleNode","of","defaults","(","letting","PyCFunctionNode","build","defaults","would","result","in","many","different","tuples",")","specialized_pycfuncs","List","of","synthesized","pycfunction","nodes","for","the","specializations","code_object","CodeObjectNode","shared","by","all","specializations","and","the","fused","function","fused_compound_types","All","fused","(","compound",")","types","(","e.g",".","floating","[",":","]",")"]
docstr: This creates the function that is indexable from Python and does
  runtime dispatch based on the argument types. The function gets the
  arg tuple and kwargs dict (or None) and the defaults tuple
  as arguments from the Binding Fused Function's tp_call.
docstr_tok: ["This","creates","the","function","that","is","indexable","from","Python","and","does","runtime","dispatch","based","on","the","argument","types",".","The","function","gets","the","arg","tuple","and","kwargs","dict","(","or","None",")","and","the","defaults","tuple","as","arguments","from","the","Binding","Fused","Function","'s","tp_call","."]
code: def make_fused_cpdef(self, orig_py_func, env, is_def):
      """
      This creates the function that is indexable from Python and does
      runtime dispatch based on the argument types. The function gets the
      arg tuple and kwargs dict (or None) and the defaults tuple
      as arguments from the Binding Fused Function's tp_call.
      """
      from . import TreeFragment, Code, UtilityCode
  
      fused_types = self._get_fused_base_types(
          [arg.type for arg in self.node.args if arg.type.is_fused]
      )
  
      context = {
          "memviewslice_cname": MemoryView.memviewslice_cname,
          "func_args": self.node.args,
          "n_fused": len(fused_types),
          "min_positional_args": self.node.num_required_args
          - self.node.num_required_kw_args
          if is_def
          else sum(1 for arg in self.node.args if arg.default is None),
          "name": orig_py_func.entry.name,
      }
  
      pyx_code = Code.PyxCodeWriter(context=context)
      decl_code = Code.PyxCodeWriter(context=context)
      decl_code.put_chunk(
          """
                  cdef extern from *:
                      void __pyx_PyErr_Clear "PyErr_Clear" ()
                      type __Pyx_ImportNumPyArrayTypeIfAvailable()
                      int __Pyx_Is_Little_Endian()
              """
      )
      decl_code.indent()
  
      pyx_code.put_chunk(
          """
                  def __pyx_fused_cpdef(signatures, args, kwargs, defaults):
                      # FIXME: use a typed signature - currently fails badly because
                      #        default arguments inherit the types we specify here!
  
                      dest_sig = [None] * {{n_fused}}
  
                      if kwargs is not None and not kwargs:
                          kwargs = None
  
                      cdef Py_ssize_t i
  
                      # instance check body
              """
      )
  
      pyx_code.indent()  # indent following code to function body
      pyx_code.named_insertion_point("imports")
      pyx_code.named_insertion_point("func_defs")
      pyx_code.named_insertion_point("local_variable_declarations")
  
      fused_index = 0
      default_idx = 0
      all_buffer_types = OrderedSet()
      seen_fused_types = set()
      for i, arg in enumerate(self.node.args):
          if arg.type.is_fused:
              arg_fused_types = arg.type.get_fused_types()
              if len(arg_fused_types) > 1:
                  raise NotImplementedError(
                      "Determination of more than one fused base "
                      "type per argument is not implemented."
                  )
              fused_type = arg_fused_types[0]
  
          if arg.type.is_fused and fused_type not in seen_fused_types:
              seen_fused_types.add(fused_type)
  
              context.update(
                  arg_tuple_idx=i,
                  arg=arg,
                  dest_sig_idx=fused_index,
                  default_idx=default_idx,
              )
  
              (
                  normal_types,
                  buffer_types,
                  pythran_types,
                  has_object_fallback,
              ) = self._split_fused_types(arg)
              self._unpack_argument(pyx_code)
  
              # 'unrolled' loop, first match breaks out of it
              if pyx_code.indenter("while 1:"):
                  if normal_types:
                      self._fused_instance_checks(
                          normal_types, pyx_code, env
                      )
                  if buffer_types or pythran_types:
                      env.use_utility_code(
                          Code.UtilityCode.load_cached(
                              "IsLittleEndian", "ModuleSetupCode.c"
                          )
                      )
                      self._buffer_checks(
                          buffer_types,
                          pythran_types,
                          pyx_code,
                          decl_code,
                          env,
                      )
                  if has_object_fallback:
                      pyx_code.context.update(
                          specialized_type_name="object"
                      )
                      pyx_code.putln(self.match)
                  else:
                      pyx_code.putln(self.no_match)
                  pyx_code.putln("break")
                  pyx_code.dedent()
  
              fused_index += 1
              all_buffer_types.update(buffer_types)
              all_buffer_types.update(
                  ty.org_buffer for ty in pythran_types
              )
  
          if arg.default:
              default_idx += 1
  
      if all_buffer_types:
          self._buffer_declarations(
              pyx_code, decl_code, all_buffer_types, pythran_types
          )
          env.use_utility_code(
              Code.UtilityCode.load_cached("Import", "ImportExport.c")
          )
          env.use_utility_code(
              Code.UtilityCode.load_cached(
                  "ImportNumPyArray", "ImportExport.c"
              )
          )
  
      pyx_code.put_chunk(
          """
                  candidates = []
                  for sig in <dict>signatures:
                      match_found = False
                      src_sig = sig.strip('()').split('|')
                      for i in range(len(dest_sig)):
                          dst_type = dest_sig[i]
                          if dst_type is not None:
                              if src_sig[i] == dst_type:
                                  match_found = True
                              else:
                                  match_found = False
                                  break
  
                      if match_found:
                          candidates.append(sig)
  
                  if not candidates:
                      raise TypeError("No matching signature found")
                  elif len(candidates) > 1:
                      raise TypeError("Function call with ambiguous argument types")
                  else:
                      return (<dict>signatures)[candidates[0]]
              """
      )
  
      fragment_code = pyx_code.getvalue()
      # print decl_code.getvalue()
      # print fragment_code
      from .Optimize import ConstantFolding
  
      fragment = TreeFragment.TreeFragment(
          fragment_code, level="module", pipeline=[ConstantFolding()]
      )
      ast = TreeFragment.SetPosTransform(self.node.pos)(fragment.root)
      UtilityCode.declare_declarations_in_scope(
          decl_code.getvalue(), env.global_scope()
      )
      ast.scope = env
      # FIXME: for static methods of cdef classes, we build the wrong signature here: first arg becomes 'self'
      ast.analyse_declarations(env)
      py_func = ast.stats[-1]  # the DefNode
      self.fragment_scope = ast.scope
  
      if isinstance(self.node, DefNode):
          py_func.specialized_cpdefs = self.nodes[:]
      else:
          py_func.specialized_cpdefs = [n.py_func for n in self.nodes]
  
      return py_func
  
imports: from __future__ import absolute_import
  import copy
  from .None import ExprNodes, PyrexTypes, MemoryView, ParseTreeTransforms, StringEncoding, Errors
  from .ExprNodes import CloneNode, ProxyNode, TupleNode
  from .Nodes import FuncDefNode, CFuncDefNode, StatListNode, DefNode
  from ..Utils import OrderedSet
label_desc: Use image node_id 20 for calling the FusedCFuncDefNode obj's underlying member method code with example usage: obj.make_fused_cpdef(orig_py_func, env, is_def) and returns: py_func