text: #
  # Array copy transformation
  #
  
  import sys
  import orio.module.loop.submodule.submodule
  from orio.module.loop.submodule.arrcopy import transformation
  from orio.main.util.globals import *
  from functools import reduce
  
  #---------------------------------------------------------------------
  
  class ArrCopy(orio.module.loop.submodule.submodule.SubModule):
      '''The array copy transformation submodule.'''
      
      def __init__(self, perf_params = None, transf_args = None, stmt = None, language='C'):
          '''Instantiate an array copy transformation submodule.'''
          
          orio.module.loop.submodule.submodule.SubModule.__init__(self, perf_params, transf_args, stmt, language)
  
      #-----------------------------------------------------------------
      
      def readTransfArgs(self, perf_params, transf_args):
          '''Process the given transformation arguments'''
  
          # all expected argument names
          AREF = 'aref'
          SUFFIX = 'suffix'
          DTYPE = 'dtype'
          DIMS = 'dimsizes'
          
          # all expected transformation arguments
          aref = None
          suffix = None
          dtype = None
          dimsizes = None
  
          # iterate over all transformation arguments
          for aname, rhs, line_no in transf_args:
              debug('arrcopy.readTransfArgs: aname, rhs, lineno=%s,%s,%s' % (aname,rhs,line_no))
              # evaluate the RHS expression
              try:
                  rhs = eval(rhs, perf_params)
              except Exception as e:
                  err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                      'failed to evaluate the argument expression: %s\n --> %s: %s' % \
                      (str(line_no), str(rhs), str(e.__class__.__name__), str(e)) )
  
              # array reference
              if aname == AREF:
                  aref = (rhs, line_no)
  
              # suffix for the array buffer name
              elif aname == SUFFIX:
                  suffix = (rhs, line_no)
  
              # array elements' data type
              elif aname == DTYPE:
                  dtype = (rhs, line_no)
  
              # array dimension sizes
              elif aname == DIMS:
                  dimsizes = (rhs, line_no)
  
              # unknown argument name
              else:
                  err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                      'unrecognized transformation argument: "%s"' % (line_no, aname))
  
          # check for undefined transformation arguments
          if aref == None:
              err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                  'missing array reference argument' % self.__class__.__name__)
          if dimsizes == None:
              err('orio.module.loop.submodule.arrcopy.arrcopy: %s: missing array dimension sizes argument' % self.__class__.__name__)
  
          # check semantics of the transformation arguments
          (aref, suffix, dtype, dimsizes) = self.checkTransfArgs(aref, suffix, dtype, dimsizes)
  
          # return information about the transformation arguments
          return (aref, suffix, dtype, dimsizes)
  
      #-----------------------------------------------------------------
  
      def checkTransfArgs(self, aref, suffix, dtype, dimsizes):
          '''Check the semantics of the given transformation arguments'''
  
          # evaluate the array reference
          rhs, line_no = aref
          if not isinstance(rhs, str):
              err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                  'array reference argument must be a string: %s' % (line_no, rhs))
          aref = rhs
  
          # evaluate the suffix of the array buffer name
          if suffix != None:
              rhs, line_no = suffix
              if rhs != None and not isinstance(rhs, str):
                  err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                      'suffix argument must be a string: %s' % (line_no, rhs))
              suffix = rhs
  
          # evaluate the data type of the array elements
          if dtype != None:
              rhs, line_no = dtype
              if rhs != None and not isinstance(rhs, str):
                  err('orio.module.loop.submodule.arrcopy.arrcopy: %s: ' + \
                      'data type argument must be a string: %s' % (line_no, rhs))
              dtype = rhs
  
          # evaluate the data type of the array elements
          rhs, line_no = dimsizes
          if ((not isinstance(rhs, list) and not isinstance(rhs, tuple)) or
              not reduce(lambda x,y: x and y, [isinstance(x, int) for x in rhs], True) or 
              not reduce(lambda x,y: x and y, [x > 0 for x in rhs], True)):
              err(('orio.module.loop.submodule.arrcopy.arrcopy:%s: ' + \
                   'array dimension sizes argument must be a list of positive ' +
                     'integers: %s') % (line_no, rhs))
          dimsizes = rhs
              
          # return information about the transformation arguments
          return (aref, suffix, dtype, dimsizes)
  
      #-----------------------------------------------------------------
  
      def optimizeArrayCopy(self, aref, suffix, dtype, dimsizes, stmt):
          '''To apply array copy optimization'''
  
          # perform the bound replacement transformation
          t = transformation.Transformation(aref, suffix, dtype, dimsizes, stmt)
          transformed_stmt = t.transform()
          
          # return the transformed statement
          return transformed_stmt
      
      #-----------------------------------------------------------------
  
      def transform(self):
          '''To perform code transformations'''
  
          # read all transformation arguments
          aref, suffix, dtype, dimsizes = self.readTransfArgs(self.perf_params, self.transf_args)
  
          # perform the bound replacement transformation
          transformed_stmt = self.optimizeArrayCopy(aref, suffix, dtype, dimsizes, self.stmt)
  
          # return the transformed statement
          return transformed_stmt
  
  
  
      
  