{-# LANGUAGE EmptyDataDecls, TypeFamilies #-} module Feldspar.Compiler.Imperative.Plugin.Naming where import Data.Char import Feldspar.Transformation import Feldspar.Core.Types import qualified Feldspar.NameExtractor as Precompiler import Feldspar.Compiler.Error import Feldspar.Compiler.Backend.C.Library import System.IO.Unsafe -- =========================================================================== -- == Precompilation plugin -- =========================================================================== data SignatureInformation = SignatureInformation { originalFunctionName :: String, generatedImperativeParameterNames :: [String], originalParameterNames :: Maybe [Maybe String] } deriving (Show, Eq) instance Default SignatureInformation where def = precompilationError InternalError "Default value should not be used" precompilationError = handleError "PluginArch/Naming" data Precompilation = Precompilation instance Transformation Precompilation where type From Precompilation = () type To Precompilation = () type Down Precompilation = SignatureInformation type Up Precompilation = () type State Precompilation = () instance Transformable Precompilation Definition where transform t s d x@(Procedure n i _ _ _ _) | n == "PLACEHOLDER" = tr { result = (result tr){ procName = n' } } where d' = d { generatedImperativeParameterNames = map varName i } tr = defaultTransform t s d' x n' = originalFunctionName d transform t s d x = defaultTransform t s d x instance Transformable Precompilation Variable where transform t s d v = Result newVar s def where newVar = v { varName = (maybeStr2Str $ getVariableName d (varName v)) ++ varName v , varLabel = () } getVariableName :: SignatureInformation -> String -> Maybe String getVariableName signatureInformation origname = case (originalParameterNames signatureInformation) of Just originalParameterNameList -> if length (generatedImperativeParameterNames signatureInformation) == length originalParameterNameList then case searchResults of [] -> Nothing otherwise -> snd $ head $ searchResults else precompilationError InternalError $ "parameter name list length mismatch:" ++ show (generatedImperativeParameterNames signatureInformation) ++ " " ++ show originalParameterNameList where searchResults = filter (((==) origname).fst) (zip (generatedImperativeParameterNames signatureInformation) originalParameterNameList) Nothing -> Nothing maybeStr2Str :: Maybe String -> String maybeStr2Str (Just s) = s ++ "_" maybeStr2Str Nothing = "" data PrecompilationExternalInfo = PrecompilationExternalInfo { originalFunctionSignature :: Precompiler.OriginalFunctionSignature, inputParametersDescriptor :: [Int], numberOfFunctionArguments :: Int, compilationMode :: CompilationMode } addPostfixNumberToMaybeString :: (Maybe String, Int) -> Maybe String addPostfixNumberToMaybeString (ms, num) = case ms of Just s -> Just $ s ++ (show num) Nothing -> Nothing inflate :: Int -> [Maybe String] -> [Maybe String] inflate target list | length list < target = inflate target (list++[Nothing]) | length list == target = list | otherwise = precompilationError InternalError "Unexpected situation in 'inflate'" -- Replicates each element of the [parameter list given by the precompiler] based on the input parameter descriptor parameterNameListConsolidator :: PrecompilationExternalInfo -> [Maybe String] parameterNameListConsolidator externalInfo = if (numberOfFunctionArguments externalInfo == (length $ inputParametersDescriptor externalInfo)) then concat $ map (\(cnt,name)->replicate cnt name) (zip (inputParametersDescriptor externalInfo) (Precompiler.originalParameterNames $ originalFunctionSignature externalInfo)) else precompilationError InternalError "numArgs should be equal to the length of the input parameters' descriptor" instance Plugin Precompilation where type ExternalInfo Precompilation = PrecompilationExternalInfo executePlugin Precompilation externalInfo procedure = result $ transform Precompilation ({-state-}) (SignatureInformation { originalFunctionName = Precompiler.originalFunctionName $ originalFunctionSignature externalInfo, generatedImperativeParameterNames = precompilationError InternalError "GIPN should have been overwritten", originalParameterNames = case compilationMode externalInfo of Standalone -> if -- ultimate check, should be enough... numberOfFunctionArguments externalInfo == length (Precompiler.originalParameterNames $ originalFunctionSignature externalInfo) then Just $ parameterNameListConsolidator externalInfo else (unsafePerformIO $ do withColor Yellow $ putStrLn $ "[WARNING @ PluginArch/Naming]:"++ " not enough named parameters in function " ++ (Precompiler.originalFunctionName $ originalFunctionSignature externalInfo) withColor Yellow $ putStrLn $ "numArgs: " ++ show (numberOfFunctionArguments externalInfo) ++ ", parameter list: " ++ show (Precompiler.originalParameterNames $ originalFunctionSignature externalInfo) return $ Just $ parameterNameListConsolidator (externalInfo { originalFunctionSignature = (originalFunctionSignature externalInfo) { Precompiler.originalParameterNames = inflate (numberOfFunctionArguments externalInfo) $ Precompiler.originalParameterNames $ originalFunctionSignature externalInfo } }) ) Interactive -> Nothing -- no parameter name handling in interactive mode }) procedure