module Curry.Syntax.Utils
( hasLanguageExtension, knownExtensions
, isTopDecl, isBlockDecl
, isTypeSig, infixOp, isTypeDecl, isValueDecl, isInfixDecl
, isDefaultDecl, isClassDecl, isTypeOrClassDecl, isInstanceDecl
, isFunctionDecl, isExternalDecl, patchModuleId
, isVariablePattern
, isVariableType, isSimpleType
, typeConstr, typeVariables, varIdent
, flatLhs, eqnArity, fieldLabel, fieldTerm, field2Tuple, opName
, funDecl, mkEquation, simpleRhs, patDecl, varDecl, constrPattern, caseAlt
, mkLet, mkVar
, apply, unapply
, constrId, nconstrId
, nconstrType
, recordLabels, nrecordLabels
, methods, impls, imethod, imethodArity
, shortenModuleAST
) where
import Control.Monad.State
import Curry.Base.Ident
import Curry.Base.Position
import Curry.Base.SpanInfo
import Curry.Files.Filenames (takeBaseName)
import Curry.Syntax.Extension
import Curry.Syntax.Type
hasLanguageExtension :: Module a -> KnownExtension -> Bool
hasLanguageExtension mdl ext = ext `elem` knownExtensions mdl
knownExtensions :: Module a -> [KnownExtension]
knownExtensions (Module _ ps _ _ _ _) =
[ e | LanguagePragma _ exts <- ps, KnownExtension _ e <- exts]
patchModuleId :: FilePath -> Module a -> Module a
patchModuleId fn m@(Module spi ps mid es is ds)
| mid == mainMIdent = Module spi ps (mkMIdent [takeBaseName fn]) es is ds
| otherwise = m
isTopDecl :: Decl a -> Bool
isTopDecl = not . isBlockDecl
isBlockDecl :: Decl a -> Bool
isBlockDecl = liftM3 ((.) (||) . (||)) isInfixDecl isTypeSig isValueDecl
isInfixDecl :: Decl a -> Bool
isInfixDecl (InfixDecl _ _ _ _) = True
isInfixDecl _ = False
isTypeDecl :: Decl a -> Bool
isTypeDecl (DataDecl _ _ _ _ _) = True
isTypeDecl (ExternalDataDecl _ _ _) = True
isTypeDecl (NewtypeDecl _ _ _ _ _) = True
isTypeDecl (TypeDecl _ _ _ _) = True
isTypeDecl _ = False
isDefaultDecl :: Decl a -> Bool
isDefaultDecl (DefaultDecl _ _) = True
isDefaultDecl _ = False
isClassDecl :: Decl a -> Bool
isClassDecl (ClassDecl _ _ _ _ _) = True
isClassDecl _ = False
isTypeOrClassDecl :: Decl a -> Bool
isTypeOrClassDecl = liftM2 (||) isTypeDecl isClassDecl
isInstanceDecl :: Decl a -> Bool
isInstanceDecl (InstanceDecl _ _ _ _ _) = True
isInstanceDecl _ = False
isTypeSig :: Decl a -> Bool
isTypeSig (TypeSig _ _ _) = True
isTypeSig _ = False
isValueDecl :: Decl a -> Bool
isValueDecl (FunctionDecl _ _ _ _) = True
isValueDecl (ExternalDecl _ _) = True
isValueDecl (PatternDecl _ _ _) = True
isValueDecl (FreeDecl _ _) = True
isValueDecl _ = False
isFunctionDecl :: Decl a -> Bool
isFunctionDecl (FunctionDecl _ _ _ _) = True
isFunctionDecl _ = False
isExternalDecl :: Decl a -> Bool
isExternalDecl (ExternalDecl _ _) = True
isExternalDecl _ = False
isVariablePattern :: Pattern a -> Bool
isVariablePattern (VariablePattern _ _ _) = True
isVariablePattern (ParenPattern _ t) = isVariablePattern t
isVariablePattern (AsPattern _ _ t) = isVariablePattern t
isVariablePattern (LazyPattern _ _) = True
isVariablePattern _ = False
isVariableType :: TypeExpr -> Bool
isVariableType (VariableType _ _) = True
isVariableType _ = False
isSimpleType :: TypeExpr -> Bool
isSimpleType (ConstructorType _ _) = True
isSimpleType (ApplyType _ ty1 ty2) = isSimpleType ty1 && isVariableType ty2
isSimpleType (VariableType _ _) = False
isSimpleType (TupleType _ tys) = all isVariableType tys
isSimpleType (ListType _ ty) = isVariableType ty
isSimpleType (ArrowType _ ty1 ty2) = isVariableType ty1 && isVariableType ty2
isSimpleType (ParenType _ ty) = isSimpleType ty
isSimpleType (ForallType _ _ _) = False
typeConstr :: TypeExpr -> QualIdent
typeConstr (ConstructorType _ tc) = tc
typeConstr (ApplyType _ ty _) = typeConstr ty
typeConstr (TupleType _ tys) = qTupleId (length tys)
typeConstr (ListType _ _) = qListId
typeConstr (ArrowType _ _ _) = qArrowId
typeConstr (ParenType _ ty) = typeConstr ty
typeConstr (VariableType _ _) =
error "Curry.Syntax.Utils.typeConstr: variable type"
typeConstr (ForallType _ _ _) =
error "Curry.Syntax.Utils.typeConstr: forall type"
typeVariables :: TypeExpr -> [Ident]
typeVariables (ConstructorType _ _) = []
typeVariables (ApplyType _ ty1 ty2) = typeVariables ty1 ++ typeVariables ty2
typeVariables (VariableType _ tv) = [tv]
typeVariables (TupleType _ tys) = concatMap typeVariables tys
typeVariables (ListType _ ty) = typeVariables ty
typeVariables (ArrowType _ ty1 ty2) = typeVariables ty1 ++ typeVariables ty2
typeVariables (ParenType _ ty) = typeVariables ty
typeVariables (ForallType _ vs ty) = vs ++ typeVariables ty
varIdent :: Var a -> Ident
varIdent (Var _ v) = v
infixOp :: InfixOp a -> Expression a
infixOp (InfixOp a op) = Variable NoSpanInfo a op
infixOp (InfixConstr a op) = Constructor NoSpanInfo a op
flatLhs :: Lhs a -> (Ident, [Pattern a])
flatLhs lhs = flat lhs []
where flat (FunLhs _ f ts) ts' = (f, ts ++ ts')
flat (OpLhs _ t1 op t2) ts' = (op, t1 : t2 : ts')
flat (ApLhs _ lhs' ts) ts' = flat lhs' (ts ++ ts')
eqnArity :: Equation a -> Int
eqnArity (Equation _ lhs _) = length $ snd $ flatLhs lhs
fieldLabel :: Field a -> QualIdent
fieldLabel (Field _ l _) = l
fieldTerm :: Field a -> a
fieldTerm (Field _ _ t) = t
field2Tuple :: Field a -> (QualIdent, a)
field2Tuple (Field _ l t) = (l, t)
opName :: InfixOp a -> QualIdent
opName (InfixOp _ op) = op
opName (InfixConstr _ c ) = c
constrId :: ConstrDecl -> Ident
constrId (ConstrDecl _ _ _ c _) = c
constrId (ConOpDecl _ _ _ _ op _) = op
constrId (RecordDecl _ _ _ c _) = c
nconstrId :: NewConstrDecl -> Ident
nconstrId (NewConstrDecl _ c _) = c
nconstrId (NewRecordDecl _ c _) = c
nconstrType :: NewConstrDecl -> TypeExpr
nconstrType (NewConstrDecl _ _ ty) = ty
nconstrType (NewRecordDecl _ _ (_, ty)) = ty
recordLabels :: ConstrDecl -> [Ident]
recordLabels (ConstrDecl _ _ _ _ _) = []
recordLabels (ConOpDecl _ _ _ _ _ _) = []
recordLabels (RecordDecl _ _ _ _ fs) = [l | FieldDecl _ ls _ <- fs, l <- ls]
nrecordLabels :: NewConstrDecl -> [Ident]
nrecordLabels (NewConstrDecl _ _ _ ) = []
nrecordLabels (NewRecordDecl _ _ (l, _)) = [l]
methods :: Decl a -> [Ident]
methods (TypeSig _ fs _) = fs
methods _ = []
impls :: Decl a -> [Ident]
impls (FunctionDecl _ _ f _) = [f]
impls _ = []
imethod :: IMethodDecl -> Ident
imethod (IMethodDecl _ f _ _) = f
imethodArity :: IMethodDecl -> Maybe Int
imethodArity (IMethodDecl _ _ a _) = a
funDecl :: SpanInfo -> a -> Ident -> [Pattern a] -> Expression a -> Decl a
funDecl spi a f ts e = FunctionDecl spi a f [mkEquation spi f ts e]
mkEquation :: SpanInfo -> Ident -> [Pattern a] -> Expression a -> Equation a
mkEquation spi f ts e = Equation spi (FunLhs NoSpanInfo f ts) (simpleRhs NoSpanInfo e)
simpleRhs :: SpanInfo -> Expression a -> Rhs a
simpleRhs spi e = SimpleRhs spi e []
patDecl :: SpanInfo -> Pattern a -> Expression a -> Decl a
patDecl spi t e = PatternDecl spi t (SimpleRhs spi e [])
varDecl :: SpanInfo -> a -> Ident -> Expression a -> Decl a
varDecl p ty = patDecl p . VariablePattern NoSpanInfo ty
constrPattern :: a -> QualIdent -> [(a, Ident)] -> Pattern a
constrPattern ty c = ConstructorPattern NoSpanInfo ty c
. map (uncurry (VariablePattern NoSpanInfo))
caseAlt :: SpanInfo -> Pattern a -> Expression a -> Alt a
caseAlt spi t e = Alt spi t (SimpleRhs spi e [])
mkLet :: [Decl a] -> Expression a -> Expression a
mkLet ds e = if null ds then e else Let NoSpanInfo ds e
mkVar :: a -> Ident -> Expression a
mkVar ty = Variable NoSpanInfo ty . qualify
apply :: Expression a -> [Expression a] -> Expression a
apply = foldl (Apply NoSpanInfo)
unapply :: Expression a -> [Expression a] -> (Expression a, [Expression a])
unapply (Apply _ e1 e2) es = unapply e1 (e2 : es)
unapply e es = (e, es)
shortenModuleAST :: Module () -> Module ()
shortenModuleAST = shortenAST
class ShortenAST a where
shortenAST :: a -> a
instance ShortenAST (Module a) where
shortenAST (Module spi _ mid ex im ds) =
Module spi [] mid ex im (map shortenAST ds)
instance ShortenAST (Decl a) where
shortenAST (FunctionDecl spi a idt _) =
FunctionDecl spi a idt []
shortenAST (ClassDecl spi cx cls tyv ds) =
ClassDecl spi cx cls tyv (map shortenAST ds)
shortenAST (InstanceDecl spi cx cls tyv ds) =
InstanceDecl spi cx cls tyv (map shortenAST ds)
shortenAST d = d