diff --git a/src/Language/PureScript/AST/Binders.hs b/src/Language/PureScript/AST/Binders.hs index 19e1d18db8..528ffb0987 100644 --- a/src/Language/PureScript/AST/Binders.hs +++ b/src/Language/PureScript/AST/Binders.hs @@ -60,7 +60,7 @@ data Binder -- | -- A binder with a type annotation -- - | TypedBinder Type Binder + | TypedBinder SourceType Binder deriving (Show) -- Manual Eq and Ord instances for `Binder` were added on 2018-03-05. Comparing diff --git a/src/Language/PureScript/AST/Declarations.hs b/src/Language/PureScript/AST/Declarations.hs index 2631b33c0a..6c2d12887a 100644 --- a/src/Language/PureScript/AST/Declarations.hs +++ b/src/Language/PureScript/AST/Declarations.hs @@ -39,16 +39,16 @@ import qualified Language.PureScript.Constants as C import qualified Text.Parsec as P -- | A map of locally-bound names in scope. -type Context = [(Ident, Type)] +type Context = [(Ident, SourceType)] -- | Holds the data necessary to do type directed search for typed holes data TypeSearch = TSBefore Environment -- ^ An Environment captured for later consumption by type directed search | TSAfter - { tsAfterIdentifiers :: [(Qualified Text, Type)] + { tsAfterIdentifiers :: [(Qualified Text, SourceType)] -- ^ The identifiers that fully satisfy the subsumption check - , tsAfterRecordFields :: Maybe [(Label, Type)] + , tsAfterRecordFields :: Maybe [(Label, SourceType)] -- ^ Record fields that are available on the first argument to the typed -- hole } @@ -56,10 +56,10 @@ data TypeSearch -- Environment deriving Show -onTypeSearchTypes :: (Type -> Type) -> TypeSearch -> TypeSearch +onTypeSearchTypes :: (SourceType -> SourceType) -> TypeSearch -> TypeSearch onTypeSearchTypes f = runIdentity . onTypeSearchTypesM (Identity . f) -onTypeSearchTypesM :: (Applicative m) => (Type -> m Type) -> TypeSearch -> m TypeSearch +onTypeSearchTypesM :: (Applicative m) => (SourceType -> m SourceType) -> TypeSearch -> m TypeSearch onTypeSearchTypesM f (TSAfter i r) = TSAfter <$> traverse (traverse f) i <*> traverse (traverse (traverse f)) r onTypeSearchTypesM _ (TSBefore env) = pure (TSBefore env) @@ -76,8 +76,8 @@ data SimpleErrorMessage | CannotGetFileInfo FilePath | CannotReadFile FilePath | CannotWriteFile FilePath - | InfiniteType Type - | InfiniteKind Kind + | InfiniteType SourceType + | InfiniteKind SourceKind | MultipleValueOpFixities (OpName 'ValueOpName) | MultipleTypeOpFixities (OpName 'TypeOpName) | OrphanTypeDeclaration Ident @@ -104,46 +104,46 @@ data SimpleErrorMessage | NameIsUndefined Ident | UndefinedTypeVariable (ProperName 'TypeName) | PartiallyAppliedSynonym (Qualified (ProperName 'TypeName)) - | EscapedSkolem Text (Maybe SourceSpan) Type - | TypesDoNotUnify Type Type - | KindsDoNotUnify Kind Kind - | ConstrainedTypeUnified Type Type - | OverlappingInstances (Qualified (ProperName 'ClassName)) [Type] [Qualified Ident] - | NoInstanceFound Constraint - | AmbiguousTypeVariables Type Constraint + | EscapedSkolem Text (Maybe SourceSpan) SourceType + | TypesDoNotUnify SourceType SourceType + | KindsDoNotUnify SourceKind SourceKind + | ConstrainedTypeUnified SourceType SourceType + | OverlappingInstances (Qualified (ProperName 'ClassName)) [SourceType] [Qualified Ident] + | NoInstanceFound SourceConstraint + | AmbiguousTypeVariables SourceType SourceConstraint | UnknownClass (Qualified (ProperName 'ClassName)) - | PossiblyInfiniteInstance (Qualified (ProperName 'ClassName)) [Type] - | CannotDerive (Qualified (ProperName 'ClassName)) [Type] - | InvalidDerivedInstance (Qualified (ProperName 'ClassName)) [Type] Int - | ExpectedTypeConstructor (Qualified (ProperName 'ClassName)) [Type] Type - | InvalidNewtypeInstance (Qualified (ProperName 'ClassName)) [Type] - | MissingNewtypeSuperclassInstance (Qualified (ProperName 'ClassName)) (Qualified (ProperName 'ClassName)) [Type] - | UnverifiableSuperclassInstance (Qualified (ProperName 'ClassName)) (Qualified (ProperName 'ClassName)) [Type] + | PossiblyInfiniteInstance (Qualified (ProperName 'ClassName)) [SourceType] + | CannotDerive (Qualified (ProperName 'ClassName)) [SourceType] + | InvalidDerivedInstance (Qualified (ProperName 'ClassName)) [SourceType] Int + | ExpectedTypeConstructor (Qualified (ProperName 'ClassName)) [SourceType] SourceType + | InvalidNewtypeInstance (Qualified (ProperName 'ClassName)) [SourceType] + | MissingNewtypeSuperclassInstance (Qualified (ProperName 'ClassName)) (Qualified (ProperName 'ClassName)) [SourceType] + | UnverifiableSuperclassInstance (Qualified (ProperName 'ClassName)) (Qualified (ProperName 'ClassName)) [SourceType] | CannotFindDerivingType (ProperName 'TypeName) | DuplicateLabel Label (Maybe Expr) | DuplicateValueDeclaration Ident | ArgListLengthsDiffer Ident | OverlappingArgNames (Maybe Ident) - | MissingClassMember (NEL.NonEmpty (Ident, Type)) + | MissingClassMember (NEL.NonEmpty (Ident, SourceType)) | ExtraneousClassMember Ident (Qualified (ProperName 'ClassName)) - | ExpectedType Type Kind + | ExpectedType SourceType SourceKind -- | constructor name, expected argument count, actual argument count | IncorrectConstructorArity (Qualified (ProperName 'ConstructorName)) Int Int - | ExprDoesNotHaveType Expr Type + | ExprDoesNotHaveType Expr SourceType | PropertyIsMissing Label | AdditionalProperty Label | TypeSynonymInstance - | OrphanInstance Ident (Qualified (ProperName 'ClassName)) (Set ModuleName) [Type] + | OrphanInstance Ident (Qualified (ProperName 'ClassName)) (Set ModuleName) [SourceType] | InvalidNewtype (ProperName 'TypeName) - | InvalidInstanceHead Type + | InvalidInstanceHead SourceType | TransitiveExportError DeclarationRef [DeclarationRef] | TransitiveDctorExportError DeclarationRef (ProperName 'ConstructorName) | ShadowedName Ident | ShadowedTypeVar Text | UnusedTypeVar Text - | WildcardInferredType Type Context - | HoleInferredType Text Type Context TypeSearch - | MissingTypeDeclaration Ident Type + | WildcardInferredType SourceType Context + | HoleInferredType Text SourceType Context TypeSearch + | MissingTypeDeclaration Ident SourceType | OverlappingPattern [[Binder]] Bool | IncompleteExhaustivityCheck | MisleadingEmptyTypeImport ModuleName (ProperName 'TypeName) @@ -164,14 +164,14 @@ data SimpleErrorMessage | CaseBinderLengthDiffers Int [Binder] | IncorrectAnonymousArgument | InvalidOperatorInBinder (Qualified (OpName 'ValueOpName)) (Qualified Ident) - | CannotGeneralizeRecursiveFunction Ident Type + | CannotGeneralizeRecursiveFunction Ident SourceType | CannotDeriveNewtypeForData (ProperName 'TypeName) | ExpectedWildcard (ProperName 'TypeName) | CannotUseBindWithDo Ident -- | instance name, type class, expected argument count, actual argument count | ClassInstanceArityMismatch Ident (Qualified (ProperName 'ClassName)) Int Int -- | a user-defined warning raised by using the Warn type class - | UserDefinedWarning Type + | UserDefinedWarning SourceType -- | a declaration couldn't be used because it contained free variables | UnusableDeclaration Ident [[Text]] | CannotDefinePrimModules ModuleName @@ -181,17 +181,17 @@ data SimpleErrorMessage -- | Error message hints, providing more detailed information about failure. data ErrorMessageHint - = ErrorUnifyingTypes Type Type + = ErrorUnifyingTypes SourceType SourceType | ErrorInExpression Expr | ErrorInModule ModuleName - | ErrorInInstance (Qualified (ProperName 'ClassName)) [Type] - | ErrorInSubsumption Type Type + | ErrorInInstance (Qualified (ProperName 'ClassName)) [SourceType] + | ErrorInSubsumption SourceType SourceType | ErrorCheckingAccessor Expr PSString - | ErrorCheckingType Expr Type - | ErrorCheckingKind Type + | ErrorCheckingType Expr SourceType + | ErrorCheckingKind SourceType | ErrorCheckingGuard | ErrorInferringType Expr - | ErrorInApplication Expr Type Expr + | ErrorInApplication Expr SourceType Expr | ErrorInDataConstructor (ProperName 'ConstructorName) | ErrorInTypeConstructor (ProperName 'TypeName) | ErrorInBindingGroup (NEL.NonEmpty Ident) @@ -201,7 +201,7 @@ data ErrorMessageHint | ErrorInTypeDeclaration Ident | ErrorInTypeClassDeclaration (ProperName 'ClassName) | ErrorInForeignImport Ident - | ErrorSolvingConstraint Constraint + | ErrorSolvingConstraint SourceConstraint | PositionedError (NEL.NonEmpty SourceSpan) deriving (Show) @@ -432,7 +432,7 @@ isExplicit _ = False data TypeDeclarationData = TypeDeclarationData { tydeclSourceAnn :: !SourceAnn , tydeclIdent :: !Ident - , tydeclType :: !Type + , tydeclType :: !SourceType } deriving (Show, Eq) overTypeDeclaration :: (TypeDeclarationData -> TypeDeclarationData) -> Declaration -> Declaration @@ -442,7 +442,7 @@ getTypeDeclaration :: Declaration -> Maybe TypeDeclarationData getTypeDeclaration (TypeDeclaration d) = Just d getTypeDeclaration _ = Nothing -unwrapTypeDeclaration :: TypeDeclarationData -> (Ident, Type) +unwrapTypeDeclaration :: TypeDeclarationData -> (Ident, SourceType) unwrapTypeDeclaration td = (tydeclIdent td, tydeclType td) -- | A value declaration assigns a name and potential binders, to an expression (or multiple guarded expressions). @@ -478,7 +478,7 @@ data Declaration -- | -- A data type declaration (data or newtype, name, arguments, data constructors) -- - = DataDeclaration SourceAnn DataDeclType (ProperName 'TypeName) [(Text, Maybe Kind)] [(ProperName 'ConstructorName, [Type])] + = DataDeclaration SourceAnn DataDeclType (ProperName 'TypeName) [(Text, Maybe SourceKind)] [(ProperName 'ConstructorName, [SourceType])] -- | -- A minimal mutually recursive set of data type declarations -- @@ -486,7 +486,7 @@ data Declaration -- | -- A type synonym declaration (name, arguments, type) -- - | TypeSynonymDeclaration SourceAnn (ProperName 'TypeName) [(Text, Maybe Kind)] Type + | TypeSynonymDeclaration SourceAnn (ProperName 'TypeName) [(Text, Maybe SourceKind)] SourceType -- | -- A type declaration for a value (name, ty) -- @@ -505,11 +505,11 @@ data Declaration -- | -- A foreign import declaration (name, type) -- - | ExternDeclaration SourceAnn Ident Type + | ExternDeclaration SourceAnn Ident SourceType -- | -- A data type foreign import (name, kind) -- - | ExternDataDeclaration SourceAnn (ProperName 'TypeName) Kind + | ExternDataDeclaration SourceAnn (ProperName 'TypeName) SourceKind -- | -- A foreign kind import (name) -- @@ -525,12 +525,12 @@ data Declaration -- | -- A type class declaration (name, argument, implies, member declarations) -- - | TypeClassDeclaration SourceAnn (ProperName 'ClassName) [(Text, Maybe Kind)] [Constraint] [FunctionalDependency] [Declaration] + | TypeClassDeclaration SourceAnn (ProperName 'ClassName) [(Text, Maybe SourceKind)] [SourceConstraint] [FunctionalDependency] [Declaration] -- | -- A type instance declaration (instance chain, chain index, name, -- dependencies, class name, instance types, member declarations) -- - | TypeInstanceDeclaration SourceAnn [Ident] Integer Ident [Constraint] (Qualified (ProperName 'ClassName)) [Type] TypeInstanceBody + | TypeInstanceDeclaration SourceAnn [Ident] Integer Ident [SourceConstraint] (Qualified (ProperName 'ClassName)) [SourceType] TypeInstanceBody deriving (Show) data ValueFixity = ValueFixity Fixity (Qualified (Either Ident (ProperName 'ConstructorName))) (OpName 'ValueOpName) @@ -767,7 +767,7 @@ data Expr -- | -- A value with a type annotation -- - | TypedValue Bool Expr Type + | TypedValue Bool Expr SourceType -- | -- A let binding -- @@ -792,7 +792,7 @@ data Expr -- at superclass implementations when searching for a dictionary, the type class name and -- instance type, and the type class dictionaries in scope. -- - | TypeClassDictionary Constraint + | TypeClassDictionary SourceConstraint (M.Map (Maybe ModuleName) (M.Map (Qualified (ProperName 'ClassName)) (M.Map (Qualified Ident) (NEL.NonEmpty NamedDict)))) [ErrorMessageHint] -- | @@ -802,7 +802,7 @@ data Expr -- | -- A placeholder for a superclass dictionary to be turned into a TypeClassDictionary during typechecking -- - | DeferredDictionary (Qualified (ProperName 'ClassName)) [Type] + | DeferredDictionary (Qualified (ProperName 'ClassName)) [SourceType] -- | -- A placeholder for an anonymous function argument -- diff --git a/src/Language/PureScript/AST/Exported.hs b/src/Language/PureScript/AST/Exported.hs index a566773a8d..f24b1dc697 100644 --- a/src/Language/PureScript/AST/Exported.hs +++ b/src/Language/PureScript/AST/Exported.hs @@ -110,8 +110,8 @@ typeInstanceConstituents (TypeInstanceDeclaration _ _ _ _ constraints className -- Note that type synonyms are disallowed in instance declarations, so -- we don't need to handle them here. - go (TypeConstructor n) = [Right n] - go (ConstrainedType c _) = fromConstraint c + go (TypeConstructor _ n) = [Right n] + go (ConstrainedType _ c _) = fromConstraint c go _ = [] typeInstanceConstituents _ = [] diff --git a/src/Language/PureScript/AST/SourcePos.hs b/src/Language/PureScript/AST/SourcePos.hs index 6ad67542d7..83341d39a3 100644 --- a/src/Language/PureScript/AST/SourcePos.hs +++ b/src/Language/PureScript/AST/SourcePos.hs @@ -82,3 +82,26 @@ internalModuleSourceSpan name = SourceSpan name (SourcePos 0 0) (SourcePos 0 0) nullSourceSpan :: SourceSpan nullSourceSpan = internalModuleSourceSpan "" + +nullSourceAnn :: SourceAnn +nullSourceAnn = (nullSourceSpan, []) + +pattern NullSourceSpan :: SourceSpan +pattern NullSourceSpan = SourceSpan "" (SourcePos 0 0) (SourcePos 0 0) + +pattern NullSourceAnn :: SourceAnn +pattern NullSourceAnn = (NullSourceSpan, []) + +nonEmptySpan :: SourceAnn -> Maybe SourceSpan +nonEmptySpan (NullSourceSpan, _) = Nothing +nonEmptySpan (ss, _) = Just ss + +widenSourceSpan :: SourceSpan -> SourceSpan -> SourceSpan +widenSourceSpan (SourceSpan n1 s1 e1) (SourceSpan n2 s2 e2) = + SourceSpan n (min s1 s2) (max e1 e2) + where + n | n1 == "" = n2 + | otherwise = n1 + +widenSourceAnn :: SourceAnn -> SourceAnn -> SourceAnn +widenSourceAnn (s1, _) (s2, _) = (widenSourceSpan s1 s2, []) diff --git a/src/Language/PureScript/AST/Traversals.hs b/src/Language/PureScript/AST/Traversals.hs index 50bf45d835..3764d2cd95 100644 --- a/src/Language/PureScript/AST/Traversals.hs +++ b/src/Language/PureScript/AST/Traversals.hs @@ -620,7 +620,7 @@ everythingWithScope f g h i j = (f'', g'', h'', i'', \s -> snd . j'' s) accumTypes :: (Monoid r) - => (Type -> r) + => (SourceType -> r) -> ( Declaration -> r , Expr -> r , Binder -> r @@ -644,7 +644,7 @@ accumTypes f = everythingOnValues mappend forDecls forValues (const mempty) (con accumKinds :: (Monoid r) - => (Kind -> r) + => (SourceKind -> r) -> ( Declaration -> r , Expr -> r , Binder -> r @@ -675,13 +675,13 @@ accumKinds f = everythingOnValues mappend forDecls forValues (const mempty) (con forValues (TypedValue _ _ ty) = forTypes ty forValues _ = mempty - forTypes (KindedType _ k) = f k + forTypes (KindedType _ _ k) = f k forTypes _ = mempty -- | -- Map a function over type annotations appearing inside a value -- -overTypes :: (Type -> Type) -> Expr -> Expr +overTypes :: (SourceType -> SourceType) -> Expr -> Expr overTypes f = let (_, f', _) = everywhereOnValues id g id in f' where g :: Expr -> Expr diff --git a/src/Language/PureScript/Comments.hs b/src/Language/PureScript/Comments.hs index fd8f678207..5c5acd82ac 100644 --- a/src/Language/PureScript/Comments.hs +++ b/src/Language/PureScript/Comments.hs @@ -1,4 +1,5 @@ {-# LANGUAGE TemplateHaskell #-} +{-# LANGUAGE DeriveGeneric #-} -- | -- Defines the types of source code comments @@ -6,13 +7,17 @@ module Language.PureScript.Comments where import Prelude.Compat +import Control.DeepSeq (NFData) import Data.Text (Text) +import GHC.Generics (Generic) import Data.Aeson.TH data Comment = LineComment Text | BlockComment Text - deriving (Show, Eq, Ord) + deriving (Show, Eq, Ord, Generic) + +instance NFData Comment $(deriveJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) ''Comment) diff --git a/src/Language/PureScript/CoreFn/Ann.hs b/src/Language/PureScript/CoreFn/Ann.hs index 5d5b96fdff..cb536cc2f7 100644 --- a/src/Language/PureScript/CoreFn/Ann.hs +++ b/src/Language/PureScript/CoreFn/Ann.hs @@ -1,25 +1,25 @@ -module Language.PureScript.CoreFn.Ann where - -import Prelude.Compat - -import Language.PureScript.AST.SourcePos -import Language.PureScript.Comments -import Language.PureScript.CoreFn.Meta -import Language.PureScript.Types - --- | --- Type alias for basic annotations --- -type Ann = (SourceSpan, [Comment], Maybe Type, Maybe Meta) - --- | --- An annotation empty of metadata aside from a source span. --- -ssAnn :: SourceSpan -> Ann -ssAnn ss = (ss, [], Nothing, Nothing) - --- | --- Remove the comments from an annotation --- -removeComments :: Ann -> Ann -removeComments (ss, _, ty, meta) = (ss, [], ty, meta) +module Language.PureScript.CoreFn.Ann where + +import Prelude.Compat + +import Language.PureScript.AST.SourcePos +import Language.PureScript.Comments +import Language.PureScript.CoreFn.Meta +import Language.PureScript.Types + +-- | +-- Type alias for basic annotations +-- +type Ann = (SourceSpan, [Comment], Maybe SourceType, Maybe Meta) + +-- | +-- An annotation empty of metadata aside from a source span. +-- +ssAnn :: SourceSpan -> Ann +ssAnn ss = (ss, [], Nothing, Nothing) + +-- | +-- Remove the comments from an annotation +-- +removeComments :: Ann -> Ann +removeComments (ss, _, ty, meta) = (ss, [], ty, meta) diff --git a/src/Language/PureScript/CoreFn/Desugar.hs b/src/Language/PureScript/CoreFn/Desugar.hs index c16c54f5ea..b404558999 100644 --- a/src/Language/PureScript/CoreFn/Desugar.hs +++ b/src/Language/PureScript/CoreFn/Desugar.hs @@ -72,7 +72,7 @@ moduleToCoreFn env (A.Module modSS coms mn decls (Just exps)) = declToCoreFn _ = [] -- | Desugars expressions from AST to CoreFn representation. - exprToCoreFn :: SourceSpan -> [Comment] -> Maybe Type -> A.Expr -> Expr Ann + exprToCoreFn :: SourceSpan -> [Comment] -> Maybe SourceType -> A.Expr -> Expr Ann exprToCoreFn _ com ty (A.Literal ss lit) = Literal (ss, com, ty, Nothing) (fmap (exprToCoreFn ss com Nothing) lit) exprToCoreFn ss com ty (A.Accessor name v) = @@ -178,12 +178,12 @@ moduleToCoreFn env (A.Module modSS coms mn decls (Just exps)) = where numConstructors - :: (Qualified (ProperName 'ConstructorName), (DataDeclType, ProperName 'TypeName, Type, [Ident])) + :: (Qualified (ProperName 'ConstructorName), (DataDeclType, ProperName 'TypeName, SourceType, [Ident])) -> Int numConstructors ty = length $ filter (((==) `on` typeConstructor) ty) $ M.toList $ dataConstructors env typeConstructor - :: (Qualified (ProperName 'ConstructorName), (DataDeclType, ProperName 'TypeName, Type, [Ident])) + :: (Qualified (ProperName 'ConstructorName), (DataDeclType, ProperName 'TypeName, SourceType, [Ident])) -> (ModuleName, ProperName 'TypeName) typeConstructor (Qualified (Just mn') _, (_, tyCtor, _, _)) = (mn', tyCtor) typeConstructor _ = internalError "Invalid argument to typeConstructor" @@ -241,7 +241,7 @@ exportToCoreFn _ = [] -- | Makes a typeclass dictionary constructor function. The returned expression -- is a function that accepts the superclass instances and member -- implementations and returns a record for the instance dictionary. -mkTypeClassConstructor :: SourceAnn -> [Constraint] -> [A.Declaration] -> Expr Ann +mkTypeClassConstructor :: SourceAnn -> [SourceConstraint] -> [A.Declaration] -> Expr Ann mkTypeClassConstructor (ss, com) [] [] = Literal (ss, com, Nothing, Just IsTypeClassConstructor) (ObjectLiteral []) mkTypeClassConstructor (ss, com) supers members = let args@(a:as) = sort $ fmap typeClassMemberName members ++ superClassDictionaryNames supers diff --git a/src/Language/PureScript/CoreFn/Optimizer.hs b/src/Language/PureScript/CoreFn/Optimizer.hs index 28e12757d3..44567022d4 100644 --- a/src/Language/PureScript/CoreFn/Optimizer.hs +++ b/src/Language/PureScript/CoreFn/Optimizer.hs @@ -37,13 +37,13 @@ optimizeClosedRecordUpdate ou@(ObjectUpdate a@(_, _, Just t, _) r updatedFields) optimizeClosedRecordUpdate e = e -- | Return the labels of a closed record, or Nothing for other types or open records. -closedRecordFields :: Type -> Maybe [Label] -closedRecordFields (TypeApp (TypeConstructor C.Record) row) = +closedRecordFields :: Type a -> Maybe [Label] +closedRecordFields (TypeApp _ (TypeConstructor _ C.Record) row) = collect row where - collect :: Type -> Maybe [Label] - collect REmpty = Just [] - collect (RCons l _ r) = collect r >>= return . (l :) + collect :: Type a -> Maybe [Label] + collect (REmpty _) = Just [] + collect (RCons _ l _ r) = collect r >>= return . (l :) collect _ = Nothing closedRecordFields _ = Nothing diff --git a/src/Language/PureScript/Docs/Convert.hs b/src/Language/PureScript/Docs/Convert.hs index be6db2f908..1acbadddbd 100644 --- a/src/Language/PureScript/Docs/Convert.hs +++ b/src/Language/PureScript/Docs/Convert.hs @@ -14,6 +14,7 @@ import Protolude hiding (check) import Control.Arrow ((&&&)) import Control.Category ((>>>)) import Control.Monad.Writer.Strict (runWriterT) +import Data.Functor (($>)) import qualified Data.Map as Map import Data.String (String) @@ -213,7 +214,7 @@ insertValueTypes env m = ident = parseIdent (declTitle d) ty = lookupName ident in - d { declInfo = ValueDeclaration ty } + d { declInfo = ValueDeclaration (ty $> ()) } go other = other diff --git a/src/Language/PureScript/Docs/Convert/ReExports.hs b/src/Language/PureScript/Docs/Convert/ReExports.hs index 241acaab49..980af53d4c 100644 --- a/src/Language/PureScript/Docs/Convert/ReExports.hs +++ b/src/Language/PureScript/Docs/Convert/ReExports.hs @@ -195,7 +195,7 @@ lookupValueDeclaration :: MonadReader P.ModuleName m) => P.ModuleName -> P.Ident -> - m (P.ModuleName, [Either (Text, P.Constraint, ChildDeclaration) Declaration]) + m (P.ModuleName, [Either (Text, Constraint', ChildDeclaration) Declaration]) lookupValueDeclaration importedFrom ident = do decls <- lookupModuleDeclarations "lookupValueDeclaration" importedFrom let @@ -360,7 +360,7 @@ lookupModuleDeclarations definedIn moduleName = do handleTypeClassMembers :: (MonadReader P.ModuleName m) => - Map P.ModuleName [Either (Text, P.Constraint, ChildDeclaration) Declaration] -> + Map P.ModuleName [Either (Text, Constraint', ChildDeclaration) Declaration] -> Map P.ModuleName [Declaration] -> m (Map P.ModuleName [Declaration], Map P.ModuleName [Declaration]) handleTypeClassMembers valsAndMembers typeClasses = @@ -375,7 +375,7 @@ handleTypeClassMembers valsAndMembers typeClasses = |> fmap splitMap valsAndMembersToEnv :: - [Either (Text, P.Constraint, ChildDeclaration) Declaration] -> TypeClassEnv + [Either (Text, Constraint', ChildDeclaration) Declaration] -> TypeClassEnv valsAndMembersToEnv xs = let (envUnhandledMembers, envValues) = partitionEithers xs envTypeClasses = [] @@ -400,7 +400,7 @@ data TypeClassEnv = TypeClassEnv -- name of the type class they belong to, and the constraint is used to -- make sure that they have the correct type if they get promoted. -- - envUnhandledMembers :: [(Text, P.Constraint, ChildDeclaration)] + envUnhandledMembers :: [(Text, Constraint', ChildDeclaration)] -- | -- A list of normal value declarations. Type class members will be added to -- this list if their parent type class is not available. @@ -468,7 +468,7 @@ handleEnv TypeClassEnv{..} = ++ T.unpack cdeclTitle) addConstraint constraint = - P.quantify . P.moveQuantifiersToFront . P.ConstrainedType constraint + P.quantify . P.moveQuantifiersToFront . P.ConstrainedType () constraint splitMap :: Map k (v1, v2) -> (Map k v1, Map k v2) splitMap = fmap fst &&& fmap snd @@ -534,12 +534,12 @@ internalErrorInModule msg = do -- If the provided Declaration is a TypeClassDeclaration, construct an -- appropriate Constraint for use with the types of its members. -- -typeClassConstraintFor :: Declaration -> Maybe P.Constraint +typeClassConstraintFor :: Declaration -> Maybe Constraint' typeClassConstraintFor Declaration{..} = case declInfo of TypeClassDeclaration tyArgs _ _ -> - Just (P.Constraint (P.Qualified Nothing (P.ProperName declTitle)) (mkConstraint tyArgs) Nothing) + Just (P.Constraint () (P.Qualified Nothing (P.ProperName declTitle)) (mkConstraint tyArgs) Nothing) _ -> Nothing where - mkConstraint = map (P.TypeVar . fst) + mkConstraint = map (P.TypeVar () . fst) diff --git a/src/Language/PureScript/Docs/Convert/Single.hs b/src/Language/PureScript/Docs/Convert/Single.hs index 045fe34c4a..e366302375 100644 --- a/src/Language/PureScript/Docs/Convert/Single.hs +++ b/src/Language/PureScript/Docs/Convert/Single.hs @@ -7,6 +7,7 @@ import Protolude hiding (moduleName) import Control.Category ((>>>)) +import Data.Functor (($>)) import qualified Data.Text as T import Language.PureScript.Docs.Types @@ -110,33 +111,34 @@ basicDeclaration sa title = Just . Right . mkDeclaration sa title convertDeclaration :: P.Declaration -> Text -> Maybe IntermediateDeclaration convertDeclaration (P.ValueDecl sa _ _ _ [P.MkUnguarded (P.TypedValue _ _ ty)]) title = - basicDeclaration sa title (ValueDeclaration ty) + basicDeclaration sa title (ValueDeclaration (ty $> ())) convertDeclaration (P.ValueDecl sa _ _ _ _) title = -- If no explicit type declaration was provided, insert a wildcard, so that -- the actual type will be added during type checking. - basicDeclaration sa title (ValueDeclaration (P.TypeWildcard (fst sa))) + basicDeclaration sa title (ValueDeclaration (P.TypeWildcard ())) convertDeclaration (P.ExternDeclaration sa _ ty) title = - basicDeclaration sa title (ValueDeclaration ty) + basicDeclaration sa title (ValueDeclaration (ty $> ())) convertDeclaration (P.DataDeclaration sa dtype _ args ctors) title = Just (Right (mkDeclaration sa title info) { declChildren = children }) where - info = DataDeclaration dtype args - children = map convertCtor ctors + info = DataDeclaration dtype (fmap (fmap (fmap ($> ()))) args) + children = map convertCtor (fmap (fmap (fmap ($> ()))) ctors) convertCtor (ctor', tys) = ChildDeclaration (P.runProperName ctor') Nothing Nothing (ChildDataConstructor tys) convertDeclaration (P.ExternDataDeclaration sa _ kind') title = - basicDeclaration sa title (ExternDataDeclaration kind') + basicDeclaration sa title (ExternDataDeclaration (kind' $> ())) convertDeclaration (P.ExternKindDeclaration sa _) title = basicDeclaration sa title ExternKindDeclaration convertDeclaration (P.TypeSynonymDeclaration sa _ args ty) title = - basicDeclaration sa title (TypeSynonymDeclaration args ty) + basicDeclaration sa title (TypeSynonymDeclaration (fmap (fmap (fmap ($> ()))) args) (ty $> ())) convertDeclaration (P.TypeClassDeclaration sa _ args implies fundeps ds) title = Just (Right (mkDeclaration sa title info) { declChildren = children }) where - info = TypeClassDeclaration args implies (convertFundepsToStrings args fundeps) + args' = fmap (fmap (fmap ($> ()))) args + info = TypeClassDeclaration args' (fmap ($> ()) implies) (convertFundepsToStrings args' fundeps) children = map convertClassMember ds convertClassMember (P.TypeDeclaration (P.TypeDeclarationData (ss, com) ident' ty)) = - ChildDeclaration (P.showIdent ident') (convertComments com) (Just ss) (ChildTypeClassMember ty) + ChildDeclaration (P.showIdent ident') (convertComments com) (Just ss) (ChildTypeClassMember (ty $> ())) convertClassMember _ = P.internalError "convertDeclaration: Invalid argument to convertClassMember." convertDeclaration (P.TypeInstanceDeclaration (ss, com) _ _ _ constraints className tys _) title = @@ -146,11 +148,11 @@ convertDeclaration (P.TypeInstanceDeclaration (ss, com) _ _ _ constraints classN typeNameStrings = ordNub (concatMap (P.everythingOnTypes (++) extractProperNames) tys) unQual x = let (P.Qualified _ y) = x in P.runProperName y - extractProperNames (P.TypeConstructor n) = [unQual n] + extractProperNames (P.TypeConstructor _ n) = [unQual n] extractProperNames _ = [] - childDecl = ChildDeclaration title (convertComments com) (Just ss) (ChildInstance constraints classApp) - classApp = foldl' P.TypeApp (P.TypeConstructor (fmap P.coerceProperName className)) tys + childDecl = ChildDeclaration title (convertComments com) (Just ss) (ChildInstance (fmap ($> ()) constraints) (classApp $> ())) + classApp = foldl' P.srcTypeApp (P.srcTypeConstructor (fmap P.coerceProperName className)) tys convertDeclaration (P.ValueFixityDeclaration sa fixity (P.Qualified mn alias) _) title = Just . Right $ mkDeclaration sa title (AliasDeclaration fixity (P.Qualified mn (Right alias))) convertDeclaration (P.TypeFixityDeclaration sa fixity (P.Qualified mn alias) _) title = diff --git a/src/Language/PureScript/Docs/Prim.hs b/src/Language/PureScript/Docs/Prim.hs index db65ea9a93..9d1b04df78 100644 --- a/src/Language/PureScript/Docs/Prim.hs +++ b/src/Language/PureScript/Docs/Prim.hs @@ -7,6 +7,7 @@ module Language.PureScript.Docs.Prim ) where import Prelude.Compat hiding (fail) +import Data.Functor (($>)) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Map as Map @@ -167,8 +168,8 @@ primKind = primKindOf P.primName lookupPrimTypeKindOf :: NameGen 'P.TypeName -> Text - -> P.Kind -lookupPrimTypeKindOf k = fst . unsafeLookupOf k + -> Kind' +lookupPrimTypeKindOf k = ($> ()) . fst . unsafeLookupOf k ( P.primTypes <> P.primBooleanTypes <> P.primOrderingTypes <> @@ -212,8 +213,8 @@ primClassOf gen title comments = Declaration , declInfo = let tcd = lookupPrimClassOf gen title - args = P.typeClassArguments tcd - superclasses = P.typeClassSuperclasses tcd + args = fmap (fmap (fmap ($> ()))) $ P.typeClassArguments tcd + superclasses = fmap ($> ()) $ P.typeClassSuperclasses tcd fundeps = convertFundepsToStrings args (P.typeClassDependencies tcd) in TypeClassDeclaration args superclasses fundeps diff --git a/src/Language/PureScript/Docs/Render.hs b/src/Language/PureScript/Docs/Render.hs index c0c656589f..c9f1a794d8 100644 --- a/src/Language/PureScript/Docs/Render.hs +++ b/src/Language/PureScript/Docs/Render.hs @@ -37,7 +37,7 @@ renderDeclarationWithOptions opts Declaration{..} = ] ExternDataDeclaration kind' -> [ keywordData - , renderType' (P.TypeConstructor (notQualified declTitle)) + , renderType' (P.TypeConstructor () (notQualified declTitle)) , syntax "::" , renderKind kind' ] @@ -85,7 +85,7 @@ renderDeclarationWithOptions opts Declaration{..} = ] where - renderType' :: P.Type -> RenderedCode + renderType' :: Type' -> RenderedCode renderType' = renderTypeWithOptions opts renderChildDeclaration :: ChildDeclaration -> RenderedCode @@ -109,17 +109,17 @@ renderChildDeclarationWithOptions opts ChildDeclaration{..} = renderType' = renderTypeWithOptions opts renderTypeAtom' = renderTypeAtomWithOptions opts -renderConstraint :: P.Constraint -> RenderedCode +renderConstraint :: Constraint' -> RenderedCode renderConstraint = renderConstraintWithOptions defaultRenderTypeOptions -renderConstraintWithOptions :: RenderTypeOptions -> P.Constraint -> RenderedCode -renderConstraintWithOptions opts (P.Constraint pn tys _) = - renderTypeWithOptions opts $ foldl P.TypeApp (P.TypeConstructor (fmap P.coerceProperName pn)) tys +renderConstraintWithOptions :: RenderTypeOptions -> Constraint' -> RenderedCode +renderConstraintWithOptions opts (P.Constraint ann pn tys _) = + renderTypeWithOptions opts $ foldl (P.TypeApp ann) (P.TypeConstructor ann (fmap P.coerceProperName pn)) tys -renderConstraints :: [P.Constraint] -> Maybe RenderedCode +renderConstraints :: [Constraint'] -> Maybe RenderedCode renderConstraints = renderConstraintsWithOptions defaultRenderTypeOptions -renderConstraintsWithOptions :: RenderTypeOptions -> [P.Constraint] -> Maybe RenderedCode +renderConstraintsWithOptions :: RenderTypeOptions -> [Constraint'] -> Maybe RenderedCode renderConstraintsWithOptions opts constraints | null constraints = Nothing | otherwise = Just $ @@ -140,12 +140,12 @@ ident' = ident . P.Qualified Nothing . P.Ident dataCtor' :: Text -> RenderedCode dataCtor' = dataCtor . notQualified -typeApp :: Text -> [(Text, Maybe P.Kind)] -> P.Type +typeApp :: Text -> [(Text, Maybe Kind')] -> Type' typeApp title typeArgs = - foldl P.TypeApp - (P.TypeConstructor (notQualified title)) + foldl (P.TypeApp ()) + (P.TypeConstructor () (notQualified title)) (map toTypeVar typeArgs) -toTypeVar :: (Text, Maybe P.Kind) -> P.Type -toTypeVar (s, Nothing) = P.TypeVar s -toTypeVar (s, Just k) = P.KindedType (P.TypeVar s) k +toTypeVar :: (Text, Maybe Kind') -> Type' +toTypeVar (s, Nothing) = P.TypeVar () s +toTypeVar (s, Just k) = P.KindedType () (P.TypeVar () s) k diff --git a/src/Language/PureScript/Docs/RenderedCode/RenderKind.hs b/src/Language/PureScript/Docs/RenderedCode/RenderKind.hs index bbdbe8ce03..f4c3862aa7 100644 --- a/src/Language/PureScript/Docs/RenderedCode/RenderKind.hs +++ b/src/Language/PureScript/Docs/RenderedCode/RenderKind.hs @@ -1,3 +1,4 @@ +{-# LANGUAGE ScopedTypeVariables #-} -- | Functions for producing RenderedCode values from PureScript Kind values. -- module Language.PureScript.Docs.RenderedCode.RenderKind @@ -20,37 +21,37 @@ import Language.PureScript.Kinds import Language.PureScript.Docs.RenderedCode.Types -typeLiterals :: Pattern () Kind RenderedCode +typeLiterals :: Pattern () (Kind a) RenderedCode typeLiterals = mkPattern match where - match (KUnknown u) = + match (KUnknown _ u) = Just $ typeVar $ T.cons 'k' (T.pack (show u)) - match (NamedKind n) = + match (NamedKind _ n) = Just $ kind n match _ = Nothing -matchRow :: Pattern () Kind ((), Kind) +matchRow :: Pattern () (Kind a) ((), Kind a) matchRow = mkPattern match where - match (Row k) = Just ((), k) + match (Row _ k) = Just ((), k) match _ = Nothing -funKind :: Pattern () Kind (Kind, Kind) +funKind :: Pattern () (Kind a) (Kind a, Kind a) funKind = mkPattern match where - match (FunKind arg ret) = Just (arg, ret) + match (FunKind _ arg ret) = Just (arg, ret) match _ = Nothing -- | Generate RenderedCode value representing a Kind -renderKind :: Kind -> RenderedCode +renderKind :: forall a. Kind a -> RenderedCode renderKind = fromMaybe (internalError "Incomplete pattern") . PA.pattern matchKind () where - matchKind :: Pattern () Kind RenderedCode + matchKind :: Pattern () (Kind a) RenderedCode matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchKind) - operators :: OperatorTable () Kind RenderedCode + operators :: OperatorTable () (Kind a) RenderedCode operators = OperatorTable [ [ Wrap matchRow $ \_ k -> syntax "#" <> sp <> k] , [ AssocR funKind $ \arg ret -> arg <> sp <> syntax "->" <> sp <> ret ] ] diff --git a/src/Language/PureScript/Docs/RenderedCode/RenderType.hs b/src/Language/PureScript/Docs/RenderedCode/RenderType.hs index 3857dfd171..e027db980d 100644 --- a/src/Language/PureScript/Docs/RenderedCode/RenderType.hs +++ b/src/Language/PureScript/Docs/RenderedCode/RenderType.hs @@ -24,47 +24,46 @@ import Language.PureScript.Kinds import Language.PureScript.Names import Language.PureScript.Pretty.Types import Language.PureScript.Types -import Language.PureScript.Label (Label) import Language.PureScript.PSString (prettyPrintString) import Language.PureScript.Docs.RenderedCode.Types import Language.PureScript.Docs.Utils.MonoidExtras import Language.PureScript.Docs.RenderedCode.RenderKind (renderKind) -typeLiterals :: Pattern () Type RenderedCode +typeLiterals :: Pattern () (Type a) RenderedCode typeLiterals = mkPattern match where match TypeWildcard{} = Just (syntax "_") - match (TypeVar var) = + match (TypeVar _ var) = Just (typeVar var) - match (PrettyPrintObject row) = + match (PrettyPrintObject _ row) = Just $ mintersperse sp [ syntax "{" , renderRow row , syntax "}" ] - match (TypeConstructor n) = + match (TypeConstructor _ n) = Just (typeCtor n) - match REmpty = + match REmpty{} = Just (syntax "()") match row@RCons{} = Just (syntax "(" <> renderRow row <> syntax ")") - match (BinaryNoParensType op l r) = + match (BinaryNoParensType _ op l r) = Just $ renderTypeAtom l <> sp <> renderTypeAtom op <> sp <> renderTypeAtom r - match (TypeOp n) = + match (TypeOp _ n) = Just (typeOp n) - match (TypeLevelString str) = + match (TypeLevelString _ str) = Just (syntax (prettyPrintString str)) match _ = Nothing -renderConstraint :: Constraint -> RenderedCode -renderConstraint (Constraint pn tys _) = - let instApp = foldl TypeApp (TypeConstructor (fmap coerceProperName pn)) tys +renderConstraint :: Constraint a -> RenderedCode +renderConstraint (Constraint ann pn tys _) = + let instApp = foldl (TypeApp ann) (TypeConstructor ann (fmap coerceProperName pn)) tys in renderType instApp -renderConstraints :: Constraint -> RenderedCode -> RenderedCode +renderConstraints :: Constraint a -> RenderedCode -> RenderedCode renderConstraints con ty = mintersperse sp [ renderConstraint con @@ -75,65 +74,65 @@ renderConstraints con ty = -- | -- Render code representing a Row -- -renderRow :: Type -> RenderedCode +renderRow :: Type a -> RenderedCode renderRow = uncurry renderRow' . rowToList where renderRow' h t = renderHead h <> renderTail t -renderHead :: [(Label, Type)] -> RenderedCode +renderHead :: [RowListItem a] -> RenderedCode renderHead = mintersperse (syntax "," <> sp) . map renderLabel -renderLabel :: (Label, Type) -> RenderedCode -renderLabel (label, ty) = +renderLabel :: RowListItem a -> RenderedCode +renderLabel (RowListItem _ label ty) = mintersperse sp [ typeVar $ prettyPrintLabel label , syntax "::" , renderType ty ] -renderTail :: Type -> RenderedCode -renderTail REmpty = mempty +renderTail :: Type a -> RenderedCode +renderTail REmpty{} = mempty renderTail other = sp <> syntax "|" <> sp <> renderType other -typeApp :: Pattern () Type (Type, Type) +typeApp :: Pattern () (Type a) (Type a, Type a) typeApp = mkPattern match where - match (TypeApp f x) = Just (f, x) + match (TypeApp _ f x) = Just (f, x) match _ = Nothing -appliedFunction :: Pattern () Type (Type, Type) +appliedFunction :: Pattern () (Type a) (Type a, Type a) appliedFunction = mkPattern match where - match (PrettyPrintFunction arg ret) = Just (arg, ret) + match (PrettyPrintFunction _ arg ret) = Just (arg, ret) match _ = Nothing -kinded :: Pattern () Type (Kind, Type) +kinded :: Pattern () (Type a) (Kind a, Type a) kinded = mkPattern match where - match (KindedType t k) = Just (k, t) + match (KindedType _ t k) = Just (k, t) match _ = Nothing -constrained :: Pattern () Type (Constraint, Type) +constrained :: Pattern () (Type a) (Constraint a, Type a) constrained = mkPattern match where - match (ConstrainedType con ty) = Just (con, ty) + match (ConstrainedType _ con ty) = Just (con, ty) match _ = Nothing -explicitParens :: Pattern () Type ((), Type) +explicitParens :: Pattern () (Type a) ((), Type a) explicitParens = mkPattern match where - match (ParensInType ty) = Just ((), ty) + match (ParensInType _ ty) = Just ((), ty) match _ = Nothing -matchTypeAtom :: Pattern () Type RenderedCode +matchTypeAtom :: Pattern () (Type a) RenderedCode matchTypeAtom = typeLiterals <+> fmap parens_ matchType where parens_ x = syntax "(" <> x <> syntax ")" -matchType :: Pattern () Type RenderedCode +matchType :: Pattern () (Type a) RenderedCode matchType = buildPrettyPrinter operators matchTypeAtom where - operators :: OperatorTable () Type RenderedCode + operators :: OperatorTable () (Type a) RenderedCode operators = OperatorTable [ [ AssocL typeApp $ \f x -> f <> sp <> x ] , [ AssocR appliedFunction $ \arg ret -> mintersperse sp [arg, syntax "->", ret] ] @@ -143,42 +142,42 @@ matchType = buildPrettyPrinter operators matchTypeAtom , [ Wrap explicitParens $ \_ ty -> ty ] ] -forall_ :: Pattern () Type ([Text], Type) +forall_ :: Pattern () (Type a) ([Text], Type a) forall_ = mkPattern match where - match (PrettyPrintForAll idents ty) = Just (idents, ty) + match (PrettyPrintForAll _ idents ty) = Just (idents, ty) match _ = Nothing -insertPlaceholders :: RenderTypeOptions -> Type -> Type +insertPlaceholders :: RenderTypeOptions -> Type a -> Type a insertPlaceholders opts = everywhereOnTypesTopDown convertForAlls . everywhereOnTypes (convert opts) -convert :: RenderTypeOptions -> Type -> Type -convert _ (TypeApp (TypeApp f arg) ret) | f == tyFunction = PrettyPrintFunction arg ret -convert opts (TypeApp o r) | o == tyRecord && prettyPrintObjects opts = PrettyPrintObject r +convert :: RenderTypeOptions -> Type a -> Type a +convert _ (TypeApp a (TypeApp _ f arg) ret) | eqType f tyFunction = PrettyPrintFunction a arg ret +convert opts (TypeApp a o r) | eqType o tyRecord && prettyPrintObjects opts = PrettyPrintObject a r convert _ other = other -convertForAlls :: Type -> Type -convertForAlls (ForAll i ty _) = go [i] ty +convertForAlls :: Type a -> Type a +convertForAlls (ForAll ann i ty _) = go [i] ty where - go idents (ForAll i' ty' _) = go (i' : idents) ty' - go idents other = PrettyPrintForAll idents other + go idents (ForAll _ i' ty' _) = go (i' : idents) ty' + go idents other = PrettyPrintForAll ann idents other convertForAlls other = other -preprocessType :: RenderTypeOptions -> Type -> Type +preprocessType :: RenderTypeOptions -> Type a -> Type a preprocessType opts = insertPlaceholders opts -- | -- Render code representing a Type -- -renderType :: Type -> RenderedCode +renderType :: Type a -> RenderedCode renderType = renderTypeWithOptions defaultRenderTypeOptions -- | -- Render code representing a Type, as it should appear inside parentheses -- -renderTypeAtom :: Type -> RenderedCode +renderTypeAtom :: Type a -> RenderedCode renderTypeAtom = renderTypeAtomWithOptions defaultRenderTypeOptions data RenderTypeOptions = RenderTypeOptions @@ -193,13 +192,13 @@ defaultRenderTypeOptions = , currentModule = Nothing } -renderTypeWithOptions :: RenderTypeOptions -> Type -> RenderedCode +renderTypeWithOptions :: RenderTypeOptions -> Type a -> RenderedCode renderTypeWithOptions opts = fromMaybe (internalError "Incomplete pattern") . PA.pattern matchType () . preprocessType opts -renderTypeAtomWithOptions :: RenderTypeOptions -> Type -> RenderedCode +renderTypeAtomWithOptions :: RenderTypeOptions -> Type a -> RenderedCode renderTypeAtomWithOptions opts = fromMaybe (internalError "Incomplete pattern") . PA.pattern matchTypeAtom () diff --git a/src/Language/PureScript/Docs/Types.hs b/src/Language/PureScript/Docs/Types.hs index 9bba522362..6fd9c1befb 100644 --- a/src/Language/PureScript/Docs/Types.hs +++ b/src/Language/PureScript/Docs/Types.hs @@ -39,6 +39,10 @@ import Language.PureScript.Docs.RenderedCode as ReExports RenderedCodeElement(..), asRenderedCodeElement, Namespace(..), FixityAlias) +type Type' = P.Type () +type Kind' = P.Kind () +type Constraint' = P.Constraint () + -------------------- -- Types @@ -147,30 +151,30 @@ data DeclarationInfo -- | -- A value declaration, with its type. -- - = ValueDeclaration P.Type + = ValueDeclaration Type' -- | -- A data/newtype declaration, with the kind of declaration (data or -- newtype) and its type arguments. Constructors are represented as child -- declarations. -- - | DataDeclaration P.DataDeclType [(Text, Maybe P.Kind)] + | DataDeclaration P.DataDeclType [(Text, Maybe Kind')] -- | -- A data type foreign import, with its kind. -- - | ExternDataDeclaration P.Kind + | ExternDataDeclaration Kind' -- | -- A type synonym, with its type arguments and its type. -- - | TypeSynonymDeclaration [(Text, Maybe P.Kind)] P.Type + | TypeSynonymDeclaration [(Text, Maybe Kind')] Type' -- | -- A type class, with its type arguments, its superclasses and functional -- dependencies. Instances and members are represented as child declarations. -- - | TypeClassDeclaration [(Text, Maybe P.Kind)] [P.Constraint] [([Text], [Text])] + | TypeClassDeclaration [(Text, Maybe Kind')] [Constraint'] [([Text], [Text])] -- | -- An operator alias declaration, with the member the alias is for and the @@ -186,7 +190,7 @@ data DeclarationInfo instance NFData DeclarationInfo -convertFundepsToStrings :: [(Text, Maybe P.Kind)] -> [P.FunctionalDependency] -> [([Text], [Text])] +convertFundepsToStrings :: [(Text, Maybe Kind')] -> [P.FunctionalDependency] -> [([Text], [Text])] convertFundepsToStrings args fundeps = map (\(P.FunctionalDependency from to) -> toArgs from to) fundeps where @@ -287,19 +291,19 @@ data ChildDeclarationInfo -- | -- A type instance declaration, with its dependencies and its type. -- - = ChildInstance [P.Constraint] P.Type + = ChildInstance [Constraint'] Type' -- | -- A data constructor, with its type arguments. -- - | ChildDataConstructor [P.Type] + | ChildDataConstructor [Type'] -- | -- A type class member, with its type. Note that the type does not include -- the type class constraint; this may be added manually if desired. For -- example, `pure` from `Applicative` would be `forall a. a -> f a`. -- - | ChildTypeClassMember P.Type + | ChildTypeClassMember Type' deriving (Show, Eq, Ord, Generic) instance NFData ChildDeclarationInfo @@ -652,15 +656,15 @@ asDeclarationInfo = do other -> throwCustomError (InvalidDeclarationType other) -asTypeArguments :: Parse PackageError [(Text, Maybe P.Kind)] +asTypeArguments :: Parse PackageError [(Text, Maybe Kind')] asTypeArguments = eachInArray asTypeArgument where asTypeArgument = (,) <$> nth 0 asText <*> nth 1 (perhaps asKind) -asKind :: Parse PackageError P.Kind -asKind = P.kindFromJSON .! InvalidKind +asKind :: Parse PackageError Kind' +asKind = P.kindFromJSON (pure ()) fromAesonParser .! InvalidKind -asType :: Parse e P.Type +asType :: Parse e Type' asType = fromAesonParser asFunDeps :: Parse PackageError [([Text], [Text])] @@ -700,10 +704,10 @@ asSourcePos :: Parse e P.SourcePos asSourcePos = P.SourcePos <$> nth 0 asIntegral <*> nth 1 asIntegral -asConstraint :: Parse PackageError P.Constraint -asConstraint = P.Constraint <$> key "constraintClass" asQualifiedProperName - <*> key "constraintArgs" (eachInArray asType) - <*> pure Nothing +asConstraint :: Parse PackageError Constraint' +asConstraint = P.Constraint () <$> key "constraintClass" asQualifiedProperName + <*> key "constraintArgs" (eachInArray asType) + <*> pure Nothing asQualifiedProperName :: Parse e (P.Qualified (P.ProperName a)) asQualifiedProperName = fromAesonParser @@ -711,6 +715,9 @@ asQualifiedProperName = fromAesonParser asQualifiedIdent :: Parse e (P.Qualified P.Ident) asQualifiedIdent = fromAesonParser +asSourceAnn :: Parse e (P.SourceAnn) +asSourceAnn = fromAesonParser + asModuleMap :: Parse PackageError (Map P.ModuleName PackageName) asModuleMap = Map.fromList <$> diff --git a/src/Language/PureScript/Environment.hs b/src/Language/PureScript/Environment.hs index 937c58f544..3e9505aab3 100644 --- a/src/Language/PureScript/Environment.hs +++ b/src/Language/PureScript/Environment.hs @@ -19,6 +19,7 @@ import qualified Data.Graph as G import Data.Foldable (toList, fold) import qualified Data.List.NonEmpty as NEL +import Language.PureScript.AST.SourcePos import Language.PureScript.Crash import Language.PureScript.Kinds import Language.PureScript.Names @@ -28,14 +29,14 @@ import qualified Language.PureScript.Constants as C -- | The @Environment@ defines all values and types which are currently in scope: data Environment = Environment - { names :: M.Map (Qualified Ident) (Type, NameKind, NameVisibility) + { names :: M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) -- ^ Values currently in scope - , types :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) + , types :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) -- ^ Type names currently in scope - , dataConstructors :: M.Map (Qualified (ProperName 'ConstructorName)) (DataDeclType, ProperName 'TypeName, Type, [Ident]) + , dataConstructors :: M.Map (Qualified (ProperName 'ConstructorName)) (DataDeclType, ProperName 'TypeName, SourceType, [Ident]) -- ^ Data constructors currently in scope, along with their associated type -- constructor name, argument types and return type. - , typeSynonyms :: M.Map (Qualified (ProperName 'TypeName)) ([(Text, Maybe Kind)], Type) + , typeSynonyms :: M.Map (Qualified (ProperName 'TypeName)) ([(Text, Maybe SourceKind)], SourceType) -- ^ Type synonyms currently in scope , typeClassDictionaries :: M.Map (Maybe ModuleName) (M.Map (Qualified (ProperName 'ClassName)) (M.Map (Qualified Ident) (NEL.NonEmpty NamedDict))) -- ^ Available type class dictionaries. When looking up 'Nothing' in the @@ -51,13 +52,13 @@ instance NFData Environment -- | Information about a type class data TypeClassData = TypeClassData - { typeClassArguments :: [(Text, Maybe Kind)] + { typeClassArguments :: [(Text, Maybe SourceKind)] -- ^ A list of type argument names, and their kinds, where kind annotations -- were provided. - , typeClassMembers :: [(Ident, Type)] + , typeClassMembers :: [(Ident, SourceType)] -- ^ A list of type class members and their types. Type arguments listed above -- are considered bound in these types. - , typeClassSuperclasses :: [Constraint] + , typeClassSuperclasses :: [SourceConstraint] -- ^ A list of superclasses of this type class. Type arguments listed above -- are considered bound in the types appearing in these constraints. , typeClassDependencies :: [FunctionalDependency] @@ -120,9 +121,9 @@ initEnvironment = Environment M.empty allPrimTypes M.empty M.empty M.empty allPr -- determine X that X does not determine. This is the same thing: everything X determines includes everything -- in its SCC, and everything determining X is either before it in an SCC path, or in the same SCC. makeTypeClassData - :: [(Text, Maybe Kind)] - -> [(Ident, Type)] - -> [Constraint] + :: [(Text, Maybe SourceKind)] + -> [(Ident, SourceType)] + -> [SourceConstraint] -> [FunctionalDependency] -> TypeClassData makeTypeClassData args m s deps = TypeClassData args m s deps determinedArgs coveringSets @@ -197,7 +198,7 @@ instance NFData NameKind -- | The kinds of a type data TypeKind - = DataType [(Text, Maybe Kind)] [(ProperName 'ConstructorName, [Type])] + = DataType [(Text, Maybe SourceKind)] [(ProperName 'ConstructorName, [SourceType])] -- ^ Data type | TypeSynonym -- ^ Type synonym @@ -267,90 +268,97 @@ primSubName :: Text -> Text -> Qualified (ProperName a) primSubName sub = Qualified (Just $ ModuleName [ProperName C.prim, ProperName sub]) . ProperName -primKind :: Text -> Kind -primKind = NamedKind . primName +primKind :: Text -> SourceKind +primKind = NamedKind nullSourceAnn . primName -primSubKind :: Text -> Text -> Kind -primSubKind sub = NamedKind . primSubName sub +primSubKind :: Text -> Text -> SourceKind +primSubKind sub = NamedKind nullSourceAnn . primSubName sub -- | Kind of ground types -kindType :: Kind +kindType :: SourceKind kindType = primKind C.typ --- To make reading the kind signatures below easier -kindConstraint :: Kind +kindConstraint :: SourceKind kindConstraint = kindType -(-:>) :: Kind -> Kind -> Kind -(-:>) = FunKind +isKindType :: Kind a -> Bool +isKindType (NamedKind _ n) = n == primName C.typ +isKindType _ = False + +-- To make reading the kind signatures below easier +(-:>) :: SourceKind -> SourceKind -> SourceKind +(-:>) = FunKind nullSourceAnn infixr 4 -:> -kindSymbol :: Kind +kindSymbol :: SourceKind kindSymbol = primKind C.symbol -kindDoc :: Kind +kindDoc :: SourceKind kindDoc = primSubKind C.typeError C.doc -kindBoolean :: Kind +kindBoolean :: SourceKind kindBoolean = primSubKind C.moduleBoolean C.kindBoolean -kindOrdering :: Kind +kindOrdering :: SourceKind kindOrdering = primSubKind C.moduleOrdering C.kindOrdering -kindRowList :: Kind +kindRowList :: SourceKind kindRowList = primSubKind C.moduleRowList C.kindRowList +kindRow :: SourceKind -> SourceKind +kindRow = Row nullSourceAnn + -- | Construct a type in the Prim module -primTy :: Text -> Type -primTy = TypeConstructor . primName +primTy :: Text -> SourceType +primTy = TypeConstructor nullSourceAnn . primName -- | Type constructor for functions -tyFunction :: Type +tyFunction :: SourceType tyFunction = primTy "Function" -- | Type constructor for strings -tyString :: Type +tyString :: SourceType tyString = primTy "String" -- | Type constructor for strings -tyChar :: Type +tyChar :: SourceType tyChar = primTy "Char" -- | Type constructor for numbers -tyNumber :: Type +tyNumber :: SourceType tyNumber = primTy "Number" -- | Type constructor for integers -tyInt :: Type +tyInt :: SourceType tyInt = primTy "Int" -- | Type constructor for booleans -tyBoolean :: Type +tyBoolean :: SourceType tyBoolean = primTy "Boolean" -- | Type constructor for arrays -tyArray :: Type +tyArray :: SourceType tyArray = primTy "Array" -- | Type constructor for records -tyRecord :: Type +tyRecord :: SourceType tyRecord = primTy "Record" -- | Check whether a type is a record -isObject :: Type -> Bool +isObject :: Type a -> Bool isObject = isTypeOrApplied tyRecord -- | Check whether a type is a function -isFunction :: Type -> Bool +isFunction :: Type a -> Bool isFunction = isTypeOrApplied tyFunction -isTypeOrApplied :: Type -> Type -> Bool -isTypeOrApplied t1 (TypeApp t2 _) = t1 == t2 -isTypeOrApplied t1 t2 = t1 == t2 +isTypeOrApplied :: Type a -> Type b -> Bool +isTypeOrApplied t1 (TypeApp _ t2 _) = eqType t1 t2 +isTypeOrApplied t1 t2 = eqType t1 t2 -- | Smart constructor for function types -function :: Type -> Type -> Type -function t1 = TypeApp (TypeApp tyFunction t1) +function :: SourceType -> SourceType -> SourceType +function t1 t2 = TypeApp nullSourceAnn (TypeApp nullSourceAnn tyFunction t1) t2 -- | Kinds in @Prim@ primKinds :: S.Set (Qualified (ProperName 'KindName)) @@ -396,11 +404,11 @@ allPrimKinds = fold -- | The primitive types in the external javascript environment with their -- associated kinds. There are also pseudo `Fail`, `Warn`, and `Partial` types -- that correspond to the classes with the same names. -primTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primTypes = M.fromList [ (primName "Function", (kindType -:> kindType -:> kindType, ExternData)) , (primName "Array", (kindType -:> kindType, ExternData)) - , (primName "Record", (Row kindType -:> kindType, ExternData)) + , (primName "Record", (kindRow kindType -:> kindType, ExternData)) , (primName "String", (kindType, ExternData)) , (primName "Char", (kindType, ExternData)) , (primName "Number", (kindType, ExternData)) @@ -410,7 +418,7 @@ primTypes = M.fromList ] -- | This 'Map' contains all of the prim types from all Prim modules. -allPrimTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +allPrimTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) allPrimTypes = M.unions [ primTypes , primBooleanTypes @@ -421,14 +429,14 @@ allPrimTypes = M.unions , primTypeErrorTypes ] -primBooleanTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primBooleanTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primBooleanTypes = M.fromList [ (primSubName C.moduleBoolean "True", (kindBoolean, ExternData)) , (primSubName C.moduleBoolean "False", (kindBoolean, ExternData)) ] -primOrderingTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primOrderingTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primOrderingTypes = M.fromList [ (primSubName C.moduleOrdering "LT", (kindOrdering, ExternData)) @@ -436,24 +444,24 @@ primOrderingTypes = , (primSubName C.moduleOrdering "GT", (kindOrdering, ExternData)) ] -primRowTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primRowTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primRowTypes = M.fromList - [ (primSubName C.moduleRow "Union", (Row kindType -:> Row kindType -:> Row kindType -:> kindConstraint, ExternData)) - , (primSubName C.moduleRow "Nub", (Row kindType -:> Row kindType -:> kindConstraint, ExternData)) - , (primSubName C.moduleRow "Lacks", (kindSymbol -:> Row kindType -:> kindConstraint, ExternData)) - , (primSubName C.moduleRow "Cons", (kindSymbol -:> kindType -:> Row kindType -:> Row kindType -:> kindConstraint, ExternData)) + [ (primSubName C.moduleRow "Union", (kindRow kindType -:> kindRow kindType -:> kindRow kindType -:> kindConstraint, ExternData)) + , (primSubName C.moduleRow "Nub", (kindRow kindType -:> kindRow kindType -:> kindConstraint, ExternData)) + , (primSubName C.moduleRow "Lacks", (kindSymbol -:> kindRow kindType -:> kindConstraint, ExternData)) + , (primSubName C.moduleRow "Cons", (kindSymbol -:> kindType -:> kindRow kindType -:> kindRow kindType -:> kindConstraint, ExternData)) ] -primRowListTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primRowListTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primRowListTypes = M.fromList [ (primSubName C.moduleRowList "Cons", (kindSymbol -:> kindType -:> kindRowList -:> kindRowList, ExternData)) , (primSubName C.moduleRowList "Nil", (kindRowList, ExternData)) - , (primSubName C.moduleRowList "RowToList", (Row kindType -:> kindRowList -:> kindConstraint, ExternData)) + , (primSubName C.moduleRowList "RowToList", (kindRow kindType -:> kindRowList -:> kindConstraint, ExternData)) ] -primSymbolTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primSymbolTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primSymbolTypes = M.fromList [ (primSubName C.moduleSymbol "Append", (kindSymbol -:> kindSymbol -:> kindSymbol -:> kindConstraint, ExternData)) @@ -461,7 +469,7 @@ primSymbolTypes = , (primSubName C.moduleSymbol "Cons", (kindSymbol -:> kindSymbol -:> kindSymbol -:> kindConstraint, ExternData)) ] -primTypeErrorTypes :: M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) +primTypeErrorTypes :: M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) primTypeErrorTypes = M.fromList [ (primSubName C.typeError "Fail", (kindDoc -:> kindConstraint, ExternData)) @@ -496,9 +504,9 @@ primRowClasses = M.fromList -- class Union (left :: # Type) (right :: # Type) (union :: # Type) | left right -> union, right union -> left, union left -> right [ (primSubName C.moduleRow "Union", makeTypeClassData - [ ("left", Just (Row kindType)) - , ("right", Just (Row kindType)) - , ("union", Just (Row kindType)) + [ ("left", Just (kindRow kindType)) + , ("right", Just (kindRow kindType)) + , ("union", Just (kindRow kindType)) ] [] [] [ FunctionalDependency [0, 1] [2] , FunctionalDependency [1, 2] [0] @@ -507,8 +515,8 @@ primRowClasses = -- class Nub (original :: # Type) (nubbed :: # Type) | i -> o , (primSubName C.moduleRow "Nub", makeTypeClassData - [ ("original", Just (Row kindType)) - , ("nubbed", Just (Row kindType)) + [ ("original", Just (kindRow kindType)) + , ("nubbed", Just (kindRow kindType)) ] [] [] [ FunctionalDependency [0] [1] ]) @@ -516,15 +524,15 @@ primRowClasses = -- class Lacks (label :: Symbol) (row :: # Type) , (primSubName C.moduleRow "Lacks", makeTypeClassData [ ("label", Just kindSymbol) - , ("row", Just (Row kindType)) + , ("row", Just (kindRow kindType)) ] [] [] []) -- class RowCons (label :: Symbol) (a :: Type) (tail :: # Type) (row :: # Type) | label tail a -> row, label row -> tail a , (primSubName C.moduleRow "Cons", makeTypeClassData [ ("label", Just kindSymbol) , ("a", Just kindType) - , ("tail", Just (Row kindType)) - , ("row", Just (Row kindType)) + , ("tail", Just (kindRow kindType)) + , ("row", Just (kindRow kindType)) ] [] [] [ FunctionalDependency [0, 1, 2] [3] , FunctionalDependency [0, 3] [1, 2] @@ -536,7 +544,7 @@ primRowListClasses = M.fromList -- class RowToList (row :: # Type) (list :: RowList) | row -> list [ (primSubName C.moduleRowList "RowToList", makeTypeClassData - [ ("row", Just (Row kindType)) + [ ("row", Just (kindRow kindType)) , ("list", Just kindRowList) ] [] [] [ FunctionalDependency [0] [1] @@ -590,7 +598,7 @@ primTypeErrorClasses = ] -- | Finds information about data constructors from the current environment. -lookupConstructor :: Environment -> Qualified (ProperName 'ConstructorName) -> (DataDeclType, ProperName 'TypeName, Type, [Ident]) +lookupConstructor :: Environment -> Qualified (ProperName 'ConstructorName) -> (DataDeclType, ProperName 'TypeName, SourceType, [Ident]) lookupConstructor env ctor = fromMaybe (internalError "Data constructor not found") $ ctor `M.lookup` dataConstructors env @@ -601,5 +609,5 @@ isNewtypeConstructor e ctor = case lookupConstructor e ctor of (Data, _, _, _) -> False -- | Finds information about values from the current environment. -lookupValue :: Environment -> Qualified Ident -> Maybe (Type, NameKind, NameVisibility) +lookupValue :: Environment -> Qualified Ident -> Maybe (SourceType, NameKind, NameVisibility) lookupValue env ident = ident `M.lookup` names env diff --git a/src/Language/PureScript/Errors.hs b/src/Language/PureScript/Errors.hs index d4807d650b..8927ed6ba1 100644 --- a/src/Language/PureScript/Errors.hs +++ b/src/Language/PureScript/Errors.hs @@ -18,10 +18,11 @@ import Data.Char (isSpace) import Data.Either (partitionEithers) import Data.Foldable (fold) import Data.Functor.Identity (Identity(..)) -import Data.List (transpose, nubBy, sort, partition, dropWhileEnd) +import Data.List (transpose, nubBy, partition, dropWhileEnd, sortBy) import qualified Data.List.NonEmpty as NEL import Data.Maybe (maybeToList, fromMaybe, mapMaybe) import qualified Data.Map as M +import Data.Ord (comparing) import qualified Data.Set as S import qualified Data.Text as T import Data.Text (Text) @@ -241,31 +242,31 @@ data Level = Error | Warning deriving Show unwrapErrorMessage :: ErrorMessage -> SimpleErrorMessage unwrapErrorMessage (ErrorMessage _ se) = se -replaceUnknowns :: Type -> State TypeMap Type +replaceUnknowns :: SourceType -> State TypeMap SourceType replaceUnknowns = everywhereOnTypesM replaceTypes where - replaceTypes :: Type -> State TypeMap Type - replaceTypes (TUnknown u) = do + replaceTypes :: SourceType -> State TypeMap SourceType + replaceTypes (TUnknown ann u) = do m <- get case M.lookup u (umUnknownMap m) of Nothing -> do let u' = umNextIndex m put $ m { umUnknownMap = M.insert u u' (umUnknownMap m), umNextIndex = u' + 1 } - return (TUnknown u') - Just u' -> return (TUnknown u') - replaceTypes (Skolem name s sko ss) = do + return (TUnknown ann u') + Just u' -> return (TUnknown ann u') + replaceTypes (Skolem ann name s sko) = do m <- get case M.lookup s (umSkolemMap m) of Nothing -> do let s' = umNextIndex m - put $ m { umSkolemMap = M.insert s (T.unpack name, s', ss) (umSkolemMap m), umNextIndex = s' + 1 } - return (Skolem name s' sko ss) - Just (_, s', _) -> return (Skolem name s' sko ss) + put $ m { umSkolemMap = M.insert s (T.unpack name, s', Just (fst ann)) (umSkolemMap m), umNextIndex = s' + 1 } + return (Skolem ann name s' sko) + Just (_, s', _) -> return (Skolem ann name s' sko) replaceTypes other = return other -onTypesInErrorMessage :: (Type -> Type) -> ErrorMessage -> ErrorMessage +onTypesInErrorMessage :: (SourceType -> SourceType) -> ErrorMessage -> ErrorMessage onTypesInErrorMessage f = runIdentity . onTypesInErrorMessageM (Identity . f) -onTypesInErrorMessageM :: Applicative m => (Type -> m Type) -> ErrorMessage -> m ErrorMessage +onTypesInErrorMessageM :: Applicative m => (SourceType -> m SourceType) -> ErrorMessage -> m ErrorMessage onTypesInErrorMessageM f (ErrorMessage hints simple) = ErrorMessage <$> traverse gHint hints <*> gSimple simple where gSimple (InfiniteType t) = InfiniteType <$> f t @@ -585,17 +586,19 @@ prettyPrintSingleError (PPEOptions codeColor full level showDocs relPath) e = fl renderSimpleErrorMessage (TypesDoNotUnify u1 u2) = let (sorted1, sorted2) = sortRows u1 u2 - sortRows :: Type -> Type -> (Type, Type) + sortRows :: Ord a => Type a -> Type a -> (Type a, Type a) sortRows r1@RCons{} r2@RCons{} = sortRows' (rowToList r1) (rowToList r2) sortRows t1 t2 = (t1, t2) -- Put the common labels last - sortRows' :: ([(Label, Type)], Type) -> ([(Label, Type)], Type) -> (Type, Type) + sortRows' :: Ord a => ([RowListItem a], Type a) -> ([RowListItem a], Type a) -> (Type a, Type a) sortRows' (s1, r1) (s2, r2) = - let (common1, unique1) = partition (flip elem s2) s1 - (common2, unique2) = partition (flip elem s1) s2 - in ( rowFromList (sort unique1 ++ sort common1, r1) - , rowFromList (sort unique2 ++ sort common2, r2) + let elem' s (RowListItem _ name ty) = any (\(RowListItem _ name' ty') -> name == name' && eqType ty ty') s + sort' = sortBy (comparing $ \(RowListItem _ name ty) -> (name, ty)) + (common1, unique1) = partition (elem' s2) s1 + (common2, unique2) = partition (elem' s1) s2 + in ( rowFromList (sort' unique1 ++ sort' common1, r1) + , rowFromList (sort' unique2 ++ sort' common2, r2) ) in paras [ line "Could not match type" , markCodeBox $ indent $ typeAsBox sorted1 @@ -630,11 +633,11 @@ prettyPrintSingleError (PPEOptions codeColor full level showDocs relPath) e = fl , markCodeBox $ indent $ line (showQualified runProperName nm) , line "because the class was not in scope. Perhaps it was not exported." ] - renderSimpleErrorMessage (NoInstanceFound (Constraint C.Fail [ ty ] _)) | Just box <- toTypelevelString ty = + renderSimpleErrorMessage (NoInstanceFound (Constraint _ C.Fail [ ty ] _)) | Just box <- toTypelevelString ty = paras [ line "A custom type error occurred while solving type class constraints:" , indent box ] - renderSimpleErrorMessage (NoInstanceFound (Constraint C.Partial + renderSimpleErrorMessage (NoInstanceFound (Constraint _ C.Partial _ (Just (PartialConstraintData bs b)))) = paras [ line "A case expression could not be determined to cover all inputs." @@ -645,13 +648,13 @@ prettyPrintSingleError (PPEOptions codeColor full level showDocs relPath) e = fl : [line "..." | not b] , line "Alternatively, add a Partial constraint to the type of the enclosing value." ] - renderSimpleErrorMessage (NoInstanceFound (Constraint C.Discard [ty] _)) = + renderSimpleErrorMessage (NoInstanceFound (Constraint _ C.Discard [ty] _)) = paras [ line "A result of type" , markCodeBox $ indent $ typeAsBox ty , line "was implicitly discarded in a do notation block." , line ("You can use " <> markCode "_ <- ..." <> " to explicitly discard the result.") ] - renderSimpleErrorMessage (NoInstanceFound (Constraint nm ts _)) = + renderSimpleErrorMessage (NoInstanceFound (Constraint _ nm ts _)) = paras [ line "No type class instance was found for" , markCodeBox $ indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm) @@ -662,7 +665,7 @@ prettyPrintSingleError (PPEOptions codeColor full level showDocs relPath) e = fl ] ] where - containsUnknowns :: Type -> Bool + containsUnknowns :: Type a -> Bool containsUnknowns = everythingOnTypes (||) go where go TUnknown{} = True @@ -1142,7 +1145,7 @@ prettyPrintSingleError (PPEOptions codeColor full level showDocs relPath) e = fl paras [ detail , line $ "in foreign import " <> markCode (showIdent nm) ] - renderHint (ErrorSolvingConstraint (Constraint nm ts _)) detail = + renderHint (ErrorSolvingConstraint (Constraint _ nm ts _)) detail = paras [ detail , line "while solving type class constraint" , markCodeBox $ indent $ Box.hsep 1 Box.left @@ -1402,19 +1405,19 @@ renderBox = unlines where whiteSpace = all isSpace -toTypelevelString :: Type -> Maybe Box.Box -toTypelevelString (TypeLevelString s) = +toTypelevelString :: Type a -> Maybe Box.Box +toTypelevelString (TypeLevelString _ s) = Just . Box.text $ decodeStringWithReplacement s -toTypelevelString (TypeApp (TypeConstructor f) x) +toTypelevelString (TypeApp _ (TypeConstructor _ f) x) | f == primSubName C.typeError "Text" = toTypelevelString x -toTypelevelString (TypeApp (TypeConstructor f) x) +toTypelevelString (TypeApp _ (TypeConstructor _ f) x) | f == primSubName C.typeError "Quote" = Just (typeAsBox x) -toTypelevelString (TypeApp (TypeConstructor f) (TypeLevelString x)) +toTypelevelString (TypeApp _ (TypeConstructor _ f) (TypeLevelString _ x)) | f == primSubName C.typeError "QuoteLabel" = Just . line . prettyPrintLabel . Label $ x -toTypelevelString (TypeApp (TypeApp (TypeConstructor f) x) ret) +toTypelevelString (TypeApp _ (TypeApp _ (TypeConstructor _ f) x) ret) | f == primSubName C.typeError "Beside" = (Box.<>) <$> toTypelevelString x <*> toTypelevelString ret -toTypelevelString (TypeApp (TypeApp (TypeConstructor f) x) ret) +toTypelevelString (TypeApp _ (TypeApp _ (TypeConstructor _ f) x) ret) | f == primSubName C.typeError "Above" = (Box.//) <$> toTypelevelString x <*> toTypelevelString ret toTypelevelString _ = Nothing diff --git a/src/Language/PureScript/Externs.hs b/src/Language/PureScript/Externs.hs index a7974bde0d..7de92875c2 100644 --- a/src/Language/PureScript/Externs.hs +++ b/src/Language/PureScript/Externs.hs @@ -99,42 +99,42 @@ data ExternsDeclaration = -- | A type declaration EDType { edTypeName :: ProperName 'TypeName - , edTypeKind :: Kind + , edTypeKind :: SourceKind , edTypeDeclarationKind :: TypeKind } -- | A type synonym | EDTypeSynonym { edTypeSynonymName :: ProperName 'TypeName - , edTypeSynonymArguments :: [(Text, Maybe Kind)] - , edTypeSynonymType :: Type + , edTypeSynonymArguments :: [(Text, Maybe SourceKind)] + , edTypeSynonymType :: SourceType } -- | A data construtor | EDDataConstructor { edDataCtorName :: ProperName 'ConstructorName , edDataCtorOrigin :: DataDeclType , edDataCtorTypeCtor :: ProperName 'TypeName - , edDataCtorType :: Type + , edDataCtorType :: SourceType , edDataCtorFields :: [Ident] } -- | A value declaration | EDValue { edValueName :: Ident - , edValueType :: Type + , edValueType :: SourceType } -- | A type class declaration | EDClass { edClassName :: ProperName 'ClassName - , edClassTypeArguments :: [(Text, Maybe Kind)] - , edClassMembers :: [(Ident, Type)] - , edClassConstraints :: [Constraint] + , edClassTypeArguments :: [(Text, Maybe SourceKind)] + , edClassMembers :: [(Ident, SourceType)] + , edClassConstraints :: [SourceConstraint] , edFunctionalDependencies :: [FunctionalDependency] } -- | An instance declaration | EDInstance { edInstanceClassName :: Qualified (ProperName 'ClassName) , edInstanceName :: Ident - , edInstanceTypes :: [Type] - , edInstanceConstraints :: Maybe [Constraint] + , edInstanceTypes :: [SourceType] + , edInstanceConstraints :: Maybe [SourceConstraint] , edInstanceChain :: [Qualified Ident] , edInstanceChainIndex :: Integer } diff --git a/src/Language/PureScript/Hierarchy.hs b/src/Language/PureScript/Hierarchy.hs index db6b9b12f6..0bbe7650b9 100644 --- a/src/Language/PureScript/Hierarchy.hs +++ b/src/Language/PureScript/Hierarchy.hs @@ -80,6 +80,6 @@ typeClassEpilogue = "\n}" superClasses :: P.Declaration -> [SuperMap] superClasses (P.TypeClassDeclaration _ sub _ supers@(_:_) _ _) = - fmap (\(P.Constraint (P.Qualified _ super) _ _) -> SuperMap (Right (super, sub))) supers + fmap (\(P.Constraint _ (P.Qualified _ super) _ _) -> SuperMap (Right (super, sub))) supers superClasses (P.TypeClassDeclaration _ sub _ _ _ _) = [SuperMap (Left sub)] superClasses _ = [] diff --git a/src/Language/PureScript/Ide/CaseSplit.hs b/src/Language/PureScript/Ide/CaseSplit.hs index 2493374d83..90f1da0adc 100644 --- a/src/Language/PureScript/Ide/CaseSplit.hs +++ b/src/Language/PureScript/Ide/CaseSplit.hs @@ -35,7 +35,7 @@ import Language.PureScript.Ide.Types import Text.Parsec as Parsec import qualified Text.PrettyPrint.Boxes as Box -type Constructor = (P.ProperName 'P.ConstructorName, [P.Type]) +type Constructor = (P.ProperName 'P.ConstructorName, [P.SourceType]) newtype WildcardAnnotations = WildcardAnnotations Bool @@ -75,11 +75,11 @@ findTypeDeclaration' t ExternsFile{..} = _ -> False) efDeclarations splitTypeConstructor :: (MonadError IdeError m) => - P.Type -> m (P.ProperName 'P.TypeName, [P.Type]) + P.Type a -> m (P.ProperName 'P.TypeName, [P.Type a]) splitTypeConstructor = go [] where - go acc (P.TypeApp ty arg) = go (arg : acc) ty - go acc (P.TypeConstructor tc) = pure (P.disqualify tc, acc) + go acc (P.TypeApp _ ty arg) = go (arg : acc) ty + go acc (P.TypeConstructor _ tc) = pure (P.disqualify tc, acc) go _ _ = throwError (GeneralError "Failed to read TypeConstructor") prettyCtor :: WildcardAnnotations -> Constructor -> Text @@ -88,11 +88,11 @@ prettyCtor wsa (ctorName, ctorArgs) = "("<> P.runProperName ctorName <> " " <> T.unwords (map (prettyPrintWildcard wsa) ctorArgs) <>")" -prettyPrintWildcard :: WildcardAnnotations -> P.Type -> Text +prettyPrintWildcard :: WildcardAnnotations -> P.Type a -> Text prettyPrintWildcard (WildcardAnnotations True) = prettyWildcard prettyPrintWildcard (WildcardAnnotations False) = const "_" -prettyWildcard :: P.Type -> Text +prettyWildcard :: P.Type a -> Text prettyWildcard t = "( _ :: " <> T.strip (T.pack (P.prettyPrintTypeAtom t)) <> ")" -- | Constructs Patterns to insert into a sourcefile @@ -116,7 +116,7 @@ addClause s wca = do pure [s, template] parseType' :: (MonadError IdeError m) => - Text -> m P.Type + Text -> m P.SourceType parseType' s = case P.lex "" (toS s) >>= P.runTokenParser "" (P.parseType <* Parsec.eof) of Right type' -> pure type' @@ -124,7 +124,7 @@ parseType' s = throwError (GeneralError ("Parsing the splittype failed with:" <> show err)) -parseTypeDeclaration' :: (MonadError IdeError m) => Text -> m (P.Ident, P.Type) +parseTypeDeclaration' :: (MonadError IdeError m) => Text -> m (P.Ident, P.SourceType) parseTypeDeclaration' s = let x = do ts <- P.lex "" (toS s) @@ -137,13 +137,13 @@ parseTypeDeclaration' s = throwError (GeneralError ("Parsing the type signature failed with: " <> toS (Box.render (P.prettyPrintParseError err)))) -splitFunctionType :: P.Type -> [P.Type] +splitFunctionType :: P.Type a -> [P.Type a] splitFunctionType t = fromMaybe [] arguments where arguments = initMay splitted splitted = splitType' t - splitType' (P.ForAll _ t' _) = splitType' t' - splitType' (P.ConstrainedType _ t') = splitType' t' - splitType' (P.TypeApp (P.TypeApp t' lhs) rhs) - | t' == P.tyFunction = lhs : splitType' rhs + splitType' (P.ForAll _ _ t' _) = splitType' t' + splitType' (P.ConstrainedType _ _ t') = splitType' t' + splitType' (P.TypeApp _ (P.TypeApp _ t' lhs) rhs) + | P.eqType t' P.tyFunction = lhs : splitType' rhs splitType' t' = [t'] diff --git a/src/Language/PureScript/Ide/Error.hs b/src/Language/PureScript/Ide/Error.hs index 4f1a453b36..3908fd708b 100644 --- a/src/Language/PureScript/Ide/Error.hs +++ b/src/Language/PureScript/Ide/Error.hs @@ -82,5 +82,5 @@ textError (ParseError parseError msg) = let escape = show in msg <> ": " <> escape parseError textError (RebuildError err) = show err -prettyPrintTypeSingleLine :: P.Type -> Text +prettyPrintTypeSingleLine :: P.Type a -> Text prettyPrintTypeSingleLine = T.unwords . map T.strip . T.lines . T.pack . P.prettyPrintTypeWithUnicode diff --git a/src/Language/PureScript/Ide/Externs.hs b/src/Language/PureScript/Ide/Externs.hs index df65a9a0ec..0b1c39a5cc 100644 --- a/src/Language/PureScript/Ide/Externs.hs +++ b/src/Language/PureScript/Ide/Externs.hs @@ -116,7 +116,7 @@ findSynonym :: P.ProperName 'P.TypeName -> [IdeDeclaration] -> Maybe IdeTypeSyno -- involved. We collect these and resolve them at the end of the conversion process. data ToResolve = TypeClassToResolve (P.ProperName 'P.ClassName) - | SynonymToResolve (P.ProperName 'P.TypeName) P.Type + | SynonymToResolve (P.ProperName 'P.TypeName) P.SourceType convertExport :: P.DeclarationRef -> Maybe (P.ModuleName, P.DeclarationRef) convertExport (P.ReExportRef _ m r) = Just (m, r) diff --git a/src/Language/PureScript/Ide/SourceFile.hs b/src/Language/PureScript/Ide/SourceFile.hs index c62e26bf8d..37868eb786 100644 --- a/src/Language/PureScript/Ide/SourceFile.hs +++ b/src/Language/PureScript/Ide/SourceFile.hs @@ -65,7 +65,7 @@ extractAstInformation (P.Module _ _ _ decls _) = in (definitions, typeAnnotations) -- | Extracts type annotations for functions from a given Module -extractTypeAnnotations :: [P.Declaration] -> [(P.Ident, P.Type)] +extractTypeAnnotations :: [P.Declaration] -> [(P.Ident, P.SourceType)] extractTypeAnnotations = mapMaybe (map P.unwrapTypeDeclaration . P.getTypeDeclaration) -- | Given a surrounding Sourcespan and a Declaration from the PS AST, extracts diff --git a/src/Language/PureScript/Ide/Types.hs b/src/Language/PureScript/Ide/Types.hs index f096769337..cb72e17bb8 100644 --- a/src/Language/PureScript/Ide/Types.hs +++ b/src/Language/PureScript/Ide/Types.hs @@ -44,38 +44,38 @@ data IdeDeclaration data IdeValue = IdeValue { _ideValueIdent :: P.Ident - , _ideValueType :: P.Type + , _ideValueType :: P.SourceType } deriving (Show, Eq, Ord, Generic, NFData) data IdeType = IdeType { _ideTypeName :: P.ProperName 'P.TypeName - , _ideTypeKind :: P.Kind - , _ideTypeDtors :: [(P.ProperName 'P.ConstructorName, P.Type)] + , _ideTypeKind :: P.SourceKind + , _ideTypeDtors :: [(P.ProperName 'P.ConstructorName, P.SourceType)] } deriving (Show, Eq, Ord, Generic, NFData) data IdeTypeSynonym = IdeTypeSynonym { _ideSynonymName :: P.ProperName 'P.TypeName - , _ideSynonymType :: P.Type - , _ideSynonymKind :: P.Kind + , _ideSynonymType :: P.SourceType + , _ideSynonymKind :: P.SourceKind } deriving (Show, Eq, Ord, Generic, NFData) data IdeDataConstructor = IdeDataConstructor { _ideDtorName :: P.ProperName 'P.ConstructorName , _ideDtorTypeName :: P.ProperName 'P.TypeName - , _ideDtorType :: P.Type + , _ideDtorType :: P.SourceType } deriving (Show, Eq, Ord, Generic, NFData) data IdeTypeClass = IdeTypeClass { _ideTCName :: P.ProperName 'P.ClassName - , _ideTCKind :: P.Kind + , _ideTCKind :: P.SourceKind , _ideTCInstances :: [IdeInstance] } deriving (Show, Eq, Ord, Generic, NFData) data IdeInstance = IdeInstance { _ideInstanceModule :: P.ModuleName , _ideInstanceName :: P.Ident - , _ideInstanceTypes :: [P.Type] - , _ideInstanceConstraints :: Maybe [P.Constraint] + , _ideInstanceTypes :: [P.SourceType] + , _ideInstanceConstraints :: Maybe [P.SourceConstraint] } deriving (Show, Eq, Ord, Generic, NFData) data IdeValueOperator = IdeValueOperator @@ -83,7 +83,7 @@ data IdeValueOperator = IdeValueOperator , _ideValueOpAlias :: P.Qualified (Either P.Ident (P.ProperName 'P.ConstructorName)) , _ideValueOpPrecedence :: P.Precedence , _ideValueOpAssociativity :: P.Associativity - , _ideValueOpType :: Maybe P.Type + , _ideValueOpType :: Maybe P.SourceType } deriving (Show, Eq, Ord, Generic, NFData) data IdeTypeOperator = IdeTypeOperator @@ -91,7 +91,7 @@ data IdeTypeOperator = IdeTypeOperator , _ideTypeOpAlias :: P.Qualified (P.ProperName 'P.TypeName) , _ideTypeOpPrecedence :: P.Precedence , _ideTypeOpAssociativity :: P.Associativity - , _ideTypeOpKind :: Maybe P.Kind + , _ideTypeOpKind :: Maybe P.SourceKind } deriving (Show, Eq, Ord, Generic, NFData) _IdeDeclValue :: Traversal' IdeDeclaration IdeValue @@ -147,7 +147,7 @@ data Annotation = Annotation { _annLocation :: Maybe P.SourceSpan , _annExportedFrom :: Maybe P.ModuleName - , _annTypeAnnotation :: Maybe P.Type + , _annTypeAnnotation :: Maybe P.SourceType , _annDocumentation :: Maybe Text } deriving (Show, Eq, Ord, Generic, NFData) @@ -158,7 +158,7 @@ emptyAnn :: Annotation emptyAnn = Annotation Nothing Nothing Nothing Nothing type DefinitionSites a = Map IdeNamespaced a -type TypeAnnotations = Map P.Ident P.Type +type TypeAnnotations = Map P.Ident P.SourceType newtype AstData a = AstData (ModuleMap (DefinitionSites a, TypeAnnotations)) -- ^ SourceSpans for the definition sites of values and types as well as type -- annotations found in a module diff --git a/src/Language/PureScript/Interactive.hs b/src/Language/PureScript/Interactive.hs index 3205316a44..bca6bf278d 100644 --- a/src/Language/PureScript/Interactive.hs +++ b/src/Language/PureScript/Interactive.hs @@ -261,7 +261,7 @@ handleTypeOf print' val = do handleKindOf :: (MonadReader PSCiConfig m, MonadState PSCiState m, MonadIO m) => (String -> m ()) - -> P.Type + -> P.SourceType -> m () handleKindOf print' typ = do st <- get diff --git a/src/Language/PureScript/Interactive/Module.hs b/src/Language/PureScript/Interactive/Module.hs index 289ed4c964..a916e619ff 100644 --- a/src/Language/PureScript/Interactive/Module.hs +++ b/src/Language/PureScript/Interactive/Module.hs @@ -56,10 +56,10 @@ createTemporaryModule exec st val = itDecl = P.ValueDecl (internalSpan, []) (P.Ident "it") P.Public [] [P.MkUnguarded val] typeDecl = P.TypeDeclaration (P.TypeDeclarationData (internalSpan, []) (P.Ident "$main") - (P.TypeApp - (P.TypeConstructor + (P.srcTypeApp + (P.srcTypeConstructor (P.Qualified (Just (P.ModuleName [P.ProperName "$Effect"])) (P.ProperName "Effect"))) - (P.TypeWildcard internalSpan))) + P.srcTypeWildcard)) mainDecl = P.ValueDecl (internalSpan, []) (P.Ident "$main") P.Public [] [P.MkUnguarded mainValue] decls = if exec then [itDecl, typeDecl, mainDecl] else [itDecl] in @@ -72,7 +72,7 @@ createTemporaryModule exec st val = -- | -- Makes a volatile module to hold a non-qualified type synonym for a fully-qualified data type declaration. -- -createTemporaryModuleForKind :: PSCiState -> P.Type -> P.Module +createTemporaryModuleForKind :: PSCiState -> P.SourceType -> P.Module createTemporaryModuleForKind st typ = let imports = psciImportedModules st diff --git a/src/Language/PureScript/Interactive/Printer.hs b/src/Language/PureScript/Interactive/Printer.hs index 608129465e..7d35b08147 100644 --- a/src/Language/PureScript/Interactive/Printer.hs +++ b/src/Language/PureScript/Interactive/Printer.hs @@ -37,12 +37,12 @@ printModuleSignatures moduleName P.Environment{..} = where printModule's showF = Box.vsep 1 Box.left . showF - findNameType :: M.Map (P.Qualified P.Ident) (P.Type, P.NameKind, P.NameVisibility) + findNameType :: M.Map (P.Qualified P.Ident) (P.SourceType, P.NameKind, P.NameVisibility) -> P.Qualified P.Ident - -> (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility)) + -> (P.Ident, Maybe (P.SourceType, P.NameKind, P.NameVisibility)) findNameType envNames m = (P.disqualify m, M.lookup m envNames) - showNameType :: (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility)) -> Box.Box + showNameType :: (P.Ident, Maybe (P.SourceType, P.NameKind, P.NameVisibility)) -> Box.Box showNameType (mIdent, Just (mType, _, _)) = textT (P.showIdent mIdent <> " :: ") Box.<> P.typeAsBox mType showNameType _ = P.internalError "The impossible happened in printModuleSignatures." @@ -61,7 +61,7 @@ printModuleSignatures moduleName P.Environment{..} = if null typeClassSuperclasses then Box.text "" else Box.text "(" - Box.<> Box.hcat Box.left (intersperse (Box.text ", ") $ map (\(P.Constraint (P.Qualified _ pn) lt _) -> textT (P.runProperName pn) Box.<+> Box.hcat Box.left (map P.typeAtomAsBox lt)) typeClassSuperclasses) + Box.<> Box.hcat Box.left (intersperse (Box.text ", ") $ map (\(P.Constraint _ (P.Qualified _ pn) lt _) -> textT (P.runProperName pn) Box.<+> Box.hcat Box.left (map P.typeAtomAsBox lt)) typeClassSuperclasses) Box.<> Box.text ") <= " className = textT (P.runProperName name) @@ -79,16 +79,16 @@ printModuleSignatures moduleName P.Environment{..} = findType - :: M.Map (P.Qualified (P.ProperName 'P.TypeName)) (P.Kind, P.TypeKind) + :: M.Map (P.Qualified (P.ProperName 'P.TypeName)) (P.SourceKind, P.TypeKind) -> P.Qualified (P.ProperName 'P.TypeName) - -> (P.Qualified (P.ProperName 'P.TypeName), Maybe (P.Kind, P.TypeKind)) + -> (P.Qualified (P.ProperName 'P.TypeName), Maybe (P.SourceKind, P.TypeKind)) findType envTypes name = (name, M.lookup name envTypes) showType :: M.Map (P.Qualified (P.ProperName 'P.ClassName)) P.TypeClassData - -> M.Map (P.Qualified (P.ProperName 'P.ConstructorName)) (P.DataDeclType, P.ProperName 'P.TypeName, P.Type, [P.Ident]) - -> M.Map (P.Qualified (P.ProperName 'P.TypeName)) ([(Text, Maybe P.Kind)], P.Type) - -> (P.Qualified (P.ProperName 'P.TypeName), Maybe (P.Kind, P.TypeKind)) + -> M.Map (P.Qualified (P.ProperName 'P.ConstructorName)) (P.DataDeclType, P.ProperName 'P.TypeName, P.SourceType, [P.Ident]) + -> M.Map (P.Qualified (P.ProperName 'P.TypeName)) ([(Text, Maybe P.SourceKind)], P.SourceType) + -> (P.Qualified (P.ProperName 'P.TypeName), Maybe (P.SourceKind, P.TypeKind)) -> Maybe Box.Box showType typeClassesEnv dataConstructorsEnv typeSynonymsEnv (n@(P.Qualified modul name), typ) = case (typ, M.lookup n typeSynonymsEnv) of diff --git a/src/Language/PureScript/Interactive/Types.hs b/src/Language/PureScript/Interactive/Types.hs index 521b61dd8a..437408fd94 100644 --- a/src/Language/PureScript/Interactive/Types.hs +++ b/src/Language/PureScript/Interactive/Types.hs @@ -174,7 +174,7 @@ data Command -- | Find the type of an expression | TypeOf P.Expr -- | Find the kind of an expression - | KindOf P.Type + | KindOf P.SourceType -- | Shows information about the current state of the REPL | ShowInfo ReplQuery -- | Paste multiple lines diff --git a/src/Language/PureScript/Kinds.hs b/src/Language/PureScript/Kinds.hs index 01df9dca87..7e843cc86d 100644 --- a/src/Language/PureScript/Kinds.hs +++ b/src/Language/PureScript/Kinds.hs @@ -1,4 +1,7 @@ +{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveFoldable #-} +{-# LANGUAGE DeriveTraversable #-} module Language.PureScript.Kinds where @@ -6,104 +9,158 @@ import Prelude.Compat import GHC.Generics (Generic) import Control.DeepSeq (NFData) +import Data.Function (fix) import Data.Text (Text) import qualified Data.Text as T -import Data.Aeson.BetterErrors (Parse, key, asText, asIntegral, nth, fromAesonParser, toAesonParser, throwCustomError) +import Data.Aeson.BetterErrors (Parse, key, asText, asIntegral, nth, fromAesonParser, toAesonParser, throwCustomError, (<|>)) import Data.Aeson ((.=)) import qualified Data.Aeson as A +import Language.PureScript.AST.SourcePos import Language.PureScript.Names import qualified Language.PureScript.Constants as C +type SourceKind = Kind SourceAnn + -- | The data type of kinds -data Kind +data Kind a -- | Unification variable of type Kind - = KUnknown Int + = KUnknown a Int -- | Kinds for labelled, unordered rows without duplicates - | Row Kind + | Row a (Kind a) -- | Function kinds - | FunKind Kind Kind + | FunKind a (Kind a) (Kind a) -- | A named kind - | NamedKind (Qualified (ProperName 'KindName)) - deriving (Show, Eq, Ord, Generic) + | NamedKind a (Qualified (ProperName 'KindName)) + deriving (Show, Generic, Functor, Foldable, Traversable) + +instance NFData a => NFData (Kind a) + +srcKUnknown :: Int -> SourceKind +srcKUnknown = KUnknown NullSourceAnn + +srcRow :: SourceKind -> SourceKind +srcRow = Row NullSourceAnn -instance NFData Kind +srcFunKind :: SourceKind -> SourceKind -> SourceKind +srcFunKind = FunKind NullSourceAnn --- This is equivalent to the derived Aeson ToJSON instance, except that we --- write it out manually so that we can define a parser which is --- backwards-compatible. -instance A.ToJSON Kind where +srcNamedKind :: Qualified (ProperName 'KindName) -> SourceKind +srcNamedKind = NamedKind NullSourceAnn + +instance A.ToJSON a => A.ToJSON (Kind a) where toJSON kind = case kind of - KUnknown i -> - obj "KUnknown" i - Row k -> - obj "Row" k - FunKind k1 k2 -> - obj "FunKind" [k1, k2] - NamedKind n -> - obj "NamedKind" n + KUnknown a i -> + obj "KUnknown" a i + Row a k -> + obj "Row" a k + FunKind a k1 k2 -> + obj "FunKind" a [k1, k2] + NamedKind a n -> + obj "NamedKind" a n where - obj :: A.ToJSON a => Text -> a -> A.Value - obj tag contents = - A.object [ "tag" .= tag, "contents" .= contents ] + obj :: A.ToJSON b => Text -> a -> b -> A.Value + obj tag ann contents = + A.object [ "tag" .= tag, "annotation" .= ann, "contents" .= contents ] --- This is equivalent to the derived Aeson FromJSON instance, except that it --- also handles JSON generated by compilers up to 0.10.3 and maps them to the +-- This handles JSON generated by compilers up to 0.10.3 and maps them to the -- new representations (i.e. NamedKinds which are defined in the Prim module). -kindFromJSON :: Parse Text Kind -kindFromJSON = do +kindFromJSON :: Parse Text a -> Parse Text a -> Parse Text (Kind a) +kindFromJSON defaultAnn annFromJSON = fix $ \go -> do t <- key "tag" asText + let annFromJSON' = key "annotation" annFromJSON <|> defaultAnn case t of "KUnknown" -> - KUnknown <$> key "contents" (nth 0 asIntegral) + KUnknown <$> annFromJSON' <*> key "contents" (nth 0 asIntegral) "Star" -> - pure kindType + kindType <$> defaultAnn "Row" -> - Row <$> key "contents" kindFromJSON + Row <$> annFromJSON' <*> key "contents" go "FunKind" -> let - kindAt n = key "contents" (nth n kindFromJSON) + kindAt n = key "contents" (nth n go) in - FunKind <$> kindAt 0 <*> kindAt 1 + FunKind <$> annFromJSON' <*> kindAt 0 <*> kindAt 1 "Symbol" -> - pure kindSymbol + kindSymbol <$> defaultAnn "NamedKind" -> - NamedKind <$> key "contents" fromAesonParser + NamedKind <$> annFromJSON' <*> key "contents" fromAesonParser other -> throwCustomError (T.append "Unrecognised tag: " other) where -- The following are copied from Environment and reimplemented to avoid -- circular dependencies. - primName :: Text -> Qualified (ProperName a) + primName :: Text -> Qualified (ProperName b) primName = Qualified (Just $ ModuleName [ProperName C.prim]) . ProperName - primKind :: Text -> Kind - primKind = NamedKind . primName + primKind = flip NamedKind . primName kindType = primKind C.typ kindSymbol = primKind C.symbol -instance A.FromJSON Kind where - parseJSON = toAesonParser id kindFromJSON +-- These overlapping instances exist to preserve compatability for common +-- instances which have a sensible default for missing annotations. +instance {-# OVERLAPPING #-} A.FromJSON (Kind SourceAnn) where + parseJSON = toAesonParser id (kindFromJSON (pure NullSourceAnn) fromAesonParser) + +instance {-# OVERLAPPING #-} A.FromJSON (Kind ()) where + parseJSON = toAesonParser id (kindFromJSON (pure ()) fromAesonParser) -everywhereOnKinds :: (Kind -> Kind) -> Kind -> Kind +instance {-# OVERLAPPING #-} A.FromJSON a => A.FromJSON (Kind a) where + parseJSON = toAesonParser id (kindFromJSON (fail "Invalid annotation") fromAesonParser) + +everywhereOnKinds :: (Kind a -> Kind a) -> Kind a -> Kind a everywhereOnKinds f = go where - go (Row k1) = f (Row (go k1)) - go (FunKind k1 k2) = f (FunKind (go k1) (go k2)) + go (Row ann k1) = f (Row ann (go k1)) + go (FunKind ann k1 k2) = f (FunKind ann (go k1) (go k2)) go other = f other -everywhereOnKindsM :: Monad m => (Kind -> m Kind) -> Kind -> m Kind +everywhereOnKindsM :: Monad m => (Kind a -> m (Kind a)) -> Kind a -> m (Kind a) everywhereOnKindsM f = go where - go (Row k1) = (Row <$> go k1) >>= f - go (FunKind k1 k2) = (FunKind <$> go k1 <*> go k2) >>= f + go (Row ann k1) = (Row ann <$> go k1) >>= f + go (FunKind ann k1 k2) = (FunKind ann <$> go k1 <*> go k2) >>= f go other = f other -everythingOnKinds :: (r -> r -> r) -> (Kind -> r) -> Kind -> r +everythingOnKinds :: (r -> r -> r) -> (Kind a -> r) -> Kind a -> r everythingOnKinds (<>.) f = go where - go k@(Row k1) = f k <>. go k1 - go k@(FunKind k1 k2) = f k <>. go k1 <>. go k2 + go k@(Row _ k1) = f k <>. go k1 + go k@(FunKind _ k1 k2) = f k <>. go k1 <>. go k2 go other = f other + +annotationForKind :: Kind a -> a +annotationForKind (KUnknown a _) = a +annotationForKind (Row a _) = a +annotationForKind (FunKind a _ _) = a +annotationForKind (NamedKind a _) = a + +instance Eq (Kind a) where + (==) = eqKind + +instance Ord (Kind a) where + compare = compareKind + +eqKind :: Kind a -> Kind b -> Bool +eqKind (KUnknown _ a) (KUnknown _ a') = a == a' +eqKind (Row _ a) (Row _ a') = eqKind a a' +eqKind (FunKind _ a b) (FunKind _ a' b') = eqKind a a' && eqKind b b' +eqKind (NamedKind _ a) (NamedKind _ a') = a == a' +eqKind _ _ = False + +compareKind :: Kind a -> Kind b -> Ordering +compareKind (KUnknown _ a) (KUnknown _ a') = compare a a' +compareKind (KUnknown {}) _ = LT + +compareKind (Row _ a) (Row _ a') = compareKind a a' +compareKind (Row {}) _ = LT +compareKind _ (Row {}) = GT + +compareKind (FunKind _ a b) (FunKind _ a' b') = compareKind a b <> compareKind a' b' +compareKind (FunKind {}) _ = LT +compareKind _ (FunKind {}) = GT + +compareKind (NamedKind _ a) (NamedKind _ a') = compare a a' +compareKind (NamedKind {}) _ = GT diff --git a/src/Language/PureScript/Linter.hs b/src/Language/PureScript/Linter.hs index 1b92f7c7d4..d90c77d96f 100644 --- a/src/Language/PureScript/Linter.hs +++ b/src/Language/PureScript/Linter.hs @@ -80,40 +80,40 @@ lint (Module _ _ mn ds _) = censor (addHint (ErrorInModule mn)) $ mapM_ lintDecl checkTypeVarsInDecl :: S.Set Text -> Declaration -> MultipleErrors checkTypeVarsInDecl s d = let (f, _, _, _, _) = accumTypes (checkTypeVars (declSourceSpan d) s) in f d - checkTypeVars :: SourceSpan -> S.Set Text -> Type -> MultipleErrors + checkTypeVars :: SourceSpan -> S.Set Text -> SourceType -> MultipleErrors checkTypeVars ss set ty = everythingWithContextOnTypes set mempty mappend step ty <> snd (findUnused ty) where - step :: S.Set Text -> Type -> (S.Set Text, MultipleErrors) - step s (ForAll tv _ _) = bindVar s tv + step :: S.Set Text -> SourceType -> (S.Set Text, MultipleErrors) + step s (ForAll _ tv _ _) = bindVar s tv step s _ = (s, mempty) bindVar :: S.Set Text -> Text -> (S.Set Text, MultipleErrors) bindVar = bind ss ShadowedTypeVar - findUnused :: Type -> (S.Set Text, MultipleErrors) + findUnused :: SourceType -> (S.Set Text, MultipleErrors) findUnused = go set where -- Recursively walk the type and prune used variables from `unused` - go :: S.Set Text -> Type -> (S.Set Text, MultipleErrors) - go unused (TypeVar v) = (S.delete v unused, mempty) - go unused (ForAll tv t1 _) = + go :: S.Set Text -> SourceType -> (S.Set Text, MultipleErrors) + go unused (TypeVar _ v) = (S.delete v unused, mempty) + go unused (ForAll _ tv t1 _) = let (nowUnused, errors) = go (S.insert tv unused) t1 restoredUnused = if S.member tv unused then S.insert tv nowUnused else nowUnused combinedErrors = if S.member tv nowUnused then errors <> errorMessage' ss (UnusedTypeVar tv) else errors in (restoredUnused, combinedErrors) - go unused (TypeApp f x) = go unused f `combine` go unused x - go unused (ConstrainedType c t1) = foldl combine (unused, mempty) $ map (go unused) (constraintArgs c <> [t1]) - go unused (RCons _ t1 rest) = go unused t1 `combine` go unused rest - go unused (KindedType t1 _) = go unused t1 - go unused (ParensInType t1) = go unused t1 - go unused (BinaryNoParensType t1 t2 t3) = go unused t1 `combine` go unused t2 `combine` go unused t3 + go unused (TypeApp _ f x) = go unused f `combine` go unused x + go unused (ConstrainedType _ c t1) = foldl combine (unused, mempty) $ map (go unused) (constraintArgs c <> [t1]) + go unused (RCons _ _ t1 rest) = go unused t1 `combine` go unused rest + go unused (KindedType _ t1 _) = go unused t1 + go unused (ParensInType _ t1) = go unused t1 + go unused (BinaryNoParensType _ t1 t2 t3) = go unused t1 `combine` go unused t2 `combine` go unused t3 go unused TUnknown{} = (unused, mempty) go unused TypeLevelString{} = (unused, mempty) go unused TypeWildcard{} = (unused, mempty) go unused TypeConstructor{} = (unused, mempty) go unused TypeOp{} = (unused, mempty) go unused Skolem{} = (unused, mempty) - go unused REmpty = (unused, mempty) + go unused REmpty{} = (unused, mempty) go unused PrettyPrintFunction{} = (unused, mempty) go unused PrettyPrintObject{} = (unused, mempty) go unused PrettyPrintForAll{} = (unused, mempty) diff --git a/src/Language/PureScript/Linter/Exhaustive.hs b/src/Language/PureScript/Linter/Exhaustive.hs index 4278f509a3..ff64b442de 100644 --- a/src/Language/PureScript/Linter/Exhaustive.hs +++ b/src/Language/PureScript/Linter/Exhaustive.hs @@ -63,15 +63,15 @@ qualifyName n defmn qn = Qualified (Just mn) n -- where: - ProperName is the name of the constructor (for example, "Nothing" in Maybe) -- - [Type] is the list of arguments, if it has (for example, "Just" has [TypeVar "a"]) -- -getConstructors :: Environment -> ModuleName -> Qualified (ProperName 'ConstructorName) -> [(ProperName 'ConstructorName, [Type])] +getConstructors :: Environment -> ModuleName -> Qualified (ProperName 'ConstructorName) -> [(ProperName 'ConstructorName, [SourceType])] getConstructors env defmn n = extractConstructors lnte where - extractConstructors :: Maybe (Kind, TypeKind) -> [(ProperName 'ConstructorName, [Type])] + extractConstructors :: Maybe (SourceKind, TypeKind) -> [(ProperName 'ConstructorName, [SourceType])] extractConstructors (Just (_, DataType _ pt)) = pt extractConstructors _ = internalError "Data name not in the scope of the current environment in extractConstructors" - lnte :: Maybe (Kind, TypeKind) + lnte :: Maybe (SourceKind, TypeKind) lnte = M.lookup qpn (types env) qpn :: Qualified (ProperName 'TypeName) @@ -83,7 +83,7 @@ getConstructors env defmn n = extractConstructors lnte Nothing -> internalError $ "Constructor " ++ T.unpack (showQualified runProperName con) ++ " not in the scope of the current environment in getConsDataName." Just (_, pm, _, _) -> qualifyName pm defmn con - getConsInfo :: Qualified (ProperName 'ConstructorName) -> Maybe (DataDeclType, ProperName 'TypeName, Type, [Ident]) + getConsInfo :: Qualified (ProperName 'ConstructorName) -> Maybe (DataDeclType, ProperName 'TypeName, SourceType, [Ident]) getConsInfo con = M.lookup con (dataConstructors env) -- | @@ -303,12 +303,12 @@ checkExhaustive ss env mn numArgs cas expr = makeResult . first ordNub $ foldl' (ty tyVar)) ] - ty :: Text -> Type + ty :: Text -> SourceType ty tyVar = - ForAll tyVar - ( ConstrainedType - (Constraint C.Partial [] (Just constraintData)) - $ TypeApp (TypeApp tyFunction (TypeVar tyVar)) (TypeVar tyVar) + srcForAll tyVar + ( srcConstrainedType + (srcConstraint C.Partial [] (Just constraintData)) + $ srcTypeApp (srcTypeApp tyFunction (srcTypeVar tyVar)) (srcTypeVar tyVar) ) Nothing diff --git a/src/Language/PureScript/Parser/Declarations.hs b/src/Language/PureScript/Parser/Declarations.hs index bfc77014cb..39ddadba19 100644 --- a/src/Language/PureScript/Parser/Declarations.hs +++ b/src/Language/PureScript/Parser/Declarations.hs @@ -41,7 +41,7 @@ import Language.PureScript.Types import qualified Text.Parsec as P import qualified Text.Parsec.Expr as P -kindedIdent :: TokenParser (Text, Maybe Kind) +kindedIdent :: TokenParser (Text, Maybe SourceKind) kindedIdent = (, Nothing) <$> identifier <|> parens ((,) <$> identifier <*> (Just <$> (indented *> doubleColon *> indented *> parseKind))) @@ -204,10 +204,11 @@ parseTypeClassDeclaration = withSourceAnnF $ do indented *> mark (P.many (same *> parseTypeDeclaration)) return $ \sa -> TypeClassDeclaration sa className idents implies dependencies members -parseConstraint :: TokenParser Constraint -parseConstraint = Constraint <$> parseQualified properName - <*> P.many (noWildcards $ noForAll parseTypeAtom) - <*> pure Nothing +parseConstraint :: TokenParser SourceConstraint +parseConstraint = withSourceAnnF $ do + name <- parseQualified properName + args <- P.many (noWildcards $ noForAll parseTypeAtom) + return $ \ann -> Constraint ann name args Nothing parseInstanceDeclaration :: TokenParser (TypeInstanceBody -> Declaration) parseInstanceDeclaration = withSourceAnnF $ do diff --git a/src/Language/PureScript/Parser/Kinds.hs b/src/Language/PureScript/Parser/Kinds.hs index bb4cc2ddc1..abdc810957 100644 --- a/src/Language/PureScript/Parser/Kinds.hs +++ b/src/Language/PureScript/Parser/Kinds.hs @@ -12,10 +12,12 @@ import Language.PureScript.Parser.Lexer import qualified Text.Parsec as P import qualified Text.Parsec.Expr as P -parseNamedKind :: TokenParser Kind -parseNamedKind = NamedKind <$> parseQualified kindName +parseNamedKind :: TokenParser SourceKind +parseNamedKind = withSourceAnnF $ do + name <- parseQualified kindName + return $ \ann -> NamedKind ann name -parseKindAtom :: TokenParser Kind +parseKindAtom :: TokenParser SourceKind parseKindAtom = indented *> P.choice [ parseNamedKind @@ -25,8 +27,8 @@ parseKindAtom = -- | -- Parse a kind -- -parseKind :: TokenParser Kind +parseKind :: TokenParser SourceKind parseKind = P.buildExpressionParser operators parseKindAtom P. "kind" where - operators = [ [ P.Prefix (symbol' "#" >> return Row) ] - , [ P.Infix (rarrow >> return FunKind) P.AssocRight ] ] + operators = [ [ P.Prefix (withSourceAnnF $ symbol' "#" >> return Row) ] + , [ P.Infix (withSourceAnnF $ rarrow >> return FunKind) P.AssocRight ] ] diff --git a/src/Language/PureScript/Parser/Types.hs b/src/Language/PureScript/Parser/Types.hs index 3a9803c7bd..9f27687326 100644 --- a/src/Language/PureScript/Parser/Types.hs +++ b/src/Language/PureScript/Parser/Types.hs @@ -15,6 +15,7 @@ import qualified Data.Text as T import Language.PureScript.AST.SourcePos import Language.PureScript.Environment +import Language.PureScript.Kinds import Language.PureScript.Parser.Common import Language.PureScript.Parser.Kinds import Language.PureScript.Parser.Lexer @@ -24,40 +25,41 @@ import Language.PureScript.Label (Label(..)) import qualified Text.Parsec as P import qualified Text.Parsec.Expr as P -parseFunction :: TokenParser Type +parseFunction :: TokenParser SourceType parseFunction = parens rarrow *> return tyFunction -parseObject :: TokenParser Type -parseObject = braces $ TypeApp tyRecord <$> parseRow +parseObject :: TokenParser SourceType +parseObject = withSourceAnnF $ braces $ do + rows <- parseRow + return $ \ann -> TypeApp ann tyRecord rows -parseTypeLevelString :: TokenParser Type -parseTypeLevelString = TypeLevelString <$> stringLiteral +parseTypeLevelString :: TokenParser SourceType +parseTypeLevelString = withSourceAnnF $ flip TypeLevelString <$> stringLiteral -parseTypeWildcard :: TokenParser Type -parseTypeWildcard = do - start <- P.getPosition - let end = P.incSourceColumn start 1 - underscore - return $ TypeWildcard (SourceSpan (P.sourceName start) (toSourcePos start) (toSourcePos end)) +parseTypeWildcard :: TokenParser SourceType +parseTypeWildcard = withSourceAnnF $ underscore $> TypeWildcard -parseTypeVariable :: TokenParser Type -parseTypeVariable = do +parseTypeVariable :: TokenParser SourceType +parseTypeVariable = withSourceAnnF $ do ident <- identifier when (ident `elem` reservedTypeNames) $ P.unexpected (T.unpack ident) - return $ TypeVar ident + return $ \ann -> TypeVar ann ident -parseTypeConstructor :: TokenParser Type -parseTypeConstructor = TypeConstructor <$> parseQualified typeName - -parseForAll :: TokenParser Type -parseForAll = mkForAll <$> ((reserved "forall" <|> reserved "∀") *> P.many1 (indented *> identifier) <* indented <* dot) - <*> parseType +parseTypeConstructor :: TokenParser SourceType +parseTypeConstructor = withSourceAnnF $ flip TypeConstructor <$> parseQualified typeName +parseForAll :: TokenParser SourceType +parseForAll = + mkForAll + <$> ((reserved "forall" <|> reserved "∀") + *> (P.many1 $ indented *> (withSourceAnnF $ flip (,) <$> identifier)) + <* indented <* dot) + <*> parseType -- | -- Parse an atomic type with no `forall` -- -noForAll :: TokenParser Type -> TokenParser Type +noForAll :: TokenParser SourceType -> TokenParser SourceType noForAll p = do ty <- p when (containsForAll ty) $ P.unexpected "forall" @@ -66,7 +68,7 @@ noForAll p = do -- | -- Parse a type as it appears in e.g. a data constructor -- -parseTypeAtom :: TokenParser Type +parseTypeAtom :: TokenParser SourceType parseTypeAtom = indented *> P.choice [ P.try parseFunction , parseTypeLevelString @@ -77,31 +79,34 @@ parseTypeAtom = indented *> P.choice , parseTypeConstructor -- This try is needed due to some unfortunate ambiguities between rows and kinded types , P.try (parens parseRow) - , ParensInType <$> parens parsePolyType + , parseParensInType ] -parseConstrainedType :: TokenParser ([Constraint], Type) -parseConstrainedType = do +parseParensInType :: TokenParser SourceType +parseParensInType = withSourceAnnF $ flip ParensInType <$> parens parsePolyType + +parseConstrainedType :: TokenParser (SourceAnn, [SourceConstraint], SourceType) +parseConstrainedType = withSourceAnnF $ do constraints <- parens (commaSep1 parseConstraint) <|> pure <$> parseConstraint _ <- rfatArrow indented ty <- parseType - return (constraints, ty) + return (, constraints, ty) where - parseConstraint = do + parseConstraint = withSourceAnnF $ do className <- parseQualified properName indented ty <- P.many parseTypeAtom - return (Constraint className ty Nothing) + return $ \ann -> Constraint ann className ty Nothing -- This is here to improve the error message when the user -- tries to use the old style constraint contexts. -- TODO: Remove this before 1.0 -typeOrConstrainedType :: TokenParser Type +typeOrConstrainedType :: TokenParser SourceType typeOrConstrainedType = do e <- P.try (Left <$> parseConstrainedType) <|> Right <$> parseTypeAtom case e of - Left ([c], ty) -> pure (ConstrainedType c ty) + Left (ann, [c], ty) -> pure (ConstrainedType ann c ty) Left _ -> P.unexpected $ unlines [ "comma in constraints." @@ -114,22 +119,34 @@ typeOrConstrainedType = do ] Right ty -> pure ty -parseAnyType :: TokenParser Type +parseAnyType :: TokenParser SourceType parseAnyType = P.buildExpressionParser operators (buildPostfixParser postfixTable typeOrConstrainedType) P. "type" where - operators = [ [ P.Infix (return TypeApp) P.AssocLeft ] - , [ P.Infix (P.try (parseQualified parseOperator) >>= \ident -> - return (BinaryNoParensType (TypeOp ident))) P.AssocRight + operators = [ [ P.Infix (return mkTypeApp) P.AssocLeft ] + , [ P.Infix parseTypeOp P.AssocRight ] , [ P.Infix (rarrow $> function) P.AssocRight ] ] - postfixTable = [ \t -> KindedType t <$> (indented *> doubleColon *> parseKind) + postfixTable = [ parseKindedType ] + mkTypeApp lhs rhs = + TypeApp (widenSourceAnn (annotationForType lhs) (annotationForType rhs)) lhs rhs + + parseTypeOp = withSourceAnnF $ do + ident <- P.try (parseQualified parseOperator) + return $ \ann lhs rhs -> + BinaryNoParensType (widenSourceAnn (annotationForType lhs) (annotationForType rhs)) (TypeOp ann ident) lhs rhs + + parseKindedType ty = do + kind <- indented *> doubleColon *> parseKind + return $ KindedType (widenSourceAnn (annotationForType ty) (annotationForKind kind)) ty kind + + -- | -- Parse a monotype -- -parseType :: TokenParser Type +parseType :: TokenParser SourceType parseType = do ty <- parseAnyType unless (isMonoType ty) $ P.unexpected "polymorphic type" @@ -138,23 +155,27 @@ parseType = do -- | -- Parse a polytype -- -parsePolyType :: TokenParser Type +parsePolyType :: TokenParser SourceType parsePolyType = parseAnyType -- | -- Parse an atomic type with no wildcards -- -noWildcards :: TokenParser Type -> TokenParser Type +noWildcards :: TokenParser SourceType -> TokenParser SourceType noWildcards p = do ty <- p when (containsWildcards ty) $ P.unexpected "type wildcard" return ty -parseNameAndType :: TokenParser t -> TokenParser (Label, t) -parseNameAndType p = (,) <$> (indented *> (Label <$> parseLabel) <* indented <* doubleColon) <*> p +parseRowListItem :: TokenParser SourceType -> TokenParser (RowListItem SourceAnn) +parseRowListItem p = withSourceAnnF $ + (\name ty ann -> RowListItem ann name ty) + <$> (indented *> (Label <$> parseLabel) <* indented <* doubleColon) <*> p -parseRowEnding :: TokenParser Type -parseRowEnding = P.option REmpty $ indented *> pipe *> indented *> parseType +parseRowEnding :: TokenParser SourceType +parseRowEnding = + (indented *> pipe *> indented *> parseType) + <|> withSourceAnnF (return REmpty) -parseRow :: TokenParser Type -parseRow = (curry rowFromList <$> commaSep (parseNameAndType parsePolyType) <*> parseRowEnding) P. "row" +parseRow :: TokenParser SourceType +parseRow = (curry rowFromList <$> commaSep (parseRowListItem parsePolyType) <*> parseRowEnding) P. "row" diff --git a/src/Language/PureScript/Pretty/Kinds.hs b/src/Language/PureScript/Pretty/Kinds.hs index 9f950af9f7..275f5e33c9 100644 --- a/src/Language/PureScript/Pretty/Kinds.hs +++ b/src/Language/PureScript/Pretty/Kinds.hs @@ -19,39 +19,39 @@ import Language.PureScript.Kinds import Language.PureScript.Names import Language.PureScript.Pretty.Common -typeLiterals :: Pattern () Kind Text +typeLiterals :: Pattern () (Kind a) Text typeLiterals = mkPattern match where - match (KUnknown u) = + match (KUnknown _ u) = Just $ T.cons 'k' (T.pack (show u)) - match (NamedKind name) = + match (NamedKind _ name) = Just $ if isQualifiedWith (moduleNameFromString "Prim") name then runProperName (disqualify name) else showQualified runProperName name match _ = Nothing -matchRow :: Pattern () Kind ((), Kind) +matchRow :: Pattern () (Kind a) ((), Kind a) matchRow = mkPattern match where - match (Row k) = Just ((), k) + match (Row _ k) = Just ((), k) match _ = Nothing -funKind :: Pattern () Kind (Kind, Kind) +funKind :: Pattern () (Kind a) (Kind a, Kind a) funKind = mkPattern match where - match (FunKind arg ret) = Just (arg, ret) + match (FunKind _ arg ret) = Just (arg, ret) match _ = Nothing -- | Generate a pretty-printed string representing a Kind -prettyPrintKind :: Kind -> Text +prettyPrintKind :: Kind a -> Text prettyPrintKind = fromMaybe (internalError "Incomplete pattern") . PA.pattern matchKind () where - matchKind :: Pattern () Kind Text + matchKind :: Pattern () (Kind a) Text matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parensT matchKind) - operators :: OperatorTable () Kind Text + operators :: OperatorTable () (Kind a) Text operators = OperatorTable [ [ Wrap matchRow $ \_ k -> "# " <> k] , [ AssocR funKind $ \arg ret -> arg <> " -> " <> ret ] ] diff --git a/src/Language/PureScript/Pretty/Types.hs b/src/Language/PureScript/Pretty/Types.hs index 40c2956eb5..9d45c7f9a5 100644 --- a/src/Language/PureScript/Pretty/Types.hs +++ b/src/Language/PureScript/Pretty/Types.hs @@ -37,112 +37,112 @@ import Text.PrettyPrint.Boxes hiding ((<+>)) -- TODO(Christoph): get rid of T.unpack s -constraintsAsBox :: TypeRenderOptions -> Constraint -> Box -> Box +constraintsAsBox :: TypeRenderOptions -> Constraint a -> Box -> Box constraintsAsBox tro con ty = constraintAsBox con `before` (" " <> text doubleRightArrow <> " " <> ty) where doubleRightArrow = if troUnicode tro then "⇒" else "=>" -constraintAsBox :: Constraint -> Box -constraintAsBox (Constraint pn tys _) = typeAsBox (foldl TypeApp (TypeConstructor (fmap coerceProperName pn)) tys) +constraintAsBox :: Constraint a -> Box +constraintAsBox (Constraint ann pn tys _) = typeAsBox (foldl (TypeApp ann) (TypeConstructor ann (fmap coerceProperName pn)) tys) -- | -- Generate a pretty-printed string representing a Row -- -prettyPrintRowWith :: TypeRenderOptions -> Char -> Char -> Type -> Box +prettyPrintRowWith :: TypeRenderOptions -> Char -> Char -> Type a -> Box prettyPrintRowWith tro open close = uncurry listToBox . toList [] where - nameAndTypeToPs :: Char -> Label -> Type -> Box + nameAndTypeToPs :: Char -> Label -> Type a -> Box nameAndTypeToPs start name ty = text (start : ' ' : T.unpack (prettyPrintLabel name) ++ " " ++ doubleColon ++ " ") <> typeAsBox ty doubleColon = if troUnicode tro then "∷" else "::" - tailToPs :: Type -> Box - tailToPs REmpty = nullBox + tailToPs :: Type a -> Box + tailToPs (REmpty _) = nullBox tailToPs other = text "| " <> typeAsBox other - listToBox :: [(Label, Type)] -> Type -> Box - listToBox [] REmpty = text [open, close] + listToBox :: [(Label, Type a)] -> Type a -> Box + listToBox [] (REmpty _) = text [open, close] listToBox [] rest = text [ open, ' ' ] <> tailToPs rest <> text [ ' ', close ] listToBox ts rest = vcat left $ zipWith (\(nm, ty) i -> nameAndTypeToPs (if i == 0 then open else ',') nm ty) ts [0 :: Int ..] ++ [ tailToPs rest, text [close] ] - toList :: [(Label, Type)] -> Type -> ([(Label, Type)], Type) - toList tys (RCons name ty row) = toList ((name, ty):tys) row + toList :: [(Label, Type a)] -> Type a -> ([(Label, Type a)], Type a) + toList tys (RCons _ name ty row) = toList ((name, ty):tys) row toList tys r = (reverse tys, r) -prettyPrintRow :: Type -> String +prettyPrintRow :: Type a -> String prettyPrintRow = render . prettyPrintRowWith defaultOptions '(' ')' -typeApp :: Pattern () Type (Type, Type) +typeApp :: Pattern () (Type a) (Type a, Type a) typeApp = mkPattern match where - match (TypeApp f x) = Just (f, x) + match (TypeApp _ f x) = Just (f, x) match _ = Nothing -appliedFunction :: Pattern () Type (Type, Type) +appliedFunction :: Pattern () (Type a) (Type a, Type a) appliedFunction = mkPattern match where - match (PrettyPrintFunction arg ret) = Just (arg, ret) + match (PrettyPrintFunction _ arg ret) = Just (arg, ret) match _ = Nothing -kinded :: Pattern () Type (Kind, Type) +kinded :: Pattern () (Type a) (Kind a, Type a) kinded = mkPattern match where - match (KindedType t k) = Just (k, t) + match (KindedType _ t k) = Just (k, t) match _ = Nothing -insertPlaceholders :: Type -> Type +insertPlaceholders :: Type a -> Type a insertPlaceholders = everywhereOnTypesTopDown convertForAlls . everywhereOnTypes convert where - convert (TypeApp (TypeApp f arg) ret) | f == tyFunction = PrettyPrintFunction arg ret - convert (TypeApp o r) | o == tyRecord = PrettyPrintObject r + convert (TypeApp _ (TypeApp ann f arg) ret) | eqType f tyFunction = PrettyPrintFunction ann arg ret + convert (TypeApp ann o r) | eqType o tyRecord = PrettyPrintObject ann r convert other = other - convertForAlls (ForAll ident ty _) = go [ident] ty + convertForAlls (ForAll ann ident ty _) = go [ident] ty where - go idents (ForAll ident' ty' _) = go (ident' : idents) ty' - go idents other = PrettyPrintForAll idents other + go idents (ForAll _ ident' ty' _) = go (ident' : idents) ty' + go idents other = PrettyPrintForAll ann idents other convertForAlls other = other -constrained :: Pattern () Type (Constraint, Type) +constrained :: Pattern () (Type a) (Constraint a, Type a) constrained = mkPattern match where - match (ConstrainedType deps ty) = Just (deps, ty) + match (ConstrainedType _ deps ty) = Just (deps, ty) match _ = Nothing -explicitParens :: Pattern () Type ((), Type) +explicitParens :: Pattern () (Type a) ((), Type a) explicitParens = mkPattern match where - match (ParensInType ty) = Just ((), ty) + match (ParensInType _ ty) = Just ((), ty) match _ = Nothing -matchTypeAtom :: TypeRenderOptions -> Pattern () Type Box +matchTypeAtom :: TypeRenderOptions -> Pattern () (Type a) Box matchTypeAtom tro@TypeRenderOptions{troSuggesting = suggesting} = typeLiterals <+> fmap ((`before` (text ")")) . (text "(" <>)) (matchType tro) where - typeLiterals :: Pattern () Type Box + typeLiterals :: Pattern () (Type a) Box typeLiterals = mkPattern match where match TypeWildcard{} = Just $ text "_" - match (TypeVar var) = Just $ text $ T.unpack var - match (TypeLevelString s) = Just $ text $ T.unpack $ prettyPrintString s - match (PrettyPrintObject row) = Just $ prettyPrintRowWith tro '{' '}' row - match (TypeConstructor ctor) = Just $ text $ T.unpack $ runProperName $ disqualify ctor - match (TUnknown u) + match (TypeVar _ var) = Just $ text $ T.unpack var + match (TypeLevelString _ s) = Just $ text $ T.unpack $ prettyPrintString s + match (PrettyPrintObject _ row) = Just $ prettyPrintRowWith tro '{' '}' row + match (TypeConstructor _ ctor) = Just $ text $ T.unpack $ runProperName $ disqualify ctor + match (TUnknown _ u) | suggesting = Just $ text "_" | otherwise = Just $ text $ 't' : show u - match (Skolem name s _ _) + match (Skolem _ name s _) | suggesting = Just $ text $ T.unpack name | otherwise = Just $ text $ T.unpack name ++ show s - match REmpty = Just $ text "()" + match (REmpty _) = Just $ text "()" match row@RCons{} = Just $ prettyPrintRowWith tro '(' ')' row - match (BinaryNoParensType op l r) = + match (BinaryNoParensType _ op l r) = Just $ typeAsBox l <> text " " <> typeAsBox op <> text " " <> typeAsBox r - match (TypeOp op) = Just $ text $ T.unpack $ showQualified runOpName op + match (TypeOp _ op) = Just $ text $ T.unpack $ showQualified runOpName op match _ = Nothing -matchType :: TypeRenderOptions -> Pattern () Type Box +matchType :: TypeRenderOptions -> Pattern () (Type a) Box matchType tro = buildPrettyPrinter operators (matchTypeAtom tro) where - operators :: OperatorTable () Type Box + operators :: OperatorTable () (Type a) Box operators = OperatorTable [ [ AssocL typeApp $ \f x -> keepSingleLinesOr (moveRight 2) f x ] , [ AssocR appliedFunction $ \arg ret -> keepSingleLinesOr id arg (text rightArrow <> " " <> ret) ] @@ -163,26 +163,26 @@ matchType tro = buildPrettyPrinter operators (matchTypeAtom tro) where | rows b1 > 1 || rows b2 > 1 = vcat left [ b1, f b2 ] | otherwise = hcat top [ b1, text " ", b2] -forall_ :: Pattern () Type ([String], Type) +forall_ :: Pattern () (Type a) ([String], Type a) forall_ = mkPattern match where - match (PrettyPrintForAll idents ty) = Just (map T.unpack idents, ty) + match (PrettyPrintForAll _ idents ty) = Just (map T.unpack idents, ty) match _ = Nothing -typeAtomAsBox :: Type -> Box +typeAtomAsBox :: Type a -> Box typeAtomAsBox = fromMaybe (internalError "Incomplete pattern") . PA.pattern (matchTypeAtom defaultOptions) () . insertPlaceholders -- | Generate a pretty-printed string representing a Type, as it should appear inside parentheses -prettyPrintTypeAtom :: Type -> String +prettyPrintTypeAtom :: Type a -> String prettyPrintTypeAtom = render . typeAtomAsBox -typeAsBox :: Type -> Box +typeAsBox :: Type a -> Box typeAsBox = typeAsBoxImpl defaultOptions -suggestedTypeAsBox :: Type -> Box +suggestedTypeAsBox :: Type a -> Box suggestedTypeAsBox = typeAsBoxImpl suggestingOptions data TypeRenderOptions = TypeRenderOptions @@ -199,26 +199,26 @@ defaultOptions = TypeRenderOptions False False unicodeOptions :: TypeRenderOptions unicodeOptions = TypeRenderOptions False True -typeAsBoxImpl :: TypeRenderOptions -> Type -> Box +typeAsBoxImpl :: TypeRenderOptions -> Type a -> Box typeAsBoxImpl tro = fromMaybe (internalError "Incomplete pattern") . PA.pattern (matchType tro) () . insertPlaceholders -- | Generate a pretty-printed string representing a 'Type' -prettyPrintType :: Type -> String +prettyPrintType :: Type a -> String prettyPrintType = prettyPrintType' defaultOptions -- | Generate a pretty-printed string representing a 'Type' using unicode -- symbols where applicable -prettyPrintTypeWithUnicode :: Type -> String +prettyPrintTypeWithUnicode :: Type a -> String prettyPrintTypeWithUnicode = prettyPrintType' unicodeOptions -- | Generate a pretty-printed string representing a suggested 'Type' -prettyPrintSuggestedType :: Type -> String +prettyPrintSuggestedType :: Type a -> String prettyPrintSuggestedType = prettyPrintType' suggestingOptions -prettyPrintType' :: TypeRenderOptions -> Type -> String +prettyPrintType' :: TypeRenderOptions -> Type a -> String prettyPrintType' tro = render . typeAsBoxImpl tro prettyPrintLabel :: Label -> Text diff --git a/src/Language/PureScript/Pretty/Values.hs b/src/Language/PureScript/Pretty/Values.hs index 7902526c03..ad45d2a19a 100644 --- a/src/Language/PureScript/Pretty/Values.hs +++ b/src/Language/PureScript/Pretty/Values.hs @@ -85,7 +85,7 @@ prettyPrintValue d (Do els) = prettyPrintValue d (Ado els yield) = text "ado " <> vcat left (map (prettyPrintDoNotationElement (d - 1)) els) // (text "in " <> prettyPrintValue (d - 1) yield) -prettyPrintValue _ (TypeClassDictionary (Constraint name tys _) _ _) = foldl1 beforeWithSpace $ text ("#dict " ++ T.unpack (runProperName (disqualify name))) : map typeAtomAsBox tys +prettyPrintValue _ (TypeClassDictionary (Constraint _ name tys _) _ _) = foldl1 beforeWithSpace $ text ("#dict " ++ T.unpack (runProperName (disqualify name))) : map typeAtomAsBox tys prettyPrintValue _ (DeferredDictionary name _) = text $ "#dict " ++ T.unpack (runProperName (disqualify name)) prettyPrintValue _ (TypeClassDictionaryAccessor className ident) = text "#dict-accessor " <> text (T.unpack (runProperName (disqualify className))) <> text "." <> text (T.unpack (showIdent ident)) <> text ">" diff --git a/src/Language/PureScript/Sugar/BindingGroups.hs b/src/Language/PureScript/Sugar/BindingGroups.hs index f78c9dd6bd..a4efc201d6 100644 --- a/src/Language/PureScript/Sugar/BindingGroups.hs +++ b/src/Language/PureScript/Sugar/BindingGroups.hs @@ -138,13 +138,13 @@ usedTypeNames moduleName = let (f, _, _, _, _) = accumTypes (everythingOnTypes (++) usedNames) in ordNub . f where - usedNames :: Type -> [ProperName 'TypeName] - usedNames (ConstrainedType con _) = + usedNames :: SourceType -> [ProperName 'TypeName] + usedNames (ConstrainedType _ con _) = case con of - (Constraint (Qualified (Just moduleName') name) _ _) + (Constraint _ (Qualified (Just moduleName') name) _ _) | moduleName == moduleName' -> [coerceProperName name] _ -> [] - usedNames (TypeConstructor (Qualified (Just moduleName') name)) + usedNames (TypeConstructor _ (Qualified (Just moduleName') name)) | moduleName == moduleName' = [name] usedNames _ = [] diff --git a/src/Language/PureScript/Sugar/Names.hs b/src/Language/PureScript/Sugar/Names.hs index afa770f2c7..22961398d2 100644 --- a/src/Language/PureScript/Sugar/Names.hs +++ b/src/Language/PureScript/Sugar/Names.hs @@ -306,35 +306,35 @@ renameInModule imports (Module modSS coms mn decls exps) = letBoundVariable :: Declaration -> Maybe Ident letBoundVariable = fmap valdeclIdent . getValueDeclaration - updateKindsEverywhere :: SourceSpan -> Kind -> m Kind + updateKindsEverywhere :: SourceSpan -> Kind a -> m (Kind a) updateKindsEverywhere pos = everywhereOnKindsM updateKind where - updateKind :: Kind -> m Kind - updateKind (NamedKind name) = NamedKind <$> updateKindName name pos + updateKind :: Kind a -> m (Kind a) + updateKind (NamedKind ann name) = NamedKind ann <$> updateKindName name pos updateKind k = return k updateTypeArguments :: (Traversable f, Traversable g) => SourceSpan - -> f (a, g Kind) -> m (f (a, g Kind)) + -> f (a, g (Kind ann)) -> m (f (a, g (Kind ann))) updateTypeArguments pos = traverse (sndM (traverse (updateKindsEverywhere pos))) - updateTypesEverywhere :: SourceSpan -> Type -> m Type + updateTypesEverywhere :: SourceSpan -> Type a -> m (Type a) updateTypesEverywhere pos = everywhereOnTypesM updateType where - updateType :: Type -> m Type - updateType (TypeOp name) = TypeOp <$> updateTypeOpName name pos - updateType (TypeConstructor name) = TypeConstructor <$> updateTypeName name pos - updateType (ConstrainedType c t) = ConstrainedType <$> updateInConstraint c <*> pure t - updateType (KindedType t k) = KindedType t <$> updateKindsEverywhere pos k + updateType :: Type a -> m (Type a) + updateType (TypeOp ann name) = TypeOp ann <$> updateTypeOpName name pos + updateType (TypeConstructor ann name) = TypeConstructor ann <$> updateTypeName name pos + updateType (ConstrainedType ann c t) = ConstrainedType ann <$> updateInConstraint c <*> pure t + updateType (KindedType ann t k) = KindedType ann t <$> updateKindsEverywhere pos k updateType t = return t - updateInConstraint :: Constraint -> m Constraint - updateInConstraint (Constraint name ts info) = - Constraint <$> updateClassName name pos <*> pure ts <*> pure info + updateInConstraint :: Constraint a -> m (Constraint a) + updateInConstraint (Constraint ann name ts info) = + Constraint ann <$> updateClassName name pos <*> pure ts <*> pure info - updateConstraints :: SourceSpan -> [Constraint] -> m [Constraint] - updateConstraints pos = traverse $ \(Constraint name ts info) -> - Constraint + updateConstraints :: SourceSpan -> [Constraint a] -> m [Constraint a] + updateConstraints pos = traverse $ \(Constraint ann name ts info) -> + Constraint ann <$> updateClassName name pos <*> traverse (updateTypesEverywhere pos) ts <*> pure info diff --git a/src/Language/PureScript/Sugar/Operators.hs b/src/Language/PureScript/Sugar/Operators.hs index 2ca1b1f88a..9a2868f4b3 100644 --- a/src/Language/PureScript/Sugar/Operators.hs +++ b/src/Language/PureScript/Sugar/Operators.hs @@ -166,11 +166,11 @@ rebracketFiltered pred_ externs modules = do internalError "BinaryNoParensBinder has no OpBinder" goBinder pos other = return (pos, other) - goType :: SourceSpan -> Type -> m Type - goType pos (BinaryNoParensType (TypeOp op) lhs rhs) = + goType :: SourceSpan -> SourceType -> m SourceType + goType pos (BinaryNoParensType ann (TypeOp ann2 op) lhs rhs) = case op `M.lookup` typeAliased of Just alias -> - return $ TypeApp (TypeApp (TypeConstructor alias) lhs) rhs + return $ TypeApp ann (TypeApp ann (TypeConstructor ann2 alias) lhs) rhs Nothing -> throwError . errorMessage' pos $ UnknownName $ fmap TyOpName op goType _ other = return other @@ -202,7 +202,7 @@ rebracketModule pred_ valueOpTable typeOpTable (Module ss coms mn ds exts) = (goDecl, goExpr', goBinder') = updateTypes goType - goType :: SourceSpan -> Type -> m Type + goType :: SourceSpan -> SourceType -> m SourceType goType = flip matchTypeOperators typeOpTable wrap :: (a -> m a) -> (SourceSpan, a) -> m (SourceSpan, a) @@ -227,8 +227,8 @@ removeParens = f goBinder (ParensInBinder b) = goBinder b goBinder b = b - goType :: Type -> Type - goType (ParensInType t) = goType t + goType :: Type a -> Type a + goType (ParensInType _ t) = goType t goType t = t decontextify @@ -302,7 +302,7 @@ customOperatorTable fixities = updateTypes :: forall m . Monad m - => (SourceSpan -> Type -> m Type) + => (SourceSpan -> SourceType -> m SourceType) -> ( Declaration -> m Declaration , SourceSpan -> Expr -> m (SourceSpan, Expr) , SourceSpan -> Binder -> m (SourceSpan, Binder) @@ -310,7 +310,7 @@ updateTypes updateTypes goType = (goDecl, goExpr, goBinder) where - goType' :: SourceSpan -> Type -> m Type + goType' :: SourceSpan -> SourceType -> m SourceType goType' = everywhereOnTypesTopDownM . goType goDecl :: Declaration -> m Declaration @@ -334,9 +334,9 @@ updateTypes goType = (goDecl, goExpr, goBinder) goExpr :: SourceSpan -> Expr -> m (SourceSpan, Expr) goExpr _ e@(PositionedValue pos _ _) = return (pos, e) - goExpr pos (TypeClassDictionary (Constraint name tys info) dicts hints) = do + goExpr pos (TypeClassDictionary (Constraint ann name tys info) dicts hints) = do tys' <- traverse (goType' pos) tys - return (pos, TypeClassDictionary (Constraint name tys' info) dicts hints) + return (pos, TypeClassDictionary (Constraint ann name tys' info) dicts hints) goExpr pos (DeferredDictionary cls tys) = do tys' <- traverse (goType' pos) tys return (pos, DeferredDictionary cls tys') diff --git a/src/Language/PureScript/Sugar/Operators/Types.hs b/src/Language/PureScript/Sugar/Operators/Types.hs index 5022a13cab..fd2e1a188d 100644 --- a/src/Language/PureScript/Sugar/Operators/Types.hs +++ b/src/Language/PureScript/Sugar/Operators/Types.hs @@ -13,22 +13,22 @@ matchTypeOperators :: MonadError MultipleErrors m => SourceSpan -> [[(Qualified (OpName 'TypeOpName), Associativity)]] - -> Type - -> m Type + -> SourceType + -> m SourceType matchTypeOperators ss = matchOperators isBinOp extractOp fromOp reapply id where - isBinOp :: Type -> Bool + isBinOp :: SourceType -> Bool isBinOp BinaryNoParensType{} = True isBinOp _ = False - extractOp :: Type -> Maybe (Type, Type, Type) - extractOp (BinaryNoParensType op l r) = Just (op, l, r) + extractOp :: SourceType -> Maybe (SourceType, SourceType, SourceType) + extractOp (BinaryNoParensType _ op l r) = Just (op, l, r) extractOp _ = Nothing - fromOp :: Type -> Maybe (SourceSpan, Qualified (OpName 'TypeOpName)) - fromOp (TypeOp q@(Qualified _ (OpName _))) = Just (ss, q) + fromOp :: SourceType -> Maybe (SourceSpan, Qualified (OpName 'TypeOpName)) + fromOp (TypeOp _ q@(Qualified _ (OpName _))) = Just (ss, q) fromOp _ = Nothing - reapply :: a -> Qualified (OpName 'TypeOpName) -> Type -> Type -> Type - reapply _ = BinaryNoParensType . TypeOp + reapply :: a -> Qualified (OpName 'TypeOpName) -> SourceType -> SourceType -> SourceType + reapply _ = srcBinaryNoParensType . srcTypeOp diff --git a/src/Language/PureScript/Sugar/TypeClasses.hs b/src/Language/PureScript/Sugar/TypeClasses.hs index 0645bcde7d..08e4af2b92 100644 --- a/src/Language/PureScript/Sugar/TypeClasses.hs +++ b/src/Language/PureScript/Sugar/TypeClasses.hs @@ -193,12 +193,12 @@ desugarDecl mn exps = go dictDecl <- typeInstanceDictionaryDeclaration sa name mn deps className tys desugared return (expRef name className tys, [d, dictDecl]) go d@(TypeInstanceDeclaration sa _ _ name deps className tys (NewtypeInstanceWithDictionary dict)) = do - let dictTy = foldl TypeApp (TypeConstructor (fmap coerceProperName className)) tys - constrainedTy = quantify (foldr ConstrainedType dictTy deps) + let dictTy = foldl srcTypeApp (srcTypeConstructor (fmap coerceProperName className)) tys + constrainedTy = quantify (foldr (srcConstrainedType) dictTy deps) return (expRef name className tys, [d, ValueDecl sa name Private [] [MkUnguarded (TypedValue True dict constrainedTy)]]) go other = return (Nothing, [other]) - expRef :: Ident -> Qualified (ProperName 'ClassName) -> [Type] -> Maybe DeclarationRef + expRef :: Ident -> Qualified (ProperName 'ClassName) -> [SourceType] -> Maybe DeclarationRef expRef name className tys | isExportedClass className && all isExportedType (getConstructors `concatMap` tys) = Just $ TypeInstanceRef genSpan name | otherwise = Nothing @@ -220,39 +220,40 @@ desugarDecl mn exps = go matchesTypeRef pn (TypeRef _ pn' _) = pn == pn' matchesTypeRef _ _ = False - getConstructors :: Type -> [Qualified (ProperName 'TypeName)] + getConstructors :: SourceType -> [Qualified (ProperName 'TypeName)] getConstructors = everythingOnTypes (++) getConstructor where - getConstructor (TypeConstructor tcname) = [tcname] + getConstructor (TypeConstructor _ tcname) = [tcname] getConstructor _ = [] genSpan :: SourceSpan genSpan = internalModuleSourceSpan "" -memberToNameAndType :: Declaration -> (Ident, Type) +memberToNameAndType :: Declaration -> (Ident, SourceType) memberToNameAndType (TypeDeclaration td) = unwrapTypeDeclaration td memberToNameAndType _ = internalError "Invalid declaration in type class definition" typeClassDictionaryDeclaration :: SourceAnn -> ProperName 'ClassName - -> [(Text, Maybe Kind)] - -> [Constraint] + -> [(Text, Maybe SourceKind)] + -> [SourceConstraint] -> [Declaration] -> Declaration typeClassDictionaryDeclaration sa name args implies members = let superclassTypes = superClassDictionaryNames implies `zip` - [ function unit (foldl TypeApp (TypeConstructor (fmap coerceProperName superclass)) tyArgs) - | (Constraint superclass tyArgs _) <- implies + [ function unit (foldl srcTypeApp (srcTypeConstructor (fmap coerceProperName superclass)) tyArgs) + | (Constraint _ superclass tyArgs _) <- implies ] members' = map (first runIdent . memberToNameAndType) members mtys = members' ++ superclassTypes - in TypeSynonymDeclaration sa (coerceProperName name) args (TypeApp tyRecord $ rowFromList (map (first (Label . mkString)) mtys, REmpty)) + toRowListItem (l, t) = srcRowListItem (Label $ mkString l) t + in TypeSynonymDeclaration sa (coerceProperName name) args (srcTypeApp tyRecord $ rowFromList (map toRowListItem mtys, srcREmpty)) typeClassMemberToDictionaryAccessor :: ModuleName -> ProperName 'ClassName - -> [(Text, Maybe Kind)] + -> [(Text, Maybe SourceKind)] -> Declaration -> Declaration typeClassMemberToDictionaryAccessor mn name args (TypeDeclaration (TypeDeclarationData sa ident ty)) = @@ -260,12 +261,12 @@ typeClassMemberToDictionaryAccessor mn name args (TypeDeclaration (TypeDeclarati in ValueDecl sa ident Private [] $ [MkUnguarded ( TypedValue False (TypeClassDictionaryAccessor className ident) $ - moveQuantifiersToFront (quantify (ConstrainedType (Constraint className (map (TypeVar . fst) args) Nothing) ty)) + moveQuantifiersToFront (quantify (srcConstrainedType (srcConstraint className (map (srcTypeVar . fst) args) Nothing) ty)) )] typeClassMemberToDictionaryAccessor _ _ _ _ = internalError "Invalid declaration in type class definition" -unit :: Type -unit = TypeApp tyRecord REmpty +unit :: SourceType +unit = srcTypeApp tyRecord srcREmpty typeInstanceDictionaryDeclaration :: forall m @@ -273,9 +274,9 @@ typeInstanceDictionaryDeclaration => SourceAnn -> Ident -> ModuleName - -> [Constraint] + -> [SourceConstraint] -> Qualified (ProperName 'ClassName) - -> [Type] + -> [SourceType] -> [Declaration] -> Desugar m Declaration typeInstanceDictionaryDeclaration sa@(ss, _) name mn deps className tys decls = @@ -303,20 +304,20 @@ typeInstanceDictionaryDeclaration sa@(ss, _) name mn deps className tys decls = -- The dictionary itself is a record literal. let superclasses = superClassDictionaryNames typeClassSuperclasses `zip` [ Abs (VarBinder ss UnusedIdent) (DeferredDictionary superclass tyArgs) - | (Constraint superclass suTyArgs _) <- typeClassSuperclasses + | (Constraint _ superclass suTyArgs _) <- typeClassSuperclasses , let tyArgs = map (replaceAllTypeVars (zip (map fst typeClassArguments) tys)) suTyArgs ] let props = Literal ss $ ObjectLiteral $ map (first mkString) (members ++ superclasses) - dictTy = foldl TypeApp (TypeConstructor (fmap coerceProperName className)) tys - constrainedTy = quantify (foldr ConstrainedType dictTy deps) + dictTy = foldl srcTypeApp (srcTypeConstructor (fmap coerceProperName className)) tys + constrainedTy = quantify (foldr srcConstrainedType dictTy deps) dict = TypeClassDictionaryConstructorApp className props result = ValueDecl sa name Private [] [MkUnguarded (TypedValue True dict constrainedTy)] return result where - memberToValue :: [(Ident, Type)] -> Declaration -> Desugar m Expr + memberToValue :: [(Ident, SourceType)] -> Declaration -> Desugar m Expr memberToValue tys' (ValueDecl (ss', _) ident _ [] [MkUnguarded val]) = do _ <- maybe (throwError . errorMessage' ss' $ ExtraneousClassMember ident className) return $ lookup ident tys' return val @@ -330,8 +331,8 @@ declIdent _ = Nothing typeClassMemberName :: Declaration -> Text typeClassMemberName = fromMaybe (internalError "typeClassMemberName: Invalid declaration in type class definition") . fmap runIdent . declIdent -superClassDictionaryNames :: [Constraint] -> [Text] +superClassDictionaryNames :: [Constraint a] -> [Text] superClassDictionaryNames supers = [ superclassName pn index - | (index, Constraint pn _ _) <- zip [0..] supers + | (index, Constraint _ pn _ _) <- zip [0..] supers ] diff --git a/src/Language/PureScript/Sugar/TypeClasses/Deriving.hs b/src/Language/PureScript/Sugar/TypeClasses/Deriving.hs index 32398ad956..59d38aba82 100755 --- a/src/Language/PureScript/Sugar/TypeClasses/Deriving.hs +++ b/src/Language/PureScript/Sugar/TypeClasses/Deriving.hs @@ -34,7 +34,7 @@ import Language.PureScript.TypeChecker.Synonyms (SynonymMap, replaceAl -- instances were derived in the same way. This data structure is used to ensure -- this property. data NewtypeDerivedInstances = NewtypeDerivedInstances - { ndiClasses :: M.Map (ModuleName, ProperName 'ClassName) ([Text], [Constraint], [FunctionalDependency]) + { ndiClasses :: M.Map (ModuleName, ProperName 'ClassName) ([Text], [SourceConstraint], [FunctionalDependency]) -- ^ A list of superclass constraints for each type class. Since type classes -- have not been desugared here, we need to track this. , ndiDerivedInstances :: S.Set ((ModuleName, ProperName 'ClassName), (ModuleName, ProperName 'TypeName)) @@ -57,11 +57,11 @@ instance Monoid NewtypeDerivedInstances where -- (no flexible instances allowed), we don't need to bother with unification when -- looking for matching superclass instances, which saves us a lot of work. Instead, -- we just match the newtype name. -extractNewtypeName :: ModuleName -> [Type] -> Maybe (ModuleName, ProperName 'TypeName) +extractNewtypeName :: ModuleName -> [SourceType] -> Maybe (ModuleName, ProperName 'TypeName) extractNewtypeName _ [] = Nothing extractNewtypeName mn xs = go (last xs) where - go (TypeApp ty (TypeVar _)) = go ty - go (TypeConstructor name) = Just (qualify mn name) + go (TypeApp _ ty (TypeVar _ _)) = go ty + go (TypeConstructor _ name) = Just (qualify mn name) go _ = Nothing -- | Elaborates deriving instance declarations by code generation. @@ -178,11 +178,11 @@ deriveInstance mn syns ndis ds (TypeInstanceDeclaration sa@(ss, _) ch idx nm dep _ -> throwError . errorMessage' ss $ InvalidNewtypeInstance className tys deriveInstance _ _ _ _ e = return e -unwrapTypeConstructor :: Type -> Maybe (Qualified (ProperName 'TypeName), [Type]) +unwrapTypeConstructor :: SourceType -> Maybe (Qualified (ProperName 'TypeName), [SourceType]) unwrapTypeConstructor = fmap (second reverse) . go where - go (TypeConstructor tyCon) = Just (tyCon, []) - go (TypeApp ty arg) = do + go (TypeConstructor _ tyCon) = Just (tyCon, []) + go (TypeApp _ ty arg) = do (tyCon, args) <- go ty return (tyCon, arg : args) go _ = Nothing @@ -196,9 +196,9 @@ deriveNewtypeInstance -> NewtypeDerivedInstances -> Qualified (ProperName 'ClassName) -> [Declaration] - -> [Type] + -> [SourceType] -> ProperName 'TypeName - -> [Type] + -> [SourceType] -> m Expr deriveNewtypeInstance ss mn syns ndis className ds tys tyConNm dargs = do verifySuperclasses @@ -226,9 +226,9 @@ deriveNewtypeInstance ss mn syns ndis className ds tys tyConNm dargs = do takeReverse :: Int -> [a] -> [a] takeReverse n = take n . reverse - stripRight :: [(Text, Maybe kind)] -> Type -> Maybe Type + stripRight :: [(Text, Maybe kind)] -> SourceType -> Maybe SourceType stripRight [] ty = Just ty - stripRight ((arg, _) : args) (TypeApp t (TypeVar arg')) + stripRight ((arg, _) : args) (TypeApp _ t (TypeVar _ arg')) | arg == arg' = stripRight args t stripRight _ _ = Nothing @@ -246,8 +246,8 @@ deriveNewtypeInstance ss mn syns ndis className ds tys tyConNm dargs = do -- Everything else raises a UnverifiableSuperclassInstance warning. -- This covers pretty much all cases we're interested in, but later we might want to do -- more work to extend this to other superclass relationships. - let determined = map (TypeVar . (args !!)) . ordNub . concatMap fdDetermined . filter ((== [length args - 1]) . fdDeterminers) $ deps - if last constraintArgs == TypeVar (last args) && all (`elem` determined) (init constraintArgs) + let determined = map (srcTypeVar . (args !!)) . ordNub . concatMap fdDetermined . filter ((== [length args - 1]) . fdDeterminers) $ deps + if eqType (last constraintArgs) (srcTypeVar (last args)) && all (`elem` determined) (init constraintArgs) then do -- Now make sure that a superclass instance was derived. Again, this is not a complete -- check, since the superclass might have multiple type arguments, so overlaps might still @@ -283,14 +283,14 @@ deriveGenericRep -> SynonymMap -> [Declaration] -> ProperName 'TypeName - -> [Type] - -> Type - -> m ([Declaration], Type) + -> [SourceType] + -> SourceType + -> m ([Declaration], SourceType) deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do checkIsWildcard ss tyConNm repTy go =<< findTypeDecl ss tyConNm ds where - go :: Declaration -> m ([Declaration], Type) + go :: Declaration -> m ([Declaration], SourceType) go (DataDeclaration (ss', _) _ _ args dctors) = do x <- freshIdent "x" (reps, to, from) <- unzip3 <$> traverse makeInst dctors @@ -337,13 +337,13 @@ deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do compN n f = f . compN (n - 1) f makeInst - :: (ProperName 'ConstructorName, [Type]) - -> m (Type, CaseAlternative, CaseAlternative) + :: (ProperName 'ConstructorName, [SourceType]) + -> m (SourceType, CaseAlternative, CaseAlternative) makeInst (ctorName, args) = do args' <- mapM (replaceAllTypeSynonymsM syns) args (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args' - return ( TypeApp (TypeApp (TypeConstructor constructor) - (TypeLevelString $ mkString (runProperName ctorName))) + return ( srcTypeApp (srcTypeApp (srcTypeConstructor constructor) + (srcTypeLevelString $ mkString (runProperName ctorName))) ctorTy , CaseAlternative [ ConstructorBinder ss constructor [matchProduct] ] (unguarded (foldl' App (Constructor ss (Qualified (Just mn) ctorName)) ctorArgs)) @@ -352,23 +352,23 @@ deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do ) makeProduct - :: [Type] - -> m (Type, Binder, [Expr], [Binder], Expr) + :: [SourceType] + -> m (SourceType, Binder, [Expr], [Binder], Expr) makeProduct [] = pure (noArgs, NullBinder, [], [], noArgs') makeProduct args = do (tys, bs1, es1, bs2, es2) <- unzip5 <$> traverse makeArg args - pure ( foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f)) tys + pure ( foldr1 (\f -> srcTypeApp (srcTypeApp (srcTypeConstructor productName) f)) tys , foldr1 (\b1 b2 -> ConstructorBinder ss productName [b1, b2]) bs1 , es1 , bs2 , foldr1 (\e1 -> App (App (Constructor ss productName) e1)) es2 ) - makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr) + makeArg :: SourceType -> m (SourceType, Binder, Expr, Binder, Expr) makeArg arg = do argName <- freshIdent "arg" - pure ( TypeApp (TypeConstructor argument) arg + pure ( srcTypeApp (srcTypeConstructor argument) arg , ConstructorBinder ss argument [ VarBinder ss argName ] , Var ss (Qualified Nothing argName) , VarBinder ss argName @@ -382,10 +382,10 @@ deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do underExpr f (CaseAlternative b [MkUnguarded e]) = CaseAlternative b (unguarded (f e)) underExpr _ _ = internalError "underExpr: expected unguarded alternative" - toRepTy :: [Type] -> Type + toRepTy :: [SourceType] -> SourceType toRepTy [] = noCtors toRepTy [only] = only - toRepTy ctors = foldr1 (\f -> TypeApp (TypeApp sumCtor f)) ctors + toRepTy ctors = foldr1 (\f -> srcTypeApp (srcTypeApp sumCtor f)) ctors toName :: Expr toName = Var ss (Qualified (Just dataGenericRep) (Ident "to")) @@ -393,17 +393,17 @@ deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do fromName :: Expr fromName = Var ss (Qualified (Just dataGenericRep) (Ident "from")) - noCtors :: Type - noCtors = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoConstructors")) + noCtors :: SourceType + noCtors = srcTypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoConstructors")) - noArgs :: Type - noArgs = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoArguments")) + noArgs :: SourceType + noArgs = srcTypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoArguments")) noArgs' :: Expr noArgs' = Constructor ss (Qualified (Just dataGenericRep) (ProperName "NoArguments")) - sumCtor :: Type - sumCtor = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "Sum")) + sumCtor :: SourceType + sumCtor = srcTypeConstructor (Qualified (Just dataGenericRep) (ProperName "Sum")) inl :: Qualified (ProperName 'ConstructorName) inl = Qualified (Just dataGenericRep) (ProperName "Inl") @@ -426,7 +426,7 @@ deriveGenericRep ss mn syns ds tyConNm tyConArgs repTy = do argument' :: Expr -> Expr argument' = App (Constructor ss argument) -checkIsWildcard :: MonadError MultipleErrors m => SourceSpan -> ProperName 'TypeName -> Type -> m () +checkIsWildcard :: MonadError MultipleErrors m => SourceSpan -> ProperName 'TypeName -> SourceType -> m () checkIsWildcard _ _ (TypeWildcard _) = return () checkIsWildcard ss tyConNm _ = throwError . errorMessage' ss $ ExpectedWildcard tyConNm @@ -468,7 +468,7 @@ deriveEq ss mn syns ds tyConNm = do where catchAll = CaseAlternative [NullBinder, NullBinder] (unguarded (Literal ss (BooleanLiteral False))) - mkCtorClause :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative + mkCtorClause :: (ProperName 'ConstructorName, [SourceType]) -> m CaseAlternative mkCtorClause (ctorName, tys) = do identsL <- replicateM (length tys) (freshIdent "l") identsR <- replicateM (length tys) (freshIdent "r") @@ -482,7 +482,7 @@ deriveEq ss mn syns ds tyConNm = do conjAll [] = Literal ss (BooleanLiteral True) conjAll xs = foldl1 preludeConj xs - toEqTest :: Expr -> Expr -> Type -> Expr + toEqTest :: Expr -> Expr -> SourceType -> Expr toEqTest l r ty | Just rec <- objectType ty , Just fields <- decomposeRec rec = @@ -547,7 +547,7 @@ deriveOrd ss mn syns ds tyConNm = do ordCompare1 :: Expr -> Expr -> Expr ordCompare1 = App . App (Var ss (Qualified (Just dataOrd) (Ident C.compare1))) - mkCtorClauses :: ((ProperName 'ConstructorName, [Type]), Bool) -> m [CaseAlternative] + mkCtorClauses :: ((ProperName 'ConstructorName, [SourceType]), Bool) -> m [CaseAlternative] mkCtorClauses ((ctorName, tys), isLast) = do identsL <- replicateM (length tys) (freshIdent "l") identsR <- replicateM (length tys) (freshIdent "r") @@ -583,7 +583,7 @@ deriveOrd ss mn syns ds tyConNm = do (unguarded (appendAll xs)) ] - toOrdering :: Expr -> Expr -> Type -> Expr + toOrdering :: Expr -> Expr -> SourceType -> Expr toOrdering l r ty | Just rec <- objectType ty , Just fields <- decomposeRec rec = @@ -608,14 +608,14 @@ deriveNewtype -> SynonymMap -> [Declaration] -> ProperName 'TypeName - -> [Type] - -> Type - -> m ([Declaration], Type) + -> [SourceType] + -> SourceType + -> m ([Declaration], SourceType) deriveNewtype ss mn syns ds tyConNm tyConArgs unwrappedTy = do checkIsWildcard ss tyConNm unwrappedTy go =<< findTypeDecl ss tyConNm ds where - go :: Declaration -> m ([Declaration], Type) + go :: Declaration -> m ([Declaration], SourceType) go (DataDeclaration (ss', _) Data name _ _) = throwError . errorMessage' ss' $ CannotDeriveNewtypeForData name go (DataDeclaration (ss', _) Newtype name args dctors) = do @@ -665,23 +665,23 @@ mkVarMn ss mn = Var ss . Qualified mn mkVar :: SourceSpan -> Ident -> Expr mkVar ss = mkVarMn ss Nothing -isAppliedVar :: Type -> Bool -isAppliedVar (TypeApp (TypeVar _) _) = True +isAppliedVar :: Type a -> Bool +isAppliedVar (TypeApp _ (TypeVar _ _) _) = True isAppliedVar _ = False -objectType :: Type -> Maybe Type -objectType (TypeApp (TypeConstructor C.Record) rec) = Just rec +objectType :: Type a -> Maybe (Type a) +objectType (TypeApp _ (TypeConstructor _ C.Record) rec) = Just rec objectType _ = Nothing -decomposeRec :: Type -> Maybe [(Label, Type)] +decomposeRec :: SourceType -> Maybe [(Label, SourceType)] decomposeRec = fmap (sortBy (comparing fst)) . go - where go (RCons str typ typs) = fmap ((str, typ) :) (go typs) - go REmpty = Just [] + where go (RCons _ str typ typs) = fmap ((str, typ) :) (go typs) + go (REmpty _) = Just [] go _ = Nothing -decomposeRec' :: Type -> [(Label, Type)] +decomposeRec' :: SourceType -> [(Label, SourceType)] decomposeRec' = sortBy (comparing fst) . go - where go (RCons str typ typs) = (str, typ) : go typs + where go (RCons _ str typ typs) = (str, typ) : go typs go _ = [] deriveFunctor @@ -700,14 +700,14 @@ deriveFunctor ss mn syns ds tyConNm = do where mkMapFunction :: Declaration -> m Expr mkMapFunction (DataDeclaration (ss', _) _ _ tys ctors) = case reverse tys of - [] -> throwError . errorMessage' ss' $ KindsDoNotUnify (FunKind kindType kindType) kindType + [] -> throwError . errorMessage' ss' $ KindsDoNotUnify (FunKind nullSourceAnn kindType kindType) kindType ((iTy, _) : _) -> do f <- freshIdent "f" m <- freshIdent "m" lam ss' f . lamCase ss' m <$> mapM (mkCtorClause iTy f) ctors mkMapFunction _ = internalError "mkMapFunction: expected DataDeclaration" - mkCtorClause :: Text -> Ident -> (ProperName 'ConstructorName, [Type]) -> m CaseAlternative + mkCtorClause :: Text -> Ident -> (ProperName 'ConstructorName, [SourceType]) -> m CaseAlternative mkCtorClause iTyName f (ctorName, ctorTys) = do idents <- replicateM (length ctorTys) (freshIdent "v") ctorTys' <- mapM (replaceAllTypeSynonymsM syns) ctorTys @@ -721,12 +721,12 @@ deriveFunctor ss mn syns ds tyConNm = do mapVar = mkVarMn ss (Just dataFunctor) (Ident C.map) -- TODO: deal with type synonyms, ala https://github.com/purescript/purescript/pull/2516 - transformArg :: Ident -> Type -> m Expr + transformArg :: Ident -> SourceType -> m Expr transformArg ident = fmap (foldr App (mkVar ss ident)) . goType where - goType :: Type -> m (Maybe Expr) + goType :: SourceType -> m (Maybe Expr) -- argument matches the index type - goType (TypeVar t) | t == iTyName = return (Just fVar) + goType (TypeVar _ t) | t == iTyName = return (Just fVar) -- records goType recTy | Just row <- objectType recTy = @@ -735,7 +735,7 @@ deriveFunctor ss mn syns ds tyConNm = do justUpdates :: [Maybe (Label, Expr)] -> Maybe [(Label, Expr)] justUpdates = foldMap (fmap return) - buildUpdate :: (Label, Type) -> m (Maybe (Label, Expr)) + buildUpdate :: (Label, SourceType) -> m (Maybe (Label, Expr)) buildUpdate (lbl, ty) = do upd <- goType ty return ((lbl,) <$> upd) @@ -747,13 +747,13 @@ deriveFunctor ss mn syns ds tyConNm = do return (lam ss arg (ObjectUpdate argVar (mkAssignment <$> updates))) -- quantifiers - goType (ForAll scopedVar t _) | scopedVar /= iTyName = goType t + goType (ForAll _ scopedVar t _) | scopedVar /= iTyName = goType t -- constraints - goType (ConstrainedType _ t) = goType t + goType (ConstrainedType _ _ t) = goType t -- under a `* -> *`, just assume functor for now - goType (TypeApp _ t) = fmap (App mapVar) <$> goType t + goType (TypeApp _ _ t) = fmap (App mapVar) <$> goType t -- otherwise do nothing - will fail type checking if type does actually contain index goType _ = return Nothing diff --git a/src/Language/PureScript/TypeChecker.hs b/src/Language/PureScript/TypeChecker.hs index 90e7917514..ed4272656c 100644 --- a/src/Language/PureScript/TypeChecker.hs +++ b/src/Language/PureScript/TypeChecker.hs @@ -48,9 +48,9 @@ addDataType => ModuleName -> DataDeclType -> ProperName 'TypeName - -> [(Text, Maybe Kind)] - -> [(ProperName 'ConstructorName, [Type])] - -> Kind + -> [(Text, Maybe SourceKind)] + -> [(ProperName 'ConstructorName, [SourceType])] + -> SourceKind -> m () addDataType moduleName dtype name args dctors ctorKind = do env <- getEnv @@ -66,14 +66,14 @@ addDataConstructor -> ProperName 'TypeName -> [Text] -> ProperName 'ConstructorName - -> [Type] + -> [SourceType] -> m () addDataConstructor moduleName dtype name args dctor tys = do env <- getEnv traverse_ checkTypeSynonyms tys - let retTy = foldl TypeApp (TypeConstructor (Qualified (Just moduleName) name)) (map TypeVar args) + let retTy = foldl srcTypeApp (srcTypeConstructor (Qualified (Just moduleName) name)) (map srcTypeVar args) let dctorTy = foldr function retTy tys - let polyType = mkForAll args dctorTy + let polyType = mkForAll (map (NullSourceAnn,) args) dctorTy let fields = [Ident ("value" <> T.pack (show n)) | n <- [0..(length tys - 1)]] putEnv $ env { dataConstructors = M.insert (Qualified (Just moduleName) dctor) (dtype, name, polyType, fields) (dataConstructors env) } @@ -81,9 +81,9 @@ addTypeSynonym :: (MonadState CheckState m, MonadError MultipleErrors m) => ModuleName -> ProperName 'TypeName - -> [(Text, Maybe Kind)] - -> Type - -> Kind + -> [(Text, Maybe SourceKind)] + -> SourceType + -> SourceKind -> m () addTypeSynonym moduleName name args ty kind = do env <- getEnv @@ -106,7 +106,7 @@ addValue :: (MonadState CheckState m) => ModuleName -> Ident - -> Type + -> SourceType -> NameKind -> m () addValue moduleName name ty nameKind = do @@ -117,8 +117,8 @@ addTypeClass :: forall m . (MonadState CheckState m, MonadError MultipleErrors m) => Qualified (ProperName 'ClassName) - -> [(Text, Maybe Kind)] - -> [Constraint] + -> [(Text, Maybe SourceKind)] + -> [SourceConstraint] -> [FunctionalDependency] -> [Declaration] -> m () @@ -127,7 +127,7 @@ addTypeClass qualifiedClassName args implies dependencies ds = do traverse_ (checkMemberIsUsable (typeSynonyms env)) classMembers modify $ \st -> st { checkEnv = (checkEnv st) { typeClasses = M.insert qualifiedClassName newClass (typeClasses . checkEnv $ st) } } where - classMembers :: [(Ident, Type)] + classMembers :: [(Ident, SourceType)] classMembers = map toPair ds newClass :: TypeClassData @@ -145,7 +145,7 @@ addTypeClass qualifiedClassName args implies dependencies ds = do -- Currently we are only checking usability based on the type class currently -- being defined. If the mentioned arguments don't include a covering set, -- then we won't be able to find a instance. - checkMemberIsUsable :: T.SynonymMap -> (Ident, Type) -> m () + checkMemberIsUsable :: T.SynonymMap -> (Ident, SourceType) -> m () checkMemberIsUsable syns (ident, memberTy) = do memberTy' <- T.replaceAllTypeSynonymsM syns memberTy let mentionedArgIndexes = S.fromList (mapMaybe argToIndex (freeTypeVariables memberTy')) @@ -180,7 +180,7 @@ checkTypeClassInstance :: (MonadState CheckState m, MonadError MultipleErrors m) => TypeClassData -> Int -- ^ index of type class argument - -> Type + -> SourceType -> m () checkTypeClassInstance cls i = check where -- If the argument is determined via fundeps then we are less restrictive in @@ -189,15 +189,15 @@ checkTypeClassInstance cls i = check where -- row types are allowed in determined type class arguments. isFunDepDetermined = S.member i (typeClassDeterminedArguments cls) check = \case - TypeVar _ -> return () - TypeLevelString _ -> return () - TypeConstructor ctor -> do + TypeVar _ _ -> return () + TypeLevelString _ _ -> return () + TypeConstructor _ ctor -> do env <- getEnv when (ctor `M.member` typeSynonyms env) . throwError . errorMessage $ TypeSynonymInstance return () - TypeApp t1 t2 -> check t1 >> check t2 - REmpty | isFunDepDetermined -> return () - RCons _ hd tl | isFunDepDetermined -> check hd >> check tl + TypeApp _ t1 t2 -> check t1 >> check t2 + REmpty _ | isFunDepDetermined -> return () + RCons _ _ hd tl | isFunDepDetermined -> check hd >> check tl ty -> throwError . errorMessage $ InvalidInstanceHead ty -- | @@ -205,7 +205,7 @@ checkTypeClassInstance cls i = check where -- checkTypeSynonyms :: (MonadState CheckState m, MonadError MultipleErrors m) - => Type + => SourceType -> m () checkTypeSynonyms = void . replaceAllTypeSynonyms @@ -346,7 +346,7 @@ typeCheckAll moduleName _ = traverse go addTypeClassDictionaries (Just moduleName) . M.singleton className $ M.singleton (tcdValue dict) (pure dict) return d - checkInstanceArity :: Ident -> Qualified (ProperName 'ClassName) -> TypeClassData -> [Type] -> m () + checkInstanceArity :: Ident -> Qualified (ProperName 'ClassName) -> TypeClassData -> [SourceType] -> m () checkInstanceArity dictName className typeClass tys = do let typeClassArity = length (typeClassArguments typeClass) instanceArity = length tys @@ -373,19 +373,19 @@ typeCheckAll moduleName _ = traverse go findNonOrphanModules :: Qualified (ProperName 'ClassName) -> TypeClassData - -> [Type] + -> [SourceType] -> S.Set ModuleName findNonOrphanModules (Qualified (Just mn') _) typeClass tys' = nonOrphanModules where nonOrphanModules :: S.Set ModuleName nonOrphanModules = S.insert mn' nonOrphanModules' - typeModule :: Type -> Maybe ModuleName - typeModule (TypeVar _) = Nothing - typeModule (TypeLevelString _) = Nothing - typeModule (TypeConstructor (Qualified (Just mn'') _)) = Just mn'' - typeModule (TypeConstructor (Qualified Nothing _)) = internalError "Unqualified type name in findNonOrphanModules" - typeModule (TypeApp t1 _) = typeModule t1 + typeModule :: SourceType -> Maybe ModuleName + typeModule (TypeVar _ _) = Nothing + typeModule (TypeLevelString _ _) = Nothing + typeModule (TypeConstructor _ (Qualified (Just mn'') _)) = Just mn'' + typeModule (TypeConstructor _ (Qualified Nothing _)) = internalError "Unqualified type name in findNonOrphanModules" + typeModule (TypeApp _ t1 _) = typeModule t1 typeModule _ = internalError "Invalid type in instance in findNonOrphanModules" modulesByTypeIndex :: M.Map Int (Maybe ModuleName) @@ -415,7 +415,7 @@ typeCheckAll moduleName _ = traverse go -> Ident -> Qualified (ProperName 'ClassName) -> TypeClassData - -> [Type] + -> [SourceType] -> S.Set ModuleName -> m () checkOverlappingInstance ch dictName className typeClass tys' nonOrphanModules = do @@ -435,8 +435,8 @@ typeCheckAll moduleName _ = traverse go instancesAreApart :: S.Set (S.Set Int) - -> [Type] - -> [Type] + -> [SourceType] + -> [SourceType] -> Bool instancesAreApart sets lhs rhs = all (any typesApart . S.toList) (S.toList sets) where @@ -445,19 +445,19 @@ typeCheckAll moduleName _ = traverse go -- Note: implementation doesn't need to care about all possible cases: -- TUnknown, Skolem, etc. - typeHeadsApart :: Type -> Type -> Bool - typeHeadsApart l r | l == r = False - typeHeadsApart (TypeVar _) _ = False - typeHeadsApart _ (TypeVar _) = False - typeHeadsApart (KindedType t1 _) t2 = typeHeadsApart t1 t2 - typeHeadsApart t1 (KindedType t2 _) = typeHeadsApart t1 t2 - typeHeadsApart (TypeApp h1 t1) (TypeApp h2 t2) = typeHeadsApart h1 h2 || typeHeadsApart t1 t2 - typeHeadsApart _ _ = True + typeHeadsApart :: SourceType -> SourceType -> Bool + typeHeadsApart l r | eqType l r = False + typeHeadsApart (TypeVar _ _) _ = False + typeHeadsApart _ (TypeVar _ _) = False + typeHeadsApart (KindedType _ t1 _) t2 = typeHeadsApart t1 t2 + typeHeadsApart t1 (KindedType _ t2 _) = typeHeadsApart t1 t2 + typeHeadsApart (TypeApp _ h1 t1) (TypeApp _ h2 t2) = typeHeadsApart h1 h2 || typeHeadsApart t1 t2 + typeHeadsApart _ _ = True checkOrphanInstance :: Ident -> Qualified (ProperName 'ClassName) - -> [Type] + -> [SourceType] -> S.Set ModuleName -> m () checkOrphanInstance dictName className tys' nonOrphanModules @@ -468,17 +468,17 @@ typeCheckAll moduleName _ = traverse go -- This function adds the argument kinds for a type constructor so that they may appear in the externs file, -- extracted from the kind of the type constructor itself. -- - withKinds :: [(Text, Maybe Kind)] -> Kind -> [(Text, Maybe Kind)] + withKinds :: [(Text, Maybe SourceKind)] -> SourceKind -> [(Text, Maybe SourceKind)] withKinds [] _ = [] - withKinds (s@(_, Just _ ):ss) (FunKind _ k) = s : withKinds ss k - withKinds ( (s, Nothing):ss) (FunKind k1 k2) = (s, Just k1) : withKinds ss k2 - withKinds _ _ = internalError "Invalid arguments to peelKinds" + withKinds (s@(_, Just _ ):ss) (FunKind _ _ k) = s : withKinds ss k + withKinds ( (s, Nothing):ss) (FunKind _ k1 k2) = (s, Just k1) : withKinds ss k2 + withKinds _ _ = internalError "Invalid arguments to peelKinds" checkNewtype :: forall m . MonadError MultipleErrors m => ProperName 'TypeName - -> [(ProperName 'ConstructorName, [Type])] + -> [(ProperName 'ConstructorName, [SourceType])] -> m () checkNewtype _ [(_, [_])] = return () checkNewtype name _ = throwError . errorMessage $ InvalidNewtype name @@ -544,12 +544,12 @@ typeCheckModule (Module ss coms mn decls (Just exps)) = untilSame :: Eq a => (a -> a) -> a -> a untilSame f a = let a' = f a in if a == a' then a else untilSame f a' - checkMemberExport :: (Type -> [DeclarationRef]) -> DeclarationRef -> m () + checkMemberExport :: (SourceType -> [DeclarationRef]) -> DeclarationRef -> m () checkMemberExport extract dr@(TypeRef _ name dctors) = do env <- getEnv for_ (M.lookup (qualify' name) (types env)) $ \(k, _) -> do let findModuleKinds = everythingOnKinds (++) $ \case - NamedKind (Qualified (Just mn') kindName) | mn' == mn -> [kindName] + NamedKind _ (Qualified (Just mn') kindName) | mn' == mn -> [kindName] _ -> [] checkExport dr $ KindRef (declRefSourceSpan dr) <$> findModuleKinds k for_ (M.lookup (qualify' name) (typeSynonyms env)) $ \(_, ty) -> @@ -606,10 +606,10 @@ typeCheckModule (Module ss coms mn decls (Just exps)) = checkTypesAreExported :: DeclarationRef -> m () checkTypesAreExported ref = checkMemberExport findTcons ref where - findTcons :: Type -> [DeclarationRef] + findTcons :: SourceType -> [DeclarationRef] findTcons = everythingOnTypes (++) go where - go (TypeConstructor (Qualified (Just mn') name)) | mn' == mn = + go (TypeConstructor _ (Qualified (Just mn') name)) | mn' == mn = [TypeRef (declRefSourceSpan ref) name (internalError "Data constructors unused in checkTypesAreExported")] go _ = [] @@ -618,10 +618,10 @@ typeCheckModule (Module ss coms mn decls (Just exps)) = checkClassesAreExported :: DeclarationRef -> m () checkClassesAreExported ref = checkMemberExport findClasses ref where - findClasses :: Type -> [DeclarationRef] + findClasses :: SourceType -> [DeclarationRef] findClasses = everythingOnTypes (++) go where - go (ConstrainedType c _) = (fmap (TypeClassRef (declRefSourceSpan ref)) . extractCurrentModuleClass . constraintClass) c + go (ConstrainedType _ c _) = (fmap (TypeClassRef (declRefSourceSpan ref)) . extractCurrentModuleClass . constraintClass) c go _ = [] extractCurrentModuleClass :: Qualified (ProperName 'ClassName) -> [ProperName 'ClassName] extractCurrentModuleClass (Qualified (Just mn') name) | mn == mn' = [name] diff --git a/src/Language/PureScript/TypeChecker/Entailment.hs b/src/Language/PureScript/TypeChecker/Entailment.hs index 2f5e754ebe..23f62f9e34 100644 --- a/src/Language/PureScript/TypeChecker/Entailment.hs +++ b/src/Language/PureScript/TypeChecker/Entailment.hs @@ -51,7 +51,7 @@ data Evidence = NamedInstance (Qualified Ident) -- | Computed instances - | WarnInstance Type -- ^ Warn type class with a user-defined warning message + | WarnInstance SourceType -- ^ Warn type class with a user-defined warning message | IsSymbolInstance PSString -- ^ The IsSymbol type class for a given Symbol literal | EmptyClassInstance -- ^ For any solved type class with no members deriving (Show, Eq) @@ -84,7 +84,7 @@ replaceTypeClassDictionaries . (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadSupply m) => Bool -> Expr - -> m (Expr, [(Ident, InstanceContext, Constraint)]) + -> m (Expr, [(Ident, InstanceContext, SourceConstraint)]) replaceTypeClassDictionaries shouldGeneralize expr = flip evalStateT M.empty $ do -- Loop, deferring any unsolved constraints, until there are no more -- constraints which can be solved, then make a generalization pass. @@ -98,16 +98,16 @@ replaceTypeClassDictionaries shouldGeneralize expr = flip evalStateT M.empty $ d -- This pass solves constraints where possible, deferring constraints if not. deferPass :: Expr -> StateT InstanceContext m (Expr, Any) deferPass = fmap (second fst) . runWriterT . f where - f :: Expr -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr + f :: Expr -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr (_, f, _) = everywhereOnValuesTopDownM return (go True) return -- This pass generalizes any remaining constraints - generalizePass :: Expr -> StateT InstanceContext m (Expr, [(Ident, InstanceContext, Constraint)]) + generalizePass :: Expr -> StateT InstanceContext m (Expr, [(Ident, InstanceContext, SourceConstraint)]) generalizePass = fmap (second snd) . runWriterT . f where - f :: Expr -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr + f :: Expr -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr (_, f, _) = everywhereOnValuesTopDownM return (go False) return - go :: Bool -> Expr -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr + go :: Bool -> Expr -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr go deferErrors (TypeClassDictionary constraint context hints) = rethrow (addHints hints) $ entails (SolverOptions shouldGeneralize deferErrors) constraint context hints go _ other = return other @@ -116,7 +116,7 @@ replaceTypeClassDictionaries shouldGeneralize expr = flip evalStateT M.empty $ d data EntailsResult a = Solved a TypeClassDict -- ^ We solved this constraint - | Unsolved Constraint + | Unsolved SourceConstraint -- ^ We couldn't solve this constraint right now, it will be generalized | Deferred -- ^ We couldn't solve this constraint right now, so it has been deferred @@ -152,17 +152,17 @@ entails . (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m, MonadSupply m) => SolverOptions -- ^ Solver options - -> Constraint + -> SourceConstraint -- ^ The constraint to solve -> InstanceContext -- ^ The contexts in which to solve the constraint -> [ErrorMessageHint] -- ^ Error message hints to apply to any instance errors - -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr + -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr entails SolverOptions{..} constraint context hints = solve constraint where - forClassName :: InstanceContext -> Qualified (ProperName 'ClassName) -> [Type] -> [TypeClassDict] + forClassName :: InstanceContext -> Qualified (ProperName 'ClassName) -> [SourceType] -> [TypeClassDict] forClassName ctx cn@C.Warn [msg] = -- Prefer a warning dictionary in scope if there is one available. -- This allows us to defer a warning by propagating the constraint. @@ -179,11 +179,11 @@ entails SolverOptions{..} constraint context hints = forClassName ctx cn@(Qualified (Just mn) _) tys = concatMap (findDicts ctx cn) (ordNub (Nothing : Just mn : map Just (mapMaybe ctorModules tys))) forClassName _ _ _ = internalError "forClassName: expected qualified class name" - ctorModules :: Type -> Maybe ModuleName - ctorModules (TypeConstructor (Qualified (Just mn) _)) = Just mn - ctorModules (TypeConstructor (Qualified Nothing _)) = internalError "ctorModules: unqualified type name" - ctorModules (TypeApp ty _) = ctorModules ty - ctorModules (KindedType ty _) = ctorModules ty + ctorModules :: SourceType -> Maybe ModuleName + ctorModules (TypeConstructor _ (Qualified (Just mn) _)) = Just mn + ctorModules (TypeConstructor _ (Qualified Nothing _)) = internalError "ctorModules: unqualified type name" + ctorModules (TypeApp _ ty _) = ctorModules ty + ctorModules (KindedType _ ty _) = ctorModules ty ctorModules _ = Nothing findDicts :: InstanceContext -> Qualified (ProperName 'ClassName) -> Maybe ModuleName -> [TypeClassDict] @@ -192,12 +192,12 @@ entails SolverOptions{..} constraint context hints = valUndefined :: Expr valUndefined = Var nullSourceSpan (Qualified (Just (ModuleName [ProperName C.prim])) (Ident C.undefined)) - solve :: Constraint -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr + solve :: SourceConstraint -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr solve con = go 0 con where - go :: Int -> Constraint -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) Expr - go work (Constraint className' tys' _) | work > 1000 = throwError . errorMessage $ PossiblyInfiniteInstance className' tys' - go work con'@(Constraint className' tys' conInfo) = WriterT . StateT . (withErrorMessageHint (ErrorSolvingConstraint con') .) . runStateT . runWriterT $ do + go :: Int -> SourceConstraint -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) Expr + go work (Constraint _ className' tys' _) | work > 1000 = throwError . errorMessage $ PossiblyInfiniteInstance className' tys' + go work con'@(Constraint _ className' tys' conInfo) = WriterT . StateT . (withErrorMessageHint (ErrorSolvingConstraint con') .) . runStateT . runWriterT $ do -- We might have unified types by solving other constraints, so we need to -- apply the latest substitution. latestSubst <- lift . lift $ gets checkSubstitution @@ -265,7 +265,7 @@ entails SolverOptions{..} constraint context hints = Deferred -> -- Constraint was deferred, just return the dictionary unchanged, -- with no unsolved constraints. Hopefully, we can solve this later. - return (TypeClassDictionary (Constraint className' tys'' conInfo) context hints) + return (TypeClassDictionary (srcConstraint className' tys'' conInfo) context hints) where -- | When checking functional dependencies, we need to use unification to make -- sure it is safe to use the selected instance. We will unify the solved type with @@ -280,8 +280,8 @@ entails SolverOptions{..} constraint context hints = -- as necessary, based on the types in the instance head. withFreshTypes :: TypeClassDict - -> Matching Type - -> m (Matching Type) + -> Matching SourceType + -> m (Matching SourceType) withFreshTypes TypeClassDictionaryInScope{..} subst = do let onType = everythingOnTypes S.union fromTypeVar typeVarsInHead = foldMap onType tcdInstanceTypes @@ -291,29 +291,29 @@ entails SolverOptions{..} constraint context hints = newSubst <- traverse withFreshType (S.toList uninstantiatedTypeVars) return (subst <> M.fromList newSubst) where - fromTypeVar (TypeVar v) = S.singleton v + fromTypeVar (TypeVar _ v) = S.singleton v fromTypeVar _ = S.empty withFreshType s = do t <- freshType return (s, t) - unique :: [Type] -> [(a, TypeClassDict)] -> m (EntailsResult a) + unique :: [SourceType] -> [(a, TypeClassDict)] -> m (EntailsResult a) unique tyArgs [] | solverDeferErrors = return Deferred -- We need a special case for nullary type classes, since we want -- to generalize over Partial constraints. - | solverShouldGeneralize && (null tyArgs || any canBeGeneralized tyArgs) = return (Unsolved (Constraint className' tyArgs conInfo)) - | otherwise = throwError . errorMessage $ NoInstanceFound (Constraint className' tyArgs conInfo) + | solverShouldGeneralize && (null tyArgs || any canBeGeneralized tyArgs) = return (Unsolved (srcConstraint className' tyArgs conInfo)) + | otherwise = throwError . errorMessage $ NoInstanceFound (srcConstraint className' tyArgs conInfo) unique _ [(a, dict)] = return $ Solved a dict unique tyArgs tcds | pairwiseAny overlapping (map snd tcds) = throwError . errorMessage $ OverlappingInstances className' tyArgs (tcds >>= (toList . namedInstanceIdentifier . tcdValue . snd)) | otherwise = return $ uncurry Solved (minimumBy (compare `on` length . tcdPath . snd) tcds) - canBeGeneralized :: Type -> Bool + canBeGeneralized :: Type a -> Bool canBeGeneralized TUnknown{} = True - canBeGeneralized (KindedType t _) = canBeGeneralized t + canBeGeneralized (KindedType _ t _) = canBeGeneralized t canBeGeneralized _ = False -- | @@ -331,7 +331,7 @@ entails SolverOptions{..} constraint context hints = -- Create dictionaries for subgoals which still need to be solved by calling go recursively -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively. - solveSubgoals :: Matching Type -> Maybe [Constraint] -> WriterT (Any, [(Ident, InstanceContext, Constraint)]) (StateT InstanceContext m) (Maybe [Expr]) + solveSubgoals :: Matching SourceType -> Maybe [SourceConstraint] -> WriterT (Any, [(Ident, InstanceContext, SourceConstraint)]) (StateT InstanceContext m) (Maybe [Expr]) solveSubgoals _ Nothing = return Nothing solveSubgoals subst (Just subgoals) = Just <$> traverse (go (work + 1) . mapConstraintArgs (map (replaceAllTypeVars (M.toList subst)))) subgoals @@ -360,21 +360,21 @@ entails SolverOptions{..} constraint context hints = subclassDictionaryValue dict className index = App (Accessor (mkString (superclassName className index)) dict) valUndefined - solveIsSymbol :: [Type] -> Maybe [TypeClassDict] - solveIsSymbol [TypeLevelString sym] = Just [TypeClassDictionaryInScope [] 0 (IsSymbolInstance sym) [] C.IsSymbol [TypeLevelString sym] Nothing] + solveIsSymbol :: [SourceType] -> Maybe [TypeClassDict] + solveIsSymbol [TypeLevelString ann sym] = Just [TypeClassDictionaryInScope [] 0 (IsSymbolInstance sym) [] C.IsSymbol [TypeLevelString ann sym] Nothing] solveIsSymbol _ = Nothing - solveSymbolCompare :: [Type] -> Maybe [TypeClassDict] - solveSymbolCompare [arg0@(TypeLevelString lhs), arg1@(TypeLevelString rhs), _] = + solveSymbolCompare :: [SourceType] -> Maybe [TypeClassDict] + solveSymbolCompare [arg0@(TypeLevelString _ lhs), arg1@(TypeLevelString _ rhs), _] = let ordering = case compare lhs rhs of LT -> C.orderingLT EQ -> C.orderingEQ GT -> C.orderingGT - args' = [arg0, arg1, TypeConstructor ordering] + args' = [arg0, arg1, srcTypeConstructor ordering] in Just [TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.SymbolCompare args' Nothing] solveSymbolCompare _ = Nothing - solveSymbolAppend :: [Type] -> Maybe [TypeClassDict] + solveSymbolAppend :: [SourceType] -> Maybe [TypeClassDict] solveSymbolAppend [arg0, arg1, arg2] = do (arg0', arg1', arg2') <- appendSymbols arg0 arg1 arg2 let args' = [arg0', arg1', arg2'] @@ -382,126 +382,127 @@ entails SolverOptions{..} constraint context hints = solveSymbolAppend _ = Nothing -- | Append type level symbols, or, run backwards, strip a prefix or suffix - appendSymbols :: Type -> Type -> Type -> Maybe (Type, Type, Type) - appendSymbols arg0@(TypeLevelString lhs) arg1@(TypeLevelString rhs) _ = Just (arg0, arg1, TypeLevelString (lhs <> rhs)) - appendSymbols arg0@(TypeLevelString lhs) _ arg2@(TypeLevelString out) = do + appendSymbols :: SourceType -> SourceType -> SourceType -> Maybe (SourceType, SourceType, SourceType) + appendSymbols arg0@(TypeLevelString _ lhs) arg1@(TypeLevelString _ rhs) _ = Just (arg0, arg1, srcTypeLevelString (lhs <> rhs)) + appendSymbols arg0@(TypeLevelString _ lhs) _ arg2@(TypeLevelString _ out) = do lhs' <- decodeString lhs out' <- decodeString out rhs <- stripPrefix lhs' out' - pure (arg0, TypeLevelString (mkString rhs), arg2) - appendSymbols _ arg1@(TypeLevelString rhs) arg2@(TypeLevelString out) = do + pure (arg0, srcTypeLevelString (mkString rhs), arg2) + appendSymbols _ arg1@(TypeLevelString _ rhs) arg2@(TypeLevelString _ out) = do rhs' <- decodeString rhs out' <- decodeString out lhs <- stripSuffix rhs' out' - pure (TypeLevelString (mkString lhs), arg1, arg2) + pure (srcTypeLevelString (mkString lhs), arg1, arg2) appendSymbols _ _ _ = Nothing - solveSymbolCons :: [Type] -> Maybe [TypeClassDict] + solveSymbolCons :: [SourceType] -> Maybe [TypeClassDict] solveSymbolCons [arg0, arg1, arg2] = do (arg0', arg1', arg2') <- consSymbol arg0 arg1 arg2 let args' = [arg0', arg1', arg2'] pure [TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.SymbolCons args' Nothing] solveSymbolCons _ = Nothing - consSymbol :: Type -> Type -> Type -> Maybe (Type, Type, Type) - consSymbol _ _ arg@(TypeLevelString s) = do + consSymbol :: SourceType -> SourceType -> SourceType -> Maybe (SourceType, SourceType, SourceType) + consSymbol _ _ arg@(TypeLevelString _ s) = do (h, t) <- T.uncons =<< decodeString s pure (mkTLString (T.singleton h), mkTLString t, arg) - where mkTLString = TypeLevelString . mkString - consSymbol arg1@(TypeLevelString h) arg2@(TypeLevelString t) _ = do + where mkTLString = srcTypeLevelString . mkString + consSymbol arg1@(TypeLevelString _ h) arg2@(TypeLevelString _ t) _ = do h' <- decodeString h t' <- decodeString t guard (T.length h' == 1) - pure (arg1, arg2, TypeLevelString (mkString $ h' <> t')) + pure (arg1, arg2, srcTypeLevelString (mkString $ h' <> t')) consSymbol _ _ _ = Nothing - solveUnion :: [Type] -> Maybe [TypeClassDict] + solveUnion :: [SourceType] -> Maybe [TypeClassDict] solveUnion [l, r, u] = do (lOut, rOut, uOut, cst) <- unionRows l r u pure [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowUnion [lOut, rOut, uOut] cst ] solveUnion _ = Nothing -- | Left biased union of two row types - unionRows :: Type -> Type -> Type -> Maybe (Type, Type, Type, Maybe [Constraint]) + unionRows :: SourceType -> SourceType -> SourceType -> Maybe (SourceType, SourceType, SourceType, Maybe [SourceConstraint]) unionRows l r _ = guard canMakeProgress $> (l, r, rowFromList out, cons) where (fixed, rest) = rowToList l - rowVar = TypeVar "r" + rowVar = srcTypeVar "r" (canMakeProgress, out, cons) = case rest of -- If the left hand side is a closed row, then we can merge -- its labels into the right hand side. - REmpty -> (True, (fixed, r), Nothing) + REmpty _ -> (True, (fixed, r), Nothing) -- If the left hand side is not definitely closed, then the only way we -- can safely make progress is to move any known labels from the left -- input into the output, and add a constraint for any remaining labels. -- Otherwise, the left hand tail might contain the same labels as on -- the right hand side, and we can't be certain we won't reorder the -- types for such labels. - _ -> (not (null fixed), (fixed, rowVar), Just [ Constraint C.RowUnion [rest, r, rowVar] Nothing ]) + _ -> (not (null fixed), (fixed, rowVar), Just [ srcConstraint C.RowUnion [rest, r, rowVar] Nothing ]) - solveRowCons :: [Type] -> Maybe [TypeClassDict] - solveRowCons [TypeLevelString sym, ty, r, _] = - Just [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowCons [TypeLevelString sym, ty, r, RCons (Label sym) ty r] Nothing ] + solveRowCons :: [SourceType] -> Maybe [TypeClassDict] + solveRowCons [TypeLevelString ann sym, ty, r, _] = + Just [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowCons [TypeLevelString ann sym, ty, r, srcRCons (Label sym) ty r] Nothing ] solveRowCons _ = Nothing - solveRowToList :: [Type] -> Maybe [TypeClassDict] + solveRowToList :: [SourceType] -> Maybe [TypeClassDict] solveRowToList [r, _] = do entries <- rowToRowList r pure [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowToList [r, entries] Nothing ] solveRowToList _ = Nothing -- | Convert a closed row to a sorted list of entries - rowToRowList :: Type -> Maybe Type + rowToRowList :: SourceType -> Maybe SourceType rowToRowList r = - guard (REmpty == rest) $> - foldr rowListCons (TypeConstructor C.RowListNil) fixed + guard (eqType rest $ REmpty ()) $> + foldr rowListCons (srcTypeConstructor C.RowListNil) fixed where (fixed, rest) = rowToSortedList r - rowListCons (lbl, ty) tl = foldl TypeApp (TypeConstructor C.RowListCons) - [ TypeLevelString (runLabel lbl) - , ty - , tl ] + rowListCons (RowListItem _ lbl ty) tl = + foldl srcTypeApp (srcTypeConstructor C.RowListCons) + [ srcTypeLevelString (runLabel lbl) + , ty + , tl ] - solveNub :: [Type] -> Maybe [TypeClassDict] + solveNub :: [SourceType] -> Maybe [TypeClassDict] solveNub [r, _] = do r' <- nubRows r pure [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowNub [r, r'] Nothing ] solveNub _ = Nothing - nubRows :: Type -> Maybe Type + nubRows :: SourceType -> Maybe SourceType nubRows r = - guard (REmpty == rest) $> - rowFromList (nubBy ((==) `on` fst) fixed, rest) + guard (eqType rest $ REmpty ()) $> + rowFromList (nubBy ((==) `on` rowListLabel) fixed, rest) where (fixed, rest) = rowToSortedList r - solveLacks :: [Type] -> Maybe [TypeClassDict] - solveLacks [TypeLevelString sym, r] = do + solveLacks :: [SourceType] -> Maybe [TypeClassDict] + solveLacks [TypeLevelString ann sym, r] = do (r', cst) <- rowLacks sym r - pure [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowLacks [TypeLevelString sym, r'] cst ] + pure [ TypeClassDictionaryInScope [] 0 EmptyClassInstance [] C.RowLacks [TypeLevelString ann sym, r'] cst ] solveLacks _ = Nothing - rowLacks :: PSString -> Type -> Maybe (Type, Maybe [Constraint]) + rowLacks :: PSString -> SourceType -> Maybe (SourceType, Maybe [SourceConstraint]) rowLacks sym r = guard (lacksSym && canMakeProgress) $> (r, cst) where (fixed, rest) = rowToList r lacksSym = - not $ sym `elem` (runLabel . fst <$> fixed) + not $ sym `elem` (runLabel . rowListLabel <$> fixed) (canMakeProgress, cst) = case rest of - REmpty -> (True, Nothing) - _ -> (not (null fixed), Just [ Constraint C.RowLacks [TypeLevelString sym, rest] Nothing ]) + REmpty _ -> (True, Nothing) + _ -> (not (null fixed), Just [ srcConstraint C.RowLacks [srcTypeLevelString sym, rest] Nothing ]) -- Check if an instance matches our list of types, allowing for types -- to be solved via functional dependencies. If the types match, we return a -- substitution which makes them match. If not, we return 'Nothing'. -matches :: [FunctionalDependency] -> TypeClassDict -> [Type] -> Matched (Matching [Type]) +matches :: [FunctionalDependency] -> TypeClassDict -> [SourceType] -> Matched (Matching [SourceType]) matches deps TypeClassDictionaryInScope{..} tys = -- First, find those types which match exactly let matched = zipWith typeHeadsAreEqual tys tcdInstanceTypes in @@ -542,76 +543,76 @@ matches deps TypeClassDictionaryInScope{..} tys = -- Check whether the type heads of two types are equal (for the purposes of type class dictionary lookup), -- and return a substitution from type variables to types which makes the type heads unify. -- - typeHeadsAreEqual :: Type -> Type -> (Matched (), Matching [Type]) - typeHeadsAreEqual (KindedType t1 _) t2 = typeHeadsAreEqual t1 t2 - typeHeadsAreEqual t1 (KindedType t2 _) = typeHeadsAreEqual t1 t2 - typeHeadsAreEqual (TUnknown u1) (TUnknown u2) | u1 == u2 = (Match (), M.empty) - typeHeadsAreEqual (Skolem _ s1 _ _) (Skolem _ s2 _ _) | s1 == s2 = (Match (), M.empty) - typeHeadsAreEqual t (TypeVar v) = (Match (), M.singleton v [t]) - typeHeadsAreEqual (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = (Match (), M.empty) - typeHeadsAreEqual (TypeLevelString s1) (TypeLevelString s2) | s1 == s2 = (Match (), M.empty) - typeHeadsAreEqual (TypeApp h1 t1) (TypeApp h2 t2) = + typeHeadsAreEqual :: Type a -> Type a -> (Matched (), Matching [Type a]) + typeHeadsAreEqual (KindedType _ t1 _) t2 = typeHeadsAreEqual t1 t2 + typeHeadsAreEqual t1 (KindedType _ t2 _) = typeHeadsAreEqual t1 t2 + typeHeadsAreEqual (TUnknown _ u1) (TUnknown _ u2) | u1 == u2 = (Match (), M.empty) + typeHeadsAreEqual (Skolem _ _ s1 _) (Skolem _ _ s2 _) | s1 == s2 = (Match (), M.empty) + typeHeadsAreEqual t (TypeVar _ v) = (Match (), M.singleton v [t]) + typeHeadsAreEqual (TypeConstructor _ c1) (TypeConstructor _ c2) | c1 == c2 = (Match (), M.empty) + typeHeadsAreEqual (TypeLevelString _ s1) (TypeLevelString _ s2) | s1 == s2 = (Match (), M.empty) + typeHeadsAreEqual (TypeApp _ h1 t1) (TypeApp _ h2 t2) = both (typeHeadsAreEqual h1 h2) (typeHeadsAreEqual t1 t2) - typeHeadsAreEqual REmpty REmpty = (Match (), M.empty) + typeHeadsAreEqual (REmpty _) (REmpty _) = (Match (), M.empty) typeHeadsAreEqual r1@RCons{} r2@RCons{} = foldr both (uncurry go rest) common where (common, rest) = alignRowsWith typeHeadsAreEqual r1 r2 - go :: ([(Label, Type)], Type) -> ([(Label, Type)], Type) -> (Matched (), Matching [Type]) - go (l, KindedType t1 _) (r, t2) = go (l, t1) (r, t2) - go (l, t1) (r, KindedType t2 _) = go (l, t1) (r, t2) - go ([], REmpty) ([], REmpty) = (Match (), M.empty) - go ([], TUnknown u1) ([], TUnknown u2) | u1 == u2 = (Match (), M.empty) - go ([], TypeVar v1) ([], TypeVar v2) | v1 == v2 = (Match (), M.empty) - go ([], Skolem _ sk1 _ _) ([], Skolem _ sk2 _ _) | sk1 == sk2 = (Match (), M.empty) - go ([], TUnknown _) _ = (Unknown, M.empty) - go (sd, r) ([], TypeVar v) = (Match (), M.singleton v [rowFromList (sd, r)]) - go _ _ = (Apart, M.empty) - typeHeadsAreEqual (TUnknown _) _ = (Unknown, M.empty) + go :: ([RowListItem a], Type a) -> ([RowListItem a], Type a) -> (Matched (), Matching [Type a]) + go (l, KindedType _ t1 _) (r, t2) = go (l, t1) (r, t2) + go (l, t1) (r, KindedType _ t2 _) = go (l, t1) (r, t2) + go ([], REmpty _) ([], REmpty _) = (Match (), M.empty) + go ([], TUnknown _ u1) ([], TUnknown _ u2) | u1 == u2 = (Match (), M.empty) + go ([], TypeVar _ v1) ([], TypeVar _ v2) | v1 == v2 = (Match (), M.empty) + go ([], Skolem _ _ sk1 _) ([], Skolem _ _ sk2 _) | sk1 == sk2 = (Match (), M.empty) + go ([], TUnknown _ _) _ = (Unknown, M.empty) + go (sd, r) ([], TypeVar _ v) = (Match (), M.singleton v [rowFromList (sd, r)]) + go _ _ = (Apart, M.empty) + typeHeadsAreEqual (TUnknown _ _) _ = (Unknown, M.empty) typeHeadsAreEqual _ _ = (Apart, M.empty) - both :: (Matched (), Matching [Type]) -> (Matched (), Matching [Type]) -> (Matched (), Matching [Type]) + both :: (Matched (), Matching [Type a]) -> (Matched (), Matching [Type a]) -> (Matched (), Matching [Type a]) both (b1, m1) (b2, m2) = (b1 <> b2, M.unionWith (++) m1 m2) -- Ensure that a substitution is valid - verifySubstitution :: Matching [Type] -> Matched (Matching [Type]) + verifySubstitution :: Matching [Type a] -> Matched (Matching [Type a]) verifySubstitution mts = foldMap meet mts $> mts where meet = pairwiseAll typesAreEqual -- Note that unknowns are only allowed to unify if they came from a type -- which was _not_ solved, i.e. one which was inferred by a functional -- dependency. - typesAreEqual :: Type -> Type -> Matched () - typesAreEqual (KindedType t1 _) t2 = typesAreEqual t1 t2 - typesAreEqual t1 (KindedType t2 _) = typesAreEqual t1 t2 - typesAreEqual (TUnknown u1) (TUnknown u2) | u1 == u2 = Match () - typesAreEqual (Skolem _ s1 _ _) (Skolem _ s2 _ _) | s1 == s2 = Match () - typesAreEqual (Skolem _ _ _ _) _ = Unknown - typesAreEqual _ (Skolem _ _ _ _) = Unknown - typesAreEqual (TypeVar v1) (TypeVar v2) | v1 == v2 = Match () - typesAreEqual (TypeLevelString s1) (TypeLevelString s2) | s1 == s2 = Match () - typesAreEqual (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Match () - typesAreEqual (TypeApp h1 t1) (TypeApp h2 t2) = typesAreEqual h1 h2 <> typesAreEqual t1 t2 - typesAreEqual REmpty REmpty = Match () - typesAreEqual r1 r2 | isRCons r1 || isRCons r2 = + typesAreEqual :: Type a -> Type a -> Matched () + typesAreEqual (KindedType _ t1 _) t2 = typesAreEqual t1 t2 + typesAreEqual t1 (KindedType _ t2 _) = typesAreEqual t1 t2 + typesAreEqual (TUnknown _ u1) (TUnknown _ u2) | u1 == u2 = Match () + typesAreEqual (Skolem _ _ s1 _) (Skolem _ _ s2 _) | s1 == s2 = Match () + typesAreEqual (Skolem _ _ _ _) _ = Unknown + typesAreEqual _ (Skolem _ _ _ _) = Unknown + typesAreEqual (TypeVar _ v1) (TypeVar _ v2) | v1 == v2 = Match () + typesAreEqual (TypeLevelString _ s1) (TypeLevelString _ s2) | s1 == s2 = Match () + typesAreEqual (TypeConstructor _ c1) (TypeConstructor _ c2) | c1 == c2 = Match () + typesAreEqual (TypeApp _ h1 t1) (TypeApp _ h2 t2) = typesAreEqual h1 h2 <> typesAreEqual t1 t2 + typesAreEqual (REmpty _) (REmpty _) = Match () + typesAreEqual r1 r2 | isRCons r1 || isRCons r2 = let (common, rest) = alignRowsWith typesAreEqual r1 r2 in fold common <> uncurry go rest where - go :: ([(Label, Type)], Type) -> ([(Label, Type)], Type) -> Matched () - go (l, KindedType t1 _) (r, t2) = go (l, t1) (r, t2) - go (l, t1) (r, KindedType t2 _) = go (l, t1) (r, t2) - go ([], TUnknown u1) ([], TUnknown u2) | u1 == u2 = Match () - go ([], Skolem _ s1 _ _) ([], Skolem _ s2 _ _) | s1 == s2 = Match () - go ([], Skolem _ _ _ _) _ = Unknown - go _ ([], Skolem _ _ _ _) = Unknown - go ([], REmpty) ([], REmpty) = Match () - go ([], TypeVar v1) ([], TypeVar v2) | v1 == v2 = Match () - go _ _ = Apart - typesAreEqual _ _ = Apart - - isRCons :: Type -> Bool + go :: ([RowListItem a], Type a) -> ([RowListItem a], Type a) -> Matched () + go (l, KindedType _ t1 _) (r, t2) = go (l, t1) (r, t2) + go (l, t1) (r, KindedType _ t2 _) = go (l, t1) (r, t2) + go ([], TUnknown _ u1) ([], TUnknown _ u2) | u1 == u2 = Match () + go ([], Skolem _ _ s1 _) ([], Skolem _ _ s2 _) | s1 == s2 = Match () + go ([], Skolem _ _ _ _) _ = Unknown + go _ ([], Skolem _ _ _ _) = Unknown + go ([], REmpty _) ([], REmpty _) = Match () + go ([], TypeVar _ v1) ([], TypeVar _ v2) | v1 == v2 = Match () + go _ _ = Apart + typesAreEqual _ _ = Apart + + isRCons :: Type a -> Bool isRCons RCons{} = True isRCons _ = False @@ -621,19 +622,19 @@ newDictionaries :: MonadState CheckState m => [(Qualified (ProperName 'ClassName), Integer)] -> Qualified Ident - -> Constraint + -> SourceConstraint -> m [NamedDict] -newDictionaries path name (Constraint className instanceTy _) = do +newDictionaries path name (Constraint _ className instanceTy _) = do tcs <- gets (typeClasses . checkEnv) let TypeClassData{..} = fromMaybe (internalError "newDictionaries: type class lookup failed") $ M.lookup className tcs - supDicts <- join <$> zipWithM (\(Constraint supName supArgs _) index -> + supDicts <- join <$> zipWithM (\(Constraint ann supName supArgs _) index -> newDictionaries ((supName, index) : path) name - (Constraint supName (instantiateSuperclass (map fst typeClassArguments) supArgs instanceTy) Nothing) + (Constraint ann supName (instantiateSuperclass (map fst typeClassArguments) supArgs instanceTy) Nothing) ) typeClassSuperclasses [0..] return (TypeClassDictionaryInScope [] 0 name path className instanceTy Nothing : supDicts) where - instantiateSuperclass :: [Text] -> [Type] -> [Type] -> [Type] + instantiateSuperclass :: [Text] -> [SourceType] -> [SourceType] -> [SourceType] instantiateSuperclass args supArgs tys = map (replaceAllTypeVars (zip args tys)) supArgs mkContext :: [NamedDict] -> InstanceContext diff --git a/src/Language/PureScript/TypeChecker/Kinds.hs b/src/Language/PureScript/TypeChecker/Kinds.hs index 58ec2f0fb6..ef6596bb79 100644 --- a/src/Language/PureScript/TypeChecker/Kinds.hs +++ b/src/Language/PureScript/TypeChecker/Kinds.hs @@ -17,6 +17,7 @@ import Control.Monad import Control.Monad.Error.Class (MonadError(..)) import Control.Monad.State +import Data.Functor (($>)) import qualified Data.Map as M import Data.Text (Text) @@ -29,17 +30,17 @@ import Language.PureScript.TypeChecker.Monad import Language.PureScript.Types -- | Generate a fresh kind variable -freshKind :: (MonadState CheckState m) => m Kind +freshKind :: (MonadState CheckState m) => m SourceKind freshKind = do k <- gets checkNextKind modify $ \st -> st { checkNextKind = k + 1 } - return $ KUnknown k + return $ KUnknown nullSourceAnn k -- | Update the substitution to solve a kind constraint solveKind :: (MonadError MultipleErrors m, MonadState CheckState m) => Int - -> Kind + -> SourceKind -> m () solveKind u k = do occursCheck u k @@ -50,13 +51,13 @@ solveKind u k = do } -- | Apply a substitution to a kind -substituteKind :: Substitution -> Kind -> Kind +substituteKind :: Substitution -> SourceKind -> SourceKind substituteKind sub = everywhereOnKinds go where - go (KUnknown u) = + go (KUnknown ann u) = case M.lookup u (substKind sub) of - Nothing -> KUnknown u - Just (KUnknown u1) | u1 == u -> KUnknown u1 + Nothing -> KUnknown ann u + Just (KUnknown ann' u1) | u1 == u -> KUnknown ann' u1 Just t -> substituteKind sub t go other = other @@ -64,30 +65,30 @@ substituteKind sub = everywhereOnKinds go occursCheck :: (MonadError MultipleErrors m) => Int - -> Kind + -> SourceKind -> m () occursCheck _ KUnknown{} = return () occursCheck u k = void $ everywhereOnKindsM go k where - go (KUnknown u') | u == u' = throwError . errorMessage . InfiniteKind $ k + go (KUnknown _ u') | u == u' = throwError . errorMessage . InfiniteKind $ k go other = return other -- | Unify two kinds unifyKinds :: (MonadError MultipleErrors m, MonadState CheckState m) - => Kind - -> Kind + => SourceKind + -> SourceKind -> m () unifyKinds k1 k2 = do sub <- gets checkSubstitution go (substituteKind sub k1) (substituteKind sub k2) where - go (KUnknown u1) (KUnknown u2) | u1 == u2 = return () - go (KUnknown u) k = solveKind u k - go k (KUnknown u) = solveKind u k - go (NamedKind k1') (NamedKind k2') | k1' == k2' = return () - go (Row k1') (Row k2') = unifyKinds k1' k2' - go (FunKind k1' k2') (FunKind k3 k4) = do + go (KUnknown _ u1) (KUnknown _ u2) | u1 == u2 = return () + go (KUnknown _ u) k = solveKind u k + go k (KUnknown _ u) = solveKind u k + go (NamedKind _ k1') (NamedKind _ k2') | k1' == k2' = return () + go (Row _ k1') (Row _ k2') = unifyKinds k1' k2' + go (FunKind _ k1' k2') (FunKind _ k3 k4) = do unifyKinds k1' k3 unifyKinds k2' k4 go k1' k2' = throwError . errorMessage $ KindsDoNotUnify k1' k2' @@ -95,15 +96,15 @@ unifyKinds k1 k2 = do -- | Infer the kind of a single type kindOf :: (MonadError MultipleErrors m, MonadState CheckState m) - => Type - -> m Kind + => SourceType + -> m SourceKind kindOf ty = fst <$> kindOfWithScopedVars ty -- | Infer the kind of a single type, returning the kinds of any scoped type variables kindOfWithScopedVars :: (MonadError MultipleErrors m, MonadState CheckState m) => - Type -> - m (Kind, [(Text, Kind)]) + SourceType -> + m (SourceKind, [(Text, SourceKind)]) kindOfWithScopedVars ty = withErrorMessageHint (ErrorCheckingKind ty) $ fmap tidyUp . withFreshSubstitution . captureSubstitution $ infer ty @@ -118,9 +119,9 @@ kindsOf => Bool -> ModuleName -> ProperName 'TypeName - -> [(Text, Maybe Kind)] - -> [Type] - -> m Kind + -> [(Text, Maybe SourceKind)] + -> [SourceType] + -> m SourceKind kindsOf isData moduleName name args ts = fmap tidyUp . withFreshSubstitution . captureSubstitution $ do tyCon <- freshKind kargs <- replicateM (length args) freshKind @@ -133,9 +134,9 @@ kindsOf isData moduleName name args ts = fmap tidyUp . withFreshSubstitution . c freshKindVar :: (MonadError MultipleErrors m, MonadState CheckState m) - => (Text, Maybe Kind) - -> Kind - -> m (ProperName 'TypeName, Kind) + => (Text, Maybe SourceKind) + -> SourceKind + -> m (ProperName 'TypeName, SourceKind) freshKindVar (arg, Nothing) kind = return (ProperName arg, kind) freshKindVar (arg, Just kind') kind = do unifyKinds kind kind' @@ -145,9 +146,9 @@ freshKindVar (arg, Just kind') kind = do kindsOfAll :: (MonadError MultipleErrors m, MonadState CheckState m) => ModuleName - -> [(ProperName 'TypeName, [(Text, Maybe Kind)], Type)] - -> [(ProperName 'TypeName, [(Text, Maybe Kind)], [Type])] - -> m ([Kind], [Kind]) + -> [(ProperName 'TypeName, [(Text, Maybe SourceKind)], SourceType)] + -> [(ProperName 'TypeName, [(Text, Maybe SourceKind)], [SourceType])] + -> m ([SourceKind], [SourceKind]) kindsOfAll moduleName syns tys = fmap tidyUp . withFreshSubstitution . captureSubstitution $ do synVars <- replicateM (length syns) freshKind let dict = zipWith (\(name, _, _) var -> (name, var)) syns synVars @@ -173,91 +174,91 @@ kindsOfAll moduleName syns tys = fmap tidyUp . withFreshSubstitution . captureSu solveTypes :: (MonadError MultipleErrors m, MonadState CheckState m) => Bool - -> [Type] - -> [Kind] - -> Kind - -> m Kind + -> [SourceType] + -> [SourceKind] + -> SourceKind + -> m SourceKind solveTypes isData ts kargs tyCon = do ks <- traverse (fmap fst . infer) ts when isData $ do - unifyKinds tyCon (foldr FunKind kindType kargs) + unifyKinds tyCon (foldr (FunKind nullSourceAnn) kindType kargs) forM_ ks $ \k -> unifyKinds k kindType unless isData $ - unifyKinds tyCon (foldr FunKind (head ks) kargs) + unifyKinds tyCon (foldr (FunKind nullSourceAnn) (head ks) kargs) return tyCon -- | Default all unknown kinds to the kindType kind of types -starIfUnknown :: Kind -> Kind -starIfUnknown (KUnknown _) = kindType -starIfUnknown (Row k) = Row (starIfUnknown k) -starIfUnknown (FunKind k1 k2) = FunKind (starIfUnknown k1) (starIfUnknown k2) +starIfUnknown :: Kind a -> Kind a +starIfUnknown (KUnknown ann _) = kindType $> ann +starIfUnknown (Row ann k) = Row ann (starIfUnknown k) +starIfUnknown (FunKind ann k1 k2) = FunKind ann (starIfUnknown k1) (starIfUnknown k2) starIfUnknown k = k -- | Infer a kind for a type infer :: (MonadError MultipleErrors m, MonadState CheckState m) - => Type - -> m (Kind, [(Text, Kind)]) + => SourceType + -> m (SourceKind, [(Text, SourceKind)]) infer ty = withErrorMessageHint (ErrorCheckingKind ty) $ infer' ty infer' :: forall m . (MonadError MultipleErrors m, MonadState CheckState m) - => Type - -> m (Kind, [(Text, Kind)]) -infer' (ForAll ident ty _) = do + => SourceType + -> m (SourceKind, [(Text, SourceKind)]) +infer' (ForAll _ ident ty _) = do k1 <- freshKind Just moduleName <- checkCurrentModule <$> get (k2, args) <- bindLocalTypeVariables moduleName [(ProperName ident, k1)] $ infer ty unifyKinds k2 kindType return (kindType, (ident, k1) : args) -infer' (KindedType ty k) = do +infer' (KindedType _ ty k) = do (k', args) <- infer ty unifyKinds k k' return (k', args) infer' other = (, []) <$> go other where - go :: Type -> m Kind - go (ForAll ident ty _) = do + go :: SourceType -> m SourceKind + go (ForAll _ ident ty _) = do k1 <- freshKind Just moduleName <- checkCurrentModule <$> get k2 <- bindLocalTypeVariables moduleName [(ProperName ident, k1)] $ go ty unifyKinds k2 kindType return kindType - go (KindedType ty k) = do + go (KindedType _ ty k) = do k' <- go ty unifyKinds k k' return k' go TypeWildcard{} = freshKind go TUnknown{} = freshKind - go (TypeLevelString _) = return kindSymbol - go (TypeVar v) = do + go (TypeLevelString {}) = return kindSymbol + go (TypeVar _ v) = do Just moduleName <- checkCurrentModule <$> get lookupTypeVariable moduleName (Qualified Nothing (ProperName v)) - go (Skolem v _ _ _) = do + go (Skolem _ v _ _) = do Just moduleName <- checkCurrentModule <$> get lookupTypeVariable moduleName (Qualified Nothing (ProperName v)) - go (TypeConstructor v) = do + go (TypeConstructor _ v) = do env <- getEnv case M.lookup v (types env) of Nothing -> throwError . errorMessage . UnknownName $ fmap TyName v Just (kind, _) -> return kind - go (TypeApp t1 t2) = do + go (TypeApp _ t1 t2) = do k0 <- freshKind k1 <- go t1 k2 <- go t2 - unifyKinds k1 (FunKind k2 k0) + unifyKinds k1 (FunKind nullSourceAnn k2 k0) return k0 - go REmpty = do + go (REmpty _) = do k <- freshKind - return $ Row k - go (RCons _ ty row) = do + return $ Row nullSourceAnn k + go (RCons _ _ ty row) = do k1 <- go ty k2 <- go row - unifyKinds k2 (Row k1) - return $ Row k1 - go (ConstrainedType (Constraint className tys _) ty) = do - k1 <- go $ foldl TypeApp (TypeConstructor (fmap coerceProperName className)) tys + unifyKinds k2 (Row nullSourceAnn k1) + return $ Row nullSourceAnn k1 + go (ConstrainedType ann2 (Constraint ann1 className tys _) ty) = do + k1 <- go $ foldl (TypeApp ann2) (TypeConstructor ann1 (fmap coerceProperName className)) tys unifyKinds k1 kindType k2 <- go ty unifyKinds k2 kindType diff --git a/src/Language/PureScript/TypeChecker/Monad.hs b/src/Language/PureScript/TypeChecker/Monad.hs index e85b1af5fd..7ec603fa7f 100644 --- a/src/Language/PureScript/TypeChecker/Monad.hs +++ b/src/Language/PureScript/TypeChecker/Monad.hs @@ -27,8 +27,8 @@ import Language.PureScript.Types -- | A substitution of unification variables for types or kinds data Substitution = Substitution - { substType :: M.Map Int Type -- ^ Type substitution - , substKind :: M.Map Int Kind -- ^ Kind substitution + { substType :: M.Map Int SourceType -- ^ Type substitution + , substKind :: M.Map Int SourceKind -- ^ Kind substitution } -- | An empty substitution @@ -68,7 +68,7 @@ type Unknown = Int -- | Temporarily bind a collection of names to values bindNames :: MonadState CheckState m - => M.Map (Qualified Ident) (Type, NameKind, NameVisibility) + => M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) -> m a -> m a bindNames newNames action = do @@ -81,7 +81,7 @@ bindNames newNames action = do -- | Temporarily bind a collection of names to types bindTypes :: MonadState CheckState m - => M.Map (Qualified (ProperName 'TypeName)) (Kind, TypeKind) + => M.Map (Qualified (ProperName 'TypeName)) (SourceKind, TypeKind) -> m a -> m a bindTypes newNames action = do @@ -95,7 +95,7 @@ bindTypes newNames action = do withScopedTypeVars :: (MonadState CheckState m, MonadWriter MultipleErrors m) => ModuleName - -> [(Text, Kind)] + -> [(Text, SourceKind)] -> m a -> m a withScopedTypeVars mn ks ma = do @@ -182,7 +182,7 @@ lookupTypeClassDictionariesForClass mn cn = fromMaybe M.empty . M.lookup cn <$> -- | Temporarily bind a collection of names to local variables bindLocalVariables :: (MonadState CheckState m) - => [(Ident, Type, NameVisibility)] + => [(Ident, SourceType, NameVisibility)] -> m a -> m a bindLocalVariables bindings = @@ -192,7 +192,7 @@ bindLocalVariables bindings = bindLocalTypeVariables :: (MonadState CheckState m) => ModuleName - -> [(ProperName 'TypeName, Kind)] + -> [(ProperName 'TypeName, SourceKind)] -> m a -> m a bindLocalTypeVariables moduleName bindings = @@ -218,7 +218,7 @@ preservingNames action = do lookupVariable :: (e ~ MultipleErrors, MonadState CheckState m, MonadError e m) => Qualified Ident - -> m Type + -> m SourceType lookupVariable qual = do env <- getEnv case M.lookup qual (names env) of @@ -252,7 +252,7 @@ lookupTypeVariable :: (e ~ MultipleErrors, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified (ProperName 'TypeName) - -> m Kind + -> m SourceKind lookupTypeVariable currentModule (Qualified moduleName name) = do env <- getEnv case M.lookup (Qualified (Just $ fromMaybe currentModule moduleName) name) (types env) of diff --git a/src/Language/PureScript/TypeChecker/Skolems.hs b/src/Language/PureScript/TypeChecker/Skolems.hs index ed7659c92f..76af631635 100644 --- a/src/Language/PureScript/TypeChecker/Skolems.hs +++ b/src/Language/PureScript/TypeChecker/Skolems.hs @@ -31,10 +31,10 @@ newSkolemConstant = do return s -- | Introduce skolem scope at every occurence of a ForAll -introduceSkolemScope :: MonadState CheckState m => Type -> m Type +introduceSkolemScope :: MonadState CheckState m => Type a -> m (Type a) introduceSkolemScope = everywhereOnTypesM go where - go (ForAll ident ty Nothing) = ForAll ident ty <$> (Just <$> newSkolemScope) + go (ForAll ann ident ty Nothing) = ForAll ann ident ty <$> (Just <$> newSkolemScope) go other = return other -- | Generate a new skolem scope @@ -45,14 +45,14 @@ newSkolemScope = do return $ SkolemScope s -- | Skolemize a type variable by replacing its instances with fresh skolem constants -skolemize :: Text -> Int -> SkolemScope -> Maybe SourceSpan -> Type -> Type -skolemize ident sko scope ss = replaceTypeVars ident (Skolem ident sko scope ss) +skolemize :: a -> Text -> Int -> SkolemScope -> Type a -> Type a +skolemize ann ident sko scope = replaceTypeVars ident (Skolem ann ident sko scope) -- | This function skolemizes type variables appearing in any type signatures or -- 'DeferredDictionary' placeholders. These type variables are the only places -- where scoped type variables can appear in expressions. -skolemizeTypesInValue :: Text -> Int -> SkolemScope -> Maybe SourceSpan -> Expr -> Expr -skolemizeTypesInValue ident sko scope ss = +skolemizeTypesInValue :: SourceAnn -> Text -> Int -> SkolemScope -> Expr -> Expr +skolemizeTypesInValue ann ident sko scope = runIdentity . onExpr' where onExpr' :: Expr -> Identity Expr @@ -60,18 +60,18 @@ skolemizeTypesInValue ident sko scope ss = onExpr :: [Text] -> Expr -> Identity ([Text], Expr) onExpr sco (DeferredDictionary c ts) - | ident `notElem` sco = return (sco, DeferredDictionary c (map (skolemize ident sko scope ss) ts)) + | ident `notElem` sco = return (sco, DeferredDictionary c (map (skolemize ann ident sko scope) ts)) onExpr sco (TypedValue check val ty) - | ident `notElem` sco = return (sco ++ peelTypeVars ty, TypedValue check val (skolemize ident sko scope ss ty)) + | ident `notElem` sco = return (sco ++ peelTypeVars ty, TypedValue check val (skolemize ann ident sko scope ty)) onExpr sco other = return (sco, other) onBinder :: [Text] -> Binder -> Identity ([Text], Binder) onBinder sco (TypedBinder ty b) - | ident `notElem` sco = return (sco ++ peelTypeVars ty, TypedBinder (skolemize ident sko scope ss ty) b) + | ident `notElem` sco = return (sco ++ peelTypeVars ty, TypedBinder (skolemize ann ident sko scope ty) b) onBinder sco other = return (sco, other) - peelTypeVars :: Type -> [Text] - peelTypeVars (ForAll i ty _) = i : peelTypeVars ty + peelTypeVars :: SourceType -> [Text] + peelTypeVars (ForAll _ i ty _) = i : peelTypeVars ty peelTypeVars _ = [] -- | Ensure skolem variables do not escape their scope @@ -100,8 +100,8 @@ skolemEscapeCheck expr@TypedValue{} = go (scopes, ssUsed) val@(TypedValue _ _ ty) = ( (allScopes, ssUsed) , [ ErrorMessage (maybe id ((:) . positionedError) ssUsed [ ErrorInExpression val ]) $ - EscapedSkolem name ssBound ty - | (name, scope, ssBound) <- collectSkolems ty + EscapedSkolem name (nonEmptySpan ssBound) ty + | (ssBound, name, scope) <- collectSkolems ty , notMember scope allScopes ] ) @@ -115,15 +115,15 @@ skolemEscapeCheck expr@TypedValue{} = allScopes = fromList newScopes <> scopes -- Collect any scopes appearing in quantifiers at the top level - collectScopes :: Type -> [SkolemScope] - collectScopes (ForAll _ t (Just sco)) = sco : collectScopes t + collectScopes :: SourceType -> [SkolemScope] + collectScopes (ForAll _ _ t (Just sco)) = sco : collectScopes t collectScopes ForAll{} = internalError "skolemEscapeCheck: No skolem scope" collectScopes _ = [] -- Collect any skolem variables appearing in a type - collectSkolems :: Type -> [(Text, SkolemScope, Maybe SourceSpan)] + collectSkolems :: SourceType -> [(SourceAnn, Text, SkolemScope)] collectSkolems = everythingOnTypes (++) collect where - collect (Skolem name _ scope srcSpan) = [(name, scope, srcSpan)] + collect (Skolem ss name _ scope) = [(ss, name, scope)] collect _ = [] go scos _ = (scos, []) skolemEscapeCheck _ = internalError "skolemEscapeCheck: untyped value" diff --git a/src/Language/PureScript/TypeChecker/Subsumption.hs b/src/Language/PureScript/TypeChecker/Subsumption.hs index 65d6a91ba3..af5275dcca 100644 --- a/src/Language/PureScript/TypeChecker/Subsumption.hs +++ b/src/Language/PureScript/TypeChecker/Subsumption.hs @@ -61,8 +61,8 @@ defaultCoercion SNoElaborate = () -- | Check that one type subsumes another, rethrowing errors to provide a better error message subsumes :: (MonadError MultipleErrors m, MonadState CheckState m) - => Type - -> Type + => SourceType + -> SourceType -> m (Expr -> Expr) subsumes ty1 ty2 = withErrorMessageHint (ErrorInSubsumption ty1 ty2) $ @@ -72,46 +72,46 @@ subsumes ty1 ty2 = subsumes' :: (MonadError MultipleErrors m, MonadState CheckState m) => ModeSing mode - -> Type - -> Type + -> SourceType + -> SourceType -> m (Coercion mode) -subsumes' mode (ForAll ident ty1 _) ty2 = do +subsumes' mode (ForAll _ ident ty1 _) ty2 = do replaced <- replaceVarWithUnknown ident ty1 subsumes' mode replaced ty2 -subsumes' mode ty1 (ForAll ident ty2 sco) = +subsumes' mode ty1 (ForAll _ ident ty2 sco) = case sco of Just sco' -> do sko <- newSkolemConstant - let sk = skolemize ident sko sco' Nothing ty2 + let sk = skolemize NullSourceAnn ident sko sco' ty2 subsumes' mode ty1 sk Nothing -> internalError "subsumes: unspecified skolem scope" -subsumes' mode (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do +subsumes' mode (TypeApp _ (TypeApp _ f1 arg1) ret1) (TypeApp _ (TypeApp _ f2 arg2) ret2) | eqType f1 tyFunction && eqType f2 tyFunction = do subsumes' SNoElaborate arg2 arg1 subsumes' SNoElaborate ret1 ret2 -- Nothing was elaborated, return the default coercion return (defaultCoercion mode) -subsumes' mode (KindedType ty1 _) ty2 = +subsumes' mode (KindedType _ ty1 _) ty2 = subsumes' mode ty1 ty2 -subsumes' mode ty1 (KindedType ty2 _) = +subsumes' mode ty1 (KindedType _ ty2 _) = subsumes' mode ty1 ty2 -- Only check subsumption for constrained types when elaborating. -- Otherwise fall back to unification. -subsumes' SElaborate (ConstrainedType con ty1) ty2 = do +subsumes' SElaborate (ConstrainedType _ con ty1) ty2 = do dicts <- getTypeClassDictionaries hints <- getHints elaborate <- subsumes' SElaborate ty1 ty2 let addDicts val = App val (TypeClassDictionary con dicts hints) return (elaborate . addDicts) -subsumes' mode (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyRecord && f2 == tyRecord = do +subsumes' mode (TypeApp _ f1 r1) (TypeApp _ f2 r2) | eqType f1 tyRecord && eqType f2 tyRecord = do let (common, ((ts1', r1'), (ts2', r2'))) = alignRowsWith (subsumes' SNoElaborate) r1 r2 -- For { ts1 | r1 } to subsume { ts2 | r2 } when r1 is empty (= we're working with a closed row), -- every property in ts2 must appear in ts1. If not, then the candidate expression is missing a required property. -- Conversely, when r2 is empty, every property in ts1 must appear in ts2, or else the expression has -- an additional property which is not allowed. - when (r1' == REmpty) - (for_ (firstMissingProp ts2' ts1') (throwError . errorMessage . PropertyIsMissing . fst)) - when (r2' == REmpty) - (for_ (firstMissingProp ts1' ts2') (throwError . errorMessage . AdditionalProperty . fst)) + when (eqType r1' $ REmpty ()) + (for_ (firstMissingProp ts2' ts1') (throwError . errorMessage . PropertyIsMissing . rowListLabel)) + when (eqType r2' $ REmpty ()) + (for_ (firstMissingProp ts1' ts2') (throwError . errorMessage . AdditionalProperty . rowListLabel)) -- Check subsumption for common labels sequence_ common unifyTypes (rowFromList (ts1', r1')) (rowFromList (ts2', r2')) @@ -119,8 +119,8 @@ subsumes' mode (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyRecord && f2 == tyRecor return (defaultCoercion mode) where -- Find the first property that's in the first list (of tuples) but not in the second - firstMissingProp t1 t2 = fst <$> uncons (minusBy' (comparing fst) t1 t2) -subsumes' mode ty1 ty2@(TypeApp obj _) | obj == tyRecord = + firstMissingProp t1 t2 = fst <$> uncons (minusBy' (comparing rowListLabel) t1 t2) +subsumes' mode ty1 ty2@(TypeApp _ obj _) | obj == tyRecord = subsumes' mode ty2 ty1 subsumes' mode ty1 ty2 = do unifyTypes ty1 ty2 diff --git a/src/Language/PureScript/TypeChecker/Synonyms.hs b/src/Language/PureScript/TypeChecker/Synonyms.hs index 08016b2315..7d5d250e94 100644 --- a/src/Language/PureScript/TypeChecker/Synonyms.hs +++ b/src/Language/PureScript/TypeChecker/Synonyms.hs @@ -24,19 +24,19 @@ import Language.PureScript.TypeChecker.Monad import Language.PureScript.Types -- | Type synonym information (arguments with kinds, aliased type), indexed by name -type SynonymMap = M.Map (Qualified (ProperName 'TypeName)) ([(Text, Maybe Kind)], Type) +type SynonymMap = M.Map (Qualified (ProperName 'TypeName)) ([(Text, Maybe SourceKind)], SourceType) replaceAllTypeSynonyms' :: SynonymMap - -> Type - -> Either MultipleErrors Type + -> SourceType + -> Either MultipleErrors SourceType replaceAllTypeSynonyms' syns = everywhereOnTypesTopDownM try where - try :: Type -> Either MultipleErrors Type + try :: SourceType -> Either MultipleErrors SourceType try t = fromMaybe t <$> go 0 [] t - go :: Int -> [Type] -> Type -> Either MultipleErrors (Maybe Type) - go c args (TypeConstructor ctor) + go :: Int -> [SourceType] -> SourceType -> Either MultipleErrors (Maybe SourceType) + go c args (TypeConstructor _ ctor) | Just (synArgs, body) <- M.lookup ctor syns , c == length synArgs = let repl = replaceAllTypeVars (zip (map fst synArgs) args) body @@ -44,11 +44,11 @@ replaceAllTypeSynonyms' syns = everywhereOnTypesTopDownM try | Just (synArgs, _) <- M.lookup ctor syns , length synArgs > c = throwError . errorMessage $ PartiallyAppliedSynonym ctor - go c args (TypeApp f arg) = go (c + 1) (arg : args) f + go c args (TypeApp _ f arg) = go (c + 1) (arg : args) f go _ _ _ = return Nothing -- | Replace fully applied type synonyms -replaceAllTypeSynonyms :: (e ~ MultipleErrors, MonadState CheckState m, MonadError e m) => Type -> m Type +replaceAllTypeSynonyms :: (e ~ MultipleErrors, MonadState CheckState m, MonadError e m) => SourceType -> m SourceType replaceAllTypeSynonyms d = do env <- getEnv either throwError return $ replaceAllTypeSynonyms' (typeSynonyms env) d @@ -57,6 +57,6 @@ replaceAllTypeSynonyms d = do replaceAllTypeSynonymsM :: MonadError MultipleErrors m => SynonymMap - -> Type - -> m Type + -> SourceType + -> m SourceType replaceAllTypeSynonymsM syns = either throwError pure . replaceAllTypeSynonyms' syns diff --git a/src/Language/PureScript/TypeChecker/TypeSearch.hs b/src/Language/PureScript/TypeChecker/TypeSearch.hs index 225410ab5b..a636e3503f 100644 --- a/src/Language/PureScript/TypeChecker/TypeSearch.hs +++ b/src/Language/PureScript/TypeChecker/TypeSearch.hs @@ -39,17 +39,17 @@ evalWriterT :: Monad m => WriterT b m r -> m r evalWriterT m = liftM fst (runWriterT m) checkSubsume - :: Maybe [(P.Ident, Entailment.InstanceContext, P.Constraint)] + :: Maybe [(P.Ident, Entailment.InstanceContext, P.SourceConstraint)] -- ^ Additional constraints we need to satisfy -> P.Environment -- ^ The Environment which contains the relevant definitions and typeclasses -> TC.CheckState -- ^ The typechecker state - -> P.Type + -> P.SourceType -- ^ The user supplied type - -> P.Type + -> P.SourceType -- ^ The type supplied by the environment - -> Maybe ((P.Expr, [(P.Ident, Entailment.InstanceContext, P.Constraint)]), P.Environment) + -> Maybe ((P.Expr, [(P.Ident, Entailment.InstanceContext, P.SourceConstraint)]), P.Environment) checkSubsume unsolved env st userT envT = checkInEnvironment env st $ do let initializeSkolems = Skolem.introduceSkolemScope @@ -79,11 +79,11 @@ checkSubsume unsolved env st userT envT = checkInEnvironment env st $ do Entailment.replaceTypeClassDictionaries (isJust unsolved) expP accessorSearch - :: Maybe [(P.Ident, Entailment.InstanceContext, P.Constraint)] + :: Maybe [(P.Ident, Entailment.InstanceContext, P.SourceConstraint)] -> P.Environment -> TC.CheckState - -> P.Type - -> ([(Label, P.Type)], [(Label, P.Type)]) + -> P.SourceType + -> ([(Label, P.SourceType)], [(Label, P.SourceType)]) -- ^ (all accessors we found, all accessors we found that match the result type) accessorSearch unsolved env st userT = maybe ([], []) fst $ checkInEnvironment env st $ do let initializeSkolems = @@ -95,28 +95,29 @@ accessorSearch unsolved env st userT = maybe ([], []) fst $ checkInEnvironment e rowType <- freshType resultType <- freshType - let recordFunction = TypeApp (TypeApp tyFunction (TypeApp tyRecord rowType)) resultType + let recordFunction = srcTypeApp (srcTypeApp tyFunction (srcTypeApp tyRecord rowType)) resultType _ <- subsumes recordFunction userT' subst <- gets TC.checkSubstitution - let solvedRow = fst (rowToList (substituteType subst rowType)) + let solvedRow = toRowPair <$> fst (rowToList (substituteType subst rowType)) tcS <- get pure (solvedRow, filter (\x -> checkAccessor tcS (substituteType subst resultType) x) solvedRow) where checkAccessor tcs x (_, type') = isJust (checkSubsume unsolved env tcs x type') + toRowPair (RowListItem _ lbl ty) = (lbl, ty) typeSearch - :: Maybe [(P.Ident, Entailment.InstanceContext, P.Constraint)] + :: Maybe [(P.Ident, Entailment.InstanceContext, P.SourceConstraint)] -- ^ Additional constraints we need to satisfy -> P.Environment -- ^ The Environment which contains the relevant definitions and typeclasses -> TC.CheckState -- ^ The typechecker state - -> P.Type + -> P.SourceType -- ^ The type we are looking for - -> ([(P.Qualified Text, P.Type)], Maybe [(Label, P.Type)]) + -> ([(P.Qualified Text, P.SourceType)], Maybe [(Label, P.SourceType)]) typeSearch unsolved env st type' = let - runTypeSearch :: Map k P.Type -> Map k P.Type + runTypeSearch :: Map k P.SourceType -> Map k P.SourceType runTypeSearch = Map.mapMaybe (\ty -> checkSubsume unsolved env st type' ty $> ty) matchingNames = runTypeSearch (Map.map (\(ty, _, _) -> ty) (P.names env)) diff --git a/src/Language/PureScript/TypeChecker/Types.hs b/src/Language/PureScript/TypeChecker/Types.hs index 51dac649e6..6275141a1a 100644 --- a/src/Language/PureScript/TypeChecker/Types.hs +++ b/src/Language/PureScript/TypeChecker/Types.hs @@ -75,7 +75,7 @@ typesOf => BindingGroupType -> ModuleName -> [((SourceAnn, Ident), Expr)] - -> m [((SourceAnn, Ident), (Expr, Type))] + -> m [((SourceAnn, Ident), (Expr, SourceType))] typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do (tys, wInfer) <- capturingSubstitution tidyUp $ do (SplitBindingGroup untyped typed dict, w) <- withoutWarnings $ typeDictionaryForBindingGroup (Just moduleName) vals @@ -144,7 +144,7 @@ typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do -- | Run type search to complete any typed hole error messages runTypeSearch - :: Maybe [(Ident, InstanceContext, Constraint)] + :: Maybe [(Ident, InstanceContext, SourceConstraint)] -- ^ Any unsolved constraints which we need to continue to satisfy -> CheckState -- ^ The final type checker state @@ -163,7 +163,7 @@ typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do generalize unsolved = varIfUnknown . constrain unsolved -- | Add any unsolved constraints - constrain cs ty = foldr ConstrainedType ty (map (\(_, _, x) -> x) cs) + constrain cs ty = foldr srcConstrainedType ty (map (\(_, _, x) -> x) cs) -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values tidyUp ts sub = first (map (second (first (second (overTypes (substituteType sub) *** substituteType sub))))) ts @@ -177,11 +177,11 @@ typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do -- -- This structure breaks down a binding group into typed and untyped parts. data SplitBindingGroup = SplitBindingGroup - { _splitBindingGroupUntyped :: [((SourceAnn, Ident), (Expr, Type))] + { _splitBindingGroupUntyped :: [((SourceAnn, Ident), (Expr, SourceType))] -- ^ The untyped expressions - , _splitBindingGroupTyped :: [((SourceAnn, Ident), (Expr, Type, Bool))] + , _splitBindingGroupTyped :: [((SourceAnn, Ident), (Expr, SourceType, Bool))] -- ^ The typed expressions, along with their type annotations - , _splitBindingGroupNames :: M.Map (Qualified Ident) (Type, NameKind, NameVisibility) + , _splitBindingGroupNames :: M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) -- ^ A map containing all expressions and their assigned types (which might be -- fresh unification variables). These will be added to the 'Environment' after -- the binding group is checked, so the value type of the 'Map' is chosen to be @@ -218,7 +218,7 @@ typeDictionaryForBindingGroup moduleName vals = do where -- | Check if a value contains a type annotation, and if so, separate it -- from the value itself. - splitTypeAnnotation :: (a, Expr) -> Either (a, Expr) (a, (Expr, Type, Bool)) + splitTypeAnnotation :: (a, Expr) -> Either (a, Expr) (a, (Expr, SourceType, Bool)) splitTypeAnnotation (a, TypedValue checkType value ty) = Right (a, (value, ty, checkType)) splitTypeAnnotation (a, PositionedValue pos c value) = bimap (second (PositionedValue pos c)) @@ -230,11 +230,11 @@ typeDictionaryForBindingGroup moduleName vals = do checkTypedBindingGroupElement :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => ModuleName - -> ((SourceAnn, Ident), (Expr, Type, Bool)) + -> ((SourceAnn, Ident), (Expr, SourceType, Bool)) -- ^ The identifier we are trying to define, along with the expression and its type annotation - -> M.Map (Qualified Ident) (Type, NameKind, NameVisibility) + -> M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) -- ^ Names brought into scope in this binding group - -> m ((SourceAnn, Ident), (Expr, Type)) + -> m ((SourceAnn, Ident), (Expr, SourceType)) checkTypedBindingGroupElement mn (ident, (val, ty, checkType)) dict = do -- Kind check (kind, args) <- kindOfWithScopedVars ty @@ -251,12 +251,12 @@ checkTypedBindingGroupElement mn (ident, (val, ty, checkType)) dict = do -- | Infer a type for a value in a binding group which lacks an annotation. typeForBindingGroupElement :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) - => ((SourceAnn, Ident), (Expr, Type)) + => ((SourceAnn, Ident), (Expr, SourceType)) -- ^ The identifier we are trying to define, along with the expression and its assigned type -- (at this point, this should be a unification variable) - -> M.Map (Qualified Ident) (Type, NameKind, NameVisibility) + -> M.Map (Qualified Ident) (SourceType, NameKind, NameVisibility) -- ^ Names brought into scope in this binding group - -> m ((SourceAnn, Ident), (Expr, Type)) + -> m ((SourceAnn, Ident), (Expr, SourceType)) typeForBindingGroupElement (ident, (val, ty)) dict = do -- Infer the type with the new names in scope TypedValue _ val' ty' <- bindNames dict $ infer val @@ -267,10 +267,10 @@ typeForBindingGroupElement (ident, (val, ty)) dict = do -- | Check the kind of a type, failing if it is not of kind *. checkTypeKind :: MonadError MultipleErrors m - => Type - -> Kind + => SourceType + -> SourceKind -> m () -checkTypeKind ty kind = guardWith (errorMessage (ExpectedType ty kind)) $ kind == kindType +checkTypeKind ty kind = guardWith (errorMessage (ExpectedType ty kind)) $ isKindType kind -- | Remove any ForAlls and ConstrainedType constructors in a type by introducing new unknowns -- or TypeClassDictionary values. @@ -280,12 +280,12 @@ checkTypeKind ty kind = guardWith (errorMessage (ExpectedType ty kind)) $ kind = instantiatePolyTypeWithUnknowns :: (MonadState CheckState m, MonadError MultipleErrors m) => Expr - -> Type - -> m (Expr, Type) -instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do + -> SourceType + -> m (Expr, SourceType) +instantiatePolyTypeWithUnknowns val (ForAll _ ident ty _) = do ty' <- replaceVarWithUnknown ident ty instantiatePolyTypeWithUnknowns val ty' -instantiatePolyTypeWithUnknowns val (ConstrainedType con ty) = do +instantiatePolyTypeWithUnknowns val (ConstrainedType _ con ty) = do dicts <- getTypeClassDictionaries hints <- getHints instantiatePolyTypeWithUnknowns (App val (TypeClassDictionary con dicts hints)) ty @@ -316,7 +316,7 @@ infer' (Literal ss (ArrayLiteral vals)) = do (val', t') <- instantiatePolyTypeWithUnknowns val t unifyTypes els t' return (TypedValue ch val' t') - return $ TypedValue True (Literal ss (ArrayLiteral ts')) (TypeApp tyArray els) + return $ TypedValue True (Literal ss (ArrayLiteral ts')) (srcTypeApp tyArray els) infer' (Literal ss (ObjectLiteral ps)) = do ensureNoDuplicateProperties ps -- We make a special case for Vars in record labels, since these are the @@ -327,29 +327,33 @@ infer' (Literal ss (ObjectLiteral ps)) = do shouldInstantiate (PositionedValue _ _ e) = shouldInstantiate e shouldInstantiate _ = False - inferProperty :: (PSString, Expr) -> m (PSString, (Expr, Type)) + inferProperty :: (PSString, Expr) -> m (PSString, (Expr, SourceType)) inferProperty (name, val) = do TypedValue _ val' ty <- infer val valAndType <- if shouldInstantiate val then instantiatePolyTypeWithUnknowns val' ty else pure (val', ty) pure (name, valAndType) + + toRowListItem (lbl, (_, ty)) = srcRowListItem (Label lbl) ty + fields <- forM ps inferProperty - let ty = TypeApp tyRecord $ rowFromList (map (Label *** snd) fields, REmpty) + let ty = srcTypeApp tyRecord $ rowFromList (map toRowListItem fields, srcREmpty) return $ TypedValue True (Literal ss (ObjectLiteral (map (fmap (uncurry (TypedValue True))) fields))) ty infer' (ObjectUpdate o ps) = do ensureNoDuplicateProperties ps row <- freshType newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> traverse (infer . snd) ps + let toRowListItem = uncurry srcRowListItem let newTys = map (\(name, TypedValue _ _ ty) -> (Label name, ty)) newVals oldTys <- zip (map (Label . fst) ps) <$> replicateM (length ps) freshType - let oldTy = TypeApp tyRecord $ rowFromList (oldTys, row) + let oldTy = srcTypeApp tyRecord $ rowFromList (toRowListItem <$> oldTys, row) o' <- TypedValue True <$> check o oldTy <*> pure oldTy - return $ TypedValue True (ObjectUpdate o' newVals) $ TypeApp tyRecord $ rowFromList (newTys, row) + return $ TypedValue True (ObjectUpdate o' newVals) $ srcTypeApp tyRecord $ rowFromList (toRowListItem <$> newTys, row) infer' (Accessor prop val) = withErrorMessageHint (ErrorCheckingAccessor val prop) $ do field <- freshType rest <- freshType - typed <- check val (TypeApp tyRecord (RCons (Label prop) field rest)) + typed <- check val (srcTypeApp tyRecord (srcRCons (Label prop) field rest)) return $ TypedValue True (Accessor prop typed) field infer' (Abs binder ret) | VarBinder ss arg <- binder = do @@ -367,7 +371,7 @@ infer' (Var ss var) = do checkVisibility var ty <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards <=< lookupVariable $ var case ty of - ConstrainedType con ty' -> do + ConstrainedType _ con ty' -> do dicts <- getTypeClassDictionaries hints <- getHints return $ TypedValue True (App (Var ss var) (TypeClassDictionary con dicts hints)) ty' @@ -398,8 +402,8 @@ infer' (DeferredDictionary className tys) = do dicts <- getTypeClassDictionaries hints <- getHints return $ TypedValue False - (TypeClassDictionary (Constraint className tys Nothing) dicts hints) - (foldl TypeApp (TypeConstructor (fmap coerceProperName className)) tys) + (TypeClassDictionary (srcConstraint className tys Nothing) dicts hints) + (foldl srcTypeApp (srcTypeConstructor (fmap coerceProperName className)) tys) infer' (TypedValue checkType val ty) = do Just moduleName <- checkCurrentModule <$> get (kind, args) <- kindOfWithScopedVars ty @@ -459,9 +463,9 @@ inferLetBinding _ _ _ _ = internalError "Invalid argument to inferLetBinding" inferBinder :: forall m . (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) - => Type + => SourceType -> Binder - -> m (M.Map Ident Type) + -> m (M.Map Ident SourceType) inferBinder _ NullBinder = return M.empty inferBinder val (LiteralBinder _ (StringLiteral _)) = unifyTypes val tyString >> return M.empty inferBinder val (LiteralBinder _ (CharLiteral _)) = unifyTypes val tyChar >> return M.empty @@ -483,29 +487,29 @@ inferBinder val (ConstructorBinder ss ctor binders) = do M.unions <$> zipWithM inferBinder (reverse args) binders _ -> throwError . errorMessage' ss . UnknownName . fmap DctorName $ ctor where - peelArgs :: Type -> ([Type], Type) + peelArgs :: Type a -> ([Type a], Type a) peelArgs = go [] where - go args (TypeApp (TypeApp fn arg) ret) | fn == tyFunction = go (arg : args) ret + go args (TypeApp _ (TypeApp _ fn arg) ret) | eqType fn tyFunction = go (arg : args) ret go args ret = (args, ret) inferBinder val (LiteralBinder _ (ObjectLiteral props)) = do row <- freshType rest <- freshType m1 <- inferRowProperties row rest props - unifyTypes val (TypeApp tyRecord row) + unifyTypes val (srcTypeApp tyRecord row) return m1 where - inferRowProperties :: Type -> Type -> [(PSString, Binder)] -> m (M.Map Ident Type) + inferRowProperties :: SourceType -> SourceType -> [(PSString, Binder)] -> m (M.Map Ident SourceType) inferRowProperties nrow row [] = unifyTypes nrow row >> return M.empty inferRowProperties nrow row ((name, binder):binders) = do propTy <- freshType m1 <- inferBinder propTy binder - m2 <- inferRowProperties nrow (RCons (Label name) propTy row) binders + m2 <- inferRowProperties nrow (srcRCons (Label name) propTy row) binders return $ m1 `M.union` m2 inferBinder val (LiteralBinder _ (ArrayLiteral binders)) = do el <- freshType m1 <- M.unions <$> traverse (inferBinder el) binders - unifyTypes val (TypeApp tyArray el) + unifyTypes val (srcTypeApp tyArray el) return m1 inferBinder val (NamedBinder ss name binder) = warnAndRethrowWithPositionTC ss $ do @@ -541,7 +545,7 @@ instantiateForBinders :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => [Expr] -> [CaseAlternative] - -> m ([Expr], [Type]) + -> m ([Expr], [SourceType]) instantiateForBinders vals cas = unzip <$> zipWithM (\val inst -> do TypedValue _ val' ty <- infer val if inst @@ -556,8 +560,8 @@ instantiateForBinders vals cas = unzip <$> zipWithM (\val inst -> do -- checkBinders :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) - => [Type] - -> Type + => [SourceType] + -> SourceType -> [CaseAlternative] -> m [CaseAlternative] checkBinders _ _ [] = return [] @@ -573,7 +577,7 @@ checkBinders nvals ret (CaseAlternative binders result : bs) = do checkGuardedRhs :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => GuardedExpr - -> Type + -> SourceType -> m GuardedExpr checkGuardedRhs (GuardedExpr [] rhs) ret = do rhs' <- TypedValue True <$> check rhs ret <*> pure ret @@ -597,7 +601,7 @@ checkGuardedRhs (GuardedExpr (PatternGuard binder expr : guards) rhs) ret = do check :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Expr - -> Type + -> SourceType -> m Expr check val ty = withErrorMessageHint (ErrorCheckingType val ty) $ check' val ty @@ -608,24 +612,24 @@ check' :: forall m . (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Expr - -> Type + -> SourceType -> m Expr -check' val (ForAll ident ty _) = do +check' val (ForAll ann ident ty _) = do scope <- newSkolemScope sko <- newSkolemConstant let ss = case val of - PositionedValue pos _ _ -> Just pos - _ -> Nothing - sk = skolemize ident sko scope ss ty - skVal = skolemizeTypesInValue ident sko scope ss val + PositionedValue pos c _ -> (pos, c) + _ -> NullSourceAnn + sk = skolemize ss ident sko scope ty + skVal = skolemizeTypesInValue ss ident sko scope val val' <- check skVal sk - return $ TypedValue True val' (ForAll ident ty (Just scope)) -check' val t@(ConstrainedType con@(Constraint (Qualified _ (ProperName className)) _ _) ty) = do + return $ TypedValue True val' (ForAll ann ident ty (Just scope)) +check' val t@(ConstrainedType _ con@(Constraint _ (Qualified _ (ProperName className)) _ _) ty) = do dictName <- freshIdent ("dict" <> className) dicts <- newDictionaries [] (Qualified Nothing dictName) con val' <- withBindingGroupVisible $ withTypeClassDictionaries dicts $ check val ty return $ TypedValue True (Abs (VarBinder nullSourceSpan dictName) val') t -check' val u@(TUnknown _) = do +check' val u@(TUnknown _ _) = do val'@(TypedValue _ _ ty) <- infer val -- Don't unify an unknown with an inferred polytype (val'', ty') <- instantiatePolyTypeWithUnknowns val' ty @@ -641,11 +645,11 @@ check' v@(Literal _ (CharLiteral _)) t | t == tyChar = return $ TypedValue True v t check' v@(Literal _ (BooleanLiteral _)) t | t == tyBoolean = return $ TypedValue True v t -check' (Literal ss (ArrayLiteral vals)) t@(TypeApp a ty) = do +check' (Literal ss (ArrayLiteral vals)) t@(TypeApp _ a ty) = do unifyTypes a tyArray array <- Literal ss . ArrayLiteral <$> forM vals (`check` ty) return $ TypedValue True array t -check' (Abs binder ret) ty@(TypeApp (TypeApp t argTy) retTy) +check' (Abs binder ret) ty@(TypeApp _ (TypeApp _ t argTy) retTy) | VarBinder ss arg <- binder = do unifyTypes t tyFunction ret' <- withBindingGroupVisible $ bindLocalVariables [(arg, argTy, Defined)] $ check ret retTy @@ -672,7 +676,7 @@ check' (DeferredDictionary className tys) ty = do dicts <- getTypeClassDictionaries hints <- getHints return $ TypedValue False - (TypeClassDictionary (Constraint className tys Nothing) dicts hints) + (TypeClassDictionary (srcConstraint className tys Nothing) dicts hints) ty check' (TypedValue checkType val ty1) ty2 = do kind <- kindOf ty1 @@ -693,26 +697,26 @@ check' (IfThenElse cond th el) ty = do th' <- check th ty el' <- check el ty return $ TypedValue True (IfThenElse cond' th' el') ty -check' e@(Literal ss (ObjectLiteral ps)) t@(TypeApp obj row) | obj == tyRecord = do +check' e@(Literal ss (ObjectLiteral ps)) t@(TypeApp _ obj row) | obj == tyRecord = do ensureNoDuplicateProperties ps ps' <- checkProperties e ps row False return $ TypedValue True (Literal ss (ObjectLiteral ps')) t check' (TypeClassDictionaryConstructorApp name ps) t = do ps' <- check' ps t return $ TypedValue True (TypeClassDictionaryConstructorApp name ps') t -check' e@(ObjectUpdate obj ps) t@(TypeApp o row) | o == tyRecord = do +check' e@(ObjectUpdate obj ps) t@(TypeApp _ o row) | o == tyRecord = do ensureNoDuplicateProperties ps -- We need to be careful to avoid duplicate labels here. -- We check _obj_ against the type _t_ with the types in _ps_ replaced with unknowns. let (propsToCheck, rest) = rowToList row - (removedProps, remainingProps) = partition (\(p, _) -> p `elem` map (Label . fst) ps) propsToCheck - us <- zip (map fst removedProps) <$> replicateM (length ps) freshType - obj' <- check obj (TypeApp tyRecord (rowFromList (us ++ remainingProps, rest))) + (removedProps, remainingProps) = partition (\(RowListItem _ p _) -> p `elem` map (Label . fst) ps) propsToCheck + us <- zipWith srcRowListItem (map rowListLabel removedProps) <$> replicateM (length ps) freshType + obj' <- check obj (srcTypeApp tyRecord (rowFromList (us ++ remainingProps, rest))) ps' <- checkProperties e ps row True return $ TypedValue True (ObjectUpdate obj' ps') t check' (Accessor prop val) ty = withErrorMessageHint (ErrorCheckingAccessor val prop) $ do rest <- freshType - val' <- check val (TypeApp tyRecord (RCons (Label prop) ty rest)) + val' <- check val (srcTypeApp tyRecord (srcRCons (Label prop) ty rest)) return $ TypedValue True (Accessor prop val') ty check' v@(Constructor _ c) ty = do env <- getEnv @@ -726,7 +730,7 @@ check' v@(Constructor _ c) ty = do check' (Let w ds val) ty = do (ds', val') <- inferLetBinding [] ds val (`check` ty) return $ TypedValue True (Let w ds' val') ty -check' val kt@(KindedType ty kind) = do +check' val kt@(KindedType _ ty kind) = do checkTypeKind ty kind val' <- check' val ty return $ TypedValue True val' kt @@ -747,32 +751,33 @@ checkProperties :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Expr -> [(PSString, Expr)] - -> Type + -> SourceType -> Bool -> m [(PSString, Expr)] -checkProperties expr ps row lax = let (ts, r') = rowToList row in go ps ts r' where - go [] [] REmpty = return [] - go [] [] u@(TUnknown _) +checkProperties expr ps row lax = let (ts, r') = rowToList row in go ps (toRowPair <$> ts) r' where + toRowPair (RowListItem _ lbl ty) = (lbl, ty) + go [] [] (REmpty _) = return [] + go [] [] u@(TUnknown _ _) | lax = return [] - | otherwise = do unifyTypes u REmpty + | otherwise = do unifyTypes u srcREmpty return [] go [] [] Skolem{} | lax = return [] go [] ((p, _): _) _ | lax = return [] | otherwise = throwError . errorMessage $ PropertyIsMissing p - go ((p,_):_) [] REmpty = throwError . errorMessage $ AdditionalProperty $ Label p + go ((p,_):_) [] (REmpty _) = throwError . errorMessage $ AdditionalProperty $ Label p go ((p,v):ps') ts r = case lookup (Label p) ts of Nothing -> do v'@(TypedValue _ _ ty) <- infer v rest <- freshType - unifyTypes r (RCons (Label p) ty rest) + unifyTypes r (srcRCons (Label p) ty rest) ps'' <- go ps' ts rest return $ (p, v') : ps'' Just ty -> do v' <- check v ty ps'' <- go ps' (delete (Label p, ty) ts) r return $ (p, v') : ps'' - go _ _ _ = throwError . errorMessage $ ExprDoesNotHaveType expr (TypeApp tyRecord row) + go _ _ _ = throwError . errorMessage $ ExprDoesNotHaveType expr (srcTypeApp tyRecord row) -- | Check the type of a function application, rethrowing errors to provide a better error message. -- @@ -791,11 +796,11 @@ checkFunctionApplication :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Expr -- ^ The function expression - -> Type + -> SourceType -- ^ The type of the function -> Expr -- ^ The argument expression - -> m (Type, Expr) + -> m (SourceType, Expr) -- ^ The result type, and the elaborated term checkFunctionApplication fn fnTy arg = withErrorMessageHint (ErrorInApplication fn fnTy arg) $ do subst <- gets checkSubstitution @@ -805,19 +810,19 @@ checkFunctionApplication fn fnTy arg = withErrorMessageHint (ErrorInApplication checkFunctionApplication' :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Expr - -> Type + -> SourceType -> Expr - -> m (Type, Expr) -checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg = do + -> m (SourceType, Expr) +checkFunctionApplication' fn (TypeApp _ (TypeApp _ tyFunction' argTy) retTy) arg = do unifyTypes tyFunction' tyFunction arg' <- check arg argTy return (retTy, App fn arg') -checkFunctionApplication' fn (ForAll ident ty _) arg = do +checkFunctionApplication' fn (ForAll _ ident ty _) arg = do replaced <- replaceVarWithUnknown ident ty checkFunctionApplication fn replaced arg -checkFunctionApplication' fn (KindedType ty _) arg = +checkFunctionApplication' fn (KindedType _ ty _) arg = checkFunctionApplication fn ty arg -checkFunctionApplication' fn (ConstrainedType con fnTy) arg = do +checkFunctionApplication' fn (ConstrainedType _ con fnTy) arg = do dicts <- getTypeClassDictionaries hints <- getHints checkFunctionApplication' (App fn (TypeClassDictionary con dicts hints)) fnTy arg diff --git a/src/Language/PureScript/TypeChecker/Unify.hs b/src/Language/PureScript/TypeChecker/Unify.hs index 04186dbc93..d53002719a 100644 --- a/src/Language/PureScript/TypeChecker/Unify.hs +++ b/src/Language/PureScript/TypeChecker/Unify.hs @@ -17,7 +17,6 @@ module Language.PureScript.TypeChecker.Unify ) where import Prelude.Compat -import Protolude (ordNub) import Control.Arrow (first, second) import Control.Monad @@ -25,8 +24,10 @@ import Control.Monad.Error.Class (MonadError(..)) import Control.Monad.State.Class (MonadState(..), gets, modify) import Control.Monad.Writer.Class (MonadWriter(..)) -import Data.List (sort) +import Data.Function (on) +import Data.List (sortBy, nubBy) import qualified Data.Map as M +import Data.Ord (comparing) import Data.Text (Text) import qualified Data.Text as T @@ -34,18 +35,17 @@ import Language.PureScript.Crash import Language.PureScript.Errors import Language.PureScript.TypeChecker.Monad import Language.PureScript.TypeChecker.Skolems -import Language.PureScript.Label (Label(..)) import Language.PureScript.Types -- | Generate a fresh type variable -freshType :: (MonadState CheckState m) => m Type +freshType :: (MonadState CheckState m) => m SourceType freshType = do t <- gets checkNextType modify $ \st -> st { checkNextType = t + 1 } - return $ TUnknown t + return $ srcTUnknown t -- | Update the substitution to solve a type constraint -solveType :: (MonadError MultipleErrors m, MonadState CheckState m) => Int -> Type -> m () +solveType :: (MonadError MultipleErrors m, MonadState CheckState m) => Int -> SourceType -> m () solveType u t = do occursCheck u t modify $ \cs -> cs { checkSubstitution = @@ -55,69 +55,69 @@ solveType u t = do } -- | Apply a substitution to a type -substituteType :: Substitution -> Type -> Type +substituteType :: Substitution -> SourceType -> SourceType substituteType sub = everywhereOnTypes go where - go (TUnknown u) = + go (TUnknown ann u) = case M.lookup u (substType sub) of - Nothing -> TUnknown u - Just (TUnknown u1) | u1 == u -> TUnknown u1 + Nothing -> TUnknown ann u + Just (TUnknown ann' u1) | u1 == u -> TUnknown ann' u1 Just t -> substituteType sub t go other = other -- | Make sure that an unknown does not occur in a type -occursCheck :: (MonadError MultipleErrors m) => Int -> Type -> m () +occursCheck :: (MonadError MultipleErrors m) => Int -> SourceType -> m () occursCheck _ TUnknown{} = return () occursCheck u t = void $ everywhereOnTypesM go t where - go (TUnknown u') | u == u' = throwError . errorMessage . InfiniteType $ t + go (TUnknown _ u') | u == u' = throwError . errorMessage . InfiniteType $ t go other = return other -- | Compute a list of all unknowns appearing in a type -unknownsInType :: Type -> [Int] +unknownsInType :: Type a -> [(a, Int)] unknownsInType t = everythingOnTypes (.) go t [] where - go :: Type -> [Int] -> [Int] - go (TUnknown u) = (u :) + go :: Type a -> [(a, Int)] -> [(a, Int)] + go (TUnknown ann u) = ((ann, u) :) go _ = id -- | Unify two types, updating the current substitution -unifyTypes :: (MonadError MultipleErrors m, MonadState CheckState m) => Type -> Type -> m () +unifyTypes :: (MonadError MultipleErrors m, MonadState CheckState m) => SourceType -> SourceType -> m () unifyTypes t1 t2 = do sub <- gets checkSubstitution withErrorMessageHint (ErrorUnifyingTypes t1 t2) $ unifyTypes' (substituteType sub t1) (substituteType sub t2) where - unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return () - unifyTypes' (TUnknown u) t = solveType u t - unifyTypes' t (TUnknown u) = solveType u t - unifyTypes' (ForAll ident1 ty1 sc1) (ForAll ident2 ty2 sc2) = + unifyTypes' (TUnknown _ u1) (TUnknown _ u2) | u1 == u2 = return () + unifyTypes' (TUnknown _ u) t = solveType u t + unifyTypes' t (TUnknown _ u) = solveType u t + unifyTypes' (ForAll ann1 ident1 ty1 sc1) (ForAll ann2 ident2 ty2 sc2) = case (sc1, sc2) of (Just sc1', Just sc2') -> do sko <- newSkolemConstant - let sk1 = skolemize ident1 sko sc1' Nothing ty1 - let sk2 = skolemize ident2 sko sc2' Nothing ty2 + let sk1 = skolemize ann1 ident1 sko sc1' ty1 + let sk2 = skolemize ann2 ident2 sko sc2' ty2 sk1 `unifyTypes` sk2 _ -> internalError "unifyTypes: unspecified skolem scope" - unifyTypes' (ForAll ident ty1 (Just sc)) ty2 = do + unifyTypes' (ForAll ann ident ty1 (Just sc)) ty2 = do sko <- newSkolemConstant - let sk = skolemize ident sko sc Nothing ty1 + let sk = skolemize ann ident sko sc ty1 sk `unifyTypes` ty2 unifyTypes' ForAll{} _ = internalError "unifyTypes: unspecified skolem scope" unifyTypes' ty f@ForAll{} = f `unifyTypes` ty - unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return () - unifyTypes' ty1@(TypeConstructor c1) ty2@(TypeConstructor c2) = + unifyTypes' (TypeVar _ v1) (TypeVar _ v2) | v1 == v2 = return () + unifyTypes' ty1@(TypeConstructor _ c1) ty2@(TypeConstructor _ c2) = guardWith (errorMessage (TypesDoNotUnify ty1 ty2)) (c1 == c2) - unifyTypes' (TypeLevelString s1) (TypeLevelString s2) | s1 == s2 = return () - unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do + unifyTypes' (TypeLevelString _ s1) (TypeLevelString _ s2) | s1 == s2 = return () + unifyTypes' (TypeApp _ t3 t4) (TypeApp _ t5 t6) = do t3 `unifyTypes` t5 t4 `unifyTypes` t6 - unifyTypes' (Skolem _ s1 _ _) (Skolem _ s2 _ _) | s1 == s2 = return () - unifyTypes' (KindedType ty1 _) ty2 = ty1 `unifyTypes` ty2 - unifyTypes' ty1 (KindedType ty2 _) = ty1 `unifyTypes` ty2 + unifyTypes' (Skolem _ _ s1 _) (Skolem _ _ s2 _) | s1 == s2 = return () + unifyTypes' (KindedType _ ty1 _) ty2 = ty1 `unifyTypes` ty2 + unifyTypes' ty1 (KindedType _ ty2 _) = ty1 `unifyTypes` ty2 unifyTypes' r1@RCons{} r2 = unifyRows r1 r2 unifyTypes' r1 r2@RCons{} = unifyRows r1 r2 - unifyTypes' r1@REmpty r2 = unifyRows r1 r2 - unifyTypes' r1 r2@REmpty = unifyRows r1 r2 + unifyTypes' r1@REmpty{} r2 = unifyRows r1 r2 + unifyTypes' r1 r2@REmpty{} = unifyRows r1 r2 unifyTypes' ty1@ConstrainedType{} ty2 = throwError . errorMessage $ ConstrainedTypeUnified ty1 ty2 unifyTypes' t3 t4@ConstrainedType{} = unifyTypes' t4 t3 @@ -132,38 +132,38 @@ unifyTypes t1 t2 = do -- -- Note: importantly, we preserve the order of the types with a given label. alignRowsWith - :: (Type -> Type -> a) - -> Type - -> Type - -> ([a], (([(Label, Type)], Type), ([(Label, Type)], Type))) + :: (Type a -> Type a -> r) + -> Type a + -> Type a + -> ([r], (([RowListItem a], Type a), ([RowListItem a], Type a))) alignRowsWith f ty1 ty2 = go s1 s2 where (s1, tail1) = rowToSortedList ty1 (s2, tail2) = rowToSortedList ty2 go [] r = ([], (([], tail1), (r, tail2))) go r [] = ([], ((r, tail1), ([], tail2))) - go lhs@((l1, t1) : r1) rhs@((l2, t2) : r2) - | l1 < l2 = (second . first . first) ((l1, t1) :) (go r1 rhs) - | l2 < l1 = (second . second . first) ((l2, t2) :) (go lhs r2) + go lhs@(RowListItem a1 l1 t1 : r1) rhs@(RowListItem a2 l2 t2 : r2) + | l1 < l2 = (second . first . first) (RowListItem a1 l1 t1 :) (go r1 rhs) + | l2 < l1 = (second . second . first) (RowListItem a2 l2 t2 :) (go lhs r2) | otherwise = first (f t1 t2 :) (go r1 r2) -- | Unify two rows, updating the current substitution -- -- Common labels are identified and unified. Remaining labels and types are unified with a -- trailing row unification variable, if appropriate. -unifyRows :: forall m. (MonadError MultipleErrors m, MonadState CheckState m) => Type -> Type -> m () +unifyRows :: forall m. (MonadError MultipleErrors m, MonadState CheckState m) => SourceType -> SourceType -> m () unifyRows r1 r2 = sequence_ matches *> uncurry unifyTails rest where (matches, rest) = alignRowsWith unifyTypes r1 r2 - unifyTails :: ([(Label, Type)], Type) -> ([(Label, Type)], Type) -> m () - unifyTails ([], TUnknown u) (sd, r) = solveType u (rowFromList (sd, r)) - unifyTails (sd, r) ([], TUnknown u) = solveType u (rowFromList (sd, r)) - unifyTails ([], REmpty) ([], REmpty) = return () - unifyTails ([], TypeVar v1) ([], TypeVar v2) | v1 == v2 = return () + unifyTails :: ([RowListItem SourceAnn], SourceType) -> ([RowListItem SourceAnn], SourceType) -> m () + unifyTails ([], TUnknown _ u) (sd, r) = solveType u (rowFromList (sd, r)) + unifyTails (sd, r) ([], TUnknown _ u) = solveType u (rowFromList (sd, r)) + unifyTails ([], REmpty _) ([], REmpty _) = return () + unifyTails ([], TypeVar _ v1) ([], TypeVar _ v2) | v1 == v2 = return () unifyTails ([], Skolem _ s1 _ _) ([], Skolem _ s2 _ _) | s1 == s2 = return () - unifyTails (sd1, TUnknown u1) (sd2, TUnknown u2) = do - forM_ sd1 $ \(_, t) -> occursCheck u2 t - forM_ sd2 $ \(_, t) -> occursCheck u1 t + unifyTails (sd1, TUnknown _ u1) (sd2, TUnknown _ u2) = do + forM_ sd1 $ occursCheck u2 . rowListType + forM_ sd2 $ occursCheck u1 . rowListType rest' <- freshType solveType u1 (rowFromList (sd2, rest')) solveType u2 (rowFromList (sd1, rest')) @@ -173,7 +173,7 @@ unifyRows r1 r2 = sequence_ matches *> uncurry unifyTails rest where -- | -- Replace a single type variable with a new unification variable -- -replaceVarWithUnknown :: (MonadState CheckState m) => Text -> Type -> m Type +replaceVarWithUnknown :: (MonadState CheckState m) => Text -> SourceType -> m SourceType replaceVarWithUnknown ident ty = do tu <- freshType return $ replaceTypeVars ident tu ty @@ -181,25 +181,25 @@ replaceVarWithUnknown ident ty = do -- | -- Replace type wildcards with unknowns -- -replaceTypeWildcards :: (MonadWriter MultipleErrors m, MonadState CheckState m) => Type -> m Type +replaceTypeWildcards :: (MonadWriter MultipleErrors m, MonadState CheckState m) => SourceType -> m SourceType replaceTypeWildcards = everywhereOnTypesM replace where - replace (TypeWildcard ss) = do + replace (TypeWildcard ann) = do t <- freshType ctx <- getLocalContext - warnWithPosition ss $ tell . errorMessage $ WildcardInferredType t ctx + warnWithPosition (fst ann) $ tell . errorMessage $ WildcardInferredType t ctx return t replace other = return other -- | -- Replace outermost unsolved unification variables with named type variables -- -varIfUnknown :: Type -> Type +varIfUnknown :: SourceType -> SourceType varIfUnknown ty = - let unks = ordNub $ unknownsInType ty + let unks = nubBy ((==) `on` snd) $ unknownsInType ty toName = T.cons 't' . T.pack . show ty' = everywhereOnTypes typeToVar ty - typeToVar :: Type -> Type - typeToVar (TUnknown u) = TypeVar (toName u) + typeToVar :: SourceType -> SourceType + typeToVar (TUnknown ann u) = TypeVar ann (toName u) typeToVar t = t - in mkForAll (sort . map toName $ unks) ty' + in mkForAll (sortBy (comparing snd) . fmap (fmap toName) $ unks) ty' diff --git a/src/Language/PureScript/TypeClassDictionaries.hs b/src/Language/PureScript/TypeClassDictionaries.hs index 84b569ca80..7f1ad25f09 100644 --- a/src/Language/PureScript/TypeClassDictionaries.hs +++ b/src/Language/PureScript/TypeClassDictionaries.hs @@ -28,9 +28,9 @@ data TypeClassDictionaryInScope v -- | The name of the type class to which this type class instance applies , tcdClassName :: Qualified (ProperName 'ClassName) -- | The types to which this type class instance applies - , tcdInstanceTypes :: [Type] + , tcdInstanceTypes :: [SourceType] -- | Type class dependencies which must be satisfied to construct this dictionary - , tcdDependencies :: Maybe [Constraint] + , tcdDependencies :: Maybe [SourceConstraint] } deriving (Show, Functor, Foldable, Traversable, Generic) diff --git a/src/Language/PureScript/Types.hs b/src/Language/PureScript/Types.hs index 3ec79431a1..13d6a30417 100644 --- a/src/Language/PureScript/Types.hs +++ b/src/Language/PureScript/Types.hs @@ -1,6 +1,8 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveFoldable #-} +{-# LANGUAGE DeriveTraversable #-} -- | -- Data types for types @@ -15,6 +17,7 @@ import Control.DeepSeq (NFData) import Control.Monad ((<=<)) import qualified Data.Aeson as A import qualified Data.Aeson.TH as A +import Data.Foldable (fold) import Data.List (sortBy) import Data.Ord (comparing) import Data.Maybe (fromMaybe) @@ -28,6 +31,9 @@ import Language.PureScript.Names import Language.PureScript.Label (Label) import Language.PureScript.PSString (PSString) +type SourceType = Type SourceAnn +type SourceConstraint = Constraint SourceAnn + -- | -- An identifier for the scope of a skolem variable -- @@ -39,52 +45,97 @@ instance NFData SkolemScope -- | -- The type of types -- -data Type +data Type a -- | A unification variable of type Type - = TUnknown Int + = TUnknown a Int -- | A named type variable - | TypeVar Text + | TypeVar a Text -- | A type-level string - | TypeLevelString PSString + | TypeLevelString a PSString -- | A type wildcard, as would appear in a partial type synonym - | TypeWildcard SourceSpan + | TypeWildcard a -- | A type constructor - | TypeConstructor (Qualified (ProperName 'TypeName)) + | TypeConstructor a (Qualified (ProperName 'TypeName)) -- | A type operator. This will be desugared into a type constructor during the -- "operators" phase of desugaring. - | TypeOp (Qualified (OpName 'TypeOpName)) + | TypeOp a (Qualified (OpName 'TypeOpName)) -- | A type application - | TypeApp Type Type + | TypeApp a (Type a) (Type a) -- | Forall quantifier - | ForAll Text Type (Maybe SkolemScope) + | ForAll a Text (Type a) (Maybe SkolemScope) -- | A type with a set of type class constraints - | ConstrainedType Constraint Type + | ConstrainedType a (Constraint a) (Type a) -- | A skolem constant - | Skolem Text Int SkolemScope (Maybe SourceSpan) + | Skolem a Text Int SkolemScope -- | An empty row - | REmpty + | REmpty a -- | A non-empty row - | RCons Label Type Type + | RCons a Label (Type a) (Type a) -- | A type with a kind annotation - | KindedType Type Kind + | KindedType a (Type a) (Kind a) -- | A placeholder used in pretty printing - | PrettyPrintFunction Type Type + | PrettyPrintFunction a (Type a) (Type a) -- | A placeholder used in pretty printing - | PrettyPrintObject Type + | PrettyPrintObject a (Type a) -- | A placeholder used in pretty printing - | PrettyPrintForAll [Text] Type + | PrettyPrintForAll a [Text] (Type a) -- | Binary operator application. During the rebracketing phase of desugaring, -- this data constructor will be removed. - | BinaryNoParensType Type Type Type + | BinaryNoParensType a (Type a) (Type a) (Type a) -- | Explicit parentheses. During the rebracketing phase of desugaring, this -- data constructor will be removed. -- -- Note: although it seems this constructor is not used, it _is_ useful, -- since it prevents certain traversals from matching. - | ParensInType Type - deriving (Show, Eq, Ord, Generic) + | ParensInType a (Type a) + deriving (Show, Generic, Functor, Foldable, Traversable) + +instance NFData a => NFData (Type a) + +srcTUnknown :: Int -> SourceType +srcTUnknown = TUnknown NullSourceAnn + +srcTypeVar :: Text -> SourceType +srcTypeVar = TypeVar NullSourceAnn + +srcTypeLevelString :: PSString -> SourceType +srcTypeLevelString = TypeLevelString NullSourceAnn + +srcTypeWildcard :: SourceType +srcTypeWildcard = TypeWildcard NullSourceAnn + +srcTypeConstructor :: Qualified (ProperName 'TypeName) -> SourceType +srcTypeConstructor = TypeConstructor NullSourceAnn + +srcTypeOp :: Qualified (OpName 'TypeOpName) -> SourceType +srcTypeOp = TypeOp NullSourceAnn + +srcTypeApp :: SourceType -> SourceType -> SourceType +srcTypeApp = TypeApp NullSourceAnn + +srcForAll :: Text -> SourceType -> Maybe SkolemScope -> SourceType +srcForAll = ForAll NullSourceAnn -instance NFData Type +srcConstrainedType :: SourceConstraint -> SourceType -> SourceType +srcConstrainedType = ConstrainedType NullSourceAnn + +srcSkolem :: Text -> Int -> SkolemScope -> SourceType +srcSkolem = Skolem NullSourceAnn + +srcREmpty :: SourceType +srcREmpty = REmpty NullSourceAnn + +srcRCons :: Label -> SourceType -> SourceType -> SourceType +srcRCons = RCons NullSourceAnn + +srcKindedType :: SourceType -> SourceKind -> SourceType +srcKindedType = KindedType NullSourceAnn + +srcBinaryNoParensType :: SourceType -> SourceType -> SourceType -> SourceType +srcBinaryNoParensType = BinaryNoParensType NullSourceAnn + +srcParensInType :: SourceType -> SourceType +srcParensInType = ParensInType NullSourceAnn -- | Additional data relevant to type class constraints data ConstraintData @@ -99,77 +150,92 @@ data ConstraintData instance NFData ConstraintData -- | A typeclass constraint -data Constraint = Constraint - { constraintClass :: Qualified (ProperName 'ClassName) +data Constraint a = Constraint + { constraintAnn :: a + -- ^ constraint annotation + , constraintClass :: Qualified (ProperName 'ClassName) -- ^ constraint class name - , constraintArgs :: [Type] + , constraintArgs :: [Type a] -- ^ type arguments , constraintData :: Maybe ConstraintData -- ^ additional data relevant to this constraint - } deriving (Show, Eq, Ord, Generic) + } deriving (Show, Generic, Functor, Foldable, Traversable) + +instance NFData a => NFData (Constraint a) -instance NFData Constraint +srcConstraint :: Qualified (ProperName 'ClassName) -> [SourceType] -> Maybe ConstraintData -> SourceConstraint +srcConstraint = Constraint NullSourceAnn -mapConstraintArgs :: ([Type] -> [Type]) -> Constraint -> Constraint +mapConstraintArgs :: ([Type a] -> [Type a]) -> Constraint a -> Constraint a mapConstraintArgs f c = c { constraintArgs = f (constraintArgs c) } -overConstraintArgs :: Functor f => ([Type] -> f [Type]) -> Constraint -> f Constraint +overConstraintArgs :: Functor f => ([Type a] -> f [Type a]) -> Constraint a -> f (Constraint a) overConstraintArgs f c = (\args -> c { constraintArgs = args }) <$> f (constraintArgs c) $(A.deriveJSON A.defaultOptions ''Type) $(A.deriveJSON A.defaultOptions ''Constraint) $(A.deriveJSON A.defaultOptions ''ConstraintData) +data RowListItem a = RowListItem + { rowListAnn :: a + , rowListLabel :: Label + , rowListType :: Type a + } deriving (Show, Generic, Functor, Foldable, Traversable) + +srcRowListItem :: Label -> SourceType -> RowListItem SourceAnn +srcRowListItem = RowListItem NullSourceAnn + -- | Convert a row to a list of pairs of labels and types -rowToList :: Type -> ([(Label, Type)], Type) +rowToList :: Type a -> ([RowListItem a], Type a) rowToList = go where - go (RCons name ty row) = - first ((name, ty) :) (rowToList row) + go (RCons ann name ty row) = + first (RowListItem ann name ty :) (rowToList row) go r = ([], r) -- | Convert a row to a list of pairs of labels and types, sorted by the labels. -rowToSortedList :: Type -> ([(Label, Type)], Type) -rowToSortedList = first (sortBy (comparing fst)) . rowToList +rowToSortedList :: Type a -> ([RowListItem a], Type a) +rowToSortedList = first (sortBy (comparing rowListLabel)) . rowToList -- | Convert a list of labels and types to a row -rowFromList :: ([(Label, Type)], Type) -> Type -rowFromList (xs, r) = foldr (uncurry RCons) r xs +rowFromList :: ([RowListItem a], Type a) -> Type a +rowFromList (xs, r) = foldr (\(RowListItem ann name ty) -> RCons ann name ty) r xs -- | Check whether a type is a monotype -isMonoType :: Type -> Bool +isMonoType :: Type a -> Bool isMonoType ForAll{} = False -isMonoType (ParensInType t) = isMonoType t -isMonoType (KindedType t _) = isMonoType t +isMonoType (ParensInType _ t) = isMonoType t +isMonoType (KindedType _ t _) = isMonoType t isMonoType _ = True -- | Universally quantify a type -mkForAll :: [Text] -> Type -> Type -mkForAll args ty = foldl (\t arg -> ForAll arg t Nothing) ty args +mkForAll :: [(a, Text)] -> Type a -> Type a +mkForAll args ty = foldl (\t (ann, arg) -> ForAll ann arg t Nothing) ty args -- | Replace a type variable, taking into account variable shadowing -replaceTypeVars :: Text -> Type -> Type -> Type +replaceTypeVars :: Text -> Type a -> Type a -> Type a replaceTypeVars v r = replaceAllTypeVars [(v, r)] -- | Replace named type variables with types -replaceAllTypeVars :: [(Text, Type)] -> Type -> Type +replaceAllTypeVars :: [(Text, Type a)] -> Type a -> Type a replaceAllTypeVars = go [] where - go :: [Text] -> [(Text, Type)] -> Type -> Type - go _ m (TypeVar v) = fromMaybe (TypeVar v) (v `lookup` m) - go bs m (TypeApp t1 t2) = TypeApp (go bs m t1) (go bs m t2) - go bs m f@(ForAll v t sco) | v `elem` keys = go bs (filter ((/= v) . fst) m) f - | v `elem` usedVars = - let v' = genName v (keys ++ bs ++ usedVars) - t' = go bs [(v, TypeVar v')] t - in ForAll v' (go (v' : bs) m t') sco - | otherwise = ForAll v (go (v : bs) m t) sco + go :: [Text] -> [(Text, Type a)] -> Type a -> Type a + go _ m (TypeVar ann v) = fromMaybe (TypeVar ann v) (v `lookup` m) + go bs m (TypeApp ann t1 t2) = TypeApp ann (go bs m t1) (go bs m t2) + go bs m f@(ForAll ann v t sco) + | v `elem` keys = go bs (filter ((/= v) . fst) m) f + | v `elem` usedVars = + let v' = genName v (keys ++ bs ++ usedVars) + t' = go bs [(v, TypeVar ann v')] t + in ForAll ann v' (go (v' : bs) m t') sco + | otherwise = ForAll ann v (go (v : bs) m t) sco where keys = map fst m usedVars = concatMap (usedTypeVariables . snd) m - go bs m (ConstrainedType c t) = ConstrainedType (mapConstraintArgs (map (go bs m)) c) (go bs m t) - go bs m (RCons name' t r) = RCons name' (go bs m t) (go bs m r) - go bs m (KindedType t k) = KindedType (go bs m t) k - go bs m (BinaryNoParensType t1 t2 t3) = BinaryNoParensType (go bs m t1) (go bs m t2) (go bs m t3) - go bs m (ParensInType t) = ParensInType (go bs m t) + go bs m (ConstrainedType ann c t) = ConstrainedType ann (mapConstraintArgs (map (go bs m)) c) (go bs m t) + go bs m (RCons ann name' t r) = RCons ann name' (go bs m t) (go bs m r) + go bs m (KindedType ann t k) = KindedType ann (go bs m t) k + go bs m (BinaryNoParensType ann t1 t2 t3) = BinaryNoParensType ann (go bs m t1) (go bs m t2) (go bs m t3) + go bs m (ParensInType ann t) = ParensInType ann (go bs m t) go _ _ ty = ty genName orig inUse = try' 0 where @@ -178,131 +244,263 @@ replaceAllTypeVars = go [] where | otherwise = orig <> T.pack (show n) -- | Collect all type variables appearing in a type -usedTypeVariables :: Type -> [Text] +usedTypeVariables :: Type a -> [Text] usedTypeVariables = ordNub . everythingOnTypes (++) go where - go (TypeVar v) = [v] + go (TypeVar _ v) = [v] go _ = [] -- | Collect all free type variables appearing in a type -freeTypeVariables :: Type -> [Text] +freeTypeVariables :: Type a -> [Text] freeTypeVariables = ordNub . go [] where - go :: [Text] -> Type -> [Text] - go bound (TypeVar v) | v `notElem` bound = [v] - go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2 - go bound (ForAll v t _) = go (v : bound) t - go bound (ConstrainedType c t) = concatMap (go bound) (constraintArgs c) ++ go bound t - go bound (RCons _ t r) = go bound t ++ go bound r - go bound (KindedType t _) = go bound t - go bound (BinaryNoParensType t1 t2 t3) = go bound t1 ++ go bound t2 ++ go bound t3 - go bound (ParensInType t) = go bound t + go :: [Text] -> Type a -> [Text] + go bound (TypeVar _ v) | v `notElem` bound = [v] + go bound (TypeApp _ t1 t2) = go bound t1 ++ go bound t2 + go bound (ForAll _ v t _) = go (v : bound) t + go bound (ConstrainedType _ c t) = concatMap (go bound) (constraintArgs c) ++ go bound t + go bound (RCons _ _ t r) = go bound t ++ go bound r + go bound (KindedType _ t _) = go bound t + go bound (BinaryNoParensType _ t1 t2 t3) = go bound t1 ++ go bound t2 ++ go bound t3 + go bound (ParensInType _ t) = go bound t go _ _ = [] -- | Universally quantify over all type variables appearing free in a type -quantify :: Type -> Type -quantify ty = foldr (\arg t -> ForAll arg t Nothing) ty $ freeTypeVariables ty +quantify :: Type a -> Type a +quantify ty = foldr (\arg t -> ForAll ann arg t Nothing) ty $ freeTypeVariables ty + where + ann = annotationForType ty -- | Move all universal quantifiers to the front of a type -moveQuantifiersToFront :: Type -> Type +moveQuantifiersToFront :: Type a -> Type a moveQuantifiersToFront = go [] [] where - go qs cs (ForAll q ty sco) = go ((q, sco) : qs) cs ty - go qs cs (ConstrainedType c ty) = go qs (c : cs) ty - go qs cs ty = foldl (\ty' (q, sco) -> ForAll q ty' sco) (foldl (flip ConstrainedType) ty cs) qs + go qs cs (ForAll ann q ty sco) = go ((ann, q, sco) : qs) cs ty + go qs cs (ConstrainedType ann c ty) = go qs ((ann, c) : cs) ty + go qs cs ty = foldl (\ty' (ann, q, sco) -> ForAll ann q ty' sco) (foldl (\ty' (ann, c) -> ConstrainedType ann c ty') ty cs) qs -- | Check if a type contains wildcards -containsWildcards :: Type -> Bool +containsWildcards :: Type a -> Bool containsWildcards = everythingOnTypes (||) go where - go :: Type -> Bool + go :: Type a -> Bool go TypeWildcard{} = True go _ = False -- | Check if a type contains `forall` -containsForAll :: Type -> Bool +containsForAll :: Type a -> Bool containsForAll = everythingOnTypes (||) go where - go :: Type -> Bool + go :: Type a -> Bool go ForAll{} = True go _ = False -everywhereOnTypes :: (Type -> Type) -> Type -> Type +everywhereOnTypes :: (Type a -> Type a) -> Type a -> Type a everywhereOnTypes f = go where - go (TypeApp t1 t2) = f (TypeApp (go t1) (go t2)) - go (ForAll arg ty sco) = f (ForAll arg (go ty) sco) - go (ConstrainedType c ty) = f (ConstrainedType (mapConstraintArgs (map go) c) (go ty)) - go (RCons name ty rest) = f (RCons name (go ty) (go rest)) - go (KindedType ty k) = f (KindedType (go ty) k) - go (PrettyPrintFunction t1 t2) = f (PrettyPrintFunction (go t1) (go t2)) - go (PrettyPrintObject t) = f (PrettyPrintObject (go t)) - go (PrettyPrintForAll args t) = f (PrettyPrintForAll args (go t)) - go (BinaryNoParensType t1 t2 t3) = f (BinaryNoParensType (go t1) (go t2) (go t3)) - go (ParensInType t) = f (ParensInType (go t)) + go (TypeApp ann t1 t2) = f (TypeApp ann (go t1) (go t2)) + go (ForAll ann arg ty sco) = f (ForAll ann arg (go ty) sco) + go (ConstrainedType ann c ty) = f (ConstrainedType ann (mapConstraintArgs (map go) c) (go ty)) + go (RCons ann name ty rest) = f (RCons ann name (go ty) (go rest)) + go (KindedType ann ty k) = f (KindedType ann (go ty) k) + go (PrettyPrintFunction ann t1 t2) = f (PrettyPrintFunction ann (go t1) (go t2)) + go (PrettyPrintObject ann t) = f (PrettyPrintObject ann (go t)) + go (PrettyPrintForAll ann args t) = f (PrettyPrintForAll ann args (go t)) + go (BinaryNoParensType ann t1 t2 t3) = f (BinaryNoParensType ann (go t1) (go t2) (go t3)) + go (ParensInType ann t) = f (ParensInType ann (go t)) go other = f other -everywhereOnTypesTopDown :: (Type -> Type) -> Type -> Type +everywhereOnTypesTopDown :: (Type a -> Type a) -> Type a -> Type a everywhereOnTypesTopDown f = go . f where - go (TypeApp t1 t2) = TypeApp (go (f t1)) (go (f t2)) - go (ForAll arg ty sco) = ForAll arg (go (f ty)) sco - go (ConstrainedType c ty) = ConstrainedType (mapConstraintArgs (map (go . f)) c) (go (f ty)) - go (RCons name ty rest) = RCons name (go (f ty)) (go (f rest)) - go (KindedType ty k) = KindedType (go (f ty)) k - go (PrettyPrintFunction t1 t2) = PrettyPrintFunction (go (f t1)) (go (f t2)) - go (PrettyPrintObject t) = PrettyPrintObject (go (f t)) - go (PrettyPrintForAll args t) = PrettyPrintForAll args (go (f t)) - go (BinaryNoParensType t1 t2 t3) = BinaryNoParensType (go (f t1)) (go (f t2)) (go (f t3)) - go (ParensInType t) = ParensInType (go (f t)) + go (TypeApp ann t1 t2) = TypeApp ann (go (f t1)) (go (f t2)) + go (ForAll ann arg ty sco) = ForAll ann arg (go (f ty)) sco + go (ConstrainedType ann c ty) = ConstrainedType ann (mapConstraintArgs (map (go . f)) c) (go (f ty)) + go (RCons ann name ty rest) = RCons ann name (go (f ty)) (go (f rest)) + go (KindedType ann ty k) = KindedType ann (go (f ty)) k + go (PrettyPrintFunction ann t1 t2) = PrettyPrintFunction ann (go (f t1)) (go (f t2)) + go (PrettyPrintObject ann t) = PrettyPrintObject ann (go (f t)) + go (PrettyPrintForAll ann args t) = PrettyPrintForAll ann args (go (f t)) + go (BinaryNoParensType ann t1 t2 t3) = BinaryNoParensType ann (go (f t1)) (go (f t2)) (go (f t3)) + go (ParensInType ann t) = ParensInType ann (go (f t)) go other = f other -everywhereOnTypesM :: Monad m => (Type -> m Type) -> Type -> m Type +everywhereOnTypesM :: Monad m => (Type a -> m (Type a)) -> Type a -> m (Type a) everywhereOnTypesM f = go where - go (TypeApp t1 t2) = (TypeApp <$> go t1 <*> go t2) >>= f - go (ForAll arg ty sco) = (ForAll arg <$> go ty <*> pure sco) >>= f - go (ConstrainedType c ty) = (ConstrainedType <$> overConstraintArgs (mapM go) c <*> go ty) >>= f - go (RCons name ty rest) = (RCons name <$> go ty <*> go rest) >>= f - go (KindedType ty k) = (KindedType <$> go ty <*> pure k) >>= f - go (PrettyPrintFunction t1 t2) = (PrettyPrintFunction <$> go t1 <*> go t2) >>= f - go (PrettyPrintObject t) = (PrettyPrintObject <$> go t) >>= f - go (PrettyPrintForAll args t) = (PrettyPrintForAll args <$> go t) >>= f - go (BinaryNoParensType t1 t2 t3) = (BinaryNoParensType <$> go t1 <*> go t2 <*> go t3) >>= f - go (ParensInType t) = (ParensInType <$> go t) >>= f + go (TypeApp ann t1 t2) = (TypeApp ann <$> go t1 <*> go t2) >>= f + go (ForAll ann arg ty sco) = (ForAll ann arg <$> go ty <*> pure sco) >>= f + go (ConstrainedType ann c ty) = (ConstrainedType ann <$> overConstraintArgs (mapM go) c <*> go ty) >>= f + go (RCons ann name ty rest) = (RCons ann name <$> go ty <*> go rest) >>= f + go (KindedType ann ty k) = (KindedType ann <$> go ty <*> pure k) >>= f + go (PrettyPrintFunction ann t1 t2) = (PrettyPrintFunction ann <$> go t1 <*> go t2) >>= f + go (PrettyPrintObject ann t) = (PrettyPrintObject ann <$> go t) >>= f + go (PrettyPrintForAll ann args t) = (PrettyPrintForAll ann args <$> go t) >>= f + go (BinaryNoParensType ann t1 t2 t3) = (BinaryNoParensType ann <$> go t1 <*> go t2 <*> go t3) >>= f + go (ParensInType ann t) = (ParensInType ann <$> go t) >>= f go other = f other -everywhereOnTypesTopDownM :: Monad m => (Type -> m Type) -> Type -> m Type +everywhereOnTypesTopDownM :: Monad m => (Type a -> m (Type a)) -> Type a -> m (Type a) everywhereOnTypesTopDownM f = go <=< f where - go (TypeApp t1 t2) = TypeApp <$> (f t1 >>= go) <*> (f t2 >>= go) - go (ForAll arg ty sco) = ForAll arg <$> (f ty >>= go) <*> pure sco - go (ConstrainedType c ty) = ConstrainedType <$> overConstraintArgs (mapM (go <=< f)) c <*> (f ty >>= go) - go (RCons name ty rest) = RCons name <$> (f ty >>= go) <*> (f rest >>= go) - go (KindedType ty k) = KindedType <$> (f ty >>= go) <*> pure k - go (PrettyPrintFunction t1 t2) = PrettyPrintFunction <$> (f t1 >>= go) <*> (f t2 >>= go) - go (PrettyPrintObject t) = PrettyPrintObject <$> (f t >>= go) - go (PrettyPrintForAll args t) = PrettyPrintForAll args <$> (f t >>= go) - go (BinaryNoParensType t1 t2 t3) = BinaryNoParensType <$> (f t1 >>= go) <*> (f t2 >>= go) <*> (f t3 >>= go) - go (ParensInType t) = ParensInType <$> (f t >>= go) + go (TypeApp ann t1 t2) = TypeApp ann <$> (f t1 >>= go) <*> (f t2 >>= go) + go (ForAll ann arg ty sco) = ForAll ann arg <$> (f ty >>= go) <*> pure sco + go (ConstrainedType ann c ty) = ConstrainedType ann <$> overConstraintArgs (mapM (go <=< f)) c <*> (f ty >>= go) + go (RCons ann name ty rest) = RCons ann name <$> (f ty >>= go) <*> (f rest >>= go) + go (KindedType ann ty k) = KindedType ann <$> (f ty >>= go) <*> pure k + go (PrettyPrintFunction ann t1 t2) = PrettyPrintFunction ann <$> (f t1 >>= go) <*> (f t2 >>= go) + go (PrettyPrintObject ann t) = PrettyPrintObject ann <$> (f t >>= go) + go (PrettyPrintForAll ann args t) = PrettyPrintForAll ann args <$> (f t >>= go) + go (BinaryNoParensType ann t1 t2 t3) = BinaryNoParensType ann <$> (f t1 >>= go) <*> (f t2 >>= go) <*> (f t3 >>= go) + go (ParensInType ann t) = ParensInType ann <$> (f t >>= go) go other = f other -everythingOnTypes :: (r -> r -> r) -> (Type -> r) -> Type -> r +everythingOnTypes :: (r -> r -> r) -> (Type a -> r) -> Type a -> r everythingOnTypes (<+>) f = go where - go t@(TypeApp t1 t2) = f t <+> go t1 <+> go t2 - go t@(ForAll _ ty _) = f t <+> go ty - go t@(ConstrainedType c ty) = foldl (<+>) (f t) (map go (constraintArgs c)) <+> go ty - go t@(RCons _ ty rest) = f t <+> go ty <+> go rest - go t@(KindedType ty _) = f t <+> go ty - go t@(PrettyPrintFunction t1 t2) = f t <+> go t1 <+> go t2 - go t@(PrettyPrintObject t1) = f t <+> go t1 - go t@(PrettyPrintForAll _ t1) = f t <+> go t1 - go t@(BinaryNoParensType t1 t2 t3) = f t <+> go t1 <+> go t2 <+> go t3 - go t@(ParensInType t1) = f t <+> go t1 + go t@(TypeApp _ t1 t2) = f t <+> go t1 <+> go t2 + go t@(ForAll _ _ ty _) = f t <+> go ty + go t@(ConstrainedType _ c ty) = foldl (<+>) (f t) (map go (constraintArgs c)) <+> go ty + go t@(RCons _ _ ty rest) = f t <+> go ty <+> go rest + go t@(KindedType _ ty _) = f t <+> go ty + go t@(PrettyPrintFunction _ t1 t2) = f t <+> go t1 <+> go t2 + go t@(PrettyPrintObject _ t1) = f t <+> go t1 + go t@(PrettyPrintForAll _ _ t1) = f t <+> go t1 + go t@(BinaryNoParensType _ t1 t2 t3) = f t <+> go t1 <+> go t2 <+> go t3 + go t@(ParensInType _ t1) = f t <+> go t1 go other = f other -everythingWithContextOnTypes :: s -> r -> (r -> r -> r) -> (s -> Type -> (s, r)) -> Type -> r +everythingWithContextOnTypes :: s -> r -> (r -> r -> r) -> (s -> Type a -> (s, r)) -> Type a -> r everythingWithContextOnTypes s0 r0 (<+>) f = go' s0 where go' s t = let (s', r) = f s t in r <+> go s' t - go s (TypeApp t1 t2) = go' s t1 <+> go' s t2 - go s (ForAll _ ty _) = go' s ty - go s (ConstrainedType c ty) = foldl (<+>) r0 (map (go' s) (constraintArgs c)) <+> go' s ty - go s (RCons _ ty rest) = go' s ty <+> go' s rest - go s (KindedType ty _) = go' s ty - go s (PrettyPrintFunction t1 t2) = go' s t1 <+> go' s t2 - go s (PrettyPrintObject t1) = go' s t1 - go s (PrettyPrintForAll _ t1) = go' s t1 - go s (BinaryNoParensType t1 t2 t3) = go' s t1 <+> go' s t2 <+> go' s t3 - go s (ParensInType t1) = go' s t1 + go s (TypeApp _ t1 t2) = go' s t1 <+> go' s t2 + go s (ForAll _ _ ty _) = go' s ty + go s (ConstrainedType _ c ty) = foldl (<+>) r0 (map (go' s) (constraintArgs c)) <+> go' s ty + go s (RCons _ _ ty rest) = go' s ty <+> go' s rest + go s (KindedType _ ty _) = go' s ty + go s (PrettyPrintFunction _ t1 t2) = go' s t1 <+> go' s t2 + go s (PrettyPrintObject _ t1) = go' s t1 + go s (PrettyPrintForAll _ _ t1) = go' s t1 + go s (BinaryNoParensType _ t1 t2 t3) = go' s t1 <+> go' s t2 <+> go' s t3 + go s (ParensInType _ t1) = go' s t1 go _ _ = r0 + +annotationForType :: Type a -> a +annotationForType (TUnknown a _) = a +annotationForType (TypeVar a _) = a +annotationForType (TypeLevelString a _) = a +annotationForType (TypeWildcard a) = a +annotationForType (TypeConstructor a _) = a +annotationForType (TypeOp a _) = a +annotationForType (TypeApp a _ _) = a +annotationForType (ForAll a _ _ _) = a +annotationForType (ConstrainedType a _ _) = a +annotationForType (Skolem a _ _ _) = a +annotationForType (REmpty a) = a +annotationForType (RCons a _ _ _) = a +annotationForType (KindedType a _ _) = a +annotationForType (PrettyPrintFunction a _ _) = a +annotationForType (PrettyPrintObject a _) = a +annotationForType (PrettyPrintForAll a _ _) = a +annotationForType (BinaryNoParensType a _ _ _) = a +annotationForType (ParensInType a _) = a + +instance Eq (Type a) where + (==) = eqType + +instance Ord (Type a) where + compare = compareType + +eqType :: Type a -> Type b -> Bool +eqType (TUnknown _ a) (TUnknown _ a') = a == a' +eqType (TypeVar _ a) (TypeVar _ a') = a == a' +eqType (TypeLevelString _ a) (TypeLevelString _ a') = a == a' +eqType (TypeWildcard _) (TypeWildcard _) = True +eqType (TypeConstructor _ a) (TypeConstructor _ a') = a == a' +eqType (TypeOp _ a) (TypeOp _ a') = a == a' +eqType (TypeApp _ a b) (TypeApp _ a' b') = eqType a a' && eqType b b' +eqType (ForAll _ a b c) (ForAll _ a' b' c') = a == a' && eqType b b' && c == c' +eqType (ConstrainedType _ a b) (ConstrainedType _ a' b') = eqConstraint a a' && eqType b b' +eqType (Skolem _ a b c) (Skolem _ a' b' c') = a == a' && b == b' && c == c' +eqType (REmpty _) (REmpty _) = True +eqType (RCons _ a b c) (RCons _ a' b' c') = a == a' && eqType b b' && eqType c c' +eqType (KindedType _ a b) (KindedType _ a' b') = eqType a a' && eqKind b b' +eqType (PrettyPrintFunction _ a b) (PrettyPrintFunction _ a' b') = eqType a a' && eqType b b' +eqType (PrettyPrintObject _ a) (PrettyPrintObject _ a') = eqType a a' +eqType (PrettyPrintForAll _ a b) (PrettyPrintForAll _ a' b') = a == a' && eqType b b' +eqType (BinaryNoParensType _ a b c) (BinaryNoParensType _ a' b' c') = eqType a a' && eqType b b' && eqType c c' +eqType (ParensInType _ a) (ParensInType _ a') = eqType a a' +eqType _ _ = False + +compareType :: Type a -> Type b -> Ordering +compareType (TUnknown _ a) (TUnknown _ a') = compare a a' +compareType (TUnknown {}) _ = LT + +compareType (TypeVar _ a) (TypeVar _ a') = compare a a' +compareType (TypeVar {}) _ = LT +compareType _ (TypeVar {}) = GT + +compareType (TypeLevelString _ a) (TypeLevelString _ a') = compare a a' +compareType (TypeLevelString {}) _ = LT +compareType _ (TypeLevelString {}) = GT + +compareType (TypeWildcard _) (TypeWildcard _) = EQ +compareType (TypeWildcard _) _ = LT +compareType _ (TypeWildcard _) = GT + +compareType (TypeConstructor _ a) (TypeConstructor _ a') = compare a a' +compareType (TypeConstructor {}) _ = LT +compareType _ (TypeConstructor {}) = GT + +compareType (TypeOp _ a) (TypeOp _ a') = compare a a' +compareType (TypeOp {}) _ = LT +compareType _ (TypeOp {}) = GT + +compareType (TypeApp _ a b) (TypeApp _ a' b') = compareType a a' <> compareType b b' +compareType (TypeApp {}) _ = LT +compareType _ (TypeApp {}) = GT + +compareType (ForAll _ a b c) (ForAll _ a' b' c') = compare a a' <> compareType b b' <> compare c c' +compareType (ForAll {}) _ = LT +compareType _ (ForAll {}) = GT + +compareType (ConstrainedType _ a b) (ConstrainedType _ a' b') = compareConstraint a a' <> compareType b b' +compareType (ConstrainedType {}) _ = LT +compareType _ (ConstrainedType {}) = GT + +compareType (Skolem _ a b c) (Skolem _ a' b' c') = compare a a' <> compare b b' <> compare c c' +compareType (Skolem {}) _ = LT +compareType _ (Skolem {}) = GT + +compareType (REmpty _) (REmpty _) = EQ +compareType (REmpty _) _ = LT +compareType _ (REmpty _) = GT + +compareType (RCons _ a b c) (RCons _ a' b' c') = compare a a' <> compareType b b' <> compareType c c' +compareType (RCons {}) _ = LT +compareType _ (RCons {}) = GT + +compareType (KindedType _ a b) (KindedType _ a' b') = compareType a a' <> compareKind b b' +compareType (KindedType {}) _ = LT +compareType _ (KindedType {}) = GT + +compareType (PrettyPrintFunction _ a b) (PrettyPrintFunction _ a' b') = compareType a a' <> compareType b b' +compareType (PrettyPrintFunction {}) _ = LT +compareType _ (PrettyPrintFunction {}) = GT + +compareType (PrettyPrintObject _ a) (PrettyPrintObject _ a') = compareType a a' +compareType (PrettyPrintObject {}) _ = LT +compareType _ (PrettyPrintObject {}) = GT + +compareType (PrettyPrintForAll _ a b) (PrettyPrintForAll _ a' b') = compare a a' <> compareType b b' +compareType (PrettyPrintForAll {}) _ = LT +compareType _ (PrettyPrintForAll {}) = GT + +compareType (BinaryNoParensType _ a b c) (BinaryNoParensType _ a' b' c') = compareType a a' <> compareType b b' <> compareType c c' +compareType (BinaryNoParensType {}) _ = LT +compareType _ (BinaryNoParensType {}) = GT + +compareType (ParensInType _ a) (ParensInType _ a') = compareType a a' +compareType (ParensInType {}) _ = GT + +instance Eq (Constraint a) where + (==) = eqConstraint + +instance Ord (Constraint a) where + compare = compareConstraint + +eqConstraint :: Constraint a -> Constraint b -> Bool +eqConstraint (Constraint _ a b c) (Constraint _ a' b' c') = a == a' && and (zipWith eqType b b') && c == c' + +compareConstraint :: Constraint a -> Constraint b -> Ordering +compareConstraint (Constraint _ a b c) (Constraint _ a' b' c') = compare a a' <> fold (zipWith compareType b b') <> compare c c' diff --git a/tests/Language/PureScript/Ide/MatcherSpec.hs b/tests/Language/PureScript/Ide/MatcherSpec.hs index cfb71024a1..22eb860e12 100644 --- a/tests/Language/PureScript/Ide/MatcherSpec.hs +++ b/tests/Language/PureScript/Ide/MatcherSpec.hs @@ -12,7 +12,7 @@ import Language.PureScript.Ide.Util import Test.Hspec value :: Text -> IdeDeclarationAnn -value s = withEmptyAnn (IdeDeclValue (IdeValue (P.Ident (toS s)) P.REmpty)) +value s = withEmptyAnn (IdeDeclValue (IdeValue (P.Ident (toS s)) P.srcREmpty)) firstResult, secondResult, fiult :: Match IdeDeclarationAnn firstResult = Match (P.moduleNameFromString "Match", value "firstResult") diff --git a/tests/Language/PureScript/Ide/SourceFileSpec.hs b/tests/Language/PureScript/Ide/SourceFileSpec.hs index dbcfed91f0..2ef859e00e 100644 --- a/tests/Language/PureScript/Ide/SourceFileSpec.hs +++ b/tests/Language/PureScript/Ide/SourceFileSpec.hs @@ -22,9 +22,9 @@ ann1 = (span1, []) ann2 = (span2, []) typeAnnotation1, value1, synonym1, class1, class2, data1, data2, valueFixity, typeFixity, foreign1, foreign2, foreign3, member1 :: P.Declaration -typeAnnotation1 = P.TypeDeclaration (P.TypeDeclarationData ann1 (P.Ident "value1") P.REmpty) +typeAnnotation1 = P.TypeDeclaration (P.TypeDeclarationData ann1 (P.Ident "value1") P.srcREmpty) value1 = P.ValueDecl ann1 (P.Ident "value1") P.Public [] [] -synonym1 = P.TypeSynonymDeclaration ann1 (P.ProperName "Synonym1") [] P.REmpty +synonym1 = P.TypeSynonymDeclaration ann1 (P.ProperName "Synonym1") [] P.srcREmpty class1 = P.TypeClassDeclaration ann1 (P.ProperName "Class1") [] [] [] [] class2 = P.TypeClassDeclaration ann1 (P.ProperName "Class2") [] [] [] [member1] data1 = P.DataDeclaration ann1 P.Newtype (P.ProperName "Data1") [] [] @@ -41,10 +41,10 @@ typeFixity = (P.Fixity P.Infix 0) (P.Qualified Nothing (P.ProperName "")) (P.OpName "~>") -foreign1 = P.ExternDeclaration ann1 (P.Ident "foreign1") P.REmpty +foreign1 = P.ExternDeclaration ann1 (P.Ident "foreign1") P.srcREmpty foreign2 = P.ExternDataDeclaration ann1 (P.ProperName "Foreign2") P.kindType foreign3 = P.ExternKindDeclaration ann1 (P.ProperName "Foreign3") -member1 = P.TypeDeclaration (P.TypeDeclarationData ann2 (P.Ident "member1") P.REmpty) +member1 = P.TypeDeclaration (P.TypeDeclarationData ann2 (P.Ident "member1") P.srcREmpty) spec :: Spec spec = do @@ -73,7 +73,7 @@ spec = do extractSpans foreign3 `shouldBe` [(IdeNamespaced IdeNSKind "Foreign3", span1)] describe "Type annotations" $ do it "extracts a type annotation" $ - extractTypeAnnotations [typeAnnotation1] `shouldBe` [(P.Ident "value1", P.REmpty)] + extractTypeAnnotations [typeAnnotation1] `shouldBe` [(P.Ident "value1", P.srcREmpty)] describe "Finding Source Spans for identifiers" $ do it "finds a value declaration" $ do Just r <- getLocation "sfValue" diff --git a/tests/Language/PureScript/Ide/StateSpec.hs b/tests/Language/PureScript/Ide/StateSpec.hs index 33d9f3071f..4775a67fc7 100644 --- a/tests/Language/PureScript/Ide/StateSpec.hs +++ b/tests/Language/PureScript/Ide/StateSpec.hs @@ -11,22 +11,22 @@ import Lens.Micro.Platform hiding ((&)) import Test.Hspec import qualified Data.Map as Map -valueOperator :: Maybe P.Type -> IdeDeclarationAnn +valueOperator :: Maybe P.SourceType -> IdeDeclarationAnn valueOperator = ideValueOp "<$>" (P.Qualified (Just (mn "Test")) (Left "function")) 2 Nothing -ctorOperator :: Maybe P.Type -> IdeDeclarationAnn +ctorOperator :: Maybe P.SourceType -> IdeDeclarationAnn ctorOperator = ideValueOp ":" (P.Qualified (Just (mn "Test")) (Right "Cons")) 2 Nothing -typeOperator :: Maybe P.Kind -> IdeDeclarationAnn +typeOperator :: Maybe P.SourceKind -> IdeDeclarationAnn typeOperator = ideTypeOp ":" (P.Qualified (Just (mn "Test")) "List") 2 Nothing testModule :: (P.ModuleName, [IdeDeclarationAnn]) testModule = (mn "Test", - [ ideValue "function" (Just P.REmpty) + [ ideValue "function" (Just P.srcREmpty) , ideDtor "Cons" "List" (Just P.tyString) , ideType "List" Nothing [] , valueOperator Nothing @@ -82,7 +82,7 @@ spec :: Spec spec = do describe "resolving operators" $ do it "resolves the type for a value operator" $ - resolveOperatorsForModule testState (snd testModule) `shouldSatisfy` elem (valueOperator (Just P.REmpty)) + resolveOperatorsForModule testState (snd testModule) `shouldSatisfy` elem (valueOperator (Just P.srcREmpty)) it "resolves the type for a constructor operator" $ resolveOperatorsForModule testState (snd testModule) `shouldSatisfy` elem (ctorOperator (Just P.tyString)) it "resolves the kind for a type operator" $ diff --git a/tests/Language/PureScript/Ide/Test.hs b/tests/Language/PureScript/Ide/Test.hs index cca8e99ef9..5cf613f2c2 100644 --- a/tests/Language/PureScript/Ide/Test.hs +++ b/tests/Language/PureScript/Ide/Test.hs @@ -55,7 +55,7 @@ annLoc (IdeDeclarationAnn a d) loc = IdeDeclarationAnn a {_annLocation = Just lo annExp :: IdeDeclarationAnn -> Text -> IdeDeclarationAnn annExp (IdeDeclarationAnn a d) e = IdeDeclarationAnn a {_annExportedFrom = Just (mn e)} d -annTyp :: IdeDeclarationAnn -> P.Type -> IdeDeclarationAnn +annTyp :: IdeDeclarationAnn -> P.SourceType -> IdeDeclarationAnn annTyp (IdeDeclarationAnn a d) ta = IdeDeclarationAnn a {_annTypeAnnotation = Just ta} d @@ -63,22 +63,22 @@ ida :: IdeDeclaration -> IdeDeclarationAnn ida = IdeDeclarationAnn emptyAnn -- | Builders for Ide declarations -ideValue :: Text -> Maybe P.Type -> IdeDeclarationAnn +ideValue :: Text -> Maybe P.SourceType -> IdeDeclarationAnn ideValue i ty = ida (IdeDeclValue (IdeValue (P.Ident i) (fromMaybe P.tyString ty))) -ideType :: Text -> Maybe P.Kind -> [(P.ProperName 'P.ConstructorName, P.Type)] -> IdeDeclarationAnn +ideType :: Text -> Maybe P.SourceKind -> [(P.ProperName 'P.ConstructorName, P.SourceType)] -> IdeDeclarationAnn ideType pn ki dtors = ida (IdeDeclType (IdeType (P.ProperName pn) (fromMaybe P.kindType ki) dtors)) -ideSynonym :: Text -> Maybe P.Type -> Maybe P.Kind -> IdeDeclarationAnn +ideSynonym :: Text -> Maybe P.SourceType -> Maybe P.SourceKind -> IdeDeclarationAnn ideSynonym pn ty kind = ida (IdeDeclTypeSynonym (IdeTypeSynonym (P.ProperName pn) (fromMaybe P.tyString ty) (fromMaybe P.kindType kind))) -ideTypeClass :: Text -> P.Kind -> [IdeInstance] -> IdeDeclarationAnn +ideTypeClass :: Text -> P.SourceKind -> [IdeInstance] -> IdeDeclarationAnn ideTypeClass pn kind instances = ida (IdeDeclTypeClass (IdeTypeClass (P.ProperName pn) kind instances)) -ideDtor :: Text -> Text -> Maybe P.Type -> IdeDeclarationAnn +ideDtor :: Text -> Text -> Maybe P.SourceType -> IdeDeclarationAnn ideDtor pn tn ty = ida (IdeDeclDataConstructor (IdeDataConstructor (P.ProperName pn) (P.ProperName tn) (fromMaybe P.tyString ty))) -ideValueOp :: Text -> P.Qualified (Either Text Text) -> Integer -> Maybe P.Associativity -> Maybe P.Type -> IdeDeclarationAnn +ideValueOp :: Text -> P.Qualified (Either Text Text) -> Integer -> Maybe P.Associativity -> Maybe P.SourceType -> IdeDeclarationAnn ideValueOp opName ident precedence assoc t = ida (IdeDeclValueOperator (IdeValueOperator @@ -88,7 +88,7 @@ ideValueOp opName ident precedence assoc t = (fromMaybe P.Infix assoc) t)) -ideTypeOp :: Text -> P.Qualified Text -> Integer -> Maybe P.Associativity -> Maybe P.Kind -> IdeDeclarationAnn +ideTypeOp :: Text -> P.Qualified Text -> Integer -> Maybe P.Associativity -> Maybe P.SourceKind -> IdeDeclarationAnn ideTypeOp opName ident precedence assoc k = ida (IdeDeclTypeOperator (IdeTypeOperator diff --git a/tests/TestDocs.hs b/tests/TestDocs.hs index 8bd082ef12..3ca26f126b 100644 --- a/tests/TestDocs.hs +++ b/tests/TestDocs.hs @@ -133,10 +133,10 @@ data DocsAssertion | ShouldHaveFunDeps P.ModuleName Text [([Text],[Text])] -- | Assert that a particular value declaration exists, and its type -- satisfies the given predicate. - | ValueShouldHaveTypeSignature P.ModuleName Text (P.Type -> Bool) + | ValueShouldHaveTypeSignature P.ModuleName Text (Docs.Type' -> Bool) -- | Assert that a particular instance declaration exists under some class or -- type declaration, and that its type satisfies the given predicate. - | InstanceShouldHaveTypeSignature P.ModuleName Text Text (P.Type -> Bool) + | InstanceShouldHaveTypeSignature P.ModuleName Text Text (Docs.Type' -> Bool) -- | Assert that a particular type alias exists, and its corresponding -- type, when rendered, matches a given string exactly -- fields: module, type synonym name, expected type @@ -225,7 +225,7 @@ data DocsAssertionFailure -- because the inferred type was used when the explicit type should have -- been. -- Fields: module name, declaration name, actual type. - | DeclarationWrongType P.ModuleName Text P.Type + | DeclarationWrongType P.ModuleName Text Docs.Type' -- | A Type synonym has been rendered in an unexpected format -- Fields: module name, declaration name, expected rendering, actual rendering | TypeSynonymMismatch P.ModuleName Text Text Text @@ -500,13 +500,13 @@ runTagsAssertion assertion tags = Just taggedLine -> TagsFail $ Tagged decl taggedLine Nothing -> TagsPass -checkConstrained :: P.Type -> Text -> Bool +checkConstrained :: P.Type a -> Text -> Bool checkConstrained ty tyClass = case ty of - P.ConstrainedType c ty' + P.ConstrainedType _ c ty' | matches tyClass c -> True | otherwise -> checkConstrained ty' tyClass - P.ForAll _ ty' _ -> + P.ForAll _ _ ty' _ -> checkConstrained ty' tyClass _ -> False @@ -593,8 +593,8 @@ testCases = , ("ExplicitTypeSignatures", [ ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "explicit" (hasTypeVar "something") - , ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "anInt" (P.tyInt ==) - , ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "aNumber" (P.tyNumber ==) + , ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "anInt" (P.tyInt `P.eqType`) + , ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "aNumber" (P.tyNumber `P.eqType`) ]) , ("ConstrainedArgument", @@ -652,7 +652,7 @@ testCases = hasTypeVar varName = getAny . P.everythingOnTypes (<>) (Any . isVar varName) - isVar varName (P.TypeVar name) | varName == T.unpack name = True + isVar varName (P.TypeVar _ name) | varName == T.unpack name = True isVar _ _ = False renderedType expected ty = diff --git a/tests/TestHierarchy.hs b/tests/TestHierarchy.hs index 898f869f8f..3cbf612193 100644 --- a/tests/TestHierarchy.hs +++ b/tests/TestHierarchy.hs @@ -53,7 +53,7 @@ main = testSpec "hierarchy" $ do (P.internalModuleSourceSpan "", []) (P.ProperName "B") [] - [P.Constraint (P.Qualified Nothing $ P.ProperName "A") [] Nothing] + [P.srcConstraint (P.Qualified Nothing $ P.ProperName "A") [] Nothing] [] [] ]