{-# LANGUAGE TypeSynonymInstances #-} module FTTools ( parseTypeString , specialiseAll , specialiseAllInverse , isInequational , parseDeclarations , rawFunctionName , rawDeclarationName , filterDataDeclarations , filterTypeDeclarations , filterClassDeclarations ) where import Language.Haskell.FreeTheorems import Language.Haskell.FreeTheorems.Theorems (Theorem, UnfoldedLift, UnfoldedClass) import Language.Haskell.FreeTheorems.Parser.Hsx (parse) import Language.Haskell.FreeTheorems.BasicSyntax ( signatureName , unpackIdent , getDeclarationName , Declaration (DataDecl, TypeDecl, ClassDecl) -- for the "filter" functions ) import Data.List (find, isInfixOf, foldl') parseDeclarations :: [ValidDeclaration] -> String -> Either String [ValidDeclaration] parseDeclarations oldDecls text = let (decls, errors) = runChecks (parse text >>= checkAgainst oldDecls) in case errors of (e:_) -> Left (show e) [] -> Right decls specialiseAll :: Intermediate -> Intermediate specialiseAll im = foldl' specialise im $ relationVariables im specialiseAllInverse :: Intermediate -> Intermediate specialiseAllInverse im = foldl' specialiseInverse im $ relationVariables im isInequational :: LanguageSubset -> Bool isInequational (SubsetWithFix InequationalTheorem) = True isInequational (SubsetWithSeq InequationalTheorem) = True isInequational _ = False instance Eq (ValidDeclaration) where x == y = rawDeclaration x == rawDeclaration y instance Show (ValidDeclaration) where show = show . prettyDeclaration . rawDeclaration instance Show (ValidSignature) where show = show . prettySignature . rawSignature instance Show (Theorem) where show = show . prettyTheorem [] instance Show (UnfoldedLift) where show = show . prettyUnfoldedLift [] instance Show (UnfoldedClass) where show = show . prettyUnfoldedClass [] {- From FTBase.hs -} -- Parses a type string and returns the named type obtained from parsing or an -- error if no type was found. The function works as follows: -- -- * If the input contains "::", then it is parsed as a named type. -- -- * If the input is only one word, the function tries to find a type with -- that name in the list of predefined types. If it can be found, that type -- is parsed as a named type. -- -- * Otherwise the input is parsed as a type without name, while a new name is -- generated. parseTypeString :: [ValidDeclaration] -> String -> Either String ValidSignature parseTypeString oldDecls input | containsTwoColons input = parseNamedType oldDecls input parseTypeString oldDecls input | isOneWord input = case find ((input==) . rawFunctionName) knownSignatures of Just vsig -> Right vsig Nothing -> parseType oldDecls input where knownSignatures = filterSignatures oldDecls parseTypeString oldDecls input = parseType oldDecls input parseType :: [ValidDeclaration] -> String -> Either String ValidSignature parseType oldDecls s = parseNamedType oldDecls ("f::"++s) parseNamedType :: [ValidDeclaration] -> String -> Either String ValidSignature parseNamedType oldDecls s = do vs <- parseDeclarations oldDecls s case filterSignatures vs of [sig] -> Right sig _ -> Left "no valid type signature" containsTwoColons = isInfixOf "::" isOneWord = (1==) . length . words rawFunctionName :: ValidSignature -> String rawFunctionName = unpackIdent . signatureName . rawSignature rawDeclarationName :: ValidDeclaration -> String rawDeclarationName = unpackIdent . getDeclarationName . rawDeclaration filterDataDeclarations = filter $ \vd -> case rawDeclaration vd of DataDecl _ -> True _ -> False filterTypeDeclarations = filter $ \vd -> case rawDeclaration vd of TypeDecl _ -> True _ -> False filterClassDeclarations = filter $ \vd -> case rawDeclaration vd of ClassDecl _ -> True _ -> False