text: # Copyright Bruno da Silva de Oliveira 2003. Use, modification and 
  # distribution is subject to the Boost Software License, Version 1.0.
  # (See accompanying file LICENSE_1_0.txt or copy at 
  # http://www.boost.org/LICENSE_1_0.txt)
  
  from Exporter import Exporter
  from policies import *
  from declarations import *
  from settings import *
  import utils
  import exporterutils
  
  
  #==============================================================================
  # FunctionExporter
  #==============================================================================
  class FunctionExporter(Exporter):
      'Generates boost.python code to export the given function.'
      
      def __init__(self, info, tail=None):
          Exporter.__init__(self, info, tail)
          
  
      def Export(self, codeunit, exported_names):
          if not self.info.exclude:
              decls = self.GetDeclarations(self.info.name)
              for decl in decls:
                  self.info.policy = exporterutils.HandlePolicy(decl, self.info.policy)
                  self.ExportDeclaration(decl, len(decls) == 1, codeunit)
                  self.ExportOpaquePointer(decl, codeunit)
              self.GenerateOverloads(decls, codeunit)  
              exported_names[self.Name()] = 1
  
  
      def ExportDeclaration(self, decl, unique, codeunit):
          name = self.info.rename or decl.name
          defs = namespaces.python + 'def("%s", ' % name
          wrapper = self.info.wrapper
          if wrapper:
              pointer = '&' + wrapper.FullName()
          else:
              pointer = decl.PointerDeclaration()
          defs += pointer            
          defs += self.PolicyCode()                            
          overload = self.OverloadName(decl)
          if overload:
              defs += ', %s()' % (namespaces.pyste + overload)
          defs += ');'
          codeunit.Write('module', self.INDENT + defs + '\n')  
          # add the code of the wrapper
          if wrapper and wrapper.code:
              codeunit.Write('declaration', wrapper.code + '\n')
              
  
      def OverloadName(self, decl):
          if decl.minArgs != decl.maxArgs:
              return '%s_overloads_%i_%i' % \
                  (decl.name, decl.minArgs, decl.maxArgs)
          else:
              return ''
  
          
      def GenerateOverloads(self, declarations, codeunit):
          codes = {}
          for decl in declarations:
              overload = self.OverloadName(decl)
              if overload and overload not in codes:
                  code = 'BOOST_PYTHON_FUNCTION_OVERLOADS(%s, %s, %i, %i)' %\
                      (overload, decl.FullName(), decl.minArgs, decl.maxArgs)
                  codeunit.Write('declaration', code + '\n')
                  codes[overload] = None
          
  
      def PolicyCode(self):
          policy = self.info.policy
          if policy is not None:
              assert isinstance(policy, Policy)
              return ', %s()' % policy.Code() 
          else:
              return ''
  
  
      def ExportOpaquePointer(self, function, codeunit):
          if self.info.policy == return_value_policy(return_opaque_pointer):
              typename = function.result.name
              macro = exporterutils.EspecializeTypeID(typename)  
              if macro:
                  codeunit.Write('declaration-outside', macro)
  
  
      def Name(self):
          return self.info.name
  