-- | Module containing functions required by test code. Not part of the public interface. module Debug.Util( hasRankNTypes, prettyPrint, -- * Exported for tests only mkLegalInfixVar, removeLet, removeExtraDigits ) where import Data.Data import Data.Generics.Uniplate.Data import Data.List.Extra import qualified Data.Map.Strict as M import Data.Maybe import Language.Haskell.TH import Language.Haskell.TH.Syntax -- | Discover the function name inside (possibly nested) let expressions -- Transform strings of the form "let (var tag "f" -> f) = f x in f_1" into "f" removeLet :: String -> String removeLet s = if "let" `isInfixOf` fst (word1 s) then case stripInfix " = " s of Just pair -> removeLet (snd pair) Nothing -> s -- this shouldn't happen... else fst $ word1 s -- | Remove possible _n suffix from discovered function names removeExtraDigits :: String -> String removeExtraDigits str = case stripInfixEnd "_" str of Just s -> fst s Nothing -> str -- | Trsansform infix operator into a valid variable name -- | For example "++"" ---> "plus_plus" -- | This transformed variable is not visible in the UI mkLegalInfixVar :: String -> String mkLegalInfixVar s = let f c acc = case M.lookup c opNames of Just "" -> acc -- no adl underscores when removing backtics Just s -> s ++ "_" ++ acc Nothing -> c : acc removeTrailing_ x = fromMaybe x $ stripSuffix "_" x in removeTrailing_ $ foldr f "" s -- | Legal variable names for each operator character opNames :: M.Map Char String opNames = M.fromList opList where opList = [ ('+', "plus"), ('-', "minus"), ('*', "star"), ('/', "div") , ('^', "caret"), ('~', "tilde"), ('%', "percent"), ('&', "amp") , ('=', "equals"), ('<', "lt"), ('>', "gt"), ('?', "quest"), (':', "cons") , ('.', "dot"), ('@', "at"), ('#', "hash"), ('!', "bang"), ('|', "bar") , ('`', "") -- remove backtics to form variable name ] hasRankNTypes, hasRankNTypes' :: Type -> Bool hasRankNTypes (ForallT _vars _ctxt typ) = hasRankNTypes' typ hasRankNTypes typ = hasRankNTypes' typ hasRankNTypes' typ = not $ null [ () | ForallT{} <- universe typ] prettyPrint :: (Data a, Ppr a) => a -> String prettyPrint = pprint . transformBi f where f (Name x _) = Name x NameS -- avoid nasty qualifications