--
-- Copyright (c) 2009-2010, ERICSSON AB All rights reserved.
-- 
-- Redistribution and use in source and binary forms, with or without
-- modification, are permitted provided that the following conditions are met:
-- 
--     * Redistributions of source code must retain the above copyright notice,
--       this list of conditions and the following disclaimer.
--     * Redistributions in binary form must reproduce the above copyright
--       notice, this list of conditions and the following disclaimer in the
--       documentation and/or other materials provided with the distribution.
--     * Neither the name of the ERICSSON AB nor the names of its contributors
--       may be used to endorse or promote products derived from this software
--       without specific prior written permission.
-- 
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
-- BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
-- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
-- THE POSSIBILITY OF SUCH DAMAGE.
--

{-# LANGUAGE UndecidableInstances, MultiParamTypeClasses, FlexibleContexts, FlexibleInstances #-}

module Feldspar.Compiler.PluginArchitecture.DefaultConvert where

import Feldspar.Compiler.Imperative.Semantics
-- ===========================================================================
--  == Defaults
-- ===========================================================================

class Default t where
    defaultValue :: t
    defaultValue = error "Default value requested."

class Combine t where
    combine :: t -> t -> t
    combine = error "Default combination function used."

instance Default Int where
    defaultValue = 0
instance Combine Int where
    combine = (+)

instance Default Bool where
    defaultValue = False

instance Default () where
    defaultValue = ()
instance Combine () where
    combine _ _ = ()

instance (Default a, Default b) => Default (a,b) where
    defaultValue = (defaultValue, defaultValue)

class Convert a b where
    convert :: a -> b

instance Default b => Convert a b where
    convert _ = defaultValue

-- ====================================================================================================
--   == ConvertAllInfos class & instance
-- ====================================================================================================
class (SemanticInfo from, SemanticInfo to
      , Convert(ProcedureInfo from)           (ProcedureInfo to)
      , Convert(BlockInfo from)               (BlockInfo to)
      , Convert(ProgramInfo from)             (ProgramInfo to)
      , Convert(EmptyInfo from)               (EmptyInfo to)
      , Convert(PrimitiveInfo from)           (PrimitiveInfo to)
      , Convert(SequenceInfo from)            (SequenceInfo to)
      , Convert(BranchInfo from)              (BranchInfo to)
      , Convert(SequentialLoopInfo from)      (SequentialLoopInfo to)
      , Convert(ParallelLoopInfo from)        (ParallelLoopInfo to)
      , Convert(FormalParameterInfo from)     (FormalParameterInfo to)
      , Convert(LocalDeclarationInfo from)    (LocalDeclarationInfo to)
      , Convert(ExpressionInfo from)          (ExpressionInfo to)
      , Convert(ConstantInfo from)            (ConstantInfo to)
      , Convert(FunctionCallInfo from)        (FunctionCallInfo to)
      , Convert(LeftValueInfo from)           (LeftValueInfo to)
      , Convert(ArrayElemReferenceInfo from)  (ArrayElemReferenceInfo to)
      , Convert(InstructionInfo from)         (InstructionInfo to)
      , Convert(AssignmentInfo from)          (AssignmentInfo to)
      , Convert(ProcedureCallInfo from)       (ProcedureCallInfo to)
      , Convert(ActualParameterInfo from)     (ActualParameterInfo to)
      , Convert(IntConstantInfo from)         (IntConstantInfo to)
      , Convert(FloatConstantInfo from)       (FloatConstantInfo to)
      , Convert(BoolConstantInfo from)        (BoolConstantInfo to)
      , Convert(ArrayConstantInfo from)       (ArrayConstantInfo to)
      , Convert(VariableInfo from)            (VariableInfo to)
      ) => ConvertAllInfos from to

instance (SemanticInfo from, SemanticInfo to
         , Convert(ProcedureInfo from)           (ProcedureInfo to)
         , Convert(BlockInfo from)               (BlockInfo to)
         , Convert(ProgramInfo from)             (ProgramInfo to)
         , Convert(EmptyInfo from)               (EmptyInfo to)
         , Convert(PrimitiveInfo from)           (PrimitiveInfo to)
         , Convert(SequenceInfo from)            (SequenceInfo to)
         , Convert(BranchInfo from)              (BranchInfo to)
         , Convert(SequentialLoopInfo from)      (SequentialLoopInfo to)
         , Convert(ParallelLoopInfo from)        (ParallelLoopInfo to)
         , Convert(FormalParameterInfo from)     (FormalParameterInfo to)
         , Convert(LocalDeclarationInfo from)    (LocalDeclarationInfo to)
         , Convert(ExpressionInfo from)          (ExpressionInfo to)
         , Convert(ConstantInfo from)            (ConstantInfo to)
         , Convert(FunctionCallInfo from)        (FunctionCallInfo to)
         , Convert(LeftValueInfo from)           (LeftValueInfo to)
         , Convert(ArrayElemReferenceInfo from)  (ArrayElemReferenceInfo to)
         , Convert(InstructionInfo from)         (InstructionInfo to)
         , Convert(AssignmentInfo from)          (AssignmentInfo to)
         , Convert(ProcedureCallInfo from)       (ProcedureCallInfo to)
         , Convert(ActualParameterInfo from)     (ActualParameterInfo to)
         , Convert(IntConstantInfo from)         (IntConstantInfo to)
         , Convert(FloatConstantInfo from)       (FloatConstantInfo to)
         , Convert(BoolConstantInfo from)        (BoolConstantInfo to)
         , Convert(ArrayConstantInfo from)       (ArrayConstantInfo to)
         , Convert(VariableInfo from)            (VariableInfo to)
         ) => ConvertAllInfos from to