packages feed

feldspar-compiler-0.2: Feldspar/Compiler/Plugins/PropagationUtils.hs

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}

module Feldspar.Compiler.Plugins.PropagationUtils where

import Feldspar.Compiler.PluginArchitecture
import qualified Data.Map as Map
--import qualified Data.Set as Set
import qualified Data.List as List

-- ========================
--       VarStatistics
-- ========================

instance Ord VariableData where
	compare v1 v2 = compare (variableName v1) $ variableName v2

type VarStatistics t = Map.Map VariableData (Occurrences t)

data Occurrences t
    = Occurrences
    { writeVar  :: Occurrence (Maybe t) --(Maybe (Expression t,[String],Bool))
    , readVar   :: Occurrence ()
    }
    deriving (Eq,Show)

data Occurrence t = Zero | One t | Multiple
    deriving (Eq,Show)

hasUse :: VarStatistics t -> VariableData -> Bool
hasUse vs var = hasRead vs var || hasWrite vs var

notUse :: VarStatistics t -> VariableData -> Bool
notUse vs var = not $ hasUse vs var

hasRead :: VarStatistics t -> VariableData -> Bool
hasRead vs var = case Map.lookup var vs of
	Nothing -> False
	Just occ -> case readVar occ of
		Zero -> False
		_ -> True

notRead :: VarStatistics t -> VariableData -> Bool
notRead vs var = not $ hasRead vs var

hasWrite :: VarStatistics t -> VariableData -> Bool
hasWrite vs var = case Map.lookup var vs of
	Nothing -> False
	Just occ -> case writeVar occ of
		Zero -> False
		_ -> True

notWrite :: VarStatistics t -> VariableData -> Bool
notWrite  vs var = not $ hasWrite  vs var

getWrite :: VarStatistics t -> VariableData -> Maybe t
getWrite vs var = case Map.lookup var vs of
	Nothing -> Nothing
	Just occ -> case writeVar occ of
		One val -> val
		_ -> Nothing

instance Default (VarStatistics t) where
    defaultValue = Map.empty

instance Combine (VarStatistics t) where
	combine fst snd = Map.unionWith combine fst snd 

instance Combine (Occurrences t) where
	combine o1 o2 = Occurrences
		(combine (writeVar o1) (writeVar o2) )
		(combine (readVar o1) (readVar o2) ) 

instance Combine (Occurrence t) where
	combine Zero x = x
	combine Multiple x = Multiple
	combine e@(One _) Zero = e
	combine (One _) _ = Multiple

multipleVarStatistics :: VarStatistics t -> VarStatistics t
multipleVarStatistics vs = Map.map multipleOccurrences vs where
	multipleOccurrences (Occurrences write read) = Occurrences (multipleOccurrence write) (multipleOccurrence read)
	multipleOccurrence Zero = Zero
	multipleOccurrence (One _) = Multiple
	multipleOccurrence Multiple = Multiple

variablesInVarStatistics :: VarStatistics t -> [VariableData]
variablesInVarStatistics vs = Map.keys vs

selectFromVarStatistics :: [VariableData] -> VarStatistics t -> VarStatistics t
selectFromVarStatistics s vs = Map.filterWithKey (\v o -> v `elem` s) vs

deleteFromVarStatistics :: [VariableData] -> VarStatistics t -> VarStatistics t
deleteFromVarStatistics s vs = Map.filterWithKey (\v o -> not $ v `elem` s) vs


-- ========================
--       Downwards
-- ========================

data Occurrence_place = Occurrence_read | Occurrence_write | Occurrence_declare | Occurrence_notopt
    deriving (Eq,Show)

instance Default Occurrence_place where
    defaultValue = Occurrence_read

class OccurrenceDownwards node where
	occurrenceDownwards :: node -> Occurrence_place

instance OccurrenceDownwards (Branch t) where
	occurrenceDownwards _ = Occurrence_notopt --condition variable OK
instance OccurrenceDownwards (SequentialLoop t) where
	occurrenceDownwards _ = Occurrence_read --condition variable OK
instance OccurrenceDownwards (ParallelLoop t) where
	occurrenceDownwards _ = Occurrence_notopt --condition variable OK
instance OccurrenceDownwards (FormalParameter t) where
	occurrenceDownwards _ = Occurrence_notopt
instance OccurrenceDownwards (LocalDeclaration t) where
	occurrenceDownwards _ = Occurrence_declare
instance OccurrenceDownwards (Assignment t) where
	occurrenceDownwards _ = Occurrence_write --left OK, right is expression
instance OccurrenceDownwards (InputActualParameterType t) where
	occurrenceDownwards _ = Occurrence_read
instance OccurrenceDownwards (OutputActualParameterType t) where
	occurrenceDownwards _ = Occurrence_write
instance OccurrenceDownwards (LeftValueInExpression t) where
	occurrenceDownwards _ = Occurrence_read -- OK
instance OccurrenceDownwards (FunctionCall t) where
	occurrenceDownwards _ = Occurrence_read -- OK



-- ========================
--       Other utils
-- ========================

instance Default [VariableData] where
	defaultValue = []


declaredVar :: (SemanticInfo t) => LocalDeclaration t -> VariableData
declaredVar = variableData.localVariable.localDeclarationData

declaredVars :: (SemanticInfo t) => Block t -> [VariableData]
declaredVars block = map declaredVar $ blockDeclarations $ blockData block

delUnusedDecl :: (ConvertAllInfos via to) =>  [VariableData] -> Block via -> BlockData to -> Block to
delUnusedDecl unusedList origblock partiallyTransformedBlock =
				Block {
					blockData = BlockData {
						blockDeclarations = filter (\d -> not $ List.elem (declaredVar d) unusedList) $ blockDeclarations partiallyTransformedBlock,
						blockInstructions = blockInstructions partiallyTransformedBlock
					},
					blockSemInf = convert $ blockSemInf origblock
				}

-- ========================
--       SemInfUtils
-- ========================

class SemInfUtils node where
	deleteSemInf :: (SemanticInfo t) => node t -> node ()

instance SemInfUtils Expression where
	deleteSemInf (LeftValueExpression lve) = LeftValueExpression $ lve {
		leftValueExpressionContents = deleteSemInf $ leftValueExpressionContents lve,
		leftValueExpressionSemInf = ()
	}
	deleteSemInf (ConstantExpression ce) = (ConstantExpression $ deleteSemInf ce)
	deleteSemInf (FunctionCallExpression fce) = FunctionCallExpression $ fce {
		functionCallData = (functionCallData fce) {
			actualParametersOfFunctionToCall = map deleteSemInf $ actualParametersOfFunctionToCall $ functionCallData fce
		},
		functionCallSemInf = ()
	}

instance SemInfUtils LeftValue where
	deleteSemInf (VariableLeftValue vlv) = VariableLeftValue vlv {
		variableLeftValueContents = deleteSemInf $ variableLeftValueContents vlv,
		variableLeftValueSemInf = ()
	}
	deleteSemInf (ArrayElemReferenceLeftValue aer) = ArrayElemReferenceLeftValue aer {
		arrayElemReferenceData = (arrayElemReferenceData aer){
			arrayName = deleteSemInf $ arrayName $ arrayElemReferenceData aer,
			arrayIndex = deleteSemInf $ arrayIndex $ arrayElemReferenceData aer
		},
		arrayElemReferenceSemInf = ()
	}

instance SemInfUtils Variable where
	deleteSemInf var = var {
		variableSemInf = ()
	}

instance SemInfUtils ActualParameter where
	deleteSemInf (InputActualParameter iap) = InputActualParameter iap {
		inputActualParameterExpression = deleteSemInf $ inputActualParameterExpression iap,
		inputActualParameterSemInf = ()
	}
	deleteSemInf (OutputActualParameter oap) = OutputActualParameter oap {
		outputActualParameterLeftValue = deleteSemInf $ outputActualParameterLeftValue oap,
		outputActualParameterSemInf = ()
	}

instance SemInfUtils Constant where
	deleteSemInf (IntConstant ic) = IntConstant ic {
		intConstantSemInf = ()
	}
	deleteSemInf (FloatConstant fc) = FloatConstant fc {
		floatConstantSemInf = ()
	}
	deleteSemInf (BoolConstant bc) = BoolConstant bc {
		boolConstantSemInf = ()
	}
	deleteSemInf (ArrayConstant ac) = ArrayConstant ac {
		arrayConstantValue = map deleteSemInf $ arrayConstantValue ac,
		arrayConstantSemInf = ()
	}