ddc-core 0.2.1.2 → 0.3.1.1
raw patch · 81 files changed
+8778/−4705 lines, 81 filesdep +deepseqdep +directorydep ~ddc-basePVP ok
version bump matches the API change (PVP)
Dependencies added: deepseq, directory
Dependency ranges changed: ddc-base
API changes (from Hackage documentation)
- DDC.Core.Check: ErrorCaseDiscrimNotAlgebraic :: Exp a n -> Type n -> Error a n
- DDC.Core.Check: ErrorCaseDiscrimTypeMismatch :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check: ErrorCaseDiscrimTypeUndeclared :: Exp a n -> Type n -> Error a n
- DDC.Core.Check: ErrorLetRegionNotRegion :: Exp a n -> Bind n -> Kind n -> Error a n
- DDC.Core.Check: ErrorLetRegionRebound :: Exp a n -> Bind n -> Error a n
- DDC.Core.Check: ErrorLetRegionWitnessOther :: Exp a n -> Bound n -> Bind n -> Error a n
- DDC.Core.Check: ErrorMaxcloMalformed :: Exp a n -> Closure n -> Error a n
- DDC.Core.Check: ErrorMaxcloNotClo :: Exp a n -> Closure n -> Kind n -> Error a n
- DDC.Core.Check: ErrorMaxeffNotEff :: Exp a n -> Effect n -> Kind n -> Error a n
- DDC.Core.Check: errorBoundRegion :: Error a n -> Bound n
- DDC.Core.Check: errorCtorBound :: Error a n -> Bound n
- DDC.Core.Check: errorTypeDiscrim :: Error a n -> Type n
- DDC.Core.Check.CheckExp: GBoundRgnCon :: (Bound n) -> TaggedClosure n
- DDC.Core.Check.CheckExp: GBoundRgnVar :: (Bound n) -> TaggedClosure n
- DDC.Core.Check.CheckExp: GBoundVal :: (Bound n) -> (TypeSum n) -> TaggedClosure n
- DDC.Core.Check.CheckExp: checkExp :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Exp a n -> Either (Error a n) (Exp a n, Type n, Effect n, Closure n)
- DDC.Core.Check.CheckExp: checkExpM :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Exp a n -> CheckM a n (Exp a n, Type n, TypeSum n, Set (TaggedClosure n))
- DDC.Core.Check.CheckExp: data TaggedClosure n
- DDC.Core.Check.CheckExp: type CheckM a n = CheckM (Error a n)
- DDC.Core.Check.CheckExp: typeOfExp :: (Ord n, Pretty n) => DataDefs n -> Exp a n -> Either (Error a n) (Type n)
- DDC.Core.Check.CheckWitness: checkWitness :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Witness n -> Either (Error a n) (Type n)
- DDC.Core.Check.CheckWitness: checkWitnessM :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Witness n -> CheckM a n (Type n)
- DDC.Core.Check.CheckWitness: type CheckM a n = CheckM (Error a n)
- DDC.Core.Check.CheckWitness: typeOfWbCon :: WbCon -> Type n
- DDC.Core.Check.CheckWitness: typeOfWiCon :: WiCon n -> Type n
- DDC.Core.Check.CheckWitness: typeOfWitness :: (Ord n, Pretty n) => DataDefs n -> Witness n -> Either (Error a n) (Type n)
- DDC.Core.Check.Error: ErrorAppMismatch :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorAppNotFun :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCannotJoin :: Witness n -> Witness n -> Type n -> Witness n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseAltResultMismatch :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseCannotInstantiate :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseDiscrimNotAlgebraic :: Exp a n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseDiscrimTypeMismatch :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseDiscrimTypeUndeclared :: Exp a n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseFieldTypeMismatch :: Exp a n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorCaseNoAlternatives :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorCaseNonExhaustive :: Exp a n -> [n] -> Error a n
- DDC.Core.Check.Error: ErrorCaseNonExhaustiveLarge :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorCaseOverlapping :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorCaseTooManyBinders :: Exp a n -> Bound n -> Int -> Int -> Error a n
- DDC.Core.Check.Error: ErrorLamBindNotData :: Exp a n -> Type n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorLamBodyNotData :: Exp a n -> Bind n -> Type n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorLamNotPure :: Exp a n -> Effect n -> Error a n
- DDC.Core.Check.Error: ErrorLamShadow :: Exp a n -> Bind n -> Error a n
- DDC.Core.Check.Error: ErrorLetBindingNotData :: Exp a n -> Bind n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorLetBodyNotData :: Exp a n -> Type n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorLetLazyNoWitness :: Exp a n -> Bind n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorLetLazyNotEmpty :: Exp a n -> Bind n -> Closure n -> Error a n
- DDC.Core.Check.Error: ErrorLetLazyNotPure :: Exp a n -> Bind n -> Effect n -> Error a n
- DDC.Core.Check.Error: ErrorLetLazyWitnessTypeMismatch :: Exp a n -> Bind n -> Type n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorLetMismatch :: Exp a n -> Bind n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionFree :: Exp a n -> Bind n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionNotRegion :: Exp a n -> Bind n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionRebound :: Exp a n -> Bind n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionWitnessConflict :: Exp a n -> Bind n -> Bind n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionWitnessInvalid :: Exp a n -> Bind n -> Error a n
- DDC.Core.Check.Error: ErrorLetRegionWitnessOther :: Exp a n -> Bound n -> Bind n -> Error a n
- DDC.Core.Check.Error: ErrorLetrecBindingNotLambda :: Exp a n -> Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorMalformedExp :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorMalformedType :: Exp a n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorMaxcloMalformed :: Exp a n -> Closure n -> Error a n
- DDC.Core.Check.Error: ErrorMaxcloNotClo :: Exp a n -> Closure n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorMaxeffNotEff :: Exp a n -> Effect n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorNakedType :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorNakedWitness :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorType :: Error n -> Error a n
- DDC.Core.Check.Error: ErrorUndefinedCtor :: Exp a n -> Error a n
- DDC.Core.Check.Error: ErrorVarAnnotMismatch :: Bound n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorWAppMismatch :: Witness n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorWAppNotCtor :: Witness n -> Type n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorWithRegionNotRegion :: Exp a n -> Bound n -> Kind n -> Error a n
- DDC.Core.Check.Error: ErrorWitnessNotEmpty :: Exp a n -> Witness n -> Type n -> Error a n
- DDC.Core.Check.Error: ErrorWitnessNotPurity :: Exp a n -> Witness n -> Type n -> Error a n
- DDC.Core.Check.Error: data Error a n
- DDC.Core.Check.Error: errorAltType1 :: Error a n -> Type n
- DDC.Core.Check.Error: errorAltType2 :: Error a n -> Type n
- DDC.Core.Check.Error: errorArgType :: Error a n -> Type n
- DDC.Core.Check.Error: errorBind :: Error a n -> Bind n
- DDC.Core.Check.Error: errorBindType :: Error a n -> Type n
- DDC.Core.Check.Error: errorBindWitness :: Error a n -> Bind n
- DDC.Core.Check.Error: errorBindWitness1 :: Error a n -> Bind n
- DDC.Core.Check.Error: errorBindWitness2 :: Error a n -> Bind n
- DDC.Core.Check.Error: errorBound :: Error a n -> Bound n
- DDC.Core.Check.Error: errorBoundRegion :: Error a n -> Bound n
- DDC.Core.Check.Error: errorChecking :: Error a n -> Exp a n
- DDC.Core.Check.Error: errorClosure :: Error a n -> Closure n
- DDC.Core.Check.Error: errorCtorBound :: Error a n -> Bound n
- DDC.Core.Check.Error: errorCtorFields :: Error a n -> Int
- DDC.Core.Check.Error: errorCtorNamesMissing :: Error a n -> [n]
- DDC.Core.Check.Error: errorEffect :: Error a n -> Effect n
- DDC.Core.Check.Error: errorExp :: Error a n -> Exp a n
- DDC.Core.Check.Error: errorKind :: Error a n -> Kind n
- DDC.Core.Check.Error: errorNotFunType :: Error a n -> Type n
- DDC.Core.Check.Error: errorParamType :: Error a n -> Type n
- DDC.Core.Check.Error: errorPatternFields :: Error a n -> Int
- DDC.Core.Check.Error: errorType :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeAnnot :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeCtor :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeDiscrim :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeEnv :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeError :: Error a n -> Error n
- DDC.Core.Check.Error: errorTypeField :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeLeft :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypePattern :: Error a n -> Type n
- DDC.Core.Check.Error: errorTypeRight :: Error a n -> Type n
- DDC.Core.Check.Error: errorWitness :: Error a n -> Witness n
- DDC.Core.Check.Error: errorWitnessLeft :: Error a n -> Witness n
- DDC.Core.Check.Error: errorWitnessRight :: Error a n -> Witness n
- DDC.Core.Check.Error: errorWitnessTypeExpect :: Error a n -> Type n
- DDC.Core.Check.Error: errorWitnessTypeHave :: Error a n -> Type n
- DDC.Core.Check.Error: instance (Show a, Show n) => Show (Error a n)
- DDC.Core.Check.TaggedClosure: GBoundRgnCon :: (Bound n) -> TaggedClosure n
- DDC.Core.Check.TaggedClosure: GBoundRgnVar :: (Bound n) -> TaggedClosure n
- DDC.Core.Check.TaggedClosure: GBoundVal :: (Bound n) -> (TypeSum n) -> TaggedClosure n
- DDC.Core.Check.TaggedClosure: closureOfTagged :: TaggedClosure n -> Closure n
- DDC.Core.Check.TaggedClosure: closureOfTaggedSet :: Ord n => Set (TaggedClosure n) -> Closure n
- DDC.Core.Check.TaggedClosure: cutTaggedClosureT :: (Eq n, Ord n) => Bind n -> TaggedClosure n -> Maybe (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: cutTaggedClosureX :: (Eq n, Ord n) => Bind n -> TaggedClosure n -> Maybe (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: cutTaggedClosureXs :: (Eq n, Ord n) => [Bind n] -> TaggedClosure n -> Maybe (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: data TaggedClosure n
- DDC.Core.Check.TaggedClosure: instance (Eq n, Pretty n) => Pretty (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: instance Eq n => Eq (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: instance LowerT TaggedClosure
- DDC.Core.Check.TaggedClosure: instance Ord n => Ord (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: instance Show n => Show (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: maskFromTaggedSet :: Ord n => TypeSum n -> Set (TaggedClosure n) -> Set (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: taggedClosureOfTyArg :: (Ord n, Pretty n) => Type n -> Set (TaggedClosure n)
- DDC.Core.Check.TaggedClosure: taggedClosureOfValBound :: (Ord n, Pretty n) => Bound n -> TaggedClosure n
- DDC.Core.Check.TaggedClosure: taggedClosureOfWeakClo :: (Ord n, Pretty n) => Closure n -> Maybe (Set (TaggedClosure n))
- DDC.Core.Collect: collectSpecBinds :: (BindStruct c, Ord n) => c n -> [Bind n]
- DDC.Core.Collect: instance BindStruct (Alt a)
- DDC.Core.Collect: instance BindStruct (Exp a)
- DDC.Core.Collect: instance BindStruct Cast
- DDC.Core.Collect: instance BindStruct LetMode
- DDC.Core.Collect: instance BindStruct TyCon
- DDC.Core.Collect: instance BindStruct Type
- DDC.Core.Collect: instance BindStruct Witness
- DDC.Core.Collect: instance Eq BindWay
- DDC.Core.Collect: instance Eq BoundLevel
- DDC.Core.Collect: instance Eq n => Eq (BindTree n)
- DDC.Core.Collect: instance Show BindWay
- DDC.Core.Collect: instance Show BoundLevel
- DDC.Core.Collect: instance Show n => Show (BindTree n)
- DDC.Core.Compounds: makeXApps :: a -> Exp a n -> [Exp a n] -> Exp a n
- DDC.Core.Compounds: makeXLAMs :: a -> [Bind n] -> Exp a n -> Exp a n
- DDC.Core.Compounds: makeXLams :: a -> [Bind n] -> Exp a n -> Exp a n
- DDC.Core.DataDef: DataCtor :: n -> [Type n] -> n -> DataCtor n
- DDC.Core.DataDef: DataDef :: n -> [Kind n] -> Maybe [(n, [Type n])] -> DataDef n
- DDC.Core.DataDef: DataDefs :: Map n (DataType n) -> Map n (DataCtor n) -> DataDefs n
- DDC.Core.DataDef: DataModeLarge :: DataMode n
- DDC.Core.DataDef: DataModeSmall :: [n] -> DataMode n
- DDC.Core.DataDef: DataType :: n -> [Kind n] -> DataMode n -> DataType n
- DDC.Core.DataDef: data DataCtor n
- DDC.Core.DataDef: data DataDef n
- DDC.Core.DataDef: data DataDefs n
- DDC.Core.DataDef: data DataMode n
- DDC.Core.DataDef: data DataType n
- DDC.Core.DataDef: dataCtorFieldTypes :: DataCtor n -> [Type n]
- DDC.Core.DataDef: dataCtorName :: DataCtor n -> n
- DDC.Core.DataDef: dataCtorTypeName :: DataCtor n -> n
- DDC.Core.DataDef: dataDefCtors :: DataDef n -> Maybe [(n, [Type n])]
- DDC.Core.DataDef: dataDefParamKinds :: DataDef n -> [Kind n]
- DDC.Core.DataDef: dataDefTypeName :: DataDef n -> n
- DDC.Core.DataDef: dataDefsCtors :: DataDefs n -> Map n (DataCtor n)
- DDC.Core.DataDef: dataDefsTypes :: DataDefs n -> Map n (DataType n)
- DDC.Core.DataDef: dataTypeMode :: DataType n -> DataMode n
- DDC.Core.DataDef: dataTypeName :: DataType n -> n
- DDC.Core.DataDef: dataTypeParamKinds :: DataType n -> [Kind n]
- DDC.Core.DataDef: emptyDataDefs :: DataDefs n
- DDC.Core.DataDef: fromListDataDefs :: Ord n => [DataDef n] -> DataDefs n
- DDC.Core.DataDef: insertDataDef :: Ord n => DataDef n -> DataDefs n -> DataDefs n
- DDC.Core.DataDef: lookupModeOfDataType :: Ord n => n -> DataDefs n -> Maybe (DataMode n)
- DDC.Core.Exp: LLetRegion :: (Bind n) -> [Bind n] -> Lets a n
- DDC.Core.Exp: instance (Eq a, Eq n) => Eq (Alt a n)
- DDC.Core.Exp: instance (Eq a, Eq n) => Eq (Exp a n)
- DDC.Core.Exp: instance (Eq a, Eq n) => Eq (Lets a n)
- DDC.Core.Exp: instance (Show a, Show n) => Show (Alt a n)
- DDC.Core.Exp: instance (Show a, Show n) => Show (Exp a n)
- DDC.Core.Exp: instance (Show a, Show n) => Show (Lets a n)
- DDC.Core.Exp: instance Eq WbCon
- DDC.Core.Exp: instance Eq n => Eq (Cast n)
- DDC.Core.Exp: instance Eq n => Eq (LetMode n)
- DDC.Core.Exp: instance Eq n => Eq (Pat n)
- DDC.Core.Exp: instance Eq n => Eq (WiCon n)
- DDC.Core.Exp: instance Eq n => Eq (Witness n)
- DDC.Core.Exp: instance Show WbCon
- DDC.Core.Exp: instance Show n => Show (Cast n)
- DDC.Core.Exp: instance Show n => Show (LetMode n)
- DDC.Core.Exp: instance Show n => Show (Pat n)
- DDC.Core.Exp: instance Show n => Show (WiCon n)
- DDC.Core.Exp: instance Show n => Show (Witness n)
- DDC.Core.Parser.Lexer: isConBody :: Char -> Bool
- DDC.Core.Parser.Lexer: isConName :: String -> Bool
- DDC.Core.Parser.Lexer: isConStart :: Char -> Bool
- DDC.Core.Parser.Lexer: isVarBody :: Char -> Bool
- DDC.Core.Parser.Lexer: isVarName :: String -> Bool
- DDC.Core.Parser.Lexer: isVarStart :: Char -> Bool
- DDC.Core.Parser.Lexer: lexExp :: Int -> String -> [Token (Tok String)]
- DDC.Core.Parser.Lexer: readCon :: String -> Maybe String
- DDC.Core.Parser.Lexer: readTcConBuiltin :: String -> Maybe TcCon
- DDC.Core.Parser.Lexer: readTwConBuiltin :: String -> Maybe TwCon
- DDC.Core.Parser.Lexer: readVar :: String -> Maybe String
- DDC.Core.Parser.Lexer: readWbConBuiltin :: String -> Maybe WbCon
- DDC.Core.Parser.Tokens: KA :: !TokAtom -> Tok n
- DDC.Core.Parser.Tokens: KAmpersand :: TokAtom
- DDC.Core.Parser.Tokens: KAngleBra :: TokAtom
- DDC.Core.Parser.Tokens: KAngleColonBra :: TokAtom
- DDC.Core.Parser.Tokens: KAngleColonKet :: TokAtom
- DDC.Core.Parser.Tokens: KAngleKet :: TokAtom
- DDC.Core.Parser.Tokens: KArrowDash :: TokAtom
- DDC.Core.Parser.Tokens: KArrowEquals :: TokAtom
- DDC.Core.Parser.Tokens: KArrowTilde :: TokAtom
- DDC.Core.Parser.Tokens: KBackSlash :: TokAtom
- DDC.Core.Parser.Tokens: KBar :: TokAtom
- DDC.Core.Parser.Tokens: KBigLambda :: TokAtom
- DDC.Core.Parser.Tokens: KBotClosure :: TokAtom
- DDC.Core.Parser.Tokens: KBotEffect :: TokAtom
- DDC.Core.Parser.Tokens: KBraceBra :: TokAtom
- DDC.Core.Parser.Tokens: KBraceKet :: TokAtom
- DDC.Core.Parser.Tokens: KCase :: TokAtom
- DDC.Core.Parser.Tokens: KColon :: TokAtom
- DDC.Core.Parser.Tokens: KColonColon :: TokAtom
- DDC.Core.Parser.Tokens: KComma :: TokAtom
- DDC.Core.Parser.Tokens: KCon :: n -> TokNamed n
- DDC.Core.Parser.Tokens: KDash :: TokAtom
- DDC.Core.Parser.Tokens: KDot :: TokAtom
- DDC.Core.Parser.Tokens: KEquals :: TokAtom
- DDC.Core.Parser.Tokens: KForget :: TokAtom
- DDC.Core.Parser.Tokens: KHat :: TokAtom
- DDC.Core.Parser.Tokens: KIn :: TokAtom
- DDC.Core.Parser.Tokens: KIndex :: Int -> TokAtom
- DDC.Core.Parser.Tokens: KJunk :: Char -> Tok n
- DDC.Core.Parser.Tokens: KKindClosure :: TokAtom
- DDC.Core.Parser.Tokens: KKindEffect :: TokAtom
- DDC.Core.Parser.Tokens: KKindRegion :: TokAtom
- DDC.Core.Parser.Tokens: KKindValue :: TokAtom
- DDC.Core.Parser.Tokens: KKindWitness :: TokAtom
- DDC.Core.Parser.Tokens: KLazy :: TokAtom
- DDC.Core.Parser.Tokens: KLet :: TokAtom
- DDC.Core.Parser.Tokens: KLetRec :: TokAtom
- DDC.Core.Parser.Tokens: KLetRegion :: TokAtom
- DDC.Core.Parser.Tokens: KLit :: n -> TokNamed n
- DDC.Core.Parser.Tokens: KN :: !(TokNamed n) -> Tok n
- DDC.Core.Parser.Tokens: KOf :: TokAtom
- DDC.Core.Parser.Tokens: KPlus :: TokAtom
- DDC.Core.Parser.Tokens: KPurify :: TokAtom
- DDC.Core.Parser.Tokens: KRoundBra :: TokAtom
- DDC.Core.Parser.Tokens: KRoundKet :: TokAtom
- DDC.Core.Parser.Tokens: KSemiColon :: TokAtom
- DDC.Core.Parser.Tokens: KSortComp :: TokAtom
- DDC.Core.Parser.Tokens: KSortProp :: TokAtom
- DDC.Core.Parser.Tokens: KSquareBra :: TokAtom
- DDC.Core.Parser.Tokens: KSquareColonBra :: TokAtom
- DDC.Core.Parser.Tokens: KSquareColonKet :: TokAtom
- DDC.Core.Parser.Tokens: KSquareKet :: TokAtom
- DDC.Core.Parser.Tokens: KTcConBuiltin :: TcCon -> TokAtom
- DDC.Core.Parser.Tokens: KTwConBuiltin :: TwCon -> TokAtom
- DDC.Core.Parser.Tokens: KUnderscore :: TokAtom
- DDC.Core.Parser.Tokens: KVar :: n -> TokNamed n
- DDC.Core.Parser.Tokens: KWbConBuiltin :: WbCon -> TokAtom
- DDC.Core.Parser.Tokens: KWeakClo :: TokAtom
- DDC.Core.Parser.Tokens: KWeakEff :: TokAtom
- DDC.Core.Parser.Tokens: KWhere :: TokAtom
- DDC.Core.Parser.Tokens: KWith :: TokAtom
- DDC.Core.Parser.Tokens: KWithRegion :: TokAtom
- DDC.Core.Parser.Tokens: data Tok n
- DDC.Core.Parser.Tokens: data TokAtom
- DDC.Core.Parser.Tokens: data TokNamed n
- DDC.Core.Parser.Tokens: describeTok :: Pretty n => Tok n -> String
- DDC.Core.Parser.Tokens: describeTokAtom :: TokAtom -> String
- DDC.Core.Parser.Tokens: describeTokNamed :: Pretty n => TokNamed n -> String
- DDC.Core.Parser.Tokens: instance Eq TokAtom
- DDC.Core.Parser.Tokens: instance Eq n => Eq (Tok n)
- DDC.Core.Parser.Tokens: instance Eq n => Eq (TokNamed n)
- DDC.Core.Parser.Tokens: instance Show TokAtom
- DDC.Core.Parser.Tokens: instance Show n => Show (Tok n)
- DDC.Core.Parser.Tokens: instance Show n => Show (TokNamed n)
- DDC.Core.Parser.Tokens: renameTok :: Ord n2 => (n1 -> n2) -> Tok n1 -> Tok n2
- DDC.Core.Pretty: instance (Pretty n, Eq n) => Pretty (Cast n)
- DDC.Core.Transform.LiftW: class LiftW (c :: * -> *) where liftW n xx = liftAtDepthW n 0 xx
- DDC.Core.Transform.LiftW: instance LiftW (Alt a)
- DDC.Core.Transform.LiftW: instance LiftW (Exp a)
- DDC.Core.Transform.LiftW: instance LiftW Bound
- DDC.Core.Transform.LiftW: instance LiftW LetMode
- DDC.Core.Transform.LiftW: instance LiftW Witness
- DDC.Core.Transform.LiftW: liftAtDepthW :: (LiftW c, Ord n) => Int -> Int -> c n -> c n
- DDC.Core.Transform.LiftW: liftW :: (LiftW c, Ord n) => Int -> c n -> c n
- DDC.Core.Transform.LiftX: class LiftX (c :: * -> *) where liftX n xx = liftAtDepthX n 0 xx
- DDC.Core.Transform.LiftX: instance LiftX (Alt a)
- DDC.Core.Transform.LiftX: instance LiftX (Exp a)
- DDC.Core.Transform.LiftX: instance LiftX Bound
- DDC.Core.Transform.SpreadX: instance SpreadX Cast
- DDC.Core.Transform.SubstituteTX: instance SubstituteTX Bound
- DDC.Core.Transform.SubstituteTX: instance SubstituteTX Cast
- DDC.Core.Transform.SubstituteWX: instance SubstituteWX Cast
- DDC.Type.Check.Monad: CheckM :: (Either err a) -> CheckM err a
- DDC.Type.Check.Monad: data CheckM err a
- DDC.Type.Check.Monad: instance Monad (CheckM err)
- DDC.Type.Check.Monad: result :: CheckM err a -> Either err a
- DDC.Type.Check.Monad: throw :: err -> CheckM err a
- DDC.Type.Compounds: replaceTypeOfBound :: Type n -> Bound n -> Bound n
- DDC.Type.Compounds: typeOfBound :: Bound n -> Type n
- DDC.Type.Exp: TypeSum :: Kind n -> Array TyConHash (Set (TypeSumVarCon n)) -> Map n (Kind n) -> Map Int (Kind n) -> [Type n] -> TypeSum n
- DDC.Type.Exp: instance Eq KiCon
- DDC.Type.Exp: instance Eq SoCon
- DDC.Type.Exp: instance Eq TcCon
- DDC.Type.Exp: instance Eq TwCon
- DDC.Type.Exp: instance Eq TyConHash
- DDC.Type.Exp: instance Ix TyConHash
- DDC.Type.Exp: instance Ord TyConHash
- DDC.Type.Exp: instance Show KiCon
- DDC.Type.Exp: instance Show SoCon
- DDC.Type.Exp: instance Show TcCon
- DDC.Type.Exp: instance Show TwCon
- DDC.Type.Exp: instance Show TyConHash
- DDC.Type.Exp: instance Show n => Show (Bind n)
- DDC.Type.Exp: instance Show n => Show (Binder n)
- DDC.Type.Exp: instance Show n => Show (Bound n)
- DDC.Type.Exp: instance Show n => Show (TyCon n)
- DDC.Type.Exp: instance Show n => Show (Type n)
- DDC.Type.Exp: instance Show n => Show (TypeSum n)
- DDC.Type.Exp: instance Show n => Show (TypeSumVarCon n)
- DDC.Type.Parser: pBinder :: Ord n => Parser n (Binder n)
- DDC.Type.Parser: pIndex :: Parser n Int
- DDC.Type.Parser: pTok :: TokAtom -> Parser n ()
- DDC.Type.Parser: pTokAs :: TokAtom -> a -> Parser n a
- DDC.Type.Parser: pType :: Ord n => Parser n (Type n)
- DDC.Type.Parser: pTypeApp :: Ord n => Parser n (Type n)
- DDC.Type.Parser: pTypeAtom :: Ord n => Parser n (Type n)
- DDC.Type.Parser: type Parser n a = Parser (Tok n) a
- DDC.Type.Rewrite: BindStack :: [Bind n] -> [Bind n] -> Int -> Int -> BindStack n
- DDC.Type.Rewrite: Sub :: Bound n -> Bool -> Set n -> Set n -> BindStack n -> BindStack n -> Sub n
- DDC.Type.Rewrite: bind0 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
- DDC.Type.Rewrite: bind0s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])
- DDC.Type.Rewrite: bind1 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
- DDC.Type.Rewrite: class Rewrite (c :: * -> *)
- DDC.Type.Rewrite: data BindStack n
- DDC.Type.Rewrite: data Sub n
- DDC.Type.Rewrite: instance Rewrite Bind
- DDC.Type.Rewrite: instance Rewrite Bound
- DDC.Type.Rewrite: instance Rewrite Cast
- DDC.Type.Rewrite: instance Rewrite LetMode
- DDC.Type.Rewrite: instance Rewrite Type
- DDC.Type.Rewrite: instance Rewrite TypeSum
- DDC.Type.Rewrite: instance Rewrite Witness
- DDC.Type.Rewrite: pushBind :: Ord n => Set n -> BindStack n -> Bind n -> (BindStack n, Bind n)
- DDC.Type.Rewrite: pushBinds :: Ord n => Set n -> BindStack n -> [Bind n] -> (BindStack n, [Bind n])
- DDC.Type.Rewrite: rewriteWith :: (Rewrite c, Ord n) => Sub n -> c n -> c n
- DDC.Type.Rewrite: stackAll :: BindStack n -> [Bind n]
- DDC.Type.Rewrite: stackAnons :: BindStack n -> Int
- DDC.Type.Rewrite: stackBinds :: BindStack n -> [Bind n]
- DDC.Type.Rewrite: stackNamed :: BindStack n -> Int
- DDC.Type.Rewrite: subBound :: Sub n -> Bound n
- DDC.Type.Rewrite: subConflict0 :: Sub n -> Set n
- DDC.Type.Rewrite: subConflict1 :: Sub n -> Set n
- DDC.Type.Rewrite: subShadow0 :: Sub n -> Bool
- DDC.Type.Rewrite: subStack0 :: Sub n -> BindStack n
- DDC.Type.Rewrite: subStack1 :: Sub n -> BindStack n
- DDC.Type.Rewrite: substBound :: Ord n => BindStack n -> Bound n -> Bound n -> Either (Bound n) Int
- DDC.Type.Rewrite: use0 :: Ord n => Sub n -> Bound n -> Bound n
- DDC.Type.Rewrite: use1 :: Ord n => Sub n -> Bound n -> Bound n
- DDC.Type.Sum: makeSumArrayElem :: TyConHash -> TypeSumVarCon n -> Type n
- DDC.Type.Sum: takeSumArrayElem :: Type n -> Maybe (TyConHash, TypeSumVarCon n)
- DDC.Type.Transform.LiftT: class LiftT (c :: * -> *) where liftT n xx = liftAtDepthT n 0 xx
- DDC.Type.Transform.LiftT: instance LiftT Bind
- DDC.Type.Transform.LiftT: instance LiftT Bound
- DDC.Type.Transform.LiftT: instance LiftT Type
- DDC.Type.Transform.LiftT: instance LiftT TypeSum
- DDC.Type.Transform.LowerT: class LowerT (c :: * -> *) where lowerT n xx = lowerAtDepthT n 0 xx
- DDC.Type.Transform.LowerT: instance LowerT Bind
- DDC.Type.Transform.LowerT: instance LowerT Bound
- DDC.Type.Transform.LowerT: instance LowerT Type
- DDC.Type.Transform.LowerT: instance LowerT TypeSum
- DDC.Type.Transform.LowerT: lowerAtDepthT :: (LowerT c, Ord n) => Int -> Int -> c n -> c n
- DDC.Type.Transform.LowerT: lowerT :: (LowerT c, Ord n) => Int -> c n -> c n
+ DDC.Core.Check: AnTEC :: (Type n) -> (Effect n) -> (Closure n) -> a -> AnTEC a n
+ DDC.Core.Check: Config :: DataDefs n -> KindEnv n -> TypeEnv n -> Bool -> Config n
+ DDC.Core.Check: ErrorCaseScrutineeNotAlgebraic :: Exp a n -> Type n -> Error a n
+ DDC.Core.Check: ErrorCaseScrutineeTypeMismatch :: Exp a n -> Type n -> Type n -> Error a n
+ DDC.Core.Check: ErrorCaseScrutineeTypeUndeclared :: Exp a n -> Type n -> Error a n
+ DDC.Core.Check: ErrorExportMismatch :: n -> Type n -> Type n -> Error a n
+ DDC.Core.Check: ErrorExportUndefined :: n -> Error a n
+ DDC.Core.Check: ErrorLetRegionWitnessFree :: Exp a n -> Bind n -> Error a n
+ DDC.Core.Check: ErrorLetRegionsNotRegion :: Exp a n -> [Bind n] -> [Kind n] -> Error a n
+ DDC.Core.Check: ErrorLetRegionsRebound :: Exp a n -> [Bind n] -> Error a n
+ DDC.Core.Check: ErrorLetRegionsWitnessOther :: Exp a n -> [Bound n] -> Bind n -> Error a n
+ DDC.Core.Check: ErrorLetrecRebound :: Exp a n -> Bind n -> Error a n
+ DDC.Core.Check: ErrorUndefinedVar :: Bound n -> Universe -> Error a n
+ DDC.Core.Check: ErrorWeakEffNotEff :: Exp a n -> Effect n -> Kind n -> Error a n
+ DDC.Core.Check: ErrorWithRegionFree :: Exp a n -> Bound n -> Type n -> Error a n
+ DDC.Core.Check: annotClosure :: AnTEC a n -> (Closure n)
+ DDC.Core.Check: annotEffect :: AnTEC a n -> (Effect n)
+ DDC.Core.Check: annotTail :: AnTEC a n -> a
+ DDC.Core.Check: annotType :: AnTEC a n -> (Type n)
+ DDC.Core.Check: checkModule :: (Ord n, Show n, Pretty n) => Config n -> Module a n -> Either (Error a n) (Module (AnTEC a n) n)
+ DDC.Core.Check: configOfProfile :: Profile n -> Config n
+ DDC.Core.Check: configPrimDataDefs :: Config n -> DataDefs n
+ DDC.Core.Check: configPrimKinds :: Config n -> KindEnv n
+ DDC.Core.Check: configPrimTypes :: Config n -> TypeEnv n
+ DDC.Core.Check: configSuppressClosures :: Config n -> Bool
+ DDC.Core.Check: data AnTEC a n
+ DDC.Core.Check: data Config n
+ DDC.Core.Check: errorBinds :: Error a n -> [Bind n]
+ DDC.Core.Check: errorBoundRegions :: Error a n -> [Bound n]
+ DDC.Core.Check: errorCtorDaCon :: Error a n -> DaCon n
+ DDC.Core.Check: errorDefType :: Error a n -> Type n
+ DDC.Core.Check: errorExportType :: Error a n -> Type n
+ DDC.Core.Check: errorKinds :: Error a n -> [Kind n]
+ DDC.Core.Check: errorName :: Error a n -> n
+ DDC.Core.Check: errorSpecOrWit :: Error a n -> Bool
+ DDC.Core.Check: errorTypeScrutinee :: Error a n -> Type n
+ DDC.Core.Check: errorUniverse :: Error a n -> Universe
+ DDC.Core.Collect: Support :: Set (Bound n) -> Set (Bound n) -> Set (Bound n) -> Set (Bound n) -> Set (Bound n) -> Set (Bound n) -> Support n
+ DDC.Core.Collect: class SupportX (c :: * -> *)
+ DDC.Core.Collect: collectBinds :: (BindStruct c, Ord n) => c n -> ([Bind n], [Bind n])
+ DDC.Core.Collect: data Support n
+ DDC.Core.Collect: support :: (SupportX c, Ord n) => KindEnv n -> TypeEnv n -> c n -> Support n
+ DDC.Core.Collect: supportDaVar :: Support n -> Set (Bound n)
+ DDC.Core.Collect: supportSpVar :: Support n -> Set (Bound n)
+ DDC.Core.Collect: supportSpVarXArg :: Support n -> Set (Bound n)
+ DDC.Core.Collect: supportTyCon :: Support n -> Set (Bound n)
+ DDC.Core.Collect: supportTyConXArg :: Support n -> Set (Bound n)
+ DDC.Core.Collect: supportWiVar :: Support n -> Set (Bound n)
+ DDC.Core.Compounds: makeXAppsWithAnnots :: Exp a n -> [(Exp a n, a)] -> Exp a n
+ DDC.Core.Compounds: splitXLets :: Exp a n -> ([Lets a n], Exp a n)
+ DDC.Core.Compounds: takeAnnotOfExp :: Exp a n -> Maybe a
+ DDC.Core.Compounds: takePrimWiConApps :: Witness n -> Maybe (n, [Witness n])
+ DDC.Core.Compounds: takeWAppsAsList :: Witness n -> [Witness n]
+ DDC.Core.Compounds: takeXApps1 :: Exp a n -> Exp a n -> (Exp a n, [Exp a n])
+ DDC.Core.Compounds: takeXAppsAsList :: Exp a n -> [Exp a n]
+ DDC.Core.Compounds: takeXAppsWithAnnots :: Exp a n -> (Exp a n, [(Exp a n, a)])
+ DDC.Core.Compounds: takeXType :: Exp a n -> Maybe (Type n)
+ DDC.Core.Compounds: takeXWitness :: Exp a n -> Maybe (Witness n)
+ DDC.Core.Compounds: wApp :: Witness n -> Witness n -> Witness n
+ DDC.Core.Compounds: wApps :: Witness n -> [Witness n] -> Witness n
+ DDC.Core.Compounds: xApps :: a -> Exp a n -> [Exp a n] -> Exp a n
+ DDC.Core.Compounds: xLAMs :: a -> [Bind n] -> Exp a n -> Exp a n
+ DDC.Core.Compounds: xLams :: a -> [Bind n] -> Exp a n -> Exp a n
+ DDC.Core.Compounds: xLets :: a -> [Lets a n] -> Exp a n -> Exp a n
+ DDC.Core.Compounds: xUnit :: a -> Exp a n
+ DDC.Core.DaCon: DaCon :: !(DaConName n) -> !(Type n) -> !Bool -> DaCon n
+ DDC.Core.DaCon: DaConNamed :: n -> DaConName n
+ DDC.Core.DaCon: DaConUnit :: DaConName n
+ DDC.Core.DaCon: daConIsAlgebraic :: DaCon n -> !Bool
+ DDC.Core.DaCon: daConName :: DaCon n -> !(DaConName n)
+ DDC.Core.DaCon: daConType :: DaCon n -> !(Type n)
+ DDC.Core.DaCon: data DaCon n
+ DDC.Core.DaCon: data DaConName n
+ DDC.Core.DaCon: dcUnit :: DaCon n
+ DDC.Core.DaCon: instance Eq n => Eq (DaConName n)
+ DDC.Core.DaCon: instance NFData n => NFData (DaCon n)
+ DDC.Core.DaCon: instance NFData n => NFData (DaConName n)
+ DDC.Core.DaCon: instance Show n => Show (DaCon n)
+ DDC.Core.DaCon: instance Show n => Show (DaConName n)
+ DDC.Core.DaCon: mkDaConAlg :: n -> Type n -> DaCon n
+ DDC.Core.DaCon: mkDaConSolid :: n -> Type n -> DaCon n
+ DDC.Core.DaCon: takeNameOfDaCon :: DaCon n -> Maybe n
+ DDC.Core.DaCon: typeOfDaCon :: DaCon n -> Type n
+ DDC.Core.Exp: DaCon :: !(DaConName n) -> !(Type n) -> !Bool -> DaCon n
+ DDC.Core.Exp: DaConNamed :: n -> DaConName n
+ DDC.Core.Exp: DaConUnit :: DaConName n
+ DDC.Core.Exp: LLetRegions :: ![Bind n] -> ![Bind n] -> Lets a n
+ DDC.Core.Exp: daConIsAlgebraic :: DaCon n -> !Bool
+ DDC.Core.Exp: daConName :: DaCon n -> !(DaConName n)
+ DDC.Core.Exp: daConType :: DaCon n -> !(Type n)
+ DDC.Core.Exp: data DaCon n
+ DDC.Core.Exp: data DaConName n
+ DDC.Core.Fragment: DebruijnBinders :: Feature
+ DDC.Core.Fragment: ErrorNakedType :: !(Type n) -> Error n
+ DDC.Core.Fragment: ErrorNakedWitness :: !(Witness n) -> Error n
+ DDC.Core.Fragment: ErrorShadowedBind :: !n -> Error n
+ DDC.Core.Fragment: ErrorUndefinedPrim :: !n -> Error n
+ DDC.Core.Fragment: ErrorUndefinedVar :: !n -> Error n
+ DDC.Core.Fragment: ErrorUnsupported :: !Feature -> Error n
+ DDC.Core.Fragment: ErrorUnusedBind :: !n -> Error n
+ DDC.Core.Fragment: Features :: Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Features
+ DDC.Core.Fragment: Fragment :: Profile n -> String -> (String -> Maybe n) -> (String -> Int -> String -> [Token (Tok n)]) -> (String -> Int -> String -> [Token (Tok n)]) -> (forall a. Module a n -> Maybe (err a)) -> (forall a. Exp a n -> Maybe (err a)) -> Fragment n
+ DDC.Core.Fragment: GeneralApplication :: Feature
+ DDC.Core.Fragment: LazyBindings :: Feature
+ DDC.Core.Fragment: NameShadowing :: Feature
+ DDC.Core.Fragment: NestedFunctions :: Feature
+ DDC.Core.Fragment: PartialApplication :: Feature
+ DDC.Core.Fragment: PartialPrims :: Feature
+ DDC.Core.Fragment: Profile :: !String -> !Features -> !(DataDefs n) -> !(KindEnv n) -> !(TypeEnv n) -> !(Type n -> Bool) -> Profile n
+ DDC.Core.Fragment: UnboundLevel0Vars :: Feature
+ DDC.Core.Fragment: UnboxedInstantiation :: Feature
+ DDC.Core.Fragment: UntrackedClosures :: Feature
+ DDC.Core.Fragment: UntrackedEffects :: Feature
+ DDC.Core.Fragment: UnusedBindings :: Feature
+ DDC.Core.Fragment: UnusedMatches :: Feature
+ DDC.Core.Fragment: class Complies (c :: * -> * -> *)
+ DDC.Core.Fragment: complies :: (Ord n, Show n, Complies c) => Profile n -> c a n -> Maybe (Error n)
+ DDC.Core.Fragment: compliesWithEnvs :: (Ord n, Show n, Complies c) => Profile n -> KindEnv n -> TypeEnv n -> c a n -> Maybe (Error n)
+ DDC.Core.Fragment: data Error n
+ DDC.Core.Fragment: data Feature
+ DDC.Core.Fragment: data Features
+ DDC.Core.Fragment: data Fragment n (err :: * -> *)
+ DDC.Core.Fragment: data Profile n
+ DDC.Core.Fragment: featuresDebruijnBinders :: Features -> Bool
+ DDC.Core.Fragment: featuresGeneralApplication :: Features -> Bool
+ DDC.Core.Fragment: featuresLazyBindings :: Features -> Bool
+ DDC.Core.Fragment: featuresNameShadowing :: Features -> Bool
+ DDC.Core.Fragment: featuresNestedFunctions :: Features -> Bool
+ DDC.Core.Fragment: featuresPartialApplication :: Features -> Bool
+ DDC.Core.Fragment: featuresPartialPrims :: Features -> Bool
+ DDC.Core.Fragment: featuresUnboundLevel0Vars :: Features -> Bool
+ DDC.Core.Fragment: featuresUnboxedInstantiation :: Features -> Bool
+ DDC.Core.Fragment: featuresUntrackedClosures :: Features -> Bool
+ DDC.Core.Fragment: featuresUntrackedEffects :: Features -> Bool
+ DDC.Core.Fragment: featuresUnusedBindings :: Features -> Bool
+ DDC.Core.Fragment: featuresUnusedMatches :: Features -> Bool
+ DDC.Core.Fragment: fragmentCheckExp :: Fragment n -> forall a. Exp a n -> Maybe (err a)
+ DDC.Core.Fragment: fragmentCheckModule :: Fragment n -> forall a. Module a n -> Maybe (err a)
+ DDC.Core.Fragment: fragmentExtension :: Fragment n -> String
+ DDC.Core.Fragment: fragmentLexExp :: Fragment n -> String -> Int -> String -> [Token (Tok n)]
+ DDC.Core.Fragment: fragmentLexModule :: Fragment n -> String -> Int -> String -> [Token (Tok n)]
+ DDC.Core.Fragment: fragmentProfile :: Fragment n -> Profile n
+ DDC.Core.Fragment: fragmentReadName :: Fragment n -> String -> Maybe n
+ DDC.Core.Fragment: instance Show (Fragment n err)
+ DDC.Core.Fragment: profileFeatures :: Profile n -> !Features
+ DDC.Core.Fragment: profileName :: Profile n -> !String
+ DDC.Core.Fragment: profilePrimDataDefs :: Profile n -> !(DataDefs n)
+ DDC.Core.Fragment: profilePrimKinds :: Profile n -> !(KindEnv n)
+ DDC.Core.Fragment: profilePrimTypes :: Profile n -> !(TypeEnv n)
+ DDC.Core.Fragment: profileTypeIsUnboxed :: Profile n -> !(Type n -> Bool)
+ DDC.Core.Fragment: zeroFeatures :: Features
+ DDC.Core.Fragment: zeroProfile :: Profile n
+ DDC.Core.Lexer: lexExp :: FilePath -> Int -> String -> [Token (Tok String)]
+ DDC.Core.Lexer: lexModuleWithOffside :: FilePath -> Int -> String -> [Token (Tok String)]
+ DDC.Core.Lexer.Names: isConBody :: Char -> Bool
+ DDC.Core.Lexer.Names: isConName :: String -> Bool
+ DDC.Core.Lexer.Names: isConStart :: Char -> Bool
+ DDC.Core.Lexer.Names: isLitBody :: Char -> Bool
+ DDC.Core.Lexer.Names: isLitName :: String -> Bool
+ DDC.Core.Lexer.Names: isLitStart :: Char -> Bool
+ DDC.Core.Lexer.Names: isVarBody :: Char -> Bool
+ DDC.Core.Lexer.Names: isVarName :: String -> Bool
+ DDC.Core.Lexer.Names: isVarStart :: Char -> Bool
+ DDC.Core.Lexer.Names: keywords :: [(String, Tok n)]
+ DDC.Core.Lexer.Names: readCon :: String -> Maybe String
+ DDC.Core.Lexer.Names: readTcConBuiltin :: String -> Maybe TcCon
+ DDC.Core.Lexer.Names: readTwConBuiltin :: String -> Maybe TwCon
+ DDC.Core.Lexer.Names: readVar :: String -> Maybe String
+ DDC.Core.Lexer.Names: readWbConBuiltin :: String -> Maybe WbCon
+ DDC.Core.Lexer.Tokens: KA :: !TokAtom -> Tok n
+ DDC.Core.Lexer.Tokens: KAmpersand :: TokAtom
+ DDC.Core.Lexer.Tokens: KAngleBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KAngleColonBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KAngleColonKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KAngleKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KArrowDash :: TokAtom
+ DDC.Core.Lexer.Tokens: KArrowDashLeft :: TokAtom
+ DDC.Core.Lexer.Tokens: KArrowEquals :: TokAtom
+ DDC.Core.Lexer.Tokens: KArrowTilde :: TokAtom
+ DDC.Core.Lexer.Tokens: KBackSlash :: TokAtom
+ DDC.Core.Lexer.Tokens: KBar :: TokAtom
+ DDC.Core.Lexer.Tokens: KBigLambda :: TokAtom
+ DDC.Core.Lexer.Tokens: KBotClosure :: TokAtom
+ DDC.Core.Lexer.Tokens: KBotEffect :: TokAtom
+ DDC.Core.Lexer.Tokens: KBraceBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KBraceKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KCase :: TokAtom
+ DDC.Core.Lexer.Tokens: KColon :: TokAtom
+ DDC.Core.Lexer.Tokens: KColonColon :: TokAtom
+ DDC.Core.Lexer.Tokens: KComma :: TokAtom
+ DDC.Core.Lexer.Tokens: KCommentBlockEnd :: TokMeta
+ DDC.Core.Lexer.Tokens: KCommentBlockStart :: TokMeta
+ DDC.Core.Lexer.Tokens: KCommentLineStart :: TokMeta
+ DDC.Core.Lexer.Tokens: KCommentUnterminated :: TokMeta
+ DDC.Core.Lexer.Tokens: KCon :: n -> TokNamed n
+ DDC.Core.Lexer.Tokens: KDaConUnit :: TokAtom
+ DDC.Core.Lexer.Tokens: KDash :: TokAtom
+ DDC.Core.Lexer.Tokens: KDo :: TokAtom
+ DDC.Core.Lexer.Tokens: KDot :: TokAtom
+ DDC.Core.Lexer.Tokens: KElse :: TokAtom
+ DDC.Core.Lexer.Tokens: KEquals :: TokAtom
+ DDC.Core.Lexer.Tokens: KExports :: TokAtom
+ DDC.Core.Lexer.Tokens: KForget :: TokAtom
+ DDC.Core.Lexer.Tokens: KHat :: TokAtom
+ DDC.Core.Lexer.Tokens: KImports :: TokAtom
+ DDC.Core.Lexer.Tokens: KIn :: TokAtom
+ DDC.Core.Lexer.Tokens: KIndex :: Int -> TokAtom
+ DDC.Core.Lexer.Tokens: KJunk :: String -> Tok n
+ DDC.Core.Lexer.Tokens: KKindClosure :: TokAtom
+ DDC.Core.Lexer.Tokens: KKindEffect :: TokAtom
+ DDC.Core.Lexer.Tokens: KKindRegion :: TokAtom
+ DDC.Core.Lexer.Tokens: KKindValue :: TokAtom
+ DDC.Core.Lexer.Tokens: KKindWitness :: TokAtom
+ DDC.Core.Lexer.Tokens: KLazy :: TokAtom
+ DDC.Core.Lexer.Tokens: KLet :: TokAtom
+ DDC.Core.Lexer.Tokens: KLetRec :: TokAtom
+ DDC.Core.Lexer.Tokens: KLetRegion :: TokAtom
+ DDC.Core.Lexer.Tokens: KLetRegions :: TokAtom
+ DDC.Core.Lexer.Tokens: KLit :: n -> TokNamed n
+ DDC.Core.Lexer.Tokens: KM :: !TokMeta -> Tok n
+ DDC.Core.Lexer.Tokens: KMatch :: TokAtom
+ DDC.Core.Lexer.Tokens: KModule :: TokAtom
+ DDC.Core.Lexer.Tokens: KN :: !(TokNamed n) -> Tok n
+ DDC.Core.Lexer.Tokens: KNewLine :: TokMeta
+ DDC.Core.Lexer.Tokens: KOf :: TokAtom
+ DDC.Core.Lexer.Tokens: KOffsideClosingBrace :: TokMeta
+ DDC.Core.Lexer.Tokens: KPlus :: TokAtom
+ DDC.Core.Lexer.Tokens: KPurify :: TokAtom
+ DDC.Core.Lexer.Tokens: KRoundBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KRoundKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KSemiColon :: TokAtom
+ DDC.Core.Lexer.Tokens: KSortComp :: TokAtom
+ DDC.Core.Lexer.Tokens: KSortProp :: TokAtom
+ DDC.Core.Lexer.Tokens: KSquareBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KSquareColonBra :: TokAtom
+ DDC.Core.Lexer.Tokens: KSquareColonKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KSquareKet :: TokAtom
+ DDC.Core.Lexer.Tokens: KTcConBuiltin :: TcCon -> TokAtom
+ DDC.Core.Lexer.Tokens: KTwConBuiltin :: TwCon -> TokAtom
+ DDC.Core.Lexer.Tokens: KType :: TokAtom
+ DDC.Core.Lexer.Tokens: KUnderscore :: TokAtom
+ DDC.Core.Lexer.Tokens: KVar :: n -> TokNamed n
+ DDC.Core.Lexer.Tokens: KWbConBuiltin :: WbCon -> TokAtom
+ DDC.Core.Lexer.Tokens: KWeakClo :: TokAtom
+ DDC.Core.Lexer.Tokens: KWeakEff :: TokAtom
+ DDC.Core.Lexer.Tokens: KWhere :: TokAtom
+ DDC.Core.Lexer.Tokens: KWith :: TokAtom
+ DDC.Core.Lexer.Tokens: KWithRegion :: TokAtom
+ DDC.Core.Lexer.Tokens: data Tok n
+ DDC.Core.Lexer.Tokens: data TokAtom
+ DDC.Core.Lexer.Tokens: data TokMeta
+ DDC.Core.Lexer.Tokens: data TokNamed n
+ DDC.Core.Lexer.Tokens: describeTok :: Pretty n => Tok n -> String
+ DDC.Core.Lexer.Tokens: describeTokAtom :: TokAtom -> String
+ DDC.Core.Lexer.Tokens: describeTokMeta :: TokMeta -> String
+ DDC.Core.Lexer.Tokens: describeTokNamed :: Pretty n => TokNamed n -> String
+ DDC.Core.Lexer.Tokens: instance Eq TokAtom
+ DDC.Core.Lexer.Tokens: instance Eq TokMeta
+ DDC.Core.Lexer.Tokens: instance Eq n => Eq (Tok n)
+ DDC.Core.Lexer.Tokens: instance Eq n => Eq (TokNamed n)
+ DDC.Core.Lexer.Tokens: instance Show TokAtom
+ DDC.Core.Lexer.Tokens: instance Show TokMeta
+ DDC.Core.Lexer.Tokens: instance Show n => Show (Tok n)
+ DDC.Core.Lexer.Tokens: instance Show n => Show (TokNamed n)
+ DDC.Core.Lexer.Tokens: renameTok :: Ord n2 => (n1 -> Maybe n2) -> Tok n1 -> Maybe (Tok n2)
+ DDC.Core.Load: AnTEC :: (Type n) -> (Effect n) -> (Closure n) -> a -> AnTEC a n
+ DDC.Core.Load: ErrorCheckExp :: !(Error () n) -> Error n
+ DDC.Core.Load: ErrorCheckType :: !(Error n) -> Error n
+ DDC.Core.Load: ErrorCompliance :: !(Error n) -> Error n
+ DDC.Core.Load: ErrorParser :: !ParseError -> Error n
+ DDC.Core.Load: ErrorRead :: !String -> Error n
+ DDC.Core.Load: annotClosure :: AnTEC a n -> (Closure n)
+ DDC.Core.Load: annotEffect :: AnTEC a n -> (Effect n)
+ DDC.Core.Load: annotTail :: AnTEC a n -> a
+ DDC.Core.Load: annotType :: AnTEC a n -> (Type n)
+ DDC.Core.Load: data AnTEC a n
+ DDC.Core.Load: data Error n
+ DDC.Core.Load: instance (Eq n, Show n, Pretty n) => Pretty (Error n)
+ DDC.Core.Load: instance Show n => Show (Error n)
+ DDC.Core.Load: loadExp :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> Map ModuleName (Module (AnTEC () n) n) -> FilePath -> [Token (Tok n)] -> Either (Error n) (Exp (AnTEC () n) n)
+ DDC.Core.Load: loadModuleFromFile :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> (String -> [Token (Tok n)]) -> FilePath -> IO (Either (Error n) (Module (AnTEC () n) n))
+ DDC.Core.Load: loadModuleFromString :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> (String -> [Token (Tok n)]) -> FilePath -> String -> Either (Error n) (Module (AnTEC () n) n)
+ DDC.Core.Load: loadModuleFromTokens :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> FilePath -> [Token (Tok n)] -> Either (Error n) (Module (AnTEC () n) n)
+ DDC.Core.Load: loadType :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> FilePath -> [Token (Tok n)] -> Either (Error n) (Type n, Kind n)
+ DDC.Core.Load: loadWitness :: (Eq n, Ord n, Show n, Pretty n) => Profile n -> FilePath -> [Token (Tok n)] -> Either (Error n) (Witness n, Type n)
+ DDC.Core.Module: ModuleCore :: !ModuleName -> !(Map n (Kind n)) -> !(Map n (Type n)) -> !(Map n (QualName n, Kind n)) -> !(Map n (QualName n, Type n)) -> !(Exp a n) -> Module a n
+ DDC.Core.Module: ModuleName :: [String] -> ModuleName
+ DDC.Core.Module: QualName :: ModuleName -> n -> QualName n
+ DDC.Core.Module: data Module a n
+ DDC.Core.Module: data ModuleName
+ DDC.Core.Module: data QualName n
+ DDC.Core.Module: instance (NFData a, NFData n) => NFData (Module a n)
+ DDC.Core.Module: instance (Show a, Show n) => Show (Module a n)
+ DDC.Core.Module: instance Eq ModuleName
+ DDC.Core.Module: instance NFData ModuleName
+ DDC.Core.Module: instance NFData n => NFData (QualName n)
+ DDC.Core.Module: instance Ord ModuleName
+ DDC.Core.Module: instance Show ModuleName
+ DDC.Core.Module: instance Show n => Show (QualName n)
+ DDC.Core.Module: instance Typeable ModuleName
+ DDC.Core.Module: instance Typeable2 Module
+ DDC.Core.Module: isMainModule :: Module a n -> Bool
+ DDC.Core.Module: isMainModuleName :: ModuleName -> Bool
+ DDC.Core.Module: moduleBody :: Module a n -> !(Exp a n)
+ DDC.Core.Module: moduleExportKinds :: Module a n -> !(Map n (Kind n))
+ DDC.Core.Module: moduleExportTypes :: Module a n -> !(Map n (Type n))
+ DDC.Core.Module: moduleImportKinds :: Module a n -> !(Map n (QualName n, Kind n))
+ DDC.Core.Module: moduleImportTypes :: Module a n -> !(Map n (QualName n, Type n))
+ DDC.Core.Module: moduleKindEnv :: Ord n => Module a n -> KindEnv n
+ DDC.Core.Module: moduleName :: Module a n -> !ModuleName
+ DDC.Core.Module: moduleTypeEnv :: Ord n => Module a n -> TypeEnv n
+ DDC.Core.Module: modulesExportKinds :: Ord n => ModuleMap a n -> KindEnv n -> KindEnv n
+ DDC.Core.Module: modulesExportTypes :: Ord n => ModuleMap a n -> TypeEnv n -> TypeEnv n
+ DDC.Core.Module: modulesGetBinds :: Ord n => Map n (Type n) -> Env n
+ DDC.Core.Module: type ModuleMap a n = Map ModuleName (Module a n)
+ DDC.Core.Parser: pBinder :: Ord n => Parser n (Binder n)
+ DDC.Core.Parser: pCon :: Parser n n
+ DDC.Core.Parser: pExpApp :: Ord n => Parser n (Exp () n)
+ DDC.Core.Parser: pExpAtom :: Ord n => Parser n (Exp () n)
+ DDC.Core.Parser: pIndex :: Parser n Int
+ DDC.Core.Parser: pLit :: Parser n n
+ DDC.Core.Parser: pModule :: (Ord n, Pretty n) => Parser n (Module () n)
+ DDC.Core.Parser: pName :: Parser n n
+ DDC.Core.Parser: pTok :: TokAtom -> Parser n ()
+ DDC.Core.Parser: pTokAs :: TokAtom -> a -> Parser n a
+ DDC.Core.Parser: pType :: Ord n => Parser n (Type n)
+ DDC.Core.Parser: pTypeApp :: Ord n => Parser n (Type n)
+ DDC.Core.Parser: pTypeAtom :: Ord n => Parser n (Type n)
+ DDC.Core.Parser: pVar :: Parser n n
+ DDC.Core.Parser: pWitnessApp :: Ord n => Parser n (Witness n)
+ DDC.Core.Parser: pWitnessAtom :: Ord n => Parser n (Witness n)
+ DDC.Core.Predicates: isXType :: Exp a n -> Bool
+ DDC.Core.Predicates: isXWitness :: Exp a n -> Bool
+ DDC.Core.Pretty: instance (Pretty n, Eq n) => Pretty (Cast a n)
+ DDC.Core.Pretty: instance (Pretty n, Eq n) => Pretty (DaCon n)
+ DDC.Core.Pretty: instance (Pretty n, Eq n) => Pretty (Module a n)
+ DDC.Core.Pretty: instance Pretty ModuleName
+ DDC.Core.Transform.LiftT: class MapBoundT (c :: * -> *) n
+ DDC.Core.Transform.LiftT: instance Ord n => MapBoundT (Alt a) n
+ DDC.Core.Transform.LiftT: instance Ord n => MapBoundT (Cast a) n
+ DDC.Core.Transform.LiftT: instance Ord n => MapBoundT (Exp a) n
+ DDC.Core.Transform.LiftT: instance Ord n => MapBoundT LetMode n
+ DDC.Core.Transform.LiftT: instance Ord n => MapBoundT Witness n
+ DDC.Core.Transform.LiftT: liftAtDepthT :: MapBoundT c n => Int -> Int -> c n -> c n
+ DDC.Core.Transform.LiftT: liftT :: MapBoundT c n => Int -> c n -> c n
+ DDC.Core.Transform.LiftT: mapBoundAtDepthT :: MapBoundT c n => (Int -> Bound n -> Bound n) -> Int -> c n -> c n
+ DDC.Core.Transform.LiftX: class MapBoundX (c :: * -> *) n
+ DDC.Core.Transform.LiftX: instance MapBoundX (Alt a) n
+ DDC.Core.Transform.LiftX: instance MapBoundX (Cast a) n
+ DDC.Core.Transform.LiftX: instance MapBoundX (Exp a) n
+ DDC.Core.Transform.LiftX: instance MapBoundX Bound n
+ DDC.Core.Transform.LiftX: instance MapBoundX LetMode n
+ DDC.Core.Transform.LiftX: instance MapBoundX Witness n
+ DDC.Core.Transform.LiftX: lowerAtDepthX :: MapBoundX c n => Int -> Int -> c n -> c n
+ DDC.Core.Transform.LiftX: lowerX :: MapBoundX c n => Int -> c n -> c n
+ DDC.Core.Transform.LiftX: mapBoundAtDepthX :: MapBoundX c n => (Int -> Bound n -> Bound n) -> Int -> c n -> c n
+ DDC.Core.Transform.Reannotate: class Reannotate c
+ DDC.Core.Transform.Reannotate: instance Reannotate Alt
+ DDC.Core.Transform.Reannotate: instance Reannotate Cast
+ DDC.Core.Transform.Reannotate: instance Reannotate Exp
+ DDC.Core.Transform.Reannotate: instance Reannotate Lets
+ DDC.Core.Transform.Reannotate: instance Reannotate Module
+ DDC.Core.Transform.Reannotate: reannotate :: Reannotate c => (a -> b) -> c a n -> c b n
+ DDC.Core.Transform.Rename: BindStack :: ![Bind n] -> ![Bind n] -> !Int -> !Int -> BindStack n
+ DDC.Core.Transform.Rename: Sub :: !(Bound n) -> !Bool -> !(Set n) -> !(Set n) -> !(BindStack n) -> !(BindStack n) -> Sub n
+ DDC.Core.Transform.Rename: bind0 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
+ DDC.Core.Transform.Rename: bind0s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])
+ DDC.Core.Transform.Rename: bind1 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
+ DDC.Core.Transform.Rename: bind1s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])
+ DDC.Core.Transform.Rename: class Rename (c :: * -> *)
+ DDC.Core.Transform.Rename: data BindStack n
+ DDC.Core.Transform.Rename: data Sub n
+ DDC.Core.Transform.Rename: instance Rename LetMode
+ DDC.Core.Transform.Rename: instance Rename Witness
+ DDC.Core.Transform.Rename: pushBind :: Ord n => Set n -> BindStack n -> Bind n -> (BindStack n, Bind n)
+ DDC.Core.Transform.Rename: pushBinds :: Ord n => Set n -> BindStack n -> [Bind n] -> (BindStack n, [Bind n])
+ DDC.Core.Transform.Rename: renameWith :: (Rename c, Ord n) => Sub n -> c n -> c n
+ DDC.Core.Transform.Rename: stackAll :: BindStack n -> ![Bind n]
+ DDC.Core.Transform.Rename: stackAnons :: BindStack n -> !Int
+ DDC.Core.Transform.Rename: stackBinds :: BindStack n -> ![Bind n]
+ DDC.Core.Transform.Rename: stackNamed :: BindStack n -> !Int
+ DDC.Core.Transform.Rename: subBound :: Sub n -> !(Bound n)
+ DDC.Core.Transform.Rename: subConflict0 :: Sub n -> !(Set n)
+ DDC.Core.Transform.Rename: subConflict1 :: Sub n -> !(Set n)
+ DDC.Core.Transform.Rename: subShadow0 :: Sub n -> !Bool
+ DDC.Core.Transform.Rename: subStack0 :: Sub n -> !(BindStack n)
+ DDC.Core.Transform.Rename: subStack1 :: Sub n -> !(BindStack n)
+ DDC.Core.Transform.Rename: substBound :: Ord n => BindStack n -> Bound n -> Bound n -> Either (Bound n) Int
+ DDC.Core.Transform.Rename: use0 :: Ord n => Sub n -> Bound n -> Bound n
+ DDC.Core.Transform.Rename: use1 :: Ord n => Sub n -> Bound n -> Bound n
+ DDC.Core.Transform.SpreadX: instance SpreadX (Cast a)
+ DDC.Core.Transform.SpreadX: instance SpreadX (Module a)
+ DDC.Core.Transform.SpreadX: instance SpreadX DaCon
+ DDC.Core.Transform.SubstituteTX: instance SubstituteTX (Cast a)
+ DDC.Core.Transform.SubstituteWX: instance SubstituteWX (Cast a)
+ DDC.Core.Transform.SubstituteXX: instance SubstituteXX Cast
+ DDC.Core.Transform.Trim: trimClosures :: Ord n => a -> [Exp a n] -> [Exp a n]
+ DDC.Core.Transform.Trim: trimX :: Ord n => Exp a n -> Exp a n
+ DDC.Type.Bind: getBindType :: Eq n => [Bind n] -> Bound n -> Maybe (Int, Type n)
+ DDC.Type.Collect: BindCasePat :: BindWay
+ DDC.Type.Collect: BindCon :: BoundLevel -> (Bound n) -> (Maybe (Kind n)) -> BindTree n
+ DDC.Type.Collect: BindDef :: BindWay -> [Bind n] -> [BindTree n] -> BindTree n
+ DDC.Type.Collect: BindForall :: BindWay
+ DDC.Type.Collect: BindLAM :: BindWay
+ DDC.Type.Collect: BindLam :: BindWay
+ DDC.Type.Collect: BindLet :: BindWay
+ DDC.Type.Collect: BindLetRec :: BindWay
+ DDC.Type.Collect: BindLetRegionWith :: BindWay
+ DDC.Type.Collect: BindLetRegions :: BindWay
+ DDC.Type.Collect: BindUse :: BoundLevel -> (Bound n) -> BindTree n
+ DDC.Type.Collect: BoundExp :: BoundLevel
+ DDC.Type.Collect: BoundSpec :: BoundLevel
+ DDC.Type.Collect: BoundWit :: BoundLevel
+ DDC.Type.Collect: bindDefT :: BindStruct c => BindWay -> [Bind n] -> [c n] -> BindTree n
+ DDC.Type.Collect: boundLevelOfBindWay :: BindWay -> BoundLevel
+ DDC.Type.Collect: class BindStruct (c :: * -> *)
+ DDC.Type.Collect: collectBinds :: (BindStruct c, Ord n) => c n -> ([Bind n], [Bind n])
+ DDC.Type.Collect: collectBound :: (BindStruct c, Ord n) => c n -> Set (Bound n)
+ DDC.Type.Collect: data BindTree n
+ DDC.Type.Collect: data BindWay
+ DDC.Type.Collect: data BoundLevel
+ DDC.Type.Collect: freeT :: (BindStruct c, Ord n) => Env n -> c n -> Set (Bound n)
+ DDC.Type.Collect: instance BindStruct TyCon
+ DDC.Type.Collect: instance BindStruct Type
+ DDC.Type.Collect: instance Eq BindWay
+ DDC.Type.Collect: instance Eq BoundLevel
+ DDC.Type.Collect: instance Eq n => Eq (BindTree n)
+ DDC.Type.Collect: instance Show BindWay
+ DDC.Type.Collect: instance Show BoundLevel
+ DDC.Type.Collect: instance Show n => Show (BindTree n)
+ DDC.Type.Collect: isBoundExpWit :: BoundLevel -> Bool
+ DDC.Type.Collect: slurpBindTree :: BindStruct c => c n -> [BindTree n]
+ DDC.Type.Compounds: arityOfType :: Type n -> Int
+ DDC.Type.Compounds: eraseTForalls :: Ord n => Type n -> Type n
+ DDC.Type.Compounds: tDistinct :: Int -> [Type n] -> Type n
+ DDC.Type.Compounds: tUnit :: Type n
+ DDC.Type.Compounds: takePrimTyConApps :: Type n -> Maybe (n, [Type n])
+ DDC.Type.Compounds: takePrimeRegion :: Type n -> Maybe (Type n)
+ DDC.Type.Compounds: takeSubstBoundsOfBinds :: [Bind n] -> [Bound n]
+ DDC.Type.Compounds: takeTFunWitArgResult :: Type n -> ([Type n], [Type n], Type n)
+ DDC.Type.DataDef: DataCtor :: !n -> !Integer -> ![Type n] -> !n -> DataCtor n
+ DDC.Type.DataDef: DataDef :: !n -> ![Kind n] -> !(Maybe [(n, [Type n])]) -> DataDef n
+ DDC.Type.DataDef: DataDefs :: !(Map n (DataType n)) -> !(Map n (DataCtor n)) -> DataDefs n
+ DDC.Type.DataDef: DataModeLarge :: DataMode n
+ DDC.Type.DataDef: DataModeSmall :: ![n] -> DataMode n
+ DDC.Type.DataDef: DataType :: !n -> ![Kind n] -> !(DataMode n) -> DataType n
+ DDC.Type.DataDef: data DataCtor n
+ DDC.Type.DataDef: data DataDef n
+ DDC.Type.DataDef: data DataDefs n
+ DDC.Type.DataDef: data DataMode n
+ DDC.Type.DataDef: data DataType n
+ DDC.Type.DataDef: dataCtorFieldTypes :: DataCtor n -> ![Type n]
+ DDC.Type.DataDef: dataCtorName :: DataCtor n -> !n
+ DDC.Type.DataDef: dataCtorTag :: DataCtor n -> !Integer
+ DDC.Type.DataDef: dataCtorTypeName :: DataCtor n -> !n
+ DDC.Type.DataDef: dataDefCtors :: DataDef n -> !(Maybe [(n, [Type n])])
+ DDC.Type.DataDef: dataDefParamKinds :: DataDef n -> ![Kind n]
+ DDC.Type.DataDef: dataDefTypeName :: DataDef n -> !n
+ DDC.Type.DataDef: dataDefsCtors :: DataDefs n -> !(Map n (DataCtor n))
+ DDC.Type.DataDef: dataDefsTypes :: DataDefs n -> !(Map n (DataType n))
+ DDC.Type.DataDef: dataTypeMode :: DataType n -> !(DataMode n)
+ DDC.Type.DataDef: dataTypeName :: DataType n -> !n
+ DDC.Type.DataDef: dataTypeParamKinds :: DataType n -> ![Kind n]
+ DDC.Type.DataDef: emptyDataDefs :: DataDefs n
+ DDC.Type.DataDef: fromListDataDefs :: Ord n => [DataDef n] -> DataDefs n
+ DDC.Type.DataDef: insertDataDef :: Ord n => DataDef n -> DataDefs n -> DataDefs n
+ DDC.Type.DataDef: instance Show n => Show (DataCtor n)
+ DDC.Type.DataDef: instance Show n => Show (DataDef n)
+ DDC.Type.DataDef: instance Show n => Show (DataDefs n)
+ DDC.Type.DataDef: instance Show n => Show (DataMode n)
+ DDC.Type.DataDef: instance Show n => Show (DataType n)
+ DDC.Type.DataDef: lookupModeOfDataType :: Ord n => n -> DataDefs n -> Maybe (DataMode n)
+ DDC.Type.Env: fromTypeMap :: Map n (Type n) -> Env n
+ DDC.Type.Env: type KindEnv n = Env n
+ DDC.Type.Env: type TypeEnv n = Env n
+ DDC.Type.Equiv: equivWithBindsT :: Ord n => [Bind n] -> [Bind n] -> Type n -> Type n -> Bool
+ DDC.Type.Exp: TcConUnit :: TcCon
+ DDC.Type.Exp: TwConDisjoint :: TwCon
+ DDC.Type.Exp: TwConDistinct :: Int -> TwCon
+ DDC.Type.Exp: TypeSumBot :: !(Kind n) -> TypeSum n
+ DDC.Type.Exp: TypeSumSet :: !(Kind n) -> !(Array TyConHash (Set (TypeSumVarCon n))) -> !(Map n (Kind n)) -> !(Map Int (Kind n)) -> ![Type n] -> TypeSum n
+ DDC.Type.Predicates: isAllocEffect :: Effect n -> Bool
+ DDC.Type.Predicates: isBAnon :: Bind n -> Bool
+ DDC.Type.Predicates: isBName :: Bind n -> Bool
+ DDC.Type.Predicates: isBNone :: Bind n -> Bool
+ DDC.Type.Predicates: isConstWitType :: Eq n => Type n -> Bool
+ DDC.Type.Predicates: isDistinctWitType :: Eq n => Type n -> Bool
+ DDC.Type.Predicates: isMutableWitType :: Eq n => Type n -> Bool
+ DDC.Type.Predicates: isReadEffect :: Effect n -> Bool
+ DDC.Type.Predicates: isSomeAllocEffect :: Effect n -> Bool
+ DDC.Type.Predicates: isSomeReadEffect :: Effect n -> Bool
+ DDC.Type.Predicates: isSomeWriteEffect :: Effect n -> Bool
+ DDC.Type.Predicates: isTVar :: Type n -> Bool
+ DDC.Type.Predicates: isWitnessType :: Eq n => Type n -> Bool
+ DDC.Type.Predicates: isWriteEffect :: Effect n -> Bool
+ DDC.Type.Transform.Crush: crushSomeT :: Ord n => Type n -> Type n
+ DDC.Type.Transform.LiftT: class MapBoundT (c :: * -> *) n
+ DDC.Type.Transform.LiftT: instance MapBoundT Bound n
+ DDC.Type.Transform.LiftT: instance Ord n => MapBoundT Bind n
+ DDC.Type.Transform.LiftT: instance Ord n => MapBoundT Type n
+ DDC.Type.Transform.LiftT: instance Ord n => MapBoundT TypeSum n
+ DDC.Type.Transform.LiftT: lowerAtDepthT :: MapBoundT c n => Int -> Int -> c n -> c n
+ DDC.Type.Transform.LiftT: lowerT :: MapBoundT c n => Int -> c n -> c n
+ DDC.Type.Transform.LiftT: mapBoundAtDepthT :: MapBoundT c n => (Int -> Bound n -> Bound n) -> Int -> c n -> c n
+ DDC.Type.Transform.Rename: BindStack :: ![Bind n] -> ![Bind n] -> !Int -> !Int -> BindStack n
+ DDC.Type.Transform.Rename: Sub :: !(Bound n) -> !Bool -> !(Set n) -> !(Set n) -> !(BindStack n) -> !(BindStack n) -> Sub n
+ DDC.Type.Transform.Rename: bind0 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
+ DDC.Type.Transform.Rename: bind0s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])
+ DDC.Type.Transform.Rename: bind1 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)
+ DDC.Type.Transform.Rename: bind1s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])
+ DDC.Type.Transform.Rename: class Rename (c :: * -> *)
+ DDC.Type.Transform.Rename: data BindStack n
+ DDC.Type.Transform.Rename: data Sub n
+ DDC.Type.Transform.Rename: instance Rename Bind
+ DDC.Type.Transform.Rename: instance Rename Type
+ DDC.Type.Transform.Rename: instance Rename TypeSum
+ DDC.Type.Transform.Rename: pushBind :: Ord n => Set n -> BindStack n -> Bind n -> (BindStack n, Bind n)
+ DDC.Type.Transform.Rename: pushBinds :: Ord n => Set n -> BindStack n -> [Bind n] -> (BindStack n, [Bind n])
+ DDC.Type.Transform.Rename: renameWith :: (Rename c, Ord n) => Sub n -> c n -> c n
+ DDC.Type.Transform.Rename: stackAll :: BindStack n -> ![Bind n]
+ DDC.Type.Transform.Rename: stackAnons :: BindStack n -> !Int
+ DDC.Type.Transform.Rename: stackBinds :: BindStack n -> ![Bind n]
+ DDC.Type.Transform.Rename: stackNamed :: BindStack n -> !Int
+ DDC.Type.Transform.Rename: subBound :: Sub n -> !(Bound n)
+ DDC.Type.Transform.Rename: subConflict0 :: Sub n -> !(Set n)
+ DDC.Type.Transform.Rename: subConflict1 :: Sub n -> !(Set n)
+ DDC.Type.Transform.Rename: subShadow0 :: Sub n -> !Bool
+ DDC.Type.Transform.Rename: subStack0 :: Sub n -> !(BindStack n)
+ DDC.Type.Transform.Rename: subStack1 :: Sub n -> !(BindStack n)
+ DDC.Type.Transform.Rename: substBound :: Ord n => BindStack n -> Bound n -> Bound n -> Either (Bound n) Int
+ DDC.Type.Transform.Rename: use0 :: Ord n => Sub n -> Bound n -> Bound n
+ DDC.Type.Transform.Rename: use1 :: Ord n => Sub n -> Bound n -> Bound n
+ DDC.Type.Universe: instance Pretty Universe
- DDC.Core.Check: ErrorCaseTooManyBinders :: Exp a n -> Bound n -> Int -> Int -> Error a n
+ DDC.Core.Check: ErrorCaseTooManyBinders :: Exp a n -> DaCon n -> Int -> Int -> Error a n
- DDC.Core.Check: ErrorLamNotPure :: Exp a n -> Effect n -> Error a n
+ DDC.Core.Check: ErrorLamNotPure :: Exp a n -> Bool -> Effect n -> Error a n
- DDC.Core.Check: ErrorLetRegionFree :: Exp a n -> Bind n -> Type n -> Error a n
+ DDC.Core.Check: ErrorLetRegionFree :: Exp a n -> [Bind n] -> Type n -> Error a n
- DDC.Core.Check: ErrorVarAnnotMismatch :: Bound n -> Type n -> Error a n
+ DDC.Core.Check: ErrorVarAnnotMismatch :: Bound n -> Type n -> Type n -> Error a n
- DDC.Core.Check: checkExp :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Exp a n -> Either (Error a n) (Exp a n, Type n, Effect n, Closure n)
+ DDC.Core.Check: checkExp :: (Ord n, Show n, Pretty n) => Config n -> KindEnv n -> TypeEnv n -> Exp a n -> Either (Error a n) (Exp (AnTEC a n) n, Type n, Effect n, Closure n)
- DDC.Core.Check: checkWitness :: (Ord n, Pretty n) => DataDefs n -> Env n -> Env n -> Witness n -> Either (Error a n) (Type n)
+ DDC.Core.Check: checkWitness :: (Ord n, Show n, Pretty n) => Config n -> KindEnv n -> TypeEnv n -> Witness n -> Either (Error a n) (Type n)
- DDC.Core.Check: typeOfExp :: (Ord n, Pretty n) => DataDefs n -> Exp a n -> Either (Error a n) (Type n)
+ DDC.Core.Check: typeOfExp :: (Ord n, Pretty n, Show n) => Config n -> KindEnv n -> TypeEnv n -> Exp a n -> Either (Error a n) (Type n)
- DDC.Core.Check: typeOfWitness :: (Ord n, Pretty n) => DataDefs n -> Witness n -> Either (Error a n) (Type n)
+ DDC.Core.Check: typeOfWitness :: (Ord n, Show n, Pretty n) => Config n -> Witness n -> Either (Error a n) (Type n)
- DDC.Core.Compounds: bindsOfLets :: Lets a n -> [Bind n]
+ DDC.Core.Compounds: bindsOfLets :: Lets a n -> ([Bind n], [Bind n])
- DDC.Core.Compounds: takeXApps :: Exp a n -> [Exp a n]
+ DDC.Core.Compounds: takeXApps :: Exp a n -> Maybe (Exp a n, [Exp a n])
- DDC.Core.Compounds: takeXConApps :: Exp a n -> Maybe (Bound n, [Exp a n])
+ DDC.Core.Compounds: takeXConApps :: Exp a n -> Maybe (DaCon n, [Exp a n])
- DDC.Core.Exp: AAlt :: (Pat n) -> (Exp a n) -> Alt a n
+ DDC.Core.Exp: AAlt :: !(Pat n) -> !(Exp a n) -> Alt a n
- DDC.Core.Exp: CastForget :: (Witness n) -> Cast n
+ DDC.Core.Exp: CastForget :: !(Witness n) -> Cast a n
- DDC.Core.Exp: CastPurify :: (Witness n) -> Cast n
+ DDC.Core.Exp: CastPurify :: !(Witness n) -> Cast a n
- DDC.Core.Exp: CastWeakenClosure :: (Closure n) -> Cast n
+ DDC.Core.Exp: CastWeakenClosure :: ![Exp a n] -> Cast a n
- DDC.Core.Exp: CastWeakenEffect :: (Effect n) -> Cast n
+ DDC.Core.Exp: CastWeakenEffect :: !(Effect n) -> Cast a n
- DDC.Core.Exp: LLet :: (LetMode n) -> (Bind n) -> (Exp a n) -> Lets a n
+ DDC.Core.Exp: LLet :: !(LetMode n) -> !(Bind n) -> !(Exp a n) -> Lets a n
- DDC.Core.Exp: LRec :: [(Bind n, Exp a n)] -> Lets a n
+ DDC.Core.Exp: LRec :: ![(Bind n, Exp a n)] -> Lets a n
- DDC.Core.Exp: LWithRegion :: (Bound n) -> Lets a n
+ DDC.Core.Exp: LWithRegion :: !(Bound n) -> Lets a n
- DDC.Core.Exp: LetLazy :: (Maybe (Witness n)) -> LetMode n
+ DDC.Core.Exp: LetLazy :: !(Maybe (Witness n)) -> LetMode n
- DDC.Core.Exp: PData :: (Bound n) -> [Bind n] -> Pat n
+ DDC.Core.Exp: PData :: !(DaCon n) -> ![Bind n] -> Pat n
- DDC.Core.Exp: WApp :: (Witness n) -> (Witness n) -> Witness n
+ DDC.Core.Exp: WApp :: !(Witness n) -> !(Witness n) -> Witness n
- DDC.Core.Exp: WCon :: (WiCon n) -> Witness n
+ DDC.Core.Exp: WCon :: !(WiCon n) -> Witness n
- DDC.Core.Exp: WJoin :: (Witness n) -> (Witness n) -> Witness n
+ DDC.Core.Exp: WJoin :: !(Witness n) -> !(Witness n) -> Witness n
- DDC.Core.Exp: WType :: (Type n) -> Witness n
+ DDC.Core.Exp: WType :: !(Type n) -> Witness n
- DDC.Core.Exp: WVar :: (Bound n) -> Witness n
+ DDC.Core.Exp: WVar :: !(Bound n) -> Witness n
- DDC.Core.Exp: WiConBound :: (Bound n) -> WiCon n
+ DDC.Core.Exp: WiConBound :: !(Bound n) -> !(Type n) -> WiCon n
- DDC.Core.Exp: WiConBuiltin :: WbCon -> WiCon n
+ DDC.Core.Exp: WiConBuiltin :: !WbCon -> WiCon n
- DDC.Core.Exp: XApp :: a -> (Exp a n) -> (Exp a n) -> Exp a n
+ DDC.Core.Exp: XApp :: !a -> !(Exp a n) -> !(Exp a n) -> Exp a n
- DDC.Core.Exp: XCase :: a -> (Exp a n) -> [Alt a n] -> Exp a n
+ DDC.Core.Exp: XCase :: !a -> !(Exp a n) -> ![Alt a n] -> Exp a n
- DDC.Core.Exp: XCast :: a -> (Cast n) -> (Exp a n) -> Exp a n
+ DDC.Core.Exp: XCast :: !a -> !(Cast a n) -> !(Exp a n) -> Exp a n
- DDC.Core.Exp: XCon :: a -> (Bound n) -> Exp a n
+ DDC.Core.Exp: XCon :: !a -> !(DaCon n) -> Exp a n
- DDC.Core.Exp: XLAM :: a -> (Bind n) -> (Exp a n) -> Exp a n
+ DDC.Core.Exp: XLAM :: !a -> !(Bind n) -> !(Exp a n) -> Exp a n
- DDC.Core.Exp: XLam :: a -> (Bind n) -> (Exp a n) -> Exp a n
+ DDC.Core.Exp: XLam :: !a -> !(Bind n) -> !(Exp a n) -> Exp a n
- DDC.Core.Exp: XLet :: a -> (Lets a n) -> (Exp a n) -> Exp a n
+ DDC.Core.Exp: XLet :: !a -> !(Lets a n) -> !(Exp a n) -> Exp a n
- DDC.Core.Exp: XType :: (Type n) -> Exp a n
+ DDC.Core.Exp: XType :: !(Type n) -> Exp a n
- DDC.Core.Exp: XVar :: a -> (Bound n) -> Exp a n
+ DDC.Core.Exp: XVar :: !a -> !(Bound n) -> Exp a n
- DDC.Core.Exp: XWitness :: (Witness n) -> Exp a n
+ DDC.Core.Exp: XWitness :: !(Witness n) -> Exp a n
- DDC.Core.Exp: data Cast n
+ DDC.Core.Exp: data Cast a n
- DDC.Core.Transform.LiftX: liftAtDepthX :: (LiftX c, Ord n) => Int -> Int -> c n -> c n
+ DDC.Core.Transform.LiftX: liftAtDepthX :: MapBoundX c n => Int -> Int -> c n -> c n
- DDC.Core.Transform.LiftX: liftX :: (LiftX c, Ord n) => Int -> c n -> c n
+ DDC.Core.Transform.LiftX: liftX :: MapBoundX c n => Int -> c n -> c n
- DDC.Type.Check: checkType :: (Ord n, Pretty n) => DataDefs n -> Env n -> Type n -> Either (Error n) (Kind n)
+ DDC.Type.Check: checkType :: (Ord n, Show n, Pretty n) => DataDefs n -> KindEnv n -> Type n -> Either (Error n) (Kind n)
- DDC.Type.Check: kindOfType :: (Ord n, Pretty n) => DataDefs n -> Type n -> Either (Error n) (Kind n)
+ DDC.Type.Check: kindOfType :: (Ord n, Show n, Pretty n) => DataDefs n -> Type n -> Either (Error n) (Kind n)
- DDC.Type.Env: Env :: Map n (Type n) -> [Type n] -> Int -> (n -> Maybe (Type n)) -> Env n
+ DDC.Type.Env: Env :: !(Map n (Type n)) -> ![Type n] -> !Int -> !(n -> Maybe (Type n)) -> Env n
- DDC.Type.Env: envMap :: Env n -> Map n (Type n)
+ DDC.Type.Env: envMap :: Env n -> !(Map n (Type n))
- DDC.Type.Env: envPrimFun :: Env n -> n -> Maybe (Type n)
+ DDC.Type.Env: envPrimFun :: Env n -> !(n -> Maybe (Type n))
- DDC.Type.Env: envStack :: Env n -> [Type n]
+ DDC.Type.Env: envStack :: Env n -> ![Type n]
- DDC.Type.Env: envStackLength :: Env n -> Int
+ DDC.Type.Env: envStackLength :: Env n -> !Int
- DDC.Type.Equiv: equivT :: (Ord n, Pretty n) => Type n -> Type n -> Bool
+ DDC.Type.Equiv: equivT :: Ord n => Type n -> Type n -> Bool
- DDC.Type.Exp: BAnon :: (Type n) -> Bind n
+ DDC.Type.Exp: BAnon :: !(Type n) -> Bind n
- DDC.Type.Exp: BName :: n -> (Type n) -> Bind n
+ DDC.Type.Exp: BName :: n -> !(Type n) -> Bind n
- DDC.Type.Exp: BNone :: (Type n) -> Bind n
+ DDC.Type.Exp: BNone :: !(Type n) -> Bind n
- DDC.Type.Exp: RName :: n -> Binder n
+ DDC.Type.Exp: RName :: !n -> Binder n
- DDC.Type.Exp: TApp :: (Type n) -> (Type n) -> Type n
+ DDC.Type.Exp: TApp :: !(Type n) -> !(Type n) -> Type n
- DDC.Type.Exp: TCon :: (TyCon n) -> Type n
+ DDC.Type.Exp: TCon :: !(TyCon n) -> Type n
- DDC.Type.Exp: TForall :: (Bind n) -> (Type n) -> Type n
+ DDC.Type.Exp: TForall :: !(Bind n) -> !(Type n) -> Type n
- DDC.Type.Exp: TSum :: (TypeSum n) -> Type n
+ DDC.Type.Exp: TSum :: !(TypeSum n) -> Type n
- DDC.Type.Exp: TVar :: (Bound n) -> Type n
+ DDC.Type.Exp: TVar :: !(Bound n) -> Type n
- DDC.Type.Exp: TyConBound :: (Bound n) -> TyCon n
+ DDC.Type.Exp: TyConBound :: !(Bound n) -> !(Kind n) -> TyCon n
- DDC.Type.Exp: TyConKind :: KiCon -> TyCon n
+ DDC.Type.Exp: TyConKind :: !KiCon -> TyCon n
- DDC.Type.Exp: TyConSort :: SoCon -> TyCon n
+ DDC.Type.Exp: TyConSort :: !SoCon -> TyCon n
- DDC.Type.Exp: TyConSpec :: TcCon -> TyCon n
+ DDC.Type.Exp: TyConSpec :: !TcCon -> TyCon n
- DDC.Type.Exp: TyConWitness :: TwCon -> TyCon n
+ DDC.Type.Exp: TyConWitness :: !TwCon -> TyCon n
- DDC.Type.Exp: TypeSumCon :: (Bound n) -> TypeSumVarCon n
+ DDC.Type.Exp: TypeSumCon :: !(Bound n) -> !(Type n) -> TypeSumVarCon n
- DDC.Type.Exp: TypeSumVar :: (Bound n) -> TypeSumVarCon n
+ DDC.Type.Exp: TypeSumVar :: !(Bound n) -> TypeSumVarCon n
- DDC.Type.Exp: UIx :: Int -> (Type n) -> Bound n
+ DDC.Type.Exp: UIx :: !Int -> Bound n
- DDC.Type.Exp: UName :: n -> (Type n) -> Bound n
+ DDC.Type.Exp: UName :: !n -> Bound n
- DDC.Type.Exp: UPrim :: n -> (Type n) -> Bound n
+ DDC.Type.Exp: UPrim :: !n -> !(Type n) -> Bound n
- DDC.Type.Exp: typeSumBoundAnon :: TypeSum n -> Map Int (Kind n)
+ DDC.Type.Exp: typeSumBoundAnon :: TypeSum n -> !(Map Int (Kind n))
- DDC.Type.Exp: typeSumBoundNamed :: TypeSum n -> Map n (Kind n)
+ DDC.Type.Exp: typeSumBoundNamed :: TypeSum n -> !(Map n (Kind n))
- DDC.Type.Exp: typeSumElems :: TypeSum n -> Array TyConHash (Set (TypeSumVarCon n))
+ DDC.Type.Exp: typeSumElems :: TypeSum n -> !(Array TyConHash (Set (TypeSumVarCon n)))
- DDC.Type.Exp: typeSumKind :: TypeSum n -> Kind n
+ DDC.Type.Exp: typeSumKind :: TypeSum n -> !(Kind n)
- DDC.Type.Exp: typeSumSpill :: TypeSum n -> [Type n]
+ DDC.Type.Exp: typeSumSpill :: TypeSum n -> ![Type n]
- DDC.Type.Transform.LiftT: liftAtDepthT :: (LiftT c, Ord n) => Int -> Int -> c n -> c n
+ DDC.Type.Transform.LiftT: liftAtDepthT :: MapBoundT c n => Int -> Int -> c n -> c n
- DDC.Type.Transform.LiftT: liftT :: (LiftT c, Ord n) => Int -> c n -> c n
+ DDC.Type.Transform.LiftT: liftT :: MapBoundT c n => Int -> c n -> c n
- DDC.Type.Transform.SpreadT: spreadT :: (SpreadT c, Ord n) => Env n -> c n -> c n
+ DDC.Type.Transform.SpreadT: spreadT :: (SpreadT c, Ord n) => TypeEnv n -> c n -> c n
- DDC.Type.Transform.SubstituteT: BindStack :: [Bind n] -> [Bind n] -> Int -> Int -> BindStack n
+ DDC.Type.Transform.SubstituteT: BindStack :: ![Bind n] -> ![Bind n] -> !Int -> !Int -> BindStack n
- DDC.Type.Transform.SubstituteT: stackAll :: BindStack n -> [Bind n]
+ DDC.Type.Transform.SubstituteT: stackAll :: BindStack n -> ![Bind n]
- DDC.Type.Transform.SubstituteT: stackAnons :: BindStack n -> Int
+ DDC.Type.Transform.SubstituteT: stackAnons :: BindStack n -> !Int
- DDC.Type.Transform.SubstituteT: stackBinds :: BindStack n -> [Bind n]
+ DDC.Type.Transform.SubstituteT: stackBinds :: BindStack n -> ![Bind n]
- DDC.Type.Transform.SubstituteT: stackNamed :: BindStack n -> Int
+ DDC.Type.Transform.SubstituteT: stackNamed :: BindStack n -> !Int
- DDC.Type.Universe: universeFromType1 :: Type n -> Maybe Universe
+ DDC.Type.Universe: universeFromType1 :: Ord n => Env n -> Type n -> Maybe Universe
- DDC.Type.Universe: universeOfType :: Type n -> Maybe Universe
+ DDC.Type.Universe: universeOfType :: Ord n => Env n -> Type n -> Maybe Universe
Files
- DDC/Core/Check.hs +19/−3
- DDC/Core/Check/CheckDaCon.hs +50/−0
- DDC/Core/Check/CheckExp.hs +1120/−946
- DDC/Core/Check/CheckModule.hs +159/−0
- DDC/Core/Check/CheckWitness.hs +99/−92
- DDC/Core/Check/Error.hs +90/−50
- DDC/Core/Check/ErrorMessage.hs +100/−62
- DDC/Core/Check/TaggedClosure.hs +27/−21
- DDC/Core/Collect.hs +12/−247
- DDC/Core/Collect/Free.hs +128/−0
- DDC/Core/Collect/Support.hs +208/−0
- DDC/Core/Compounds.hs +239/−79
- DDC/Core/DaCon.hs +100/−0
- DDC/Core/DataDef.hs +0/−135
- DDC/Core/Exp.hs +5/−178
- DDC/Core/Exp/Base.hs +186/−0
- DDC/Core/Exp/NFData.hs +82/−0
- DDC/Core/Fragment.hs +65/−0
- DDC/Core/Fragment/Compliance.hs +388/−0
- DDC/Core/Fragment/Error.hs +59/−0
- DDC/Core/Fragment/Feature.hs +63/−0
- DDC/Core/Fragment/Profile.hs +111/−0
- DDC/Core/Lexer.hs +215/−0
- DDC/Core/Lexer/Comments.hs +64/−0
- DDC/Core/Lexer/Names.hs +226/−0
- DDC/Core/Lexer/Offside.hs +265/−0
- DDC/Core/Lexer/Tokens.hs +347/−0
- DDC/Core/Load.hs +240/−0
- DDC/Core/Module.hs +147/−0
- DDC/Core/Parser.hs +32/−619
- DDC/Core/Parser/Base.hs +98/−0
- DDC/Core/Parser/Exp.hs +547/−0
- DDC/Core/Parser/Lexer.hs +0/−293
- DDC/Core/Parser/Module.hs +125/−0
- DDC/Core/Parser/Param.hs +122/−0
- DDC/Core/Parser/Tokens.hs +0/−263
- DDC/Core/Parser/Type.hs +209/−0
- DDC/Core/Parser/Witness.hs +84/−0
- DDC/Core/Predicates.hs +35/−12
- DDC/Core/Pretty.hs +119/−30
- DDC/Core/Transform/LiftT.hs +107/−0
- DDC/Core/Transform/LiftW.hs +0/−116
- DDC/Core/Transform/LiftX.hs +133/−49
- DDC/Core/Transform/Reannotate.hs +68/−0
- DDC/Core/Transform/Rename.hs +41/−0
- DDC/Core/Transform/SpreadX.hs +62/−24
- DDC/Core/Transform/SubstituteTX.hs +18/−21
- DDC/Core/Transform/SubstituteWX.hs +25/−27
- DDC/Core/Transform/SubstituteXX.hs +25/−12
- DDC/Core/Transform/Trim.hs +112/−0
- DDC/Type/Bind.hs +31/−0
- DDC/Type/Check.hs +24/−57
- DDC/Type/Check/CheckCon.hs +22/−19
- DDC/Type/Check/CheckError.hs +0/−141
- DDC/Type/Check/Error.hs +71/−0
- DDC/Type/Check/ErrorMessage.hs +75/−0
- DDC/Type/Check/Monad.hs +0/−28
- DDC/Type/Collect.hs +185/−0
- DDC/Type/Collect/FreeT.hs +47/−0
- DDC/Type/Compounds.hs +138/−60
- DDC/Type/DataDef.hs +142/−0
- DDC/Type/Env.hs +58/−23
- DDC/Type/Equiv.hs +62/−83
- DDC/Type/Exp.hs +7/−259
- DDC/Type/Exp/Base.hs +267/−0
- DDC/Type/Exp/NFData.hs +81/−0
- DDC/Type/Parser.hs +0/−236
- DDC/Type/Predicates.hs +157/−10
- DDC/Type/Pretty.hs +7/−8
- DDC/Type/Rewrite.hs +0/−264
- DDC/Type/Sum.hs +94/−48
- DDC/Type/Transform/Crush.hs +48/−15
- DDC/Type/Transform/Instantiate.hs +12/−2
- DDC/Type/Transform/LiftT.hs +87/−41
- DDC/Type/Transform/LowerT.hs +0/−63
- DDC/Type/Transform/Rename.hs +246/−0
- DDC/Type/Transform/SpreadT.hs +18/−14
- DDC/Type/Transform/SubstituteT.hs +5/−5
- DDC/Type/Transform/Trim.hs +6/−3
- DDC/Type/Universe.hs +43/−24
- ddc-core.cabal +69/−23
DDC/Core/Check.hs view
@@ -1,17 +1,33 @@ --- | Type checker for the Disciple core language.+-- | Type checker for the Disciple Core language.+-- +-- The functions in this module do not check for language fragment compliance.+-- This needs to be done separately via "DDC.Core.Fragment".+-- module DDC.Core.Check- ( -- * Checking Expressions- checkExp, typeOfExp+ ( -- * Configuration+ Config(..)+ , configOfProfile + -- * Checking Modules+ , checkModule++ -- * Checking Expressions+ , checkExp, typeOfExp+ -- * Checking Witnesses , checkWitness, typeOfWitness , typeOfWiCon + -- * Annotations+ , AnTEC(..)+ -- * Error messages , Error(..)) where import DDC.Core.Check.Error import DDC.Core.Check.ErrorMessage ()+import DDC.Core.Check.CheckModule import DDC.Core.Check.CheckExp import DDC.Core.Check.CheckWitness+
+ DDC/Core/Check/CheckDaCon.hs view
@@ -0,0 +1,50 @@++module DDC.Core.Check.CheckDaCon+ (checkDaConM)+where+import DDC.Core.Check.Error+import DDC.Core.Check.CheckWitness+import DDC.Core.DaCon+import DDC.Core.Exp+import DDC.Type.Compounds+import DDC.Type.DataDef+import DDC.Control.Monad.Check (throw)+import Control.Monad+import Prelude as L+import qualified Data.Map as Map+++-- | Check a data constructor.+-- The data constructor must be in the set of data type declarations.+checkDaConM+ :: (Ord n, Eq n, Show n)+ => Config n+ -> Exp a n -- ^ The full expression for error messages.+ -> DaCon n -- ^ Data constructor to check.+ -> CheckM a n ()++checkDaConM _ _ dc+ | DaConUnit <- daConName dc+ = return ()++checkDaConM config xx dc+ | DaConNamed nCtor <- daConName dc+ , daConIsAlgebraic dc+ = let tResult = snd $ takeTFunArgResult $ eraseTForalls $ typeOfDaCon dc+ defs = configPrimDataDefs config+ in case liftM fst $ takeTyConApps tResult of+ Just (TyConBound u _)+ | Just nType <- takeNameOfBound u+ , Just dataType <- Map.lookup nType (dataDefsTypes defs)+ -> case dataTypeMode dataType of+ DataModeSmall nsCtors+ | L.elem nCtor nsCtors -> return ()+ | otherwise -> throw $ ErrorUndefinedCtor xx++ DataModeLarge -> return ()++ _ -> throw $ ErrorUndefinedCtor xx++checkDaConM _ _ _+ = return ()+
DDC/Core/Check/CheckExp.hs view
@@ -1,946 +1,1120 @@---- | Type checker for the Disciple Core language.-module DDC.Core.Check.CheckExp- ( checkExp- , typeOfExp- , CheckM- , checkExpM- , TaggedClosure(..))-where-import DDC.Core.DataDef-import DDC.Core.Predicates-import DDC.Core.Compounds-import DDC.Core.Exp-import DDC.Core.Pretty-import DDC.Core.Collect-import DDC.Core.Check.Error-import DDC.Core.Check.CheckWitness-import DDC.Core.Check.TaggedClosure-import DDC.Type.Transform.SubstituteT-import DDC.Type.Transform.Crush-import DDC.Type.Transform.Trim-import DDC.Type.Transform.Instantiate-import DDC.Type.Transform.LiftT-import DDC.Type.Transform.LowerT-import DDC.Type.Equiv-import DDC.Type.Universe-import DDC.Type.Compounds-import DDC.Type.Predicates-import DDC.Type.Sum as Sum-import DDC.Type.Env (Env)-import DDC.Type.Check.Monad (result, throw)-import DDC.Base.Pretty ()-import Data.Set (Set)-import qualified DDC.Type.Env as Env-import qualified DDC.Type.Check as T-import qualified Data.Set as Set-import qualified Data.Map as Map-import Control.Monad-import Data.List as L-import Data.Maybe----- Wrappers ---------------------------------------------------------------------- | Type check an expression. ------ If it's good, you get a new version with types attached to all the bound--- variables, as well its the type, effect and closure. ------ If it's bad, you get a description of the error.------ The returned expression has types attached to all variable occurrences, --- so you can call `typeOfExp` on any open subterm.-checkExp - :: (Ord n, Pretty n)- => DataDefs n -- ^ Data type definitions.- -> Env n -- ^ Kind environment.- -> Env n -- ^ Type environment.- -> Exp a n -- ^ Expression to check.- -> Either (Error a n)- ( Exp a n- , Type n- , Effect n- , Closure n)--checkExp defs kenv tenv xx - = result- $ do (xx', t, effs, clos) <- checkExpM defs kenv tenv xx- return ( xx'- , t- , TSum effs- , closureOfTaggedSet clos)----- | Like `checkExp`, but check in an empty environment,--- and only return the value type of an expression.------ As this function is not given an environment, the types of free variables--- must be attached directly to the bound occurrences.--- This attachment is performed by `checkExp` above.----typeOfExp - :: (Ord n, Pretty n)- => DataDefs n- -> Exp a n- -> Either (Error a n) (Type n)-typeOfExp defs xx - = case checkExp defs Env.empty Env.empty xx of- Left err -> Left err- Right (_, t, _, _) -> Right t----- checkExp ---------------------------------------------------------------------- | Like `checkExp` but using the `CheckM` monad to handle errors.-checkExpM - :: (Ord n, Pretty n)- => DataDefs n -- ^ Data type definitions.- -> Env n -- ^ Kind environment.- -> Env n -- ^ Type environment.- -> Exp a n -- ^ Expression to check.- -> CheckM a n - ( Exp a n- , Type n- , TypeSum n- , Set (TaggedClosure n))--checkExpM defs kenv tenv xx- = checkExpM' defs kenv tenv xx-{-} = do (xx', t, eff, clo) <- checkExpM' defs kenv tenv xx- trace (pretty $ vcat - [ text "checkExpM: " <+> ppr xx - , text " :: " <+> ppr t - , text " :!: " <+> ppr eff- , text " :$: " <+> ppr clo- , text ""])- $ return (xx', t, eff, clo)--}---- variables -------------------------------------checkExpM' _defs _kenv tenv (XVar a u)- = do let tBound = typeOfBound u- let mtEnv = Env.lookup u tenv-- let mkResult- -- When annotation on the bound is bot,- -- then use the type from the environment.- | Just tEnv <- mtEnv- , isBot tBound- = return tEnv-- -- The bound has an explicit type annotation,- -- which matches the one from the environment.- -- - -- When the bound is a deBruijn index we need to lift the- -- annotation on the original binder through any lambdas- -- between the binding occurrence and the use.- | Just tEnv <- mtEnv- , UIx i _ <- u- , equivT tBound (liftT (i + 1) tEnv) - = return tBound-- -- The bound has an explicit type annotation,- -- which matches the one from the environment.- | Just tEnv <- mtEnv- , equivT tBound tEnv- = return tEnv-- -- The bound has an explicit type annotation,- -- which does not match the one from the environment.- -- This shouldn't happen because the parser doesn't add non-bot- -- annotations to bound variables.- | Just tEnv <- mtEnv- = throw $ ErrorVarAnnotMismatch u tEnv-- -- Variable not in environment, so use annotation.- -- This happens when checking open terms.- | otherwise- = return tBound- - tResult <- mkResult-- return ( XVar a u - , tResult- , Sum.empty kEffect- , Set.singleton - $ taggedClosureOfValBound - $ replaceTypeOfBound tResult u)----- constructors ----------------------------------checkExpM' defs _kenv _tenv xx@(XCon a u)- | UName n _ <- u- = case Map.lookup n (dataDefsCtors defs) of- Nothing -> throw $ ErrorUndefinedCtor xx- Just _ - -> return - ( XCon a u- , typeOfBound u- , Sum.empty kEffect- , Set.empty)-- | UPrim{} <- u- = return ( XCon a u- , typeOfBound u- , Sum.empty kEffect- , Set.empty)-- -- Constructors can't be locally bound.- | otherwise- = throw $ ErrorMalformedExp xx----- application --------------------------------------- value-type application.-checkExpM' defs kenv tenv xx@(XApp a x1 (XType t2))- = do (x1', t1, effs1, clos1) <- checkExpM defs kenv tenv x1- k2 <- checkTypeM defs kenv t2- case t1 of- TForall b11 t12- | typeOfBind b11 == k2- -> return ( XApp a x1' (XType t2) - , substituteT b11 t2 t12- , substituteT b11 t2 effs1- , clos1 `Set.union` taggedClosureOfTyArg t2)-- | otherwise -> throw $ ErrorAppMismatch xx (typeOfBind b11) t2- _ -> throw $ ErrorAppNotFun xx t1 t2----- value-witness application.-checkExpM' defs kenv tenv xx@(XApp a x1 (XWitness w2))- = do (x1', t1, effs1, clos1) <- checkExpM defs kenv tenv x1- t2 <- checkWitnessM defs kenv tenv w2- case t1 of- TApp (TApp (TCon (TyConWitness TwConImpl)) t11) t12- | t11 `equivT` t2 - -> return ( XApp a x1' (XWitness w2)- , t12- , effs1- , clos1)-- | otherwise -> throw $ ErrorAppMismatch xx t11 t2- _ -> throw $ ErrorAppNotFun xx t1 t2- ---- value-value application.-checkExpM' defs kenv tenv xx@(XApp a x1 x2)- = do (x1', t1, effs1, clos1) <- checkExpM defs kenv tenv x1- (x2', t2, effs2, clos2) <- checkExpM defs kenv tenv x2-- -- Note: we don't need to use the closure of the function because- -- all of its components will already be part of clos1 above.- case t1 of- TApp (TApp (TApp (TApp (TCon (TyConSpec TcConFun)) t11) eff) _clo) t12- | t11 `equivT` t2 - , effs <- Sum.fromList kEffect [eff]- -> return ( XApp a x1' x2'- , t12- , effs1 `Sum.union` effs2 `Sum.union` effs- , clos1 `Set.union` clos2)-- | otherwise -> throw $ ErrorAppMismatch xx t11 t2- _ -> throw $ ErrorAppNotFun xx t1 t2----- spec abstraction ------------------------------checkExpM' defs kenv tenv xx@(XLAM a b1 x2)- = do let t1 = typeOfBind b1- _ <- checkTypeM defs kenv t1-- -- Check the body- let kenv' = Env.extend b1 kenv- let tenv' = Env.lift 1 tenv- (x2', t2, e2, c2) <- checkExpM defs kenv' tenv' x2- k2 <- checkTypeM defs kenv' t2-- when (Env.memberBind b1 kenv)- $ throw $ ErrorLamShadow xx b1-- -- The body of a spec abstraction must be pure.- when (e2 /= Sum.empty kEffect)- $ throw $ ErrorLamNotPure xx (TSum e2)-- -- The body of a spec abstraction must have data kind.- when (not $ isDataKind k2)- $ throw $ ErrorLamBodyNotData xx b1 t2 k2-- -- Mask closure terms due to locally bound region vars.- let c2_cut = Set.fromList- $ mapMaybe (cutTaggedClosureT b1)- $ Set.toList c2-- return ( XLAM a b1 x2'- , TForall b1 t2- , Sum.empty kEffect- , c2_cut)- ---- function abstractions -------------------------checkExpM' defs kenv tenv xx@(XLam a b1 x2)- = do let t1 = typeOfBind b1- k1 <- checkTypeM defs kenv t1-- -- Check the body.- let tenv' = Env.extend b1 tenv- (x2', t2, e2, c2) <- checkExpM defs kenv tenv' x2 - k2 <- checkTypeM defs kenv t2-- -- The form of the function constructor depends on what universe the - -- binder is in.- case universeFromType2 k1 of- Just UniverseData- | not $ isDataKind k1 -> throw $ ErrorLamBindNotData xx t1 k1- | not $ isDataKind k2 -> throw $ ErrorLamBodyNotData xx b1 t2 k2 - | otherwise- -> let - -- Cut closure terms due to locally bound value vars.- -- This also lowers deBruijn indices in un-cut closure terms.- c2_cut = Set.fromList- $ mapMaybe (cutTaggedClosureX b1)- $ Set.toList c2-- -- Trim the closure before we annotate the returned function- -- type with it. - -- This should always succeed because trimClosure only returns- -- Nothing if the closure is miskinded, and we've already- -- allready checked that.- Just c2_captured- = trimClosure $ closureOfTaggedSet c2_cut-- in return ( XLam a b1 x2'- , tFun t1 (TSum e2) c2_captured t2- , Sum.empty kEffect- , c2_cut) -- Just UniverseWitness- | e2 /= Sum.empty kEffect -> throw $ ErrorLamNotPure xx (TSum e2)- | not $ isDataKind k2 -> throw $ ErrorLamBodyNotData xx b1 t2 k2- | otherwise - -> return ( XLam a b1 x2'- , tImpl t1 t2- , Sum.empty kEffect- , c2)-- _ -> throw $ ErrorMalformedType xx k1----- let ---------------------------------------------checkExpM' defs kenv tenv xx@(XLet a (LLet mode b11 x12) x2)- = do -- Check the right of the binding.- (x12', t12, effs12, clo12) - <- checkExpM defs kenv tenv x12-- -- Check binder annotation against the type we inferred for the right.- (b11', k11') - <- checkLetBindOfTypeM xx defs kenv tenv t12 b11-- -- The right of the binding should have data kind.- when (not $ isDataKind k11')- $ throw $ ErrorLetBindingNotData xx b11' k11'- - -- Check the body expression.- let tenv1 = Env.extend b11' tenv- (x2', t2, effs2, c2) <- checkExpM defs kenv tenv1 x2-- -- The body should have data kind.- k2 <- checkTypeM defs kenv t2- when (not $ isDataKind k2)- $ throw $ ErrorLetBodyNotData xx t2 k2-- -- Mask closure terms due to locally bound value vars.- let c2_cut = Set.fromList- $ mapMaybe (cutTaggedClosureX b11')- $ Set.toList c2-- -- Check purity and emptiness for lazy bindings.- (case mode of- LetStrict -> return ()- LetLazy _- -> do let eff12' = TSum effs12- when (not $ isBot eff12')- $ throw $ ErrorLetLazyNotPure xx b11 eff12'-- let clo12' = closureOfTaggedSet clo12- when (not $ isBot clo12')- $ throw $ ErrorLetLazyNotEmpty xx b11 clo12')-- -- Check region witness for lazy bindings.- (case mode of- LetStrict -> return ()-- -- Type of lazy binding has no head region, like Unit and (->).- LetLazy Nothing- -> do case takeDataTyConApps t12 of- Just (_tc, t1 : _)- -> do k1 <- checkTypeM defs kenv t1- when (isRegionKind k1)- $ throw $ ErrorLetLazyNoWitness xx b11 t12-- _ -> return ()-- -- Type of lazy binding might have a head region,- -- so we need a Lazy witness for it.- LetLazy (Just wit)- -> do tWit <- checkWitnessM defs kenv tenv wit- let tWitExp = case takeDataTyConApps t12 of- Just (_tc, tR : _ts) -> tLazy tR- _ -> tHeadLazy t12-- when (not $ equivT tWit tWitExp)- $ throw $ ErrorLetLazyWitnessTypeMismatch - xx b11 tWit t12 tWitExp)- -- return ( XLet a (LLet mode b11' x12') x2'- , t2- , effs12 `Sum.union` effs2- , clo12 `Set.union` c2_cut)----- letrec ------------------------------------------checkExpM' defs kenv tenv xx@(XLet a (LRec bxs) xBody)- = do - let (bs, xs) = unzip bxs-- -- Check all the annotations.- ks <- mapM (checkTypeM defs kenv) - $ map typeOfBind bs-- -- Check all the annots have data kind.- zipWithM_ (\b k- -> when (not $ isDataKind k)- $ throw $ ErrorLetBindingNotData xx b k)- bs ks-- -- All right hand sides need to be lambdas.- forM_ xs $ \x - -> when (not $ (isXLam x || isXLAM x))- $ throw $ ErrorLetrecBindingNotLambda xx x-- -- All variables are in scope in all right hand sides.- let tenv' = Env.extends bs tenv-- -- Check the right hand sides.- (xsRight', tsRight, _effssBinds, clossBinds) - <- liftM unzip4 $ mapM (checkExpM defs kenv tenv') xs-- -- Check annots on binders against inferred types of the bindings.- zipWithM_ (\b t- -> if not $ equivT (typeOfBind b) t- then throw $ ErrorLetMismatch xx b t- else return ())- bs tsRight-- -- Check the body expression.- (xBody', tBody, effsBody, closBody) - <- checkExpM defs kenv tenv' xBody-- -- The body type must have data kind.- kBody <- checkTypeM defs kenv tBody- when (not $ isDataKind kBody)- $ throw $ ErrorLetBodyNotData xx tBody kBody-- -- Cut closure terms due to locally bound value vars.- -- This also lowers deBruijn indices in un-cut closure terms.- let clos_cut - = Set.fromList- $ mapMaybe (cutTaggedClosureXs bs)- $ Set.toList - $ Set.unions (closBody : clossBinds)-- return ( XLet a (LRec (zip bs xsRight')) xBody'- , tBody- , effsBody- , clos_cut)----- letregion ---------------------------------------checkExpM' defs kenv tenv xx@(XLet a (LLetRegion b bs) x)- = case takeSubstBoundOfBind b of- Nothing -> checkExpM defs kenv tenv x- Just u- -> do- -- Check the type on the region binder.- let k = typeOfBind b- checkTypeM defs kenv k-- -- The binder must have region kind.- when (not $ isRegionKind k)- $ throw $ ErrorLetRegionNotRegion xx b k-- -- We can't shadow region binders because we might have witnesses- -- in the environment that conflict with the ones created here.- when (Env.memberBind b kenv)- $ throw $ ErrorLetRegionRebound xx b- - -- Check the witness types.- let kenv' = Env.extend b kenv- let tenv' = Env.lift 1 tenv- mapM_ (checkTypeM defs kenv') $ map typeOfBind bs-- -- Check that the witnesses bound here are for the region,- -- and they don't conflict with each other.- checkWitnessBindsM xx u bs-- -- Check the body expression.- let tenv2 = Env.extends bs tenv'- (xBody', tBody, effs, clo) <- checkExpM defs kenv' tenv2 x-- -- The body type must have data kind.- kBody <- checkTypeM defs kenv' tBody- when (not $ isDataKind kBody)- $ throw $ ErrorLetBodyNotData xx tBody kBody-- -- The bound region variable cannot be free in the body type.- let fvsT = freeT Env.empty tBody- when (Set.member u fvsT)- $ throw $ ErrorLetRegionFree xx b tBody- - -- Delete effects on the bound region from the result.- let effs' = Sum.delete (tRead (TVar u))- $ Sum.delete (tWrite (TVar u))- $ Sum.delete (tAlloc (TVar u))- $ effs-- -- Delete the bound region variable from the closure.- -- Mask closure terms due to locally bound region vars.- let c2_cut = Set.fromList- $ mapMaybe (cutTaggedClosureT b)- $ Set.toList clo-- return ( XLet a (LLetRegion b bs) xBody'- , lowerT 1 tBody- , lowerT 1 effs'- , c2_cut)----- withregion ------------------------------------checkExpM' defs kenv tenv xx@(XLet a (LWithRegion u) x)- = do -- Check the type on the region handle.- let k = typeOfBound u- checkTypeM defs kenv k-- -- The handle must have region kind.- when (not $ isRegionKind k)- $ throw $ ErrorWithRegionNotRegion xx u k- - -- Check the body expression.- (xBody', tBody, effs, clo) - <- checkExpM defs kenv tenv x-- -- The body type must have data kind.- kBody <- checkTypeM defs kenv tBody- when (not $ isDataKind kBody)- $ throw $ ErrorLetBodyNotData xx tBody kBody- - -- Delete effects on the bound region from the result.- let tu = TCon $ TyConBound u- let effs' = Sum.delete (tRead tu)- $ Sum.delete (tWrite tu)- $ Sum.delete (tAlloc tu)- $ effs- - -- Delete the bound region handle from the closure.- let clo_masked = Set.delete (GBoundRgnCon u) clo-- return ( XLet a (LWithRegion u) xBody'- , tBody- , effs'- , clo_masked)- ---- case expression -------------------------------checkExpM' defs kenv tenv xx@(XCase a xDiscrim alts)- = do- -- Check the discriminant.- (xDiscrim', tDiscrim, effsDiscrim, closDiscrim) - <- checkExpM defs kenv tenv xDiscrim-- -- Split the type into the type constructor names and type parameters.- -- Also check that it's algebraic data, and not a function or effect- -- type etc. - (nTyCon, tsArgs)- <- case takeTyConApps tDiscrim of- Just (tc, ts)- | TyConBound (UName n t) <- tc- , takeResultKind t == kData- -> return (n, ts)- - | TyConBound (UPrim n t) <- tc- , takeResultKind t == kData- -> return (n, ts)-- _ -> throw $ ErrorCaseDiscrimNotAlgebraic xx tDiscrim-- -- Get the mode of the data type, - -- this tells us how many constructors there are.- mode - <- case lookupModeOfDataType nTyCon defs of- Nothing -> throw $ ErrorCaseDiscrimTypeUndeclared xx tDiscrim- Just m -> return m-- -- Check the alternatives.- (alts', ts, effss, closs) - <- liftM unzip4- $ mapM (checkAltM xx defs kenv tenv tDiscrim tsArgs) alts-- -- There must be at least one alternative- when (null ts)- $ throw $ ErrorCaseNoAlternatives xx-- -- All alternative result types must be identical.- let (tAlt : _) = ts- forM_ ts $ \tAlt' - -> when (not $ equivT tAlt tAlt') - $ throw $ ErrorCaseAltResultMismatch xx tAlt tAlt'-- -- Check for overlapping alternatives.- let pats = [p | AAlt p _ <- alts]- let psDefaults = filter isPDefault pats- let nsCtorsMatched = mapMaybe takeCtorNameOfAlt alts-- -- Alts overlapping because there are multiple defaults.- when (length psDefaults > 1)- $ throw $ ErrorCaseOverlapping xx-- -- Alts overlapping because the same ctor is used multiple times.- when (length (nub nsCtorsMatched) /= length nsCtorsMatched )- $ throw $ ErrorCaseOverlapping xx-- -- Check for alts overlapping because a default is not last.- -- Also check there is at least one alternative.- (case pats of- [] -> throw $ ErrorCaseNoAlternatives xx-- _ | or $ map isPDefault $ init pats - -> throw $ ErrorCaseOverlapping xx-- | otherwise- -> return ())-- -- Check the alternatives are exhaustive.- (case mode of-- -- Small types have some finite number of constructors.- DataModeSmall nsCtors- -- If there is a default alternative then we've covered all the- -- possibiliies. We know this we've also checked for overlap.- | any isPDefault [p | AAlt p _ <- alts]- -> return ()-- -- Look for unmatched constructors.- | nsCtorsMissing <- nsCtors \\ nsCtorsMatched- , not $ null nsCtorsMissing- -> throw $ ErrorCaseNonExhaustive xx nsCtorsMissing-- -- All constructors were matched.- | otherwise - -> return ()-- -- Large types have an effectively infinite number of constructors- -- (like integer literals), so there needs to be a default alt.- DataModeLarge - | any isPDefault [p | AAlt p _ <- alts] -> return ()- | otherwise - -> throw $ ErrorCaseNonExhaustiveLarge xx)-- let effsMatch - = Sum.singleton kEffect - $ crushEffect $ tHeadRead tDiscrim-- return ( XCase a xDiscrim' alts'- , tAlt- , Sum.unions kEffect (effsDiscrim : effsMatch : effss)- , Set.unions (closDiscrim : closs) )----- type cast ---------------------------------------- Weaken an effect, adding in the given terms.-checkExpM' defs kenv tenv xx@(XCast a c@(CastWeakenEffect eff) x1)- = do - -- Check the effect term.- kEff <- checkTypeM defs kenv eff- when (not $ isEffectKind kEff)- $ throw $ ErrorMaxeffNotEff xx eff kEff-- -- Check the body.- (x1', t1, effs, clo) <- checkExpM defs kenv tenv x1-- return ( XCast a c x1'- , t1- , Sum.insert eff effs- , clo)----- Weaken a closure, adding in the given terms.-checkExpM' defs kenv tenv xx@(XCast a c@(CastWeakenClosure clo2) x1)- = do - -- Check the closure term.- kClo <- checkTypeM defs kenv clo2- when (not $ isClosureKind kClo)- $ throw $ ErrorMaxcloNotClo xx clo2 kClo-- -- The closure supplied to weakclo can only contain Use terms- -- of region variables.- clos2- <- case taggedClosureOfWeakClo clo2 of- Nothing -> throw $ ErrorMaxcloMalformed xx clo2- Just clos2' -> return clos2'-- -- Check the body.- (x1', t1, effs, clos) <- checkExpM defs kenv tenv x1-- return ( XCast a c x1'- , t1- , effs- , Set.union clos clos2)----- Purify an effect, given a witness that it is pure.-checkExpM' defs kenv tenv xx@(XCast a c@(CastPurify w) x1)- = do tW <- checkWitnessM defs kenv tenv w- (x1', t1, effs, clo) <- checkExpM defs kenv tenv x1- - effs' <- case tW of- TApp (TCon (TyConWitness TwConPure)) effMask- -> return $ Sum.delete effMask effs- _ -> throw $ ErrorWitnessNotPurity xx w tW-- return ( XCast a c x1'- , t1- , effs'- , clo)----- Forget a closure, given a witness that it is empty.-checkExpM' defs kenv tenv xx@(XCast a c@(CastForget w) x1)- = do tW <- checkWitnessM defs kenv tenv w- (x1', t1, effs, clos) <- checkExpM defs kenv tenv x1-- clos' <- case tW of- TApp (TCon (TyConWitness TwConEmpty)) cloMask- -> return $ maskFromTaggedSet - (Sum.singleton kClosure cloMask)- clos-- _ -> throw $ ErrorWitnessNotEmpty xx w tW-- return ( XCast a c x1'- , t1- , effs- , clos')----- Type and witness expressions can only appear as the arguments --- to applications.-checkExpM' _defs _kenv _tenv xx@(XType _)- = throw $ ErrorNakedType xx --checkExpM' _defs _kenv _tenv xx@(XWitness _)- = throw $ ErrorNakedWitness xx------------------------------------------------------------------------------------- | Check a case alternative.-checkAltM - :: (Pretty n, Ord n) - => Exp a n -- ^ Whole case expression, for error messages.- -> DataDefs n -- ^ Data type definitions.- -> Env n -- ^ Kind environment.- -> Env n -- ^ Type environment.- -> Type n -- ^ Type of discriminant.- -> [Type n] -- ^ Args to type constructor of discriminant.- -> Alt a n -- ^ Alternative to check.- -> CheckM a n - ( Alt a n- , Type n- , TypeSum n- , Set (TaggedClosure n))--checkAltM _xx defs kenv tenv _tDiscrim _tsArgs (AAlt PDefault xBody)- = do (xBody', tBody, effBody, cloBody)- <- checkExpM defs kenv tenv xBody-- return ( AAlt PDefault xBody'- , tBody- , effBody- , cloBody)--checkAltM xx defs kenv tenv tDiscrim tsArgs (AAlt (PData uCon bsArg) xBody)- = do - -- Take the type of the constructor and instantiate it with the - -- type arguments we got from the discriminant. - -- If the ctor type doesn't instantiate then it won't have enough foralls - -- on the front, which should have been checked by the def checker.- let tCtor = typeOfBound uCon- tCtor_inst - <- case instantiateTs tCtor tsArgs of- Nothing -> throw $ ErrorCaseCannotInstantiate xx tDiscrim tCtor- Just t -> return t- - -- Split the constructor type into the field and result types.- let (tsFields_ctor, tResult) - = takeTFunArgResult tCtor_inst-- -- The result type of the constructor must match the discriminant type.- -- If it doesn't then the constructor in the pattern probably isn't for- -- the discriminant type.- when (not $ equivT tDiscrim tResult)- $ throw $ ErrorCaseDiscrimTypeMismatch xx tDiscrim tResult-- -- There must be at least as many fields as variables in the pattern.- -- It's ok to bind less fields than provided by the constructor.- when (length tsFields_ctor < length bsArg)- $ throw $ ErrorCaseTooManyBinders xx uCon - (length tsFields_ctor)- (length bsArg)-- -- Merge the field types we get by instantiating the constructor- -- type with possible annotations from the source program.- -- If the annotations don't match, then we throw an error.- tsFields <- zipWithM (mergeAnnot xx)- (map typeOfBind bsArg)- tsFields_ctor -- -- Extend the environment with the field types.- let bsArg' = zipWith replaceTypeOfBind tsFields bsArg- let tenv' = Env.extends bsArg' tenv- - -- Check the body in this new environment.- (xBody', tBody, effsBody, closBody)- <- checkExpM defs kenv tenv' xBody-- -- Cut closure terms due to locally bound value vars.- -- This also lowers deBruijn indices in un-cut closure terms.- let closBody_cut - = Set.fromList- $ mapMaybe (cutTaggedClosureXs bsArg')- $ Set.toList closBody-- return ( AAlt (PData uCon bsArg') xBody'- , tBody- , effsBody- , closBody_cut)----- | Merge a type annotation on a pattern field with a type we get by--- instantiating the constructor type.-mergeAnnot :: Eq n => Exp a n -> Type n -> Type n -> CheckM a n (Type n)-mergeAnnot xx tAnnot tActual- -- Annotation is bottom, so just use the real type.- | isBot tAnnot = return tActual-- -- Annotation matches actual type, all good.- | tAnnot == tActual = return tActual-- -- Annotation does not match actual type.- | otherwise - = throw $ ErrorCaseFieldTypeMismatch xx tAnnot tActual------------------------------------------------------------------------------------- | Check the set of witness bindings bound in a letregion for conflicts.-checkWitnessBindsM :: Ord n => Exp a n -> Bound n -> [Bind n] -> CheckM a n ()-checkWitnessBindsM xx nRegion bsWits- = mapM_ (checkWitnessBindM xx nRegion bsWits) bsWits---checkWitnessBindM - :: Ord n - => Exp a n- -> Bound n -- ^ Region variable bound in the letregion.- -> [Bind n] -- ^ Other witness bindings in the same set.- -> Bind n -- ^ The witness binding to check.- -> CheckM a n ()--checkWitnessBindM xx uRegion bsWit bWit- = let btsWit - = [(typeOfBind b, b) | b <- bsWit]-- -- Check the argument of a witness type is for the region we're- -- introducing here.- checkWitnessArg t- = case t of- TVar u'- | uRegion /= u' -> throw $ ErrorLetRegionWitnessOther xx uRegion bWit- | otherwise -> return ()-- TCon (TyConBound u')- | uRegion /= u' -> throw $ ErrorLetRegionWitnessOther xx uRegion bWit- | otherwise -> return ()-- -- The parser should ensure the right of a witness is a - -- constructor or variable.- _ -> throw $ ErrorLetRegionWitnessInvalid xx bWit-- in case typeOfBind bWit of- TApp (TCon (TyConWitness TwConGlobal)) t2- -> checkWitnessArg t2-- TApp (TCon (TyConWitness TwConConst)) t2- | Just bConflict <- L.lookup (tMutable t2) btsWit- -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict- | otherwise -> checkWitnessArg t2-- TApp (TCon (TyConWitness TwConMutable)) t2- | Just bConflict <- L.lookup (tConst t2) btsWit- -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict- | otherwise -> checkWitnessArg t2-- TApp (TCon (TyConWitness TwConLazy)) t2- | Just bConflict <- L.lookup (tManifest t2) btsWit- -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict- | otherwise -> checkWitnessArg t2-- TApp (TCon (TyConWitness TwConManifest)) t2- | Just bConflict <- L.lookup (tLazy t2) btsWit- -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict- | otherwise -> checkWitnessArg t2-- _ -> throw $ ErrorLetRegionWitnessInvalid xx bWit------------------------------------------------------------------------------------- | Check a type in the exp checking monad.-checkTypeM :: (Ord n, Pretty n) - => DataDefs n - -> Env n - -> Type n - -> CheckM a n (Kind n)--checkTypeM defs kenv tt- = case T.checkType defs kenv tt of- Left err -> throw $ ErrorType err- Right k -> return k------------------------------------------------------------------------------------- | Check the type annotation of a let bound variable against the type--- inferred for the right of the binding.--- If the annotation is Bot then we just replace the annotation,--- otherwise it must match that for the right of the binding.-checkLetBindOfTypeM - :: (Eq n, Ord n, Pretty n) - => Exp a n - -> DataDefs n -- Data type definitions.- -> Env n -- Kind environment. - -> Env n -- Type environment.- -> Type n - -> Bind n - -> CheckM a n (Bind n, Kind n)--checkLetBindOfTypeM xx defs kenv _tenv tRight b- -- If the annotation is Bot then just replace it.- | isBot (typeOfBind b)- = do k <- checkTypeM defs kenv tRight- return ( replaceTypeOfBind tRight b - , k)-- -- The type of the binder must match that of the right of the binding.- | not $ equivT (typeOfBind b) tRight- = throw $ ErrorLetMismatch xx b tRight-- | otherwise- = do k <- checkTypeM defs kenv (typeOfBind b)- return (b, k)-+-- | Type checker for the Disciple Core language.+module DDC.Core.Check.CheckExp+ ( Config (..)+ , AnTEC (..)+ , checkExp+ , typeOfExp+ , CheckM+ , checkExpM+ , TaggedClosure(..))+where+import DDC.Core.Predicates+import DDC.Core.Compounds+import DDC.Core.Collect+import DDC.Core.Pretty+import DDC.Core.Exp+import DDC.Core.Check.Error+import DDC.Core.Check.CheckDaCon+import DDC.Core.Check.CheckWitness+import DDC.Core.Check.TaggedClosure+import DDC.Type.Transform.SubstituteT+import DDC.Type.Transform.Crush+import DDC.Type.Transform.Trim+import DDC.Type.Transform.Instantiate+import DDC.Type.Transform.LiftT+import DDC.Type.DataDef+import DDC.Type.Equiv+import DDC.Type.Universe+import DDC.Type.Sum as Sum+import DDC.Type.Env (Env, KindEnv, TypeEnv)+import DDC.Control.Monad.Check (throw, result)+import Data.Set (Set)+import qualified DDC.Type.Env as Env+import qualified Data.Set as Set+import Control.Monad+import DDC.Data.ListUtils+import Data.List as L+import Data.Maybe+import Data.Typeable+import Control.DeepSeq+++-- Annot ----------------------------------------------------------------------+-- | The type checker adds this annotation to every node in the AST, +-- giving its type, effect and closure.+---+-- NOTE: We wwant to leave the components lazy so that the checker+-- doesn't actualy need to produce the type components if they're+-- not needed.+data AnTEC a n+ = AnTEC+ { annotType :: (Type n)+ , annotEffect :: (Effect n)+ , annotClosure :: (Closure n)+ , annotTail :: a }+ deriving (Show, Typeable)+++instance (NFData a, NFData n) => NFData (AnTEC a n) where+ rnf !an+ = rnf (annotType an)+ `seq` rnf (annotEffect an)+ `seq` rnf (annotClosure an)+ `seq` rnf (annotTail an)+++instance Pretty (AnTEC a n) where+ ppr _ = text "AnTEC" ++++-- Wrappers -------------------------------------------------------------------+-- | Type check an expression. +--+-- If it's good, you get a new version with types attached to all the bound+-- variables, as well its the type, effect and closure. +--+-- If it's bad, you get a description of the error.+--+-- The returned expression has types attached to all variable occurrences, +-- so you can call `typeOfExp` on any open subterm.+--+-- The kinds and types of primitives are added to the environments +-- automatically, you don't need to supply these as part of the +-- starting environments.+--+checkExp + :: (Ord n, Show n, Pretty n)+ => Config n -- ^ Static configuration.+ -> KindEnv n -- ^ Starting Kind environment.+ -> TypeEnv n -- ^ Strating Type environment.+ -> Exp a n -- ^ Expression to check.+ -> Either (Error a n)+ ( Exp (AnTEC a n) n+ , Type n+ , Effect n+ , Closure n)++checkExp !config !kenv !tenv !xx + = result+ $ do (xx', t, effs, clos) + <- checkExpM config + (Env.union kenv (configPrimKinds config))+ (Env.union tenv (configPrimTypes config))+ xx+ return ( xx'+ , t+ , TSum effs+ , closureOfTaggedSet clos)+++-- | Like `checkExp`, but only return the value type of an expression.+typeOfExp + :: (Ord n, Pretty n, Show n)+ => Config n -- ^ Static configuration.+ -> KindEnv n -- ^ Starting Kind environment+ -> TypeEnv n -- ^ Starting Type environment.+ -> Exp a n -- ^ Expression to check.+ -> Either (Error a n) (Type n)+typeOfExp !config !kenv !tenv !xx + = case checkExp config kenv tenv xx of+ Left err -> Left err+ Right (_, t, _, _) -> Right t+++-- checkExp -------------------------------------------------------------------+-- | Like `checkExp` but using the `CheckM` monad to handle errors.+checkExpM + :: (Show n, Pretty n, Ord n)+ => Config n -- ^ Static config.+ -> Env n -- ^ Kind environment.+ -> Env n -- ^ Type environment.+ -> Exp a n -- ^ Expression to check.+ -> CheckM a n + ( Exp (AnTEC a n) n+ , Type n+ , TypeSum n+ , Set (TaggedClosure n))++checkExpM !config !kenv !tenv !xx+ = {-# SCC checkExpM #-}+ checkExpM' config kenv tenv xx++-- variables ------------------------------------+checkExpM' !_config !_kenv !tenv (XVar a u)+ = case Env.lookup u tenv of+ Nothing -> throw $ ErrorUndefinedVar u UniverseData+ Just t + -> returnX a + (\z -> XVar z u)+ t+ (Sum.empty kEffect)+ (Set.singleton $ taggedClosureOfValBound t u)+++-- constructors ---------------------------------+checkExpM' !config !_kenv !_tenv xx@(XCon a dc)+ = do + -- All data constructors need to have valid type annotations.+ when (isBot $ daConType dc)+ $ throw $ ErrorUndefinedCtor xx++ -- Check that the constructor is in the data type declarations.+ checkDaConM config xx dc++ -- Type of the data constructor.+ let tResult + = typeOfDaCon dc++ returnX a+ (\z -> XCon z dc)+ tResult+ (Sum.empty kEffect)+ Set.empty+++-- application ------------------------------------+-- value-type application.+--+-- Note: We don't need to substitute into the effect of x1 (effs1)+-- because the body of a type abstraction is required to be pure.+-- +-- We don't need to substitute into the closure either, because+-- the bound type variable is not visible outside the abstraction.+-- thus we can't be sharing objects that have it in its type.+--+checkExpM' !config !kenv !tenv xx@(XApp a x1 (XType t2))+ = do (x1', t1, effs1, clos1) <- checkExpM config kenv tenv x1++ -- Check the type argument.+ k2 <- checkTypeM config kenv t2++ -- Take any Use annots from a region arg.+ -- This always matches because we just checked 't2'+ let Just t2_clo = taggedClosureOfTyArg kenv t2++ case t1 of+ TForall b11 t12+ | typeOfBind b11 == k2+ -> returnX a+ (\z -> XApp z x1' (XType t2))+ (substituteT b11 t2 t12)+ effs1 + (clos1 `Set.union` t2_clo)++ | otherwise -> throw $ ErrorAppMismatch xx (typeOfBind b11) t2+ _ -> throw $ ErrorAppNotFun xx t1 t2+++-- value-witness application.+checkExpM' !config !kenv !tenv xx@(XApp a x1 (XWitness w2))+ = do (x1', t1, effs1, clos1) <- checkExpM config kenv tenv x1+ t2 <- checkWitnessM config kenv tenv w2+ case t1 of+ TApp (TApp (TCon (TyConWitness TwConImpl)) t11) t12+ | t11 `equivT` t2 + -> returnX a+ (\z -> XApp z x1' (XWitness w2))+ t12 effs1 clos1++ | otherwise -> throw $ ErrorAppMismatch xx t11 t2+ _ -> throw $ ErrorAppNotFun xx t1 t2+ ++-- value-value application.+checkExpM' !config !kenv !tenv xx@(XApp a x1 x2)+ = do (x1', t1, effs1, clos1) <- checkExpM config kenv tenv x1+ (x2', t2, effs2, clos2) <- checkExpM config kenv tenv x2++ -- Note: we don't need to use the closure of the function because+ -- all of its components will already be part of clos1 above.+ case t1 of+ TApp (TApp (TApp (TApp (TCon (TyConSpec TcConFun)) t11) eff) _clo) t12+ | t11 `equivT` t2 + , effs <- Sum.fromList kEffect [eff]+ -> returnX a+ (\z -> XApp z x1' x2')+ t12+ (effs1 `Sum.union` effs2 `Sum.union` effs)+ (clos1 `Set.union` clos2)++ | otherwise -> throw $ ErrorAppMismatch xx t11 t2+ _ -> throw $ ErrorAppNotFun xx t1 t2+++-- spec abstraction -----------------------------+checkExpM' !config !kenv !tenv xx@(XLAM a b1 x2)+ = do let t1 = typeOfBind b1+ _ <- checkTypeM config kenv t1++ -- Check the body+ let kenv' = Env.extend b1 kenv+ let tenv' = Env.lift 1 tenv+ (x2', t2, e2, c2) <- checkExpM config kenv' tenv' x2+ k2 <- checkTypeM config kenv' t2++ when (Env.memberBind b1 kenv)+ $ throw $ ErrorLamShadow xx b1++ -- The body of a spec abstraction must be pure.+ when (e2 /= Sum.empty kEffect)+ $ throw $ ErrorLamNotPure xx True (TSum e2)++ -- The body of a spec abstraction must have data kind.+ when (not $ isDataKind k2)+ $ throw $ ErrorLamBodyNotData xx b1 t2 k2++ -- Mask closure terms due to locally bound region vars.+ let c2_cut = Set.fromList+ $ mapMaybe (cutTaggedClosureT b1)+ $ Set.toList c2++ returnX a+ (\z -> XLAM z b1 x2')+ (TForall b1 t2)+ (Sum.empty kEffect)+ c2_cut+ ++-- function abstraction -------------------------+checkExpM' !config !kenv !tenv xx@(XLam a b1 x2)+ = do + -- Check the type of the binder.+ let t1 = typeOfBind b1+ k1 <- checkTypeM config kenv t1++ -- Check the body.+ let tenv' = Env.extend b1 tenv+ (x2', t2, e2, c2) <- checkExpM config kenv tenv' x2 ++ -- The typing rules guarantee that the checked type of an + -- expression is well kinded, but we need to check it again+ -- to find out what that kind is.+ k2 <- checkTypeM config kenv t2++ -- The form of the function constructor depends on what universe the + -- binder is in.+ case universeFromType2 k1 of++ -- This is a data abstraction.+ Just UniverseData++ -- The body of a data abstraction must accept data.+ | not $ isDataKind k1+ -> throw $ ErrorLamBindNotData xx t1 k1++ -- The body of a data abstraction must produce data.+ | not $ isDataKind k2+ -> throw $ ErrorLamBodyNotData xx b1 t2 k2 ++ -- Looks good.+ | otherwise+ -> let + -- Cut closure terms due to locally bound value vars.+ -- This also lowers deBruijn indices in un-cut closure terms.+ c2_cut = Set.fromList+ $ mapMaybe (cutTaggedClosureX b1)+ $ Set.toList c2++ -- Trim the closure before we annotate the returned function+ -- type with it. This should always succeed because trimClosure+ -- only returns Nothing if the closure is miskinded, and we've+ -- already already checked that.+ Just c2_captured++ -- If we're suppressing closures then just drop them on the+ -- floor. The consumer of this core program doesn't care.+ | configSuppressClosures config+ = Just $ tBot kClosure++ | otherwise+ = trimClosure $ closureOfTaggedSet c2_cut++ in returnX a+ (\z -> XLam z b1 x2')+ (tFun t1 (TSum e2) c2_captured t2)+ (Sum.empty kEffect)+ c2_cut++ -- This is a witness abstraction.+ Just UniverseWitness++ -- The body of a witness abstraction must be pure.+ | e2 /= Sum.empty kEffect + -> throw $ ErrorLamNotPure xx False (TSum e2)++ -- The body of a witness abstraction must produce data.+ | not $ isDataKind k2 + -> throw $ ErrorLamBodyNotData xx b1 t2 k2++ -- Looks good.+ | otherwise + -> returnX a+ (\z -> XLam z b1 x2')+ (tImpl t1 t2)+ (Sum.empty kEffect)+ c2++ _ -> throw $ ErrorMalformedType xx k1+++-- let --------------------------------------------+checkExpM' !config !kenv !tenv xx@(XLet a lts x2)+ | case lts of+ LLet{} -> True+ LRec{} -> True+ _ -> False++ = do+ -- Check the bindings+ (lts', bs', effs12, clo12)+ <- checkLetsM xx config kenv tenv lts++ -- Check the body expression.+ let tenv1 = Env.extends bs' tenv+ (x2', t2, effs2, c2) <- checkExpM config kenv tenv1 x2++ -- The body should have data kind.+ k2 <- checkTypeM config kenv t2+ when (not $ isDataKind k2)+ $ throw $ ErrorLetBodyNotData xx t2 k2++ -- Mask closure terms due to locally bound value vars.+ let c2_cut = Set.fromList+ $ mapMaybe (cutTaggedClosureXs bs')+ $ Set.toList c2++ returnX a+ (\z -> XLet z lts' x2')+ t2+ (effs12 `Sum.union` effs2)+ (clo12 `Set.union` c2_cut)+++-- letregion --------------------------------------+checkExpM' !config !kenv !tenv xx@(XLet a (LLetRegions bsRgn bsWit) x)+ = case takeSubstBoundsOfBinds bsRgn of+ [] -> checkExpM config kenv tenv x + us -> do+ -- + let depth = length $ map isBAnon bsRgn++ -- Check the type on the region binders.+ let ks = map typeOfBind bsRgn+ mapM_ (checkTypeM config kenv) ks++ -- The binders must have region kind.+ when (any (not . isRegionKind) ks) + $ throw $ ErrorLetRegionsNotRegion xx bsRgn ks++ -- We can't shadow region binders because we might have witnesses+ -- in the environment that conflict with the ones created here.+ let rebounds = filter (flip Env.memberBind kenv) bsRgn+ when (not $ null rebounds)+ $ throw $ ErrorLetRegionsRebound xx rebounds+ + -- Check the witness types.+ let kenv' = Env.extends bsRgn kenv+ let tenv' = Env.lift depth tenv+ mapM_ (checkTypeM config kenv') $ map typeOfBind bsWit++ -- Check that the witnesses bound here are for the region,+ -- and they don't conflict with each other.+ checkWitnessBindsM kenv xx us bsWit++ -- Check the body expression.+ let tenv2 = Env.extends bsWit tenv'+ (xBody', tBody, effs, clo) <- checkExpM config kenv' tenv2 x++ -- The body type must have data kind.+ kBody <- checkTypeM config kenv' tBody+ when (not $ isDataKind kBody)+ $ throw $ ErrorLetBodyNotData xx tBody kBody++ -- The bound region variable cannot be free in the body type.+ let fvsT = freeT Env.empty tBody+ when (any (flip Set.member fvsT) us)+ $ throw $ ErrorLetRegionFree xx bsRgn tBody+ + -- Delete effects on the bound region from the result.+ let delEff es u = Sum.delete (tRead (TVar u))+ $ Sum.delete (tWrite (TVar u))+ $ Sum.delete (tAlloc (TVar u))+ $ es+ let effs' = foldl delEff effs us ++ -- Delete the bound region variable from the closure.+ -- Mask closure terms due to locally bound region vars.+ let cutClo c r = mapMaybe (cutTaggedClosureT r) c+ let c2_cut = Set.fromList + $ foldl cutClo (Set.toList clo) bsRgn++ returnX a+ (\z -> XLet z (LLetRegions bsRgn bsWit) xBody')+ (lowerT depth tBody)+ (lowerT depth effs')+ c2_cut+++-- withregion -----------------------------------+checkExpM' !config !kenv !tenv xx@(XLet a (LWithRegion u) x)+ = do+ -- The handle must have region kind.+ (case Env.lookup u kenv of+ Nothing -> throw $ ErrorUndefinedVar u UniverseSpec++ Just k | not $ isRegionKind k+ -> throw $ ErrorWithRegionNotRegion xx u k++ _ -> return ())+ + -- Check the body expression.+ (xBody', tBody, effs, clo) + <- checkExpM config kenv tenv x++ -- The body type must have data kind.+ kBody <- checkTypeM config kenv tBody+ when (not $ isDataKind kBody)+ $ throw $ ErrorLetBodyNotData xx tBody kBody+ + -- The bound region variable cannot be free in the body type.+ let tcs = supportTyCon+ $ support Env.empty Env.empty tBody+ when (Set.member u tcs)+ $ throw $ ErrorWithRegionFree xx u tBody++ -- Delete effects on the bound region from the result.+ let tu = TCon $ TyConBound u kRegion+ let effs' = Sum.delete (tRead tu)+ $ Sum.delete (tWrite tu)+ $ Sum.delete (tAlloc tu)+ $ effs+ + -- Delete the bound region handle from the closure.+ let clo_masked = Set.delete (GBoundRgnCon u) clo++ returnX a+ (\z -> XLet z (LWithRegion u) xBody')+ tBody+ effs'+ clo_masked+ ++-- case expression ------------------------------+checkExpM' !config !kenv !tenv xx@(XCase a xDiscrim alts)+ = do + -- Check the discriminant.+ (xDiscrim', tDiscrim, effsDiscrim, closDiscrim) + <- checkExpM config kenv tenv xDiscrim++ -- Split the type into the type constructor names and type parameters.+ -- Also check that it's algebraic data, and not a function or effect+ -- type etc. + (mmode, tsArgs)+ <- case takeTyConApps tDiscrim of+ Just (tc, ts)+ | TyConSpec TcConUnit <- tc+ -> return ( Just (DataModeSmall [])+ , [] )+ -- ISSUE #269: Refactor DataModeSmall to hold DaCons instead of names.+ -- The DataModeSmall should hold DaCons instead of+ -- names, as we don't have a name for Unit.++ | TyConBound (UName nTyCon) k <- tc+ , takeResultKind k == kData+ -> return ( lookupModeOfDataType nTyCon (configPrimDataDefs config)+ , ts )+ + | TyConBound (UPrim nTyCon _) k <- tc+ , takeResultKind k == kData+ -> return ( lookupModeOfDataType nTyCon (configPrimDataDefs config)+ , ts )++ _ -> throw $ ErrorCaseScrutineeNotAlgebraic xx tDiscrim++ -- Get the mode of the data type, + -- this tells us how many constructors there are.+ mode + <- case mmode of+ Nothing -> throw $ ErrorCaseScrutineeTypeUndeclared xx tDiscrim+ Just m -> return m++ -- Check the alternatives.+ (alts', ts, effss, closs) + <- liftM unzip4+ $ mapM (checkAltM xx config kenv tenv tDiscrim tsArgs) alts++ -- There must be at least one alternative+ when (null ts)+ $ throw $ ErrorCaseNoAlternatives xx++ -- All alternative result types must be identical.+ let (tAlt : _) = ts+ forM_ ts $ \tAlt' + -> when (not $ equivT tAlt tAlt') + $ throw $ ErrorCaseAltResultMismatch xx tAlt tAlt'++ -- Check for overlapping alternatives.+ let pats = [p | AAlt p _ <- alts]+ let psDefaults = filter isPDefault pats+ let nsCtorsMatched = mapMaybe takeCtorNameOfAlt alts++ -- Alts overlapping because there are multiple defaults.+ when (length psDefaults > 1)+ $ throw $ ErrorCaseOverlapping xx++ -- Alts overlapping because the same ctor is used multiple times.+ when (length (nub nsCtorsMatched) /= length nsCtorsMatched )+ $ throw $ ErrorCaseOverlapping xx++ -- Check for alts overlapping because a default is not last.+ -- Also check there is at least one alternative.+ (case pats of+ [] -> throw $ ErrorCaseNoAlternatives xx++ _ | Just patsInit <- takeInit pats+ , or $ map isPDefault $ patsInit+ -> throw $ ErrorCaseOverlapping xx++ | otherwise+ -> return ())++ -- Check the alternatives are exhaustive.+ (case mode of++ -- Small types have some finite number of constructors.+ DataModeSmall nsCtors+ -- If there is a default alternative then we've covered all the+ -- possibiliies. We know this we've also checked for overlap.+ | any isPDefault [p | AAlt p _ <- alts]+ -> return ()++ -- Look for unmatched constructors.+ | nsCtorsMissing <- nsCtors \\ nsCtorsMatched+ , not $ null nsCtorsMissing+ -> throw $ ErrorCaseNonExhaustive xx nsCtorsMissing++ -- All constructors were matched.+ | otherwise + -> return ()++ -- Large types have an effectively infinite number of constructors+ -- (like integer literals), so there needs to be a default alt.+ DataModeLarge + | any isPDefault [p | AAlt p _ <- alts] -> return ()+ | otherwise + -> throw $ ErrorCaseNonExhaustiveLarge xx)++ let effsMatch + = Sum.singleton kEffect + $ crushEffect $ tHeadRead tDiscrim++ returnX a+ (\z -> XCase z xDiscrim' alts')+ tAlt+ (Sum.unions kEffect (effsDiscrim : effsMatch : effss))+ (Set.unions (closDiscrim : closs))+++-- type cast -------------------------------------+-- Weaken an effect, adding in the given terms.+checkExpM' !config !kenv !tenv xx@(XCast a (CastWeakenEffect eff) x1)+ = do+ -- Check the effect term.+ kEff <- checkTypeM config kenv eff+ when (not $ isEffectKind kEff)+ $ throw $ ErrorWeakEffNotEff xx eff kEff++ -- Check the body.+ (x1', t1, effs, clo) <- checkExpM config kenv tenv x1+ let c' = CastWeakenEffect eff++ returnX a+ (\z -> XCast z c' x1')+ t1+ (Sum.insert eff effs)+ clo+++-- Weaken a closure, adding in the given terms.+checkExpM' !config !kenv !tenv (XCast a (CastWeakenClosure xs) x1)+ = do+ -- Check the contained expressions.+ (xs', closs)+ <- liftM unzip+ $ mapM (checkArgM config kenv tenv) xs++ -- Check the body.+ (x1', t1, effs, clos) <- checkExpM config kenv tenv x1+ let c' = CastWeakenClosure xs'++ returnX a+ (\z -> XCast z c' x1')+ t1+ effs+ (Set.unions (clos : closs))+++-- Purify an effect, given a witness that it is pure.+checkExpM' !config !kenv !tenv xx@(XCast a (CastPurify w) x1)+ = do+ tW <- checkWitnessM config kenv tenv w+ (x1', t1, effs, clo) <- checkExpM config kenv tenv x1+ + effs' <- case tW of+ TApp (TCon (TyConWitness TwConPure)) effMask+ -> return $ Sum.delete effMask effs+ _ -> throw $ ErrorWitnessNotPurity xx w tW++ let c' = CastPurify w++ returnX a+ (\z -> XCast z c' x1')+ t1 effs' clo+++-- Forget a closure, given a witness that it is empty.+checkExpM' !config !kenv !tenv xx@(XCast a (CastForget w) x1)+ = do + tW <- checkWitnessM config kenv tenv w+ (x1', t1, effs, clos) <- checkExpM config kenv tenv x1++ clos' <- case tW of+ TApp (TCon (TyConWitness TwConEmpty)) cloMask+ -> return $ maskFromTaggedSet + (Sum.singleton kClosure cloMask)+ clos++ _ -> throw $ ErrorWitnessNotEmpty xx w tW++ let c' = CastForget w++ returnX a+ (\z -> XCast z c' x1')+ t1 effs clos'+++-- Type and witness expressions can only appear as the arguments +-- to applications.+checkExpM' !_config !_kenv !_tenv xx@(XType _)+ = throw $ ErrorNakedType xx ++checkExpM' !_config !_kenv !_tenv xx@(XWitness _)+ = throw $ ErrorNakedWitness xx++checkExpM' _ _ _ _+ = error "checkExpM: bogus warning killer"+++-- | Like `checkExp` but we allow naked types and witnesses.+checkArgM + :: (Show n, Pretty n, Ord n)+ => Config n -- ^ Static config.+ -> Env n -- ^ Kind environment.+ -> Env n -- ^ Type environment.+ -> Exp a n -- ^ Expression to check.+ -> CheckM a n + ( Exp (AnTEC a n) n+ , Set (TaggedClosure n))++checkArgM !config !kenv !tenv !xx+ = case xx of+ XType t+ -> do checkTypeM config kenv t+ let Just clo = taggedClosureOfTyArg kenv t++ return ( XType t+ , clo)++ XWitness w+ -> do checkWitnessM config kenv tenv w+ return ( XWitness w+ , Set.empty)++ _ -> do+ (xx', _, _, clos) <- checkExpM config kenv tenv xx+ return ( xx'+ , clos)+++-- | Helper function for building the return value of checkExpM'+-- It builts the AnTEC annotation and attaches it to the new AST node,+-- as well as returning the current effect and closure in the appropriate+-- form as part of the tuple.+returnX :: Ord n + => a+ -> (AnTEC a n -> Exp (AnTEC a n) n)+ -> Type n + -> TypeSum n+ -> Set (TaggedClosure n)+ -> CheckM a n + ( Exp (AnTEC a n) n+ , Type n+ , TypeSum n+ , Set (TaggedClosure n))++returnX !a !f !t !es !cs+ = let e = TSum es+ c = closureOfTaggedSet cs+ in return (f (AnTEC t e c a)+ , t, es, cs)+{-# INLINE returnX #-}++-------------------------------------------------------------------------------+-- | Check some let bindings.+checkLetsM + :: (Show n, Pretty n, Ord n)+ => Exp a n -- ^ Enclosing expression, for error messages.+ -> Config n -- ^ Static config.+ -> Env n -- ^ Kind environment.+ -> Env n -- ^ Type environment.+ -> Lets a n+ -> CheckM a n+ ( Lets (AnTEC a n) n+ , [Bind n]+ , TypeSum n+ , Set (TaggedClosure n))++checkLetsM !xx !config !kenv !tenv (LLet mode b11 x12)+ = do + -- Check the right of the binding.+ (x12', t12, effs12, clo12) + <- checkExpM config kenv tenv x12++ -- Check binder annotation against the type we inferred for the right.+ (b11', k11') + <- checkLetBindOfTypeM xx config kenv tenv t12 b11++ -- The right of the binding should have data kind.+ when (not $ isDataKind k11')+ $ throw $ ErrorLetBindingNotData xx b11' k11'+ + -- Check purity and emptiness for lazy bindings.+ (case mode of+ LetStrict -> return ()+ LetLazy _+ -> do let eff12' = TSum effs12+ when (not $ isBot eff12')+ $ throw $ ErrorLetLazyNotPure xx b11 eff12'++ let clo12' = closureOfTaggedSet clo12+ when (not $ isBot clo12')+ $ throw $ ErrorLetLazyNotEmpty xx b11 clo12')++ -- Check region witness for lazy bindings.+ (case mode of+ LetStrict -> return ()++ -- Type of lazy binding has no head region, like Unit and (->).+ LetLazy Nothing+ -> do case takeDataTyConApps t12 of+ Just (_tc, t1 : _)+ -> do k1 <- checkTypeM config kenv t1+ when (isRegionKind k1)+ $ throw $ ErrorLetLazyNoWitness xx b11 t12++ _ -> return ()++ -- Type of lazy binding might have a head region,+ -- so we need a Lazy witness for it.+ LetLazy (Just wit)+ -> do tWit <- checkWitnessM config kenv tenv wit+ let tWitExp = case takeDataTyConApps t12 of+ Just (_tc, tR : _ts) -> tLazy tR+ _ -> tHeadLazy t12++ when (not $ equivT tWit tWitExp)+ $ throw $ ErrorLetLazyWitnessTypeMismatch + xx b11 tWit t12 tWitExp)+ + return ( LLet mode b11' x12'+ , [b11']+ , effs12+ , clo12)++-- letrec ---------------------------------------+checkLetsM !xx !config !kenv !tenv (LRec bxs)+ = do + let (bs, xs) = unzip bxs++ -- No named binders can be multiply defined.+ (case duplicates $ filter isBName bs of+ [] -> return ()+ b : _ -> throw $ ErrorLetrecRebound xx b)++ -- Check the types on all the binders.+ ks <- mapM (checkTypeM config kenv) + $ map typeOfBind bs++ -- Check all the binders have data kind.+ zipWithM_ (\b k+ -> when (not $ isDataKind k)+ $ throw $ ErrorLetBindingNotData xx b k)+ bs ks++ -- All right hand sides need to be lambdas.+ forM_ xs $ \x + -> when (not $ (isXLam x || isXLAM x))+ $ throw $ ErrorLetrecBindingNotLambda xx x++ -- All variables are in scope in all right hand sides.+ let tenv' = Env.extends bs tenv++ -- Check the right hand sides.+ (xsRight', tsRight, _effssBinds, clossBinds) + <- liftM unzip4 $ mapM (checkExpM config kenv tenv') xs++ -- Check annots on binders against inferred types of the bindings.+ zipWithM_ (\b t+ -> if not $ equivT (typeOfBind b) t+ then throw $ ErrorLetMismatch xx b t+ else return ())+ bs tsRight++ -- Cut closure terms due to locally bound value vars.+ let clos_cut + = Set.fromList+ $ mapMaybe (cutTaggedClosureXs bs)+ $ Set.toList + $ Set.unions clossBinds++ return ( LRec (zip bs xsRight')+ , zipWith replaceTypeOfBind tsRight bs+ , Sum.empty kEffect+ , clos_cut)++checkLetsM _xx _config _kenv _tenv _lts+ = error "checkLetsM: case should have been handled in checkExpM"+++-- | Take elements of a list that have more than once occurrence.+duplicates :: Eq a => [a] -> [a]+duplicates [] = []+duplicates (x : xs)+ | L.elem x xs = x : duplicates (filter (/= x) xs)+ | otherwise = duplicates xs+++-------------------------------------------------------------------------------+-- | Check a case alternative.+checkAltM + :: (Show n, Pretty n, Ord n) + => Exp a n -- ^ Whole case expression, for error messages.+ -> Config n -- ^ Data type definitions.+ -> Env n -- ^ Kind environment.+ -> Env n -- ^ Type environment.+ -> Type n -- ^ Type of discriminant.+ -> [Type n] -- ^ Args to type constructor of discriminant.+ -> Alt a n -- ^ Alternative to check.+ -> CheckM a n + ( Alt (AnTEC a n) n+ , Type n+ , TypeSum n+ , Set (TaggedClosure n))++checkAltM !_xx !config !kenv !tenv !_tDiscrim !_tsArgs (AAlt PDefault xBody)+ = do (xBody', tBody, effBody, cloBody)+ <- checkExpM config kenv tenv xBody++ return ( AAlt PDefault xBody'+ , tBody+ , effBody+ , cloBody)++checkAltM !xx !config !kenv !tenv !tDiscrim !tsArgs (AAlt (PData dc bsArg) xBody)+ = do + let Just aCase = takeAnnotOfExp xx++ -- If the data constructor isn't defined then the spread + -- transform won't have given it a proper type.+ -- Note that we can't simply check whether the constructor is in the+ -- environment because literals like 42# never are.+ (if isBot (daConType dc)+ then throw $ ErrorUndefinedCtor $ XCon aCase dc+ else return ())++ -- Take the type of the constructor and instantiate it with the + -- type arguments we got from the discriminant. + -- If the ctor type doesn't instantiate then it won't have enough foralls + -- on the front, which should have been checked by the def checker.+ let tCtor = daConType dc++ tCtor_inst + <- case instantiateTs tCtor tsArgs of+ Nothing -> throw $ ErrorCaseCannotInstantiate xx tDiscrim tCtor+ Just t -> return t+ + -- Split the constructor type into the field and result types.+ let (tsFields_ctor, tResult) + = takeTFunArgResult tCtor_inst++ -- The result type of the constructor must match the discriminant type.+ -- If it doesn't then the constructor in the pattern probably isn't for+ -- the discriminant type.+ when (not $ equivT tDiscrim tResult)+ $ throw $ ErrorCaseScrutineeTypeMismatch xx tDiscrim tResult++ -- There must be at least as many fields as variables in the pattern.+ -- It's ok to bind less fields than provided by the constructor.+ when (length tsFields_ctor < length bsArg)+ $ throw $ ErrorCaseTooManyBinders xx dc+ (length tsFields_ctor)+ (length bsArg)++ -- Merge the field types we get by instantiating the constructor+ -- type with possible annotations from the source program.+ -- If the annotations don't match, then we throw an error.+ tsFields <- zipWithM (mergeAnnot xx)+ (map typeOfBind bsArg)+ tsFields_ctor ++ -- Extend the environment with the field types.+ let bsArg' = zipWith replaceTypeOfBind tsFields bsArg+ let tenv' = Env.extends bsArg' tenv+ + -- Check the body in this new environment.+ (xBody', tBody, effsBody, closBody)+ <- checkExpM config kenv tenv' xBody++ -- Cut closure terms due to locally bound value vars.+ -- This also lowers deBruijn indices in un-cut closure terms.+ let closBody_cut + = Set.fromList+ $ mapMaybe (cutTaggedClosureXs bsArg')+ $ Set.toList closBody++ return ( AAlt (PData dc bsArg') xBody'+ , tBody+ , effsBody+ , closBody_cut)+++-- | Merge a type annotation on a pattern field with a type we get by+-- instantiating the constructor type.+mergeAnnot :: Eq n => Exp a n -> Type n -> Type n -> CheckM a n (Type n)+mergeAnnot !xx !tAnnot !tActual+ -- Annotation is bottom, so just use the real type.+ | isBot tAnnot = return tActual++ -- Annotation matches actual type, all good.+ | tAnnot == tActual = return tActual++ -- Annotation does not match actual type.+ | otherwise + = throw $ ErrorCaseFieldTypeMismatch xx tAnnot tActual+++-------------------------------------------------------------------------------+-- | Check the set of witness bindings bound in a letregion for conflicts.+checkWitnessBindsM + :: (Show n, Ord n) + => KindEnv n + -> Exp a n + -> [Bound n] + -> [Bind n] + -> CheckM a n ()++checkWitnessBindsM !kenv !xx !nRegions !bsWits+ = mapM_ (checkWitnessBindM kenv xx nRegions bsWits) bsWits+++checkWitnessBindM + :: (Show n, Ord n)+ => Env n+ -> Exp a n+ -> [Bound n] -- ^ Region variables bound in the letregion.+ -> [Bind n] -- ^ Other witness bindings in the same set.+ -> Bind n -- ^ The witness binding to check.+ -> CheckM a n ()++checkWitnessBindM !kenv !xx !uRegions !bsWit !bWit+ = let btsWit + = [(typeOfBind b, b) | b <- bsWit]++ -- Check the argument of a witness type is for the region we're+ -- introducing here.+ checkWitnessArg t+ = case t of+ TVar u'+ | all (/= u') uRegions -> throw $ ErrorLetRegionsWitnessOther xx uRegions bWit+ | otherwise -> return ()++ TCon (TyConBound u' _)+ | all (/= u') uRegions -> throw $ ErrorLetRegionsWitnessOther xx uRegions bWit+ | otherwise -> return ()+ + -- The parser should ensure the right of a witness is a + -- constructor or variable.+ _ -> throw $ ErrorLetRegionWitnessInvalid xx bWit+ + inEnv t+ = case t of+ TVar u' | Env.member u' kenv -> True+ TCon (TyConBound u' _) | Env.member u' kenv -> True+ _ -> False + + in case typeOfBind bWit of+ TApp (TCon (TyConWitness TwConGlobal)) t2+ -> checkWitnessArg t2++ TApp (TCon (TyConWitness TwConConst)) t2+ | Just bConflict <- L.lookup (tMutable t2) btsWit+ -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict+ | otherwise -> checkWitnessArg t2++ TApp (TCon (TyConWitness TwConMutable)) t2+ | Just bConflict <- L.lookup (tConst t2) btsWit+ -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict+ | otherwise -> checkWitnessArg t2++ TApp (TCon (TyConWitness TwConLazy)) t2+ | Just bConflict <- L.lookup (tManifest t2) btsWit+ -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict+ | otherwise -> checkWitnessArg t2++ TApp (TCon (TyConWitness TwConManifest)) t2+ | Just bConflict <- L.lookup (tLazy t2) btsWit+ -> throw $ ErrorLetRegionWitnessConflict xx bWit bConflict+ | otherwise -> checkWitnessArg t2+ + (takeTyConApps -> Just (TyConWitness (TwConDistinct 2), [t1, t2]))+ | inEnv t1 -> checkWitnessArg t2+ | inEnv t2 -> checkWitnessArg t1+ | t1 /= t2 -> mapM_ checkWitnessArg [t1, t2]+ | otherwise -> throw $ ErrorLetRegionWitnessInvalid xx bWit++ (takeTyConApps -> Just (TyConWitness (TwConDistinct _), ts))+ -> mapM_ checkWitnessArg ts++ _ -> throw $ ErrorLetRegionWitnessInvalid xx bWit+++-------------------------------------------------------------------------------+-- | Check the type annotation of a let bound variable against the type+-- inferred for the right of the binding.+-- If the annotation is Bot then we just replace the annotation,+-- otherwise it must match that for the right of the binding.+checkLetBindOfTypeM + :: (Ord n, Show n, Pretty n) + => Exp a n + -> Config n -- Data type definitions.+ -> Env n -- Kind environment. + -> Env n -- Type environment.+ -> Type n + -> Bind n + -> CheckM a n (Bind n, Kind n)++checkLetBindOfTypeM !xx !config !kenv !_tenv !tRight b+ -- If the annotation is Bot then just replace it.+ | isBot (typeOfBind b)+ = do k <- checkTypeM config kenv tRight+ return ( replaceTypeOfBind tRight b + , k)++ -- The type of the binder must match that of the right of the binding.+ | not $ equivT (typeOfBind b) tRight+ = throw $ ErrorLetMismatch xx b tRight++ | otherwise+ = do k <- checkTypeM config kenv (typeOfBind b)+ return (b, k)
+ DDC/Core/Check/CheckModule.hs view
@@ -0,0 +1,159 @@++module DDC.Core.Check.CheckModule+ ( checkModule+ , checkModuleM)+where+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Check.CheckExp+import DDC.Core.Check.Error+import DDC.Type.Compounds+import DDC.Base.Pretty+import DDC.Type.Equiv+import DDC.Type.Env (KindEnv, TypeEnv)+import DDC.Control.Monad.Check (result, throw)+import Data.Map (Map)+import qualified DDC.Type.Check as T+import qualified DDC.Type.Env as Env+import qualified Data.Map as Map+++-- Wrappers -------------------------------------------------------------------+-- | Type check a module.+--+-- If it's good, you get a new version with types attached to all the bound+-- variables+--+-- If it's bad, you get a description of the error.+checkModule+ :: (Ord n, Show n, Pretty n)+ => Config n -- ^ Static configuration.+ -> Module a n -- ^ Module to check.+ -> Either (Error a n) (Module (AnTEC a n) n)++checkModule !config !xx + = result + $ checkModuleM + config + (configPrimKinds config)+ (configPrimTypes config)+ xx+++-- checkModule ----------------------------------------------------------------+-- | Like `checkModule` but using the `CheckM` monad to handle errors.+checkModuleM + :: (Ord n, Show n, Pretty n)+ => Config n -- ^ Static configuration.+ -> KindEnv n -- ^ Starting kind environment.+ -> TypeEnv n -- ^ Starting type environment.+ -> Module a n -- ^ Module to check.+ -> CheckM a n (Module (AnTEC a n) n)++checkModuleM !config !kenv !tenv mm@ModuleCore{}+ = do + -- Convert the imported kind and type map to a list of binds.+ let bksImport = [BName n k | (n, (_, k)) <- Map.toList $ moduleImportKinds mm]+ let btsImport = [BName n t | (n, (_, t)) <- Map.toList $ moduleImportTypes mm]++ -- Check the imported kinds and types.+ -- The imported types are in scope in both imported and exported signatures.+ mapM_ (checkTypeM config kenv) $ map typeOfBind bksImport+ let kenv' = Env.union kenv $ Env.fromList bksImport++ mapM_ (checkTypeM config kenv') $ map typeOfBind btsImport+ let tenv' = Env.union tenv $ Env.fromList btsImport++ -- Check the sigs for exported things.+ mapM_ (checkTypeM config kenv') $ Map.elems $ moduleExportKinds mm+ mapM_ (checkTypeM config kenv') $ Map.elems $ moduleExportTypes mm+ + -- Check our let bindings.+ (x', _, _effs, _) <- checkExpM config kenv' tenv' (moduleBody mm)++ -- Check that each exported signature matches the type of its binding.+ envDef <- checkModuleBinds (moduleExportKinds mm) (moduleExportTypes mm) x'++ -- Check that all exported bindings are defined by the module.+ mapM_ (checkBindDefined envDef) $ Map.keys $ moduleExportTypes mm++ -- Return the checked bindings as they have explicit type annotations.+ let mm' = mm { moduleBody = x' }+ return mm'+++-- | Check that the exported signatures match the types of their bindings.+checkModuleBinds + :: Ord n+ => Map n (Kind n) -- ^ Kinds of exported types.+ -> Map n (Type n) -- ^ Types of exported values.+ -> Exp (AnTEC a n) n+ -> CheckM a n (TypeEnv n) -- ^ Environment of top-level bindings+ -- defined by the module++checkModuleBinds !ksExports !tsExports !xx+ = case xx of+ XLet _ (LLet _ b _) x2 + -> do checkModuleBind ksExports tsExports b+ env <- checkModuleBinds ksExports tsExports x2+ return $ Env.extend b env++ XLet _ (LRec bxs) x2+ -> do mapM_ (checkModuleBind ksExports tsExports) $ map fst bxs+ env <- checkModuleBinds ksExports tsExports x2+ return $ Env.extends (map fst bxs) env++ XLet _ (LLetRegions _ _) x2+ -> checkModuleBinds ksExports tsExports x2++ _ -> return Env.empty+++-- | If some bind is exported, then check that it matches the exported version.+checkModuleBind + :: Ord n+ => Map n (Kind n) -- ^ Kinds of exported types.+ -> Map n (Type n) -- ^ Types of exported values.+ -> Bind n+ -> CheckM a n ()++checkModuleBind !_ksExports !tsExports !b+ | BName n tDef <- b+ = case Map.lookup n tsExports of+ Nothing -> return ()+ Just tExport + | equivT tDef tExport -> return ()+ | otherwise -> throw $ ErrorExportMismatch n tExport tDef++ -- Only named bindings can be exported, + -- so we don't need to worry about non-named ones.+ | otherwise+ = return ()+++-- | Check that a top-level binding is actually defined by the module.+checkBindDefined + :: Ord n+ => TypeEnv n -- ^ Types defined by the module.+ -> n -- ^ Name of an exported binding.+ -> CheckM a n ()++checkBindDefined env n+ = case Env.lookup (UName n) env of+ Just _ -> return ()+ _ -> throw $ ErrorExportUndefined n+++-------------------------------------------------------------------------------+-- | Check a type in the exp checking monad.+checkTypeM :: (Ord n, Show n, Pretty n) + => Config n + -> KindEnv n + -> Type n + -> CheckM a n (Kind n)++checkTypeM !config !kenv !tt+ = case T.checkType (configPrimDataDefs config) kenv tt of+ Left err -> throw $ ErrorType err+ Right k -> return k+
DDC/Core/Check/CheckWitness.hs view
@@ -1,31 +1,34 @@- -- | Type checker for witness expressions. module DDC.Core.Check.CheckWitness- ( checkWitness+ ( Config(..)+ , configOfProfile++ , checkWitness , typeOfWitness , typeOfWiCon , typeOfWbCon , CheckM- , checkWitnessM)+ , checkWitnessM++ , checkTypeM) where-import DDC.Core.DataDef import DDC.Core.Exp import DDC.Core.Pretty import DDC.Core.Check.Error-import DDC.Core.Check.ErrorMessage ()+import DDC.Core.Check.ErrorMessage ()+import DDC.Type.DataDef import DDC.Type.Transform.SubstituteT import DDC.Type.Compounds-import DDC.Type.Predicates-import DDC.Type.Equiv-import DDC.Type.Transform.LiftT-import DDC.Type.Sum as Sum-import DDC.Type.Env (Env)-import DDC.Type.Check.Monad (result, throw)-import DDC.Base.Pretty ()-import qualified DDC.Type.Env as Env-import qualified DDC.Type.Check as T-import qualified DDC.Type.Check.Monad as G+import DDC.Type.Universe+import DDC.Type.Sum as Sum+import DDC.Type.Env (KindEnv, TypeEnv)+import DDC.Control.Monad.Check (throw, result)+import DDC.Base.Pretty ()+import qualified DDC.Control.Monad.Check as G+import qualified DDC.Type.Env as Env+import qualified DDC.Type.Check as T+import qualified DDC.Core.Fragment as F -- | Type checker monad. @@ -33,6 +36,46 @@ type CheckM a n = G.CheckM (Error a n) +-- Config ---------------------------------------------------------------------+-- | Static configuration for the type checker.+-- These fields don't change as we decend into the tree.+--+-- The starting configuration should be converted from the profile that+-- defines the language fragment you are checking. +-- See "DDC.Core.Fragment" and use `configOfProfile` below.+data Config n+ = Config+ { -- | Data type definitions.+ configPrimDataDefs :: DataDefs n ++ -- | Kinds of primitive types.+ , configPrimKinds :: KindEnv n++ -- | Types of primitive operators.+ , configPrimTypes :: TypeEnv n++ -- | Suppress all closure information, + -- annotating all functions with an empty closure.+ -- + -- This is used when checking the Disciple Core Salt fragment,+ -- as transforms in this language don't use the closure+ -- information.+ , configSuppressClosures :: Bool }+++-- | Convert a langage profile to a type checker configuration.+configOfProfile :: F.Profile n -> Config n+configOfProfile profile+ = Config+ { configPrimDataDefs = F.profilePrimDataDefs profile+ , configPrimKinds = F.profilePrimKinds profile+ , configPrimTypes = F.profilePrimTypes profile++ , configSuppressClosures + = F.featuresUntrackedClosures+ $ F.profileFeatures profile }++ -- Wrappers -------------------------------------------------------------------- -- | Check a witness. -- @@ -44,16 +87,20 @@ -- The returned expression has types attached to all variable occurrences, -- so you can call `typeOfWitness` on any open subterm. --+-- The kinds and types of primitives are added to the environments +-- automatically, you don't need to supply these as part of the +-- starting environments.+-- checkWitness- :: (Ord n, Pretty n)- => DataDefs n -- ^ Data type definitions.- -> Env n -- ^ Kind Environment.- -> Env n -- ^ Type Environment.+ :: (Ord n, Show n, Pretty n)+ => Config n -- ^ Static configuration.+ -> KindEnv n -- ^ Starting Kind Environment.+ -> TypeEnv n -- ^ Strating Type Environment. -> Witness n -- ^ Witness to check. -> Either (Error a n) (Type n) -checkWitness defs kenv tenv xx- = result $ checkWitnessM defs kenv tenv xx+checkWitness config kenv tenv xx+ = result $ checkWitnessM config kenv tenv xx -- | Like `checkWitness`, but check in an empty environment.@@ -63,78 +110,38 @@ -- This attachment is performed by `checkWitness` above. -- typeOfWitness - :: (Ord n, Pretty n) - => DataDefs n+ :: (Ord n, Show n, Pretty n) + => Config n -> Witness n -> Either (Error a n) (Type n) -typeOfWitness defs ww +typeOfWitness config ww = result - $ checkWitnessM defs Env.empty Env.empty ww+ $ checkWitnessM config Env.empty Env.empty ww ------------------------------------------------------------------------------ -- | Like `checkWitness` but using the `CheckM` monad to manage errors. checkWitnessM - :: (Ord n, Pretty n)- => DataDefs n -- ^ Data type definitions.- -> Env n -- ^ Kind environment.- -> Env n -- ^ Type environment.+ :: (Ord n, Show n, Pretty n)+ => Config n -- ^ Data type definitions.+ -> KindEnv n -- ^ Kind environment.+ -> TypeEnv n -- ^ Type environment. -> Witness n -- ^ Witness to check. -> CheckM a n (Type n) -checkWitnessM _defs _kenv tenv (WVar u)- = do let tBound = typeOfBound u- let mtEnv = Env.lookup u tenv-- let mkResult- -- When annotation on the bound is bot,- -- then use the type from the environment.- | Just tEnv <- mtEnv- , isBot tBound- = return tEnv-- -- The bound has an explicit type annotation,- -- which matches the one from the environment.- -- - -- When the bound is a deBruijn index we need to lift the- -- annotation on the original binder through any lambdas- -- between the binding occurrence and the use.- | Just tEnv <- mtEnv- , UIx i _ <- u- , equivT tBound (liftT (i + 1) tEnv) - = return tBound-- -- The bound has an explicit type annotation,- -- which matches the one from the environment.- | Just tEnv <- mtEnv- , equivT tBound tEnv- = return tEnv-- -- The bound has an explicit type annotation,- -- which does not match the one from the environment.- -- This shouldn't happen because the parser doesn't add non-bot- -- annotations to bound variables.- | Just tEnv <- mtEnv- = throw $ ErrorVarAnnotMismatch u tEnv-- -- Variable not in environment, so use annotation.- -- This happens when checking open terms.- | otherwise- = return tBound- - tResult <- mkResult- return tResult-+checkWitnessM !_config !_kenv !tenv (WVar u)+ = case Env.lookup u tenv of+ Nothing -> throw $ ErrorUndefinedVar u UniverseWitness+ Just t -> return t -checkWitnessM _defs _kenv _tenv (WCon wc)+checkWitnessM !_config !_kenv !_tenv (WCon wc) = return $ typeOfWiCon wc- --- value-type application-checkWitnessM defs kenv tenv ww@(WApp w1 (WType t2))- = do t1 <- checkWitnessM defs kenv tenv w1- k2 <- checkTypeM defs kenv t2+-- witness-type application+checkWitnessM !config !kenv !tenv ww@(WApp w1 (WType t2))+ = do t1 <- checkWitnessM config kenv tenv w1+ k2 <- checkTypeM config kenv t2 case t1 of TForall b11 t12 | typeOfBind b11 == k2@@ -144,9 +151,9 @@ _ -> throw $ ErrorWAppNotCtor ww t1 t2 -- witness-witness application-checkWitnessM defs kenv tenv ww@(WApp w1 w2)- = do t1 <- checkWitnessM defs kenv tenv w1- t2 <- checkWitnessM defs kenv tenv w2+checkWitnessM !config !kenv !tenv ww@(WApp w1 w2)+ = do t1 <- checkWitnessM config kenv tenv w1+ t2 <- checkWitnessM config kenv tenv w2 case t1 of TApp (TApp (TCon (TyConWitness TwConImpl)) t11) t12 | t11 == t2 @@ -156,9 +163,9 @@ _ -> throw $ ErrorWAppNotCtor ww t1 t2 -- witness joining-checkWitnessM defs kenv tenv ww@(WJoin w1 w2)- = do t1 <- checkWitnessM defs kenv tenv w1- t2 <- checkWitnessM defs kenv tenv w2+checkWitnessM !config !kenv !tenv ww@(WJoin w1 w2)+ = do t1 <- checkWitnessM config kenv tenv w1+ t2 <- checkWitnessM config kenv tenv w2 case (t1, t2) of ( TApp (TCon (TyConWitness TwConPure)) eff1 , TApp (TCon (TyConWitness TwConPure)) eff2)@@ -173,8 +180,8 @@ _ -> throw $ ErrorCannotJoin ww w1 t1 w2 t2 -- embedded types-checkWitnessM defs kenv _tenv (WType t)- = checkTypeM defs kenv t+checkWitnessM !config !kenv !_tenv (WType t)+ = checkTypeM config kenv t -- | Take the type of a witness constructor.@@ -182,7 +189,7 @@ typeOfWiCon wc = case wc of WiConBuiltin wb -> typeOfWbCon wb- WiConBound u -> typeOfBound u+ WiConBound _ t -> t -- | Take the type of a builtin witness constructor.@@ -199,14 +206,14 @@ -- checkType ------------------------------------------------------------------ -- | Check a type in the exp checking monad. checkTypeM - :: (Ord n, Pretty n) - => DataDefs n - -> Env n + :: (Ord n, Show n, Pretty n) + => Config n + -> KindEnv n -> Type n -> CheckM a n (Kind n) -checkTypeM defs kenv tt- = case T.checkType defs kenv tt of+checkTypeM config kenv tt+ = case T.checkType (configPrimDataDefs config) kenv tt of Left err -> throw $ ErrorType err Right k -> return k
DDC/Core/Check/Error.hs view
@@ -3,47 +3,65 @@ (Error(..)) where import DDC.Core.Exp+import DDC.Type.Universe import qualified DDC.Type.Check as T -- | All the things that can go wrong when type checking an expression -- or witness. data Error a n+ -- Type ------------------------------------------- -- | Found a kind error when checking a type. = ErrorType { errorTypeError :: T.Error n } - -- | Found a malformed expression, - -- and we don't have a more specific diagnosis.- | ErrorMalformedExp- { errorChecking :: Exp a n }- -- | Found a malformed type, -- and we don't have a more specific diagnosis. | ErrorMalformedType { errorChecking :: Exp a n , errorType :: Type n } - -- | Found a naked `XType` that wasn't the argument of an application.- | ErrorNakedType- { errorChecking :: Exp a n } - -- | Found a naked `XWitness` that wasn't the argument of an application.- | ErrorNakedWitness+ -- Module -----------------------------------------+ -- | Exported value is undefined.+ | ErrorExportUndefined+ { errorName :: n }++ -- | Type signature of exported binding does not match the type at+ -- the definition site.+ | ErrorExportMismatch+ { errorName :: n+ , errorExportType :: Type n+ , errorDefType :: Type n }+++ -- Exp --------------------------------------------+ -- | Found a malformed expression, + -- and we don't have a more specific diagnosis.+ | ErrorMalformedExp { errorChecking :: Exp a n } + -- Var --------------------------------------------- -- | A bound occurrence of a variable who's type annotation does not match+ -- | An undefined type variable.+ | ErrorUndefinedVar+ { errorBound :: Bound n + , errorUniverse :: Universe }++ -- | A bound occurrence of a variable whose type annotation does not match -- the corresponding annotation in the environment. | ErrorVarAnnotMismatch { errorBound :: Bound n+ , errorTypeAnnot :: Type n , errorTypeEnv :: Type n } + -- Con -------------------------------------------- -- | A data constructor that wasn't in the set of data definitions. | ErrorUndefinedCtor { errorChecking :: Exp a n } + -- Application ------------------------------------ -- | A function application where the parameter and argument don't match. | ErrorAppMismatch@@ -68,6 +86,7 @@ -- | A type or witness abstraction where the body has a visible side effect. | ErrorLamNotPure { errorChecking :: Exp a n+ , errorSpecOrWit :: Bool , errorEffect :: Effect n } -- | A value function where the parameter does not have data kind.@@ -140,26 +159,32 @@ { errorChecking :: Exp a n , errorExp :: Exp a n } + -- | A recursive let-expression that has more than one binding+ -- with the same name.+ | ErrorLetrecRebound+ { errorChecking :: Exp a n+ , errorBind :: Bind n } + -- Letregion --------------------------------------- -- | A letregion-expression where the bound variable does not have- -- region kind.- | ErrorLetRegionNotRegion+ -- | A letregion-expression where the some of the bound variables do not+ -- have region kind.+ | ErrorLetRegionsNotRegion { errorChecking :: Exp a n- , errorBind :: Bind n- , errorKind :: Kind n }+ , errorBinds :: [Bind n]+ , errorKinds :: [Kind n] } - -- | A letregion-expression that tried to shadow a pre-existing named- -- region variable.- | ErrorLetRegionRebound+ -- | A letregion-expression that tried to shadow some pre-existing named+ -- region variables.+ | ErrorLetRegionsRebound { errorChecking :: Exp a n- , errorBind :: Bind n }+ , errorBinds :: [Bind n] } - -- | A letregion-expression where the bound region variable is free in- -- the type of the body.+ -- | A letregion-expression where some of the the bound region variables+ -- are free in the type of the body. | ErrorLetRegionFree { errorChecking :: Exp a n- , errorBind :: Bind n+ , errorBinds :: [Bind n] , errorType :: Type n } -- | A letregion-expression that tried to create a witness with an @@ -176,18 +201,33 @@ -- | A letregion-expression where a bound witnesses was not for the -- the region variable being introduced.- | ErrorLetRegionWitnessOther+ | ErrorLetRegionsWitnessOther { errorChecking :: Exp a n- , errorBoundRegion :: Bound n+ , errorBoundRegions :: [Bound n] , errorBindWitness :: Bind n } + -- | A letregion-expression where the witness binding references some+ -- free region variable that is not the one being introduced.+ | ErrorLetRegionWitnessFree+ { errorChecking :: Exp a n+ , errorBindWitness :: Bind n }+ ++ -- Withregion ------------------------------------- -- | A withregion-expression where the handle does not have region kind. | ErrorWithRegionNotRegion { errorChecking :: Exp a n , errorBound :: Bound n , errorKind :: Kind n } + -- | A letregion-expression where some of the the bound region variables+ -- are free in the type of the body.+ | ErrorWithRegionFree+ { errorChecking :: Exp a n+ , errorBound :: Bound n+ , errorType :: Type n } + -- Witnesses -------------------------------------- -- | A witness application where the argument type does not match -- the parameter type.@@ -224,16 +264,16 @@ -- Case Expressions -------------------------------- -- | A case-expression where the discriminant type is not algebraic.- | ErrorCaseDiscrimNotAlgebraic+ -- | A case-expression where the scrutinee type is not algebraic.+ | ErrorCaseScrutineeNotAlgebraic { errorChecking :: Exp a n- , errorTypeDiscrim :: Type n }+ , errorTypeScrutinee :: Type n } - -- | A case-expression where the discriminant type is not in our set+ -- | A case-expression where the scrutinee type is not in our set -- of data type declarations.- | ErrorCaseDiscrimTypeUndeclared+ | ErrorCaseScrutineeTypeUndeclared { errorChecking :: Exp a n - , errorTypeDiscrim :: Type n }+ , errorTypeScrutinee :: Type n } -- | A case-expression with no alternatives. | ErrorCaseNoAlternatives@@ -258,22 +298,22 @@ -- | A case-expression where one of the patterns has too many binders. | ErrorCaseTooManyBinders { errorChecking :: Exp a n- , errorCtorBound :: Bound n+ , errorCtorDaCon :: DaCon n , errorCtorFields :: Int , errorPatternFields :: Int } -- | A case-expression where the pattern types could not be instantiated- -- with the arguments of the discriminant type.+ -- with the arguments of the scrutinee type. | ErrorCaseCannotInstantiate { errorChecking :: Exp a n- , errorTypeCtor :: Type n- , errorTypeDiscrim :: Type n }+ , errorTypeScrutinee :: Type n + , errorTypeCtor :: Type n } - -- | A case-expression where the type of the discriminant does not match+ -- | A case-expression where the type of the scrutinee does not match -- the type of the pattern.- | ErrorCaseDiscrimTypeMismatch+ | ErrorCaseScrutineeTypeMismatch { errorChecking :: Exp a n- , errorTypeDiscrim :: Type n+ , errorTypeScrutinee :: Type n , errorTypePattern :: Type n } -- | A case-expression where the annotation on a pattern variable binder@@ -292,22 +332,22 @@ -- Casts ------------------------------------------- -- | A maxeff-cast where the type provided does not have effect kind.- | ErrorMaxeffNotEff+ -- | A weakeff-cast where the type provided does not have effect kind.+ | ErrorWeakEffNotEff { errorChecking :: Exp a n , errorEffect :: Effect n , errorKind :: Kind n } - -- | A maxclo-cast where the type provided does not have closure kind.- | ErrorMaxcloNotClo- { errorChecking :: Exp a n- , errorClosure :: Closure n- , errorKind :: Kind n } - -- | A maxclo-case where the closure provided is malformed. - -- It can only contain `Use` terms.- | ErrorMaxcloMalformed- { errorChecking :: Exp a n - , errorClosure :: Closure n }+ -- Types ------------------------------------------+ -- | Found a naked `XType` that wasn't the argument of an application.+ | ErrorNakedType+ { errorChecking :: Exp a n }+++ -- Witnesses --------------------------------------+ -- | Found a naked `XWitness` that wasn't the argument of an application.+ | ErrorNakedWitness+ { errorChecking :: Exp a n } deriving (Show)
DDC/Core/Check/ErrorMessage.hs view
@@ -1,4 +1,3 @@-{-# OPTIONS_HADDOCK hide #-} -- | Errors produced when checking core expressions. module DDC.Core.Check.ErrorMessage (Error(..))@@ -6,9 +5,11 @@ import DDC.Core.Pretty import DDC.Core.Check.Error import DDC.Type.Compounds+import DDC.Type.Universe -instance (Pretty n, Eq n) => Pretty (Error a n) where+instance (Show n, Eq n, Pretty n) + => Pretty (Error a n) where ppr err = case err of ErrorType err' -> ppr err'@@ -21,22 +22,38 @@ , empty , text "with: " <> align (ppr xx) ] - ErrorNakedType xx- -> vcat [ text "Found naked type in core program."- , empty- , text "with: " <> align (ppr xx) ]+ -- Modules ---------------------------------------+ ErrorExportUndefined n+ -> vcat [ text "Exported value '" <> ppr n <> text "' is undefined." ] - ErrorNakedWitness xx- -> vcat [ text "Found naked witness in core program."- , empty- , text "with: " <> align (ppr xx) ]+ ErrorExportMismatch n tExport tDef+ -> vcat [ text "Type of exported value does not match type of definition."+ , text " with binding: " <> ppr n+ , text " type of export: " <> ppr tExport+ , text " type of definition: " <> ppr tDef ] + -- Variable ---------------------------------------- ErrorVarAnnotMismatch u t+ ErrorUndefinedVar u universe+ -> case universe of+ UniverseSpec+ -> vcat [ text "Undefined spec variable: " <> ppr u ]++ UniverseData+ -> vcat [ text "Undefined value variable: " <> ppr u ]++ UniverseWitness+ -> vcat [ text "Undefined witness variable: " <> ppr u ]++ -- Universes other than the above don't have variables,+ -- but let's not worry about that here.+ _ -> vcat [ text "Undefined variable: " <> ppr u ]++ ErrorVarAnnotMismatch u tEnv tAnnot -> vcat [ text "Type mismatch in annotation." , text " Variable: " <> ppr u- , text " has annotation: " <> (ppr $ typeOfBound u)- , text " which conflicts with: " <> ppr t+ , text " has annotation: " <> ppr tAnnot+ , text " which conflicts with: " <> ppr tEnv , text " from environment." ] @@ -68,11 +85,14 @@ , text " is already in the environment." , text "with: " <> align (ppr xx) ] - ErrorLamNotPure xx eff- -> vcat [ text "Impure type abstraction"- , text " has effect: " <> ppr eff- , empty- , text "with: " <> align (ppr xx) ]+ ErrorLamNotPure xx spec eff+ -> let universe' = if spec then text "spec"+ else text "witness"+ in vcat + [ text "Impure" <+> universe' <+> text "abstraction"+ , text " has effect: " <> ppr eff+ , empty+ , text "with: " <> align (ppr xx) ] ErrorLamBindNotData xx t1 k1@@ -158,29 +178,33 @@ , empty , text "with: " <> align (ppr xx) ] + ErrorLetrecRebound xx b+ -> vcat [ text "Redefined binder '" <> ppr b <> text "' in letrec."+ , empty+ , text "with: " <> align (ppr xx) ] -- Letregion --------------------------------------- ErrorLetRegionNotRegion xx b k- -> vcat [ text "Letregion binder does not have region kind."- , text " Region binder: " <> ppr b- , text " has kind: " <> ppr k- , text " but is must be: %" + ErrorLetRegionsNotRegion xx bs ks+ -> vcat [ text "Letregion binders do not have region kind."+ , text " Region binders: " <> (hcat $ map ppr bs)+ , text " has kinds: " <> (hcat $ map ppr ks)+ , text " but they must all be: %" , empty- , text "with: " <> align (ppr xx) ]+ , text "with: " <> align (ppr xx) ] - ErrorLetRegionRebound xx b- -> vcat [ text "Region variable shadows existing one."- , text " Region variable: " <> ppr b- , text " is already in environment"+ ErrorLetRegionsRebound xx bs+ -> vcat [ text "Region variables shadow existing ones."+ , text " Region variables: " <> (hcat $ map ppr bs)+ , text " are already in environment" , empty- , text "with: " <> align (ppr xx) ]+ , text "with: " <> align (ppr xx) ] - ErrorLetRegionFree xx b t- -> vcat [ text "Region variable escapes scope of letregion."- , text " The region variable: " <> ppr b- , text " is free in the body type: " <> ppr t+ ErrorLetRegionFree xx bs t+ -> vcat [ text "Region variables escape scope of letregion."+ , text " The region variables: " <> (hcat $ map ppr bs)+ , text " is free in the body type: " <> ppr t , empty- , text "with: " <> align (ppr xx) ]+ , text "with: " <> align (ppr xx) ] ErrorLetRegionWitnessInvalid xx b -> vcat [ text "Invalid witness type with letregion."@@ -196,12 +220,27 @@ , empty , text "with: " <> align (ppr xx) ] - ErrorLetRegionWitnessOther xx b1 b2- -> vcat [ text "Witness type is not for bound region."- , text " letregion binds: " <> ppr b1+ ErrorLetRegionsWitnessOther xx bs1 b2+ -> vcat [ text "Witness type is not for bound regions."+ , text " letregion binds: " <> (hsep $ map ppr bs1) , text " but witness type is: " <> ppr b2 , empty , text "with: " <> align (ppr xx) ]+ + ErrorLetRegionWitnessFree xx b+ -> vcat [ text "Witness type references a free region variable."+ , text " the binding: " <> ppr b + , text " contains free region variables."+ , empty+ , text "with: " <> align (ppr xx) ]+ + -- Withregion -------------------------------------+ ErrorWithRegionFree xx u t+ -> vcat [ text "Region handle escapes scope of withregion."+ , text " The region handle: " <> ppr u+ , text " is used in the body type: " <> ppr t+ , empty+ , text "with: " <> align (ppr xx) ] ErrorWithRegionNotRegion xx u k -> vcat [ text "Withregion handle does not have region kind."@@ -251,15 +290,15 @@ -- Case Expressions -------------------------------- ErrorCaseDiscrimNotAlgebraic xx tDiscrim- -> vcat [ text "Discriminant of case expression is not algebraic data."- , text " Discriminant type: " <> ppr tDiscrim+ ErrorCaseScrutineeNotAlgebraic xx tScrutinee+ -> vcat [ text "Scrutinee of case expression is not algebraic data."+ , text " Scrutinee type: " <> ppr tScrutinee , empty , text "with: " <> align (ppr xx) ] - ErrorCaseDiscrimTypeUndeclared xx tDiscrim- -> vcat [ text "Type of discriminant does not have a data declaration."- , text " Discriminant type: " <> ppr tDiscrim+ ErrorCaseScrutineeTypeUndeclared xx tScrutinee+ -> vcat [ text "Type of scrutinee does not have a data declaration."+ , text " Scrutinee type: " <> ppr tScrutinee , empty , text "with: " <> align (ppr xx) ] @@ -295,18 +334,18 @@ , empty , text "with: " <> align (ppr xx) ] - ErrorCaseCannotInstantiate xx tCtor tDiscrim- -> vcat [ text "Cannot instantiate constructor type with discriminant type args."+ ErrorCaseCannotInstantiate xx tScrutinee tCtor+ -> vcat [ text "Cannot instantiate constructor type with scrutinee type args." , text " Either the constructor has an invalid type,"- , text " or the type of the discriminant does not match the type of the pattern."+ , text " or the type of the scrutinee does not match the type of the pattern."+ , text " Scrutinee type: " <> ppr tScrutinee , text " Constructor type: " <> ppr tCtor- , text " Discriminant type: " <> ppr tDiscrim , empty , text "with: " <> align (ppr xx) ] - ErrorCaseDiscrimTypeMismatch xx tDiscrim tPattern- -> vcat [ text "Discriminant type does not match result of pattern type."- , text " Discriminant type: " <> ppr tDiscrim+ ErrorCaseScrutineeTypeMismatch xx tScrutinee tPattern+ -> vcat [ text "Scrutinee type does not match result of pattern type."+ , text " Scrutinee type: " <> ppr tScrutinee , text " Pattern type: " <> ppr tPattern , empty , text "with: " <> align (ppr xx) ]@@ -327,24 +366,23 @@ -- Casts ------------------------------------------- ErrorMaxeffNotEff xx eff k- -> vcat [ text "Type provided for a 'maxeff' does not have effect kind."+ ErrorWeakEffNotEff xx eff k+ -> vcat [ text "Type provided for a 'weakeff' does not have effect kind." , text " Type: " <> ppr eff , text " has kind: " <> ppr k , empty , text "with: " <> align (ppr xx) ]-- ErrorMaxcloNotClo xx clo k- -> vcat [ text "Type provided for a 'maxclo' does not have closure kind."- , text " Type: " <> ppr clo- , text " has kind: " <> ppr k+ + -- Type -------------------------------------------+ ErrorNakedType xx+ -> vcat [ text "Found naked type in core program." , empty , text "with: " <> align (ppr xx) ] - ErrorMaxcloMalformed xx clo- -> vcat [ text "Type provided for a 'maxclo' is malformed."- , text " Closure: " <> ppr clo- , text " can only contain 'Use' terms."+ -- Witness ----------------------------------------+ ErrorNakedWitness xx+ -> vcat [ text "Found naked witness in core program." , empty , text "with: " <> align (ppr xx) ]- ++
DDC/Core/Check/TaggedClosure.hs view
@@ -11,7 +11,7 @@ , cutTaggedClosureXs , cutTaggedClosureT) where-import DDC.Type.Transform.LowerT+import DDC.Type.Transform.LiftT import DDC.Type.Transform.Trim import DDC.Type.Compounds import DDC.Type.Predicates@@ -20,6 +20,8 @@ import Control.Monad import Data.Maybe import Data.Set (Set)+import DDC.Type.Env (Env)+import qualified DDC.Type.Env as Env import qualified DDC.Type.Sum as Sum import qualified Data.Set as Set @@ -62,9 +64,9 @@ GBoundRgnCon u -> text "CLORGNCON" <+> ppr u -instance LowerT TaggedClosure where- lowerAtDepthT n d cc- = let down = lowerAtDepthT n d+instance Ord n => MapBoundT TaggedClosure n where+ mapBoundAtDepthT f d cc+ = let down = mapBoundAtDepthT f d in case cc of GBoundVal u ts -> GBoundVal (down u) (down ts) GBoundRgnVar u1 -> GBoundRgnVar (down u1)@@ -77,7 +79,7 @@ = case gg of GBoundVal _ clos -> TSum $ clos GBoundRgnVar u -> tUse (TVar u)- GBoundRgnCon u -> tUse (TCon (TyConBound u))+ GBoundRgnCon u -> tUse (TCon (TyConBound u kRegion)) -- | Convert a set of tagged closures to a regular closure by dropping the@@ -92,31 +94,35 @@ -- | Yield the tagged closure of a value variable. taggedClosureOfValBound :: (Ord n, Pretty n) - => Bound n -> TaggedClosure n+ => Type n -> Bound n -> TaggedClosure n -taggedClosureOfValBound u+taggedClosureOfValBound t u = GBoundVal u $ Sum.singleton kClosure - $ (let clo = tDeepUse $ typeOfBound u+ $ (let clo = tDeepUse t in fromMaybe clo (trimClosure clo)) --- | Yield the tagged closure of a type argument.+-- | Yield the tagged closure of a type argument,+-- or `Nothing` for out-of-scope type vars. taggedClosureOfTyArg :: (Ord n, Pretty n) - => Type n -> Set (TaggedClosure n)+ => Env n -> Type n -> Maybe (Set (TaggedClosure n)) -taggedClosureOfTyArg tt+taggedClosureOfTyArg kenv tt = case tt of TVar u- | isRegionKind (typeOfBound u)- -> Set.singleton $ GBoundRgnVar u-- TCon (TyConBound u)- | isRegionKind (typeOfBound u)- -> Set.singleton $ GBoundRgnCon u+ -> case Env.lookup u kenv of+ Nothing -> Nothing+ Just k + | isRegionKind k -> Just $ Set.singleton $ GBoundRgnVar u+ | otherwise -> Just Set.empty+ + TCon (TyConBound u k)+ | isRegionKind k+ -> Just $ Set.singleton $ GBoundRgnCon u - _ -> Set.empty+ _ -> Just $ Set.empty -- | Convert the closure provided as a 'weakclo' to tagged form.@@ -136,8 +142,8 @@ Just (TyConSpec TcConUse, [TVar u]) -> Just $ GBoundRgnVar u - Just (TyConSpec TcConUse, [TCon (TyConBound u)])- -> Just $ GBoundRgnVar u+ Just (TyConSpec TcConUse, [TCon (TyConBound u _)])+ -> Just $ GBoundRgnCon u _ -> Nothing @@ -163,7 +169,7 @@ | otherwise -> Just gg GBoundRgnCon u- | Sum.elem (tUse (TCon (TyConBound u))) ts1 + | Sum.elem (tUse (TCon (TyConBound u kRegion))) ts1 -> Nothing | otherwise -> Just gg
DDC/Core/Collect.hs view
@@ -1,253 +1,18 @@ -- | Collecting sets of variables and constructors. module DDC.Core.Collect- ( freeT+ ( -- * Free Variables+ freeT , freeX- , collectBound- , collectSpecBinds)-where-import DDC.Type.Compounds-import DDC.Core.Exp-import DDC.Type.Env (Env)-import qualified DDC.Type.Env as Env-import qualified DDC.Type.Sum as Sum-import qualified Data.Set as Set-import Data.Set (Set) ---- freeT ------------------------------------------------------------------------- | Collect the free Spec variables in a thing (level-1).-freeT :: (BindStruct c, Ord n) - => Env n -> c n -> Set (Bound n)-freeT tenv xx = Set.unions $ map (freeOfTreeT tenv) $ slurpBindTree xx--freeOfTreeT :: Ord n => Env n -> BindTree n -> Set (Bound n)-freeOfTreeT kenv tt- = case tt of- BindDef way bs ts- | BoundSpec <- boundLevelOfBindWay way- , kenv' <- Env.extends bs kenv- -> Set.unions $ map (freeOfTreeT kenv') ts-- BindDef _ _ ts- -> Set.unions $ map (freeOfTreeT kenv) ts-- BindUse BoundSpec u- | Env.member u kenv -> Set.empty- | otherwise -> Set.singleton u- _ -> Set.empty----- freeX ------------------------------------------------------------------------- | Collect the free Data and Witness variables in a thing (level-0).-freeX :: (BindStruct c, Ord n) - => Env n -> c n -> Set (Bound n)-freeX tenv xx = Set.unions $ map (freeOfTreeX tenv) $ slurpBindTree xx--freeOfTreeX :: Ord n => Env n -> BindTree n -> Set (Bound n)-freeOfTreeX tenv tt- = case tt of- BindDef way bs ts- | BoundExpWit <- boundLevelOfBindWay way- , tenv' <- Env.extends bs tenv- -> Set.unions $ map (freeOfTreeX tenv') ts-- BindDef _ _ ts- -> Set.unions $ map (freeOfTreeX tenv) ts-- BindUse BoundExpWit u- | Env.member u tenv -> Set.empty- | otherwise -> Set.singleton u- _ -> Set.empty----- collectBound ------------------------------------------------------------------ | Collect all the bound variables in a thing, --- independent of whether they are free or not.-collectBound :: (BindStruct c, Ord n) => c n -> Set (Bound n)-collectBound - = Set.unions . map collectBoundOfTree . slurpBindTree --collectBoundOfTree :: Ord n => BindTree n -> Set (Bound n)-collectBoundOfTree tt- = case tt of- BindDef _ _ ts -> Set.unions $ map collectBoundOfTree ts- BindUse _ u -> Set.singleton u- BindCon _ u -> Set.singleton u----- collectSpecBinds -------------------------------------------------------------- | Collect all the Spec binders in a thing.-collectSpecBinds :: (BindStruct c, Ord n) => c n -> [Bind n]-collectSpecBinds - = concatMap collectSpecBindsOfTree . slurpBindTree- --collectSpecBindsOfTree :: Ord n => BindTree n -> [Bind n]-collectSpecBindsOfTree tt- = case tt of- BindDef way bs ts- | BoundSpec <- boundLevelOfBindWay way- -> concat ( bs- : map collectSpecBindsOfTree ts)-- | otherwise- -> concatMap collectSpecBindsOfTree ts-- _ -> []------------------------------------------------------------------------------------- | A description of the binding structure of some type or expression.-data BindTree n- -- | An abstract binding expression.- = BindDef BindWay [Bind n] [BindTree n]-- -- | Use of a variable.- | BindUse BoundLevel (Bound n)-- -- | Use of a constructor.- | BindCon BoundLevel (Bound n)- deriving (Eq, Show)----- | Describes how a variable was bound.-data BindWay- = BindForall- | BindLAM- | BindLam- | BindLet- | BindLetRec- | BindLetRegion- | BindLetRegionWith- | BindCasePat- deriving (Eq, Show)----- | What level this binder is at.-data BoundLevel- = BoundSpec- | BoundExpWit- deriving (Eq, Show)----- | Get the `BoundLevel` corresponding to a `BindWay`.-boundLevelOfBindWay :: BindWay -> BoundLevel-boundLevelOfBindWay way- = case way of- BindForall -> BoundSpec- BindLAM -> BoundSpec- BindLam -> BoundExpWit- BindLet -> BoundExpWit- BindLetRec -> BoundExpWit- BindLetRegion -> BoundSpec- BindLetRegionWith -> BoundExpWit- BindCasePat -> BoundExpWit----- BindStruct ------------------------------------------------------------------class BindStruct (c :: * -> *) where- slurpBindTree :: c n -> [BindTree n]---instance BindStruct Type where- slurpBindTree tt- = case tt of- TVar u -> [BindUse BoundSpec u]- TCon tc -> slurpBindTree tc- TForall b t -> [bindDefT BindForall [b] [t]]- TApp t1 t2 -> slurpBindTree t1 ++ slurpBindTree t2- TSum ts -> concatMap slurpBindTree $ Sum.toList ts---instance BindStruct TyCon where- slurpBindTree tc- = case tc of- TyConBound u -> [BindCon BoundSpec u]- _ -> []---instance BindStruct (Exp a) where- slurpBindTree xx- = case xx of- XVar _ u -> [BindUse BoundExpWit u]- XCon _ u -> [BindCon BoundExpWit u]- XApp _ x1 x2 -> slurpBindTree x1 ++ slurpBindTree x2- XLAM _ b x -> [bindDefT BindLAM [b] [x]]- XLam _ b x -> [bindDefX BindLam [b] [x]] -- XLet _ (LLet m b x1) x2- -> slurpBindTree m- ++ slurpBindTree x1- ++ [bindDefX BindLet [b] [x2]]-- XLet _ (LRec bxs) x2- -> [bindDefX BindLetRec - (map fst bxs) - (map snd bxs ++ [x2])]- - XLet _ (LLetRegion b bs) x2- -> [ BindDef BindLetRegion [b]- [bindDefX BindLetRegionWith bs [x2]]]-- XLet _ (LWithRegion u) x2- -> BindUse BoundExpWit u : slurpBindTree x2-- XCase _ x alts -> slurpBindTree x ++ concatMap slurpBindTree alts- XCast _ c x -> slurpBindTree c ++ slurpBindTree x- XType t -> slurpBindTree t- XWitness w -> slurpBindTree w---instance BindStruct LetMode where- slurpBindTree mm- = case mm of- LetLazy (Just w) -> slurpBindTree w- _ -> []---instance BindStruct Cast where- slurpBindTree cc- = case cc of- CastWeakenEffect eff -> slurpBindTree eff- CastWeakenClosure clo -> slurpBindTree clo- CastPurify w -> slurpBindTree w- CastForget w -> slurpBindTree w---instance BindStruct (Alt a) where- slurpBindTree alt- = case alt of- AAlt PDefault x- -> slurpBindTree x-- AAlt (PData _ bs) x- -> [bindDefX BindCasePat bs [x]]---instance BindStruct Witness where- slurpBindTree ww- = case ww of- WVar u -> [BindUse BoundExpWit u]- WCon{} -> []- WApp w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2- WJoin w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2- WType t -> slurpBindTree t----- | Helper for constructing the `BindTree` for an expression or witness binder.-bindDefX :: BindStruct c - => BindWay -> [Bind n] -> [c n] -> BindTree n-bindDefX way bs xs- = BindDef way bs- $ concatMap (slurpBindTree . typeOfBind) bs- ++ concatMap slurpBindTree xs----- | Helper for constructing the `BindTree` for a type binder.-bindDefT :: BindStruct c- => BindWay -> [Bind n] -> [c n] -> BindTree n-bindDefT way bs xs- = BindDef way bs $ concatMap slurpBindTree xs-+ -- * Bounds and Binds+ , collectBound+ , collectBinds + -- * Support+ , Support (..)+ , SupportX (..))+where+import DDC.Core.Collect.Free+import DDC.Core.Collect.Support+import DDC.Type.Collect
+ DDC/Core/Collect/Free.hs view
@@ -0,0 +1,128 @@+-- | Collecting sets of variables and constructors.+module DDC.Core.Collect.Free+ (freeX)+where+import DDC.Type.Collect+import DDC.Type.Compounds+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Type.Env (Env)+import qualified DDC.Type.Env as Env+import qualified Data.Set as Set+import Data.Set (Set)+++-- freeX ----------------------------------------------------------------------+-- | Collect the free Data and Witness variables in a thing (level-0).+freeX :: (BindStruct c, Ord n) + => Env n -> c n -> Set (Bound n)+freeX tenv xx = Set.unions $ map (freeOfTreeX tenv) $ slurpBindTree xx++freeOfTreeX :: Ord n => Env n -> BindTree n -> Set (Bound n)+freeOfTreeX tenv tt+ = {-# SCC freeOfTreeX #-}+ case tt of+ BindDef way bs ts+ | isBoundExpWit $ boundLevelOfBindWay way+ , tenv' <- Env.extends bs tenv+ -> Set.unions $ map (freeOfTreeX tenv') ts++ BindDef _ _ ts+ -> Set.unions $ map (freeOfTreeX tenv) ts++ BindUse bl u+ | isBoundExpWit bl+ , Env.member u tenv -> Set.empty+ | isBoundExpWit bl -> Set.singleton u+ _ -> Set.empty+++-- Module ---------------------------------------------------------------------+instance BindStruct (Module a) where+ slurpBindTree mm+ = slurpBindTree $ moduleBody mm+++-- Exp ------------------------------------------------------------------------+instance BindStruct (Exp a) where+ slurpBindTree xx+ = case xx of+ XVar _ u+ -> [BindUse BoundExp u]++ XCon _ dc+ -> case daConName dc of+ DaConUnit -> []+ DaConNamed n -> [BindCon BoundExp (UName n) Nothing]++ XApp _ x1 x2 -> slurpBindTree x1 ++ slurpBindTree x2+ XLAM _ b x -> [bindDefT BindLAM [b] [x]]+ XLam _ b x -> [bindDefX BindLam [b] [x]] ++ XLet _ (LLet m b x1) x2+ -> slurpBindTree m+ ++ slurpBindTree x1+ ++ [bindDefX BindLet [b] [x2]]++ XLet _ (LRec bxs) x2+ -> [bindDefX BindLetRec + (map fst bxs) + (map snd bxs ++ [x2])]+ + XLet _ (LLetRegions b bs) x2+ -> [ BindDef BindLetRegions b+ [bindDefX BindLetRegionWith bs [x2]]]++ XLet _ (LWithRegion u) x2+ -> BindUse BoundExp u : slurpBindTree x2++ XCase _ x alts -> slurpBindTree x ++ concatMap slurpBindTree alts+ XCast _ c x -> slurpBindTree c ++ slurpBindTree x+ XType t -> slurpBindTree t+ XWitness w -> slurpBindTree w+++instance BindStruct LetMode where+ slurpBindTree mode+ = case mode of+ LetStrict -> []+ LetLazy Nothing -> []+ LetLazy (Just ww) -> slurpBindTree ww+++instance BindStruct (Cast a) where+ slurpBindTree cc+ = case cc of+ CastWeakenEffect eff -> slurpBindTree eff+ CastWeakenClosure xs -> concatMap slurpBindTree xs+ CastPurify w -> slurpBindTree w+ CastForget w -> slurpBindTree w+++instance BindStruct (Alt a) where+ slurpBindTree alt+ = case alt of+ AAlt PDefault x+ -> slurpBindTree x++ AAlt (PData _ bs) x+ -> [bindDefX BindCasePat bs [x]]+++instance BindStruct Witness where+ slurpBindTree ww+ = case ww of+ WVar u -> [BindUse BoundWit u]+ WCon{} -> []+ WApp w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2+ WJoin w1 w2 -> slurpBindTree w1 ++ slurpBindTree w2+ WType t -> slurpBindTree t+++-- | Helper for constructing the `BindTree` for an expression or witness binder.+bindDefX :: BindStruct c + => BindWay -> [Bind n] -> [c n] -> BindTree n+bindDefX way bs xs+ = BindDef way bs+ $ concatMap (slurpBindTree . typeOfBind) bs+ ++ concatMap slurpBindTree xs
+ DDC/Core/Collect/Support.hs view
@@ -0,0 +1,208 @@++module DDC.Core.Collect.Support+ ( Support (..)+ , SupportX (..))+where+import DDC.Core.Compounds+import DDC.Core.Exp+import DDC.Type.Collect.FreeT+import Data.Set (Set)+import DDC.Type.Env (KindEnv, TypeEnv)+import qualified DDC.Type.Env as Env+import qualified Data.Set as Set+import Data.Monoid+++data Support n+ = Support+ { -- | Type constructors used in the expression.+ supportTyCon :: Set (Bound n)++ -- | Type constructors used in the argument of a value-type application.+ , supportTyConXArg :: Set (Bound n)++ -- | Free spec variables in an expression.+ , supportSpVar :: Set (Bound n)++ -- | Type constructors used in the argument of a value-type application.+ , supportSpVarXArg :: Set (Bound n)++ -- | Free witness variables in an expression.+ -- (from the Witness universe)+ , supportWiVar :: Set (Bound n)++ -- | Free value variables in an expression.+ -- (from the Data universe)+ , supportDaVar :: Set (Bound n) }+ deriving Show+++instance Ord n => Monoid (Support n) where+ mempty = Support+ { supportTyCon = Set.empty+ , supportTyConXArg = Set.empty+ , supportSpVar = Set.empty+ , supportSpVarXArg = Set.empty+ , supportWiVar = Set.empty+ , supportDaVar = Set.empty }++ mappend sp1 sp2+ = Support+ { supportTyCon = Set.unions [supportTyCon sp1, supportTyCon sp2]+ , supportTyConXArg = Set.unions [supportTyConXArg sp1, supportTyConXArg sp2]+ , supportSpVar = Set.unions [supportSpVar sp1, supportSpVar sp2]+ , supportSpVarXArg = Set.unions [supportSpVarXArg sp1, supportSpVarXArg sp2]+ , supportWiVar = Set.unions [supportWiVar sp1, supportWiVar sp2]+ , supportDaVar = Set.unions [supportDaVar sp1, supportDaVar sp2] }+++class SupportX (c :: * -> *) where+ support+ :: Ord n+ => KindEnv n -> TypeEnv n+ -> c n+ -> Support n+++instance SupportX Type where+ support kenv _tenv t+ = let (fvs1, tcs) = freeVarConT kenv t+ in mempty { supportTyCon = tcs+ , supportSpVar = fvs1 }+++instance SupportX Bind where+ support kenv tenv b+ = support kenv tenv + $ typeOfBind b+++instance SupportX (Exp a) where+ support kenv tenv xx+ = case xx of+ XVar _ u + | Env.member u tenv -> mempty+ | otherwise -> mempty { supportDaVar = Set.singleton u}++ XCon{} + -> mempty++ XLAM _ b x+ -> support kenv tenv b + <> support (Env.extend b kenv) tenv x++ XLam _ b x+ -> support kenv tenv b+ <> support kenv (Env.extend b tenv) x++ XApp _ x1 x2+ -> let s1 = support kenv tenv x1 + s2 = support kenv tenv x2+ in mappend s1 s2++ XLet _a lts x2+ -> let s1 = support kenv tenv lts+ (bs1, bs0) = bindsOfLets lts+ kenv' = Env.extends bs1 kenv+ tenv' = Env.extends bs0 tenv+ s2 = support kenv' tenv' x2+ in mappend s1 s2++ XCase _ x1 alts+ -> let s1 = support kenv tenv x1+ ss = mconcat $ map (support kenv tenv) alts+ in mappend s1 ss++ XCast _ c1 x2+ -> let s1 = support kenv tenv c1+ s2 = support kenv tenv x2+ in mappend s1 s2++ XType t + -> let sup = support kenv tenv t+ in sup { supportTyConXArg = supportTyCon sup+ , supportSpVarXArg = supportSpVar sup }++ XWitness w -> support kenv tenv w+++instance SupportX (Alt a) where+ support kenv tenv aa+ = case aa of+ AAlt PDefault x+ -> support kenv tenv x++ AAlt (PData _dc bs0) x+ -> let tenv' = Env.extends bs0 tenv+ in support kenv tenv' x+++instance SupportX Witness where+ support kenv tenv ww+ = case ww of+ WVar u+ | Env.member u tenv -> mempty+ | otherwise -> mempty { supportWiVar = Set.singleton u }++ WCon{}+ -> mempty++ WApp w1 w2+ -> support kenv tenv w1+ <> support kenv tenv w2++ WJoin w1 w2+ -> support kenv tenv w1+ <> support kenv tenv w2++ WType t+ -> support kenv tenv t+++instance SupportX (Cast a) where+ support kenv tenv cc+ = case cc of+ CastWeakenEffect eff+ -> support kenv tenv eff++ CastWeakenClosure xs+ -> mconcat $ map (support kenv tenv) xs++ CastPurify w+ -> support kenv tenv w++ CastForget w+ -> support kenv tenv w+ ++instance SupportX (Lets a) where+ support kenv tenv lts+ = case lts of+ LLet m b x+ -> support kenv tenv m+ <> support kenv tenv b+ <> support kenv (Env.extend b tenv) x++ LRec bxs+ -> (mconcat $ map (support kenv tenv) $ map fst bxs)+ <> (let tenv' = Env.extends (map fst bxs) tenv+ in mconcat $ map (support kenv tenv') $ map snd bxs)++ LLetRegions bs ws+ -> (mconcat $ map (support kenv tenv) bs)+ <> (let kenv' = Env.extends bs kenv+ in mconcat $ map (support kenv' tenv) ws)++ LWithRegion u+ | Env.member u kenv -> mempty+ | otherwise -> mempty { supportSpVar = Set.singleton u }+++instance SupportX LetMode where+ support kenv tenv mm+ = case mm of+ LetStrict -> mempty+ LetLazy Nothing -> mempty+ LetLazy (Just w) -> support kenv tenv w++
DDC/Core/Compounds.hs view
@@ -1,79 +1,93 @@ -- | Utilities for constructing and destructing compound expressions. module DDC.Core.Compounds - ( -- * Lets- bindsOfLets- , specBindsOfLets- , valwitBindsOfLets+ ( module DDC.Type.Compounds+ , module DDC.Core.DaCon - -- * Patterns- , bindsOfPat+ -- * Annotations+ , takeAnnotOfExp -- * Lambdas- , makeXLAMs, takeXLAMs- , makeXLams, takeXLams- , takeXLamFlags+ , xLAMs+ , xLams , makeXLamFlags+ , takeXLAMs+ , takeXLams+ , takeXLamFlags -- * Applications- , makeXApps+ , xApps+ , makeXAppsWithAnnots , takeXApps+ , takeXApps1+ , takeXAppsAsList+ , takeXAppsWithAnnots , takeXConApps , takeXPrimApps - -- * Alternatives- , takeCtorNameOfAlt)-where-import DDC.Type.Compounds-import DDC.Core.Exp-+ -- * Lets+ , xLets+ , splitXLets + , bindsOfLets+ , specBindsOfLets+ , valwitBindsOfLets --- | Take the binds of a `Lets`.-bindsOfLets :: Lets a n -> [Bind n]-bindsOfLets ll- = case ll of- LLet _ b _ -> [b]- LRec bxs -> map fst bxs- LLetRegion b bs -> b : bs- LWithRegion{} -> []+ -- * Patterns+ , bindsOfPat + -- * Alternatives+ , takeCtorNameOfAlt --- | Like `bindsOfLets` but only take the type binders.-specBindsOfLets :: Lets a n -> [Bind n]-specBindsOfLets ll- = case ll of- LLet _ _ _ -> []- LRec _ -> []- LLetRegion b _ -> [b]- LWithRegion{} -> []+ -- * Witnesses+ , wApp+ , wApps+ , takeXWitness+ , takeWAppsAsList+ , takePrimWiConApps + -- * Types+ , takeXType --- | Like `bindsOfLets` but only take the value and witness binders.-valwitBindsOfLets :: Lets a n -> [Bind n]-valwitBindsOfLets ll- = case ll of- LLet _ b _ -> [b]- LRec bxs -> map fst bxs- LLetRegion _ bs -> bs- LWithRegion{} -> []+ -- * Units+ , xUnit)+where+import DDC.Type.Compounds+import DDC.Core.Exp+import DDC.Core.DaCon --- | Take the binds of a `Pat`.-bindsOfPat :: Pat n -> [Bind n]-bindsOfPat pp- = case pp of- PDefault -> []- PData _ bs -> bs+-- Annotations ----------------------------------------------------------------+-- | Take the outermost annotation from an expression,+-- or Nothing if this is an `XType` or `XWitness` without an annotation.+takeAnnotOfExp :: Exp a n -> Maybe a+takeAnnotOfExp xx+ = case xx of+ XVar a _ -> Just a+ XCon a _ -> Just a+ XLAM a _ _ -> Just a+ XLam a _ _ -> Just a+ XApp a _ _ -> Just a+ XLet a _ _ -> Just a+ XCase a _ _ -> Just a+ XCast a _ _ -> Just a+ XType{} -> Nothing+ XWitness{} -> Nothing -- Lambdas ------------------------------------------------------------------------ | Make some nested type lambda abstractions.-makeXLAMs :: a -> [Bind n] -> Exp a n -> Exp a n-makeXLAMs a bs x+-- | Make some nested type lambdas.+xLAMs :: a -> [Bind n] -> Exp a n -> Exp a n+xLAMs a bs x = foldr (XLAM a) x (reverse bs) --- | Split nested value and witness lambdas from the front of an expression,+-- | Make some nested value or witness lambdas.+xLams :: a -> [Bind n] -> Exp a n -> Exp a n+xLams a bs x+ = foldr (XLam a) x (reverse bs)+++-- | Split type lambdas from the front of an expression, -- or `Nothing` if there aren't any. takeXLAMs :: Exp a n -> Maybe ([Bind n], Exp a n) takeXLAMs xx@@ -84,12 +98,6 @@ (bs, body) -> Just (bs, body) --- | Make some nested value or witness lambda abstractions.-makeXLams :: a -> [Bind n] -> Exp a n -> Exp a n-makeXLams a bs x- = foldr (XLam a) x (reverse bs)-- -- | Split nested value or witness lambdas from the front of an expression, -- or `Nothing` if there aren't any. takeXLams :: Exp a n -> Maybe ([Bind n], Exp a n)@@ -101,6 +109,17 @@ (bs, body) -> Just (bs, body) +-- | Make some nested lambda abstractions,+-- using a flag to indicate whether the lambda is a+-- level-1 (True), or level-0 (False) binder.+makeXLamFlags :: a -> [(Bool, Bind n)] -> Exp a n -> Exp a n+makeXLamFlags a fbs x+ = foldr (\(f, b) x'+ -> if f then XLAM a b x'+ else XLam a b x')+ x fbs++ -- | Split nested lambdas from the front of an expression, -- with a flag indicating whether the lambda was a level-1 (True), -- or level-0 (False) binder.@@ -114,59 +133,200 @@ (bs, body) -> Just (bs, body) --- | Make some nested lambda abstractions,--- using a flag to indicate whether the lambda is a--- level-1 (True), or level-0 (False) binder.-makeXLamFlags :: a -> [(Bool, Bind n)] -> Exp a n -> Exp a n-makeXLamFlags a fbs x- = foldr (\(f, b) x'- -> if f then XLAM a b x'- else XLam a b x')- x fbs+-- Applications ---------------------------------------------------------------+-- | Build sequence of value applications.+xApps :: a -> Exp a n -> [Exp a n] -> Exp a n+xApps a t1 ts = foldl (XApp a) t1 ts --- Applications ------------------------------------------------------------------ | Build sequence of type applications.-makeXApps :: a -> Exp a n -> [Exp a n] -> Exp a n-makeXApps a t1 ts = foldl (XApp a) t1 ts+-- | Build sequence of applications.+-- Similar to `xApps` but also takes list of annotations for +-- the `XApp` constructors.+makeXAppsWithAnnots :: Exp a n -> [(Exp a n, a)] -> Exp a n+makeXAppsWithAnnots f xas+ = case xas of+ [] -> f+ (arg,a ) : as -> makeXAppsWithAnnots (XApp a f arg) as --- | Flatten an application into the function parts and arguments, if any.-takeXApps :: Exp a n -> [Exp a n]+-- | Flatten an application into the function part and its arguments.+--+-- Returns `Nothing` if there is no outer application.+takeXApps :: Exp a n -> Maybe (Exp a n, [Exp a n]) takeXApps xx+ = case takeXAppsAsList xx of+ (x1 : xsArgs) -> Just (x1, xsArgs)+ _ -> Nothing+++-- | Flatten an application into the function part and its arguments.+--+-- This is like `takeXApps` above, except we know there is at least one argument.+takeXApps1 :: Exp a n -> Exp a n -> (Exp a n, [Exp a n])+takeXApps1 x1 x2+ = case takeXApps x1 of+ Nothing -> (x1, [x2])+ Just (x11, x12s) -> (x11, x12s ++ [x2])+++-- | Flatten an application into the function parts and arguments, if any.+takeXAppsAsList :: Exp a n -> [Exp a n]+takeXAppsAsList xx = case xx of- XApp _ x1 x2 -> takeXApps x1 ++ [x2]+ XApp _ x1 x2 -> takeXAppsAsList x1 ++ [x2] _ -> [xx] +-- | Destruct sequence of applications.+-- Similar to `takeXAppsAsList` but also keeps annotations for later.+takeXAppsWithAnnots :: Exp a n -> (Exp a n, [(Exp a n, a)])+takeXAppsWithAnnots xx+ = case xx of+ XApp a f arg+ -> let (f', args') = takeXAppsWithAnnots f+ in (f', args' ++ [(arg,a)])++ _ -> (xx, [])++ -- | Flatten an application of a primop into the variable -- and its arguments. -- -- Returns `Nothing` if the expression isn't a primop application. takeXPrimApps :: Exp a n -> Maybe (n, [Exp a n]) takeXPrimApps xx- = case takeXApps xx of- XVar _ (UPrim p _) : xs -> Just (p, xs)- _ -> Nothing+ = case takeXAppsAsList xx of+ XVar _ (UPrim p _) : xs -> Just (p, xs)+ _ -> Nothing -- | Flatten an application of a data constructor into the constructor -- and its arguments. -- -- Returns `Nothing` if the expression isn't a constructor application.-takeXConApps :: Exp a n -> Maybe (Bound n, [Exp a n])+takeXConApps :: Exp a n -> Maybe (DaCon n, [Exp a n]) takeXConApps xx- = case takeXApps xx of- XCon _ u : xs -> Just (u, xs)+ = case takeXAppsAsList xx of+ XCon _ dc : xs -> Just (dc, xs) _ -> Nothing +-- Lets -----------------------------------------------------------------------+-- | Wrap some let-bindings around an expression.+xLets :: a -> [Lets a n] -> Exp a n -> Exp a n+xLets a lts x+ = foldr (XLet a) x lts+++-- | Split let-bindings from the front of an expression, if any.+splitXLets :: Exp a n -> ([Lets a n], Exp a n)+splitXLets xx+ = case xx of+ XLet _ lts x + -> let (lts', x') = splitXLets x+ in (lts : lts', x')++ _ -> ([], xx)++-- | Take the binds of a `Lets`.+--+-- The level-1 and level-0 binders are returned separately.+bindsOfLets :: Lets a n -> ([Bind n], [Bind n])+bindsOfLets ll+ = case ll of+ LLet _ b _ -> ([], [b])+ LRec bxs -> ([], map fst bxs)+ LLetRegions bs bbs -> (bs, bbs)+ LWithRegion{} -> ([], [])+++-- | Like `bindsOfLets` but only take the spec (level-1) binders.+specBindsOfLets :: Lets a n -> [Bind n]+specBindsOfLets ll+ = case ll of+ LLet _ _ _ -> []+ LRec _ -> []+ LLetRegions bs _ -> bs+ LWithRegion{} -> []+++-- | Like `bindsOfLets` but only take the value and witness (level-0) binders.+valwitBindsOfLets :: Lets a n -> [Bind n]+valwitBindsOfLets ll+ = case ll of+ LLet _ b _ -> [b]+ LRec bxs -> map fst bxs+ LLetRegions _ bs -> bs+ LWithRegion{} -> []++ -- Alternatives --------------------------------------------------------------- -- | Take the constructor name of an alternative, if there is one. takeCtorNameOfAlt :: Alt a n -> Maybe n takeCtorNameOfAlt aa = case aa of- AAlt (PData u _) _ -> takeNameOfBound u+ AAlt (PData dc _) _ -> takeNameOfDaCon dc _ -> Nothing +-- Patterns -------------------------------------------------------------------+-- | Take the binds of a `Pat`.+bindsOfPat :: Pat n -> [Bind n]+bindsOfPat pp+ = case pp of+ PDefault -> []+ PData _ bs -> bs+++-- Witnesses ------------------------------------------------------------------+-- | Construct a witness application+wApp :: Witness n -> Witness n -> Witness n+wApp = WApp+++-- | Construct a sequence of witness applications+wApps :: Witness n -> [Witness n] -> Witness n+wApps = foldl wApp+++-- | Take the witness from an `XWitness` argument, if any.+takeXWitness :: Exp a n -> Maybe (Witness n)+takeXWitness xx+ = case xx of+ XWitness t -> Just t+ _ -> Nothing+++-- | Flatten an application into the function parts and arguments, if any.+takeWAppsAsList :: Witness n -> [Witness n]+takeWAppsAsList ww+ = case ww of+ WApp w1 w2 -> takeWAppsAsList w1 ++ [w2]+ _ -> [ww]+++-- | Flatten an application of a witness into the witness constructor+-- name and its arguments.+--+-- Returns nothing if there is no witness constructor in head position.+takePrimWiConApps :: Witness n -> Maybe (n, [Witness n])+takePrimWiConApps ww+ = case takeWAppsAsList ww of+ WCon wc : args | WiConBound (UPrim n _) _ <- wc+ -> Just (n, args)+ _ -> Nothing+++-- Types ----------------------------------------------------------------------+-- | Take the type from an `XType` argument, if any.+takeXType :: Exp a n -> Maybe (Type n)+takeXType xx+ = case xx of+ XType t -> Just t+ _ -> Nothing+++-- Units -----------------------------------------------------------------------+-- | Construct a value of unit type.+xUnit :: a -> Exp a n+xUnit a = XCon a dcUnit
+ DDC/Core/DaCon.hs view
@@ -0,0 +1,100 @@++module DDC.Core.DaCon + ( DaCon (..)+ , DaConName (..)++ , dcUnit+ , mkDaConAlg+ , mkDaConSolid+ , takeNameOfDaCon+ , typeOfDaCon)+where+import DDC.Type.Compounds+import DDC.Type.Exp+import Control.DeepSeq+++-------------------------------------------------------------------------------+-- | Data constructor names.+data DaConName n+ -- | The unit data constructor is builtin.+ = DaConUnit++ -- | Data constructor name defined by the client.+ | DaConNamed n+ deriving (Eq, Show)+++instance NFData n => NFData (DaConName n) where+ rnf dcn+ = case dcn of+ DaConUnit -> ()+ DaConNamed n -> rnf n+++-------------------------------------------------------------------------------+-- | Data constructors.+data DaCon n+ = DaCon+ { -- | Name of the data constructor.+ daConName :: !(DaConName n)++ -- | Type of the data constructor.+ -- The type must be closed.+ , daConType :: !(Type n)++ -- | Algebraic constructors can be deconstructed with case-expressions,+ -- and must have a data type declaration.+ -- + -- Non-algebraic types like 'Float' can't be inspected with+ -- case-expressions.+ , daConIsAlgebraic :: !Bool }+ deriving Show+++instance NFData n => NFData (DaCon n) where+ rnf !dc+ = rnf (daConName dc)+ `seq` rnf (daConType dc)+ `seq` rnf (daConIsAlgebraic dc)+++-- | Take the name of data constructor.+takeNameOfDaCon :: DaCon n -> Maybe n+takeNameOfDaCon dc+ = case daConName dc of+ DaConUnit -> Nothing+ DaConNamed n -> Just n+++-- | Take the type annotation of a data constructor.+typeOfDaCon :: DaCon n -> Type n+typeOfDaCon dc = daConType dc+++-- | The unit data constructor.+dcUnit :: DaCon n+dcUnit = DaCon+ { daConName = DaConUnit+ , daConType = tUnit+ , daConIsAlgebraic = True }+++-- | Make an algebraic data constructor.+mkDaConAlg :: n -> Type n -> DaCon n+mkDaConAlg n t+ = DaCon+ { daConName = DaConNamed n+ , daConType = t+ , daConIsAlgebraic = True }+++-- | Make a non-algebraic (solid) constructor.+-- These are used for location values in the interpreter,+-- and for floating point literals in the main compiler.+mkDaConSolid :: n -> Type n -> DaCon n+mkDaConSolid n t+ = DaCon+ { daConName = DaConNamed n+ , daConType = t+ , daConIsAlgebraic = False }
− DDC/Core/DataDef.hs
@@ -1,135 +0,0 @@---- | Algebraic data type definitions.-module DDC.Core.DataDef- ( DataDef (..)-- -- * Data type definition table- , DataDefs (..)- , DataMode (..)- , DataType (..)- , DataCtor (..)-- , emptyDataDefs- , insertDataDef- , fromListDataDefs- , lookupModeOfDataType)-where-import DDC.Type.Exp-import Data.Map (Map)-import qualified Data.Map as Map-import Data.Maybe-import Control.Monad----- | The definition of a single data type.-data DataDef n- = DataDef- { -- | Name of the data type.- dataDefTypeName :: n-- -- | Kinds of type parameters.- , dataDefParamKinds :: [Kind n]-- -- | Constructors of the data type, or Nothing if there are- -- too many to list (like with `Int`).- , dataDefCtors :: Maybe [(n, [Type n])] }------ DataDefs ---------------------------------------------------------------------- | A table of data type definitions,--- unpacked into type and data constructors so we can find them easily.-data DataDefs n- = DataDefs- { dataDefsTypes :: Map n (DataType n)- , dataDefsCtors :: Map n (DataCtor n) }----- | The mode of a data type records how many data constructors there are.--- This can be set to 'Large' for large primitive types like Int and Float.--- In this case we don't ever expect them all to be enumerated--- as case alternatives.-data DataMode n- = DataModeSmall [n]- | DataModeLarge----- | Describes a data type constructor, used in the `DataDefs` table.-data DataType n- = DataType - { -- | Name of data type constructor.- dataTypeName :: n-- -- | Kinds of type parameters to constructor.- , dataTypeParamKinds :: [Kind n]-- -- | Names of data constructors of this data type,- -- or `Nothing` if it has infinitely many constructors.- , dataTypeMode :: DataMode n }----- | Describes a data constructor, used in the `DataDefs` table.-data DataCtor n- = DataCtor- { -- | Name of data constructor.- dataCtorName :: n-- -- | Field types of constructor.- , dataCtorFieldTypes :: [Type n]-- -- | Name of result type of constructor.- , dataCtorTypeName :: n }------ | An empty table of data type definitions.-emptyDataDefs :: DataDefs n-emptyDataDefs- = DataDefs- { dataDefsTypes = Map.empty- , dataDefsCtors = Map.empty }----- | Insert a data type definition into some DataDefs.-insertDataDef :: Ord n => DataDef n -> DataDefs n -> DataDefs n-insertDataDef (DataDef nType ks mCtors) dataDefs- = let defType = DataType- { dataTypeName = nType- , dataTypeParamKinds = ks- , dataTypeMode = defMode }-- defMode = case mCtors of- Nothing -> DataModeLarge- Just ctors -> DataModeSmall (map fst ctors)-- makeDefCtor (nCtor, tsFields)- = DataCtor- { dataCtorName = nCtor- , dataCtorFieldTypes = tsFields- , dataCtorTypeName = nType }-- defCtors = case mCtors of- Nothing -> Nothing- Just cs -> Just $ map makeDefCtor cs-- in dataDefs- { dataDefsTypes = Map.insert nType defType (dataDefsTypes dataDefs)- , dataDefsCtors = Map.union (dataDefsCtors dataDefs)- $ Map.fromList [(n, def) | def@(DataCtor n _ _) - <- concat $ maybeToList defCtors] }----- | Build a `DataDefs` table from a list of `DataDef`-fromListDataDefs :: Ord n => [DataDef n] -> DataDefs n-fromListDataDefs defs- = foldr insertDataDef emptyDataDefs defs------ | Yield the list of data constructor names for some data type, --- or `Nothing` for large types with too many constructors to list.-lookupModeOfDataType :: Ord n => n -> DataDefs n -> Maybe (DataMode n)-lookupModeOfDataType n defs- = liftM dataTypeMode $ Map.lookup n (dataDefsTypes defs)--
DDC/Core/Exp.hs view
@@ -5,6 +5,8 @@ -- * Computation expressions , Exp (..)+ , DaCon (..)+ , DaConName(..) , Cast (..) , Lets (..) , LetMode (..)@@ -16,183 +18,8 @@ , WiCon (..) , WbCon (..)) where+import DDC.Core.Exp.Base+import DDC.Core.Exp.NFData ()+import DDC.Core.DaCon import DDC.Type.Exp-import DDC.Type.Sum ()----- Values ------------------------------------------------------------------------ | Well-typed expressions live in the Data universe, and their types always--- have kind '*'. --- --- Expressions do something useful at runtime, and might diverge or cause--- side effects.-data Exp a n- -- | Value variable or primitive operation.- = XVar a (Bound n)-- -- | Data constructor or literal.- | XCon a (Bound n)-- -- | Type abstraction (level-1).- | XLAM a (Bind n) (Exp a n)-- -- | Value and Witness abstraction (level-0).- | XLam a (Bind n) (Exp a n)-- -- | Application.- | XApp a (Exp a n) (Exp a n)-- -- | Possibly recursive bindings.- | XLet a (Lets a n) (Exp a n)-- -- | Case branching.- | XCase a (Exp a n) [Alt a n]-- -- | Type cast.- | XCast a (Cast n) (Exp a n)-- -- | Type can appear as the argument of an application.- | XType (Type n)-- -- | Witness can appear as the argument of an application.- | XWitness (Witness n)- deriving (Eq, Show)----- | Type casts.-data Cast n- -- | Weaken the effect of an expression.- = CastWeakenEffect (Effect n)- - -- | Weaken the closure of an expression.- | CastWeakenClosure (Closure n)-- -- | Purify the effect of an expression.- | CastPurify (Witness n)-- -- | Hide sharing of the closure of an expression.- | CastForget (Witness n)- deriving (Eq, Show)----- | Possibly recursive bindings.-data Lets a n- -- | Non-recursive expression binding.- = LLet (LetMode n) (Bind n) (Exp a n)-- -- | Recursive binding of lambda abstractions.- | LRec [(Bind n, Exp a n)]-- -- | Bind a local region variable,- -- and witnesses to its properties.- | LLetRegion (Bind n) [Bind n]- - -- | Holds a region handle during evaluation.- | LWithRegion (Bound n)- deriving (Eq, Show)----- | Describes how a let binding should be evaluated.-data LetMode n- -- | Evaluate binding before substituting the result.- = LetStrict-- -- | Use lazy evaluation. - -- The witness shows that the head region of the bound expression- -- can contain thunks (is lazy), or Nothing if there is no head region.- | LetLazy (Maybe (Witness n))- deriving (Eq, Show)----- | Case alternatives.-data Alt a n- = AAlt (Pat n) (Exp a n)- deriving (Eq, Show)----- | Pattern matching.-data Pat n- -- | The default pattern always succeeds.- = PDefault- - -- | Match a data constructor and bind its arguments.- | PData (Bound n) [Bind n]- deriving (Eq, Show)- ---- Witness ----------------------------------------------------------------------- | When a witness exists in the program it guarantees that a--- certain property of the program is true.-data Witness n- -- | Witness variable.- = WVar (Bound n)- - -- | Witness constructor.- | WCon (WiCon n)- - -- | Witness application.- | WApp (Witness n) (Witness n)-- -- | Joining of witnesses.- | WJoin (Witness n) (Witness n)-- -- | Type can appear as the argument of an application.- | WType (Type n)- deriving (Eq, Show)----- | Witness constructors.-data WiCon n- -- | Witness constructors baked into the language.- = WiConBuiltin WbCon-- -- | Witness constructors defined in the environment.- -- In the interpreter we use this to hold runtime capabilities.- | WiConBound (Bound n)- deriving (Eq, Show)----- | Built-in witness constructors.------ These are used to convert a runtime capability into a witness that--- the corresponding property is true.-data WbCon- -- | (axiom) The pure effect is pure.- -- - -- @pure :: Pure !0@- = WbConPure -- -- | (axiom) The empty closure is empty.- --- -- @empty :: Empty $0@- | WbConEmpty-- -- | Convert a capability guaranteeing that a region is in the global- -- heap into a witness that a closure using this region is empty.- -- This lets us rely on the garbage collector to reclaim objects- -- in the region. It is needed when we suspend the evaluation of - -- expressions that have a region in their closure, because the- -- type of the returned thunk may not reveal that it references- -- objects in that region.- -- - -- @use :: [r: %]. Global r => Empty (Use r)@- | WbConUse -- -- | Convert a capability guaranteeing the constancy of a region into- -- a witness that a read from that region is pure.- -- This lets us suspend applications that read constant objects,- -- because it doesn't matter if the read is delayed, we'll always- -- get the same result.- --- -- @read :: [r: %]. Const r => Pure (Read r)@- | WbConRead -- -- | Convert a capability guaranteeing the constancy of a region into- -- a witness that allocation into that region is pure.- -- This lets us increase the sharing of constant objects,- -- because we can't tell constant objects of the same value apart.- -- - -- @alloc :: [r: %]. Const r => Pure (Alloc r)@- | WbConAlloc- deriving (Eq, Show)
+ DDC/Core/Exp/Base.hs view
@@ -0,0 +1,186 @@++module DDC.Core.Exp.Base where+import DDC.Core.DaCon+import DDC.Type.Exp+import DDC.Type.Sum ()+++-- Values ---------------------------------------------------------------------+-- | Well-typed expressions produce `Data` values when evaluated, +-- and their types aways have kind '*' (Data)+data Exp a n+ -- | Value variable or primitive operation.+ = XVar !a !(Bound n)++ -- | Data constructor or literal.+ | XCon !a !(DaCon n)++ -- | Type abstraction (level-1).+ | XLAM !a !(Bind n) !(Exp a n)++ -- | Value and Witness abstraction (level-0).+ | XLam !a !(Bind n) !(Exp a n)++ -- | Application.+ | XApp !a !(Exp a n) !(Exp a n)++ -- | Possibly recursive bindings.+ | XLet !a !(Lets a n) !(Exp a n)++ -- | Case branching.+ | XCase !a !(Exp a n) ![Alt a n]++ -- | Type cast.+ | XCast !a !(Cast a n) !(Exp a n)++ -- | Type can appear as the argument of an application.+ | XType !(Type n)++ -- | Witness can appear as the argument of an application.+ | XWitness !(Witness n)+ deriving (Eq, Show)++deriving instance Eq n => Eq (DaCon n)+++-- | Type casts.+data Cast a n+ -- | Weaken the effect of an expression.+ -- The given effect is added to the effect+ -- of the body.+ = CastWeakenEffect !(Effect n)+ + -- | Weaken the closure of an expression.+ -- The closures of these expressions are added to the closure+ -- of the body.+ | CastWeakenClosure ![Exp a n]++ -- | Purify the effect (action) of an expression.+ | CastPurify !(Witness n)++ -- | Forget about the closure (sharing) of an expression.+ | CastForget !(Witness n)+ deriving (Eq, Show)+++-- | Possibly recursive bindings.+data Lets a n+ -- | Non-recursive expression binding.+ = LLet !(LetMode n) !(Bind n) !(Exp a n)++ -- | Recursive binding of lambda abstractions.+ | LRec ![(Bind n, Exp a n)]++ -- | Bind a local region variable,+ -- and witnesses to its properties.+ | LLetRegions ![Bind n] ![Bind n]+ + -- | Holds a region handle during evaluation.+ | LWithRegion !(Bound n)+ deriving (Eq, Show)+++-- | Describes how a let binding should be evaluated.+data LetMode n+ -- | Evaluate binding before substituting the result.+ = LetStrict++ -- | Use lazy evaluation. + -- The witness shows that the head region of the bound expression+ -- can contain thunks (is lazy), or Nothing if there is no head region.+ | LetLazy !(Maybe (Witness n))+ deriving (Eq, Show)+++-- | Case alternatives.+data Alt a n+ = AAlt !(Pat n) !(Exp a n)+ deriving (Eq, Show)+++-- | Pattern matching.+data Pat n+ -- | The default pattern always succeeds.+ = PDefault+ + -- | Match a data constructor and bind its arguments.+ | PData !(DaCon n) ![Bind n]+ deriving (Eq, Show)+ ++-- Witness --------------------------------------------------------------------+-- | When a witness exists in the program it guarantees that a+-- certain property of the program is true.+data Witness n+ -- | Witness variable.+ = WVar !(Bound n)+ + -- | Witness constructor.+ | WCon !(WiCon n)+ + -- | Witness application.+ | WApp !(Witness n) !(Witness n)++ -- | Joining of witnesses.+ | WJoin !(Witness n) !(Witness n)++ -- | Type can appear as the argument of an application.+ | WType !(Type n)+ deriving (Eq, Show)+++-- | Witness constructors.+data WiCon n+ -- | Witness constructors baked into the language.+ = WiConBuiltin !WbCon++ -- | Witness constructors defined in the environment.+ -- In the interpreter we use this to hold runtime capabilities.+ -- The attached type must be closed.+ | WiConBound !(Bound n) !(Type n)+ deriving (Eq, Show)+++-- | Built-in witness constructors.+--+-- These are used to convert a runtime capability into a witness that+-- the corresponding property is true.+data WbCon+ -- | (axiom) The pure effect is pure.+ -- + -- @pure :: Pure !0@+ = WbConPure ++ -- | (axiom) The empty closure is empty.+ --+ -- @empty :: Empty $0@+ | WbConEmpty++ -- | Convert a capability guaranteeing that a region is in the global+ -- heap, into a witness that a closure using this region is empty.+ -- This lets us rely on the garbage collector to reclaim objects+ -- in the region. It is needed when we suspend the evaluation of + -- expressions that have a region in their closure, because the+ -- type of the returned thunk may not reveal that it references+ -- objects in that region.+ -- + -- @use :: [r : %]. Global r => Empty (Use r)@+ | WbConUse ++ -- | Convert a capability guaranteeing the constancy of a region, into+ -- a witness that a read from that region is pure.+ -- This lets us suspend applications that read constant objects,+ -- because it doesn't matter if the read is delayed, we'll always+ -- get the same result.+ --+ -- @read :: [r : %]. Const r => Pure (Read r)@+ | WbConRead ++ -- | Convert a capability guaranteeing the constancy of a region, into+ -- a witness that allocation into that region is pure.+ -- This lets us increase the sharing of constant objects,+ -- because we can't tell constant objects of the same value apart.+ -- + -- @alloc :: [r : %]. Const r => Pure (Alloc r)@+ | WbConAlloc+ deriving (Eq, Show)
+ DDC/Core/Exp/NFData.hs view
@@ -0,0 +1,82 @@++module DDC.Core.Exp.NFData where+import DDC.Core.Exp.Base+import Control.DeepSeq+++instance (NFData a, NFData n) => NFData (Exp a n) where+ rnf xx+ = case xx of+ XVar a u -> rnf a `seq` rnf u+ XCon a dc -> rnf a `seq` rnf dc+ XLAM a b x -> rnf a `seq` rnf b `seq` rnf x+ XLam a b x -> rnf a `seq` rnf b `seq` rnf x+ XApp a x1 x2 -> rnf a `seq` rnf x1 `seq` rnf x2+ XLet a lts x -> rnf a `seq` rnf lts `seq` rnf x+ XCase a x alts -> rnf a `seq` rnf x `seq` rnf alts+ XCast a c x -> rnf a `seq` rnf c `seq` rnf x+ XType t -> rnf t+ XWitness w -> rnf w+++instance (NFData a, NFData n) => NFData (Cast a n) where+ rnf cc+ = case cc of+ CastWeakenEffect e -> rnf e+ CastWeakenClosure xs -> rnf xs+ CastPurify w -> rnf w+ CastForget w -> rnf w+++instance (NFData a, NFData n) => NFData (Lets a n) where+ rnf lts+ = case lts of+ LLet mode b x -> rnf mode `seq` rnf b `seq` rnf x+ LRec bxs -> rnf bxs+ LLetRegions bs1 bs2 -> rnf bs1 `seq` rnf bs2+ LWithRegion u -> rnf u+++instance NFData n => NFData (LetMode n) where+ rnf mode+ = case mode of+ LetStrict -> ()+ LetLazy mw -> rnf mw+++instance (NFData a, NFData n) => NFData (Alt a n) where+ rnf aa+ = case aa of+ AAlt w x -> rnf w `seq` rnf x+++instance NFData n => NFData (Pat n) where+ rnf pp+ = case pp of+ PDefault -> ()+ PData dc bs -> rnf dc `seq` rnf bs+++instance NFData n => NFData (Witness n) where+ rnf ww+ = case ww of+ WVar u -> rnf u+ WCon c -> rnf c+ WApp w1 w2 -> rnf w1 `seq` rnf w2+ WJoin w1 w2 -> rnf w1 `seq` rnf w2+ WType tt -> rnf tt+++instance NFData n => NFData (WiCon n) where+ rnf wi+ = case wi of+ WiConBuiltin wb -> rnf wb+ WiConBound u t -> rnf u `seq` rnf t++instance NFData WbCon++++++
+ DDC/Core/Fragment.hs view
@@ -0,0 +1,65 @@++-- | The ambient Disciple Core language is specialised to concrete languages+-- by adding primitive operations and optionally restricting the set of +-- available language features. This specialisation results in user-facing+-- language fragments such as @Disciple Core Lite@ and @Disciple Core Salt@.+module DDC.Core.Fragment+ ( -- * Langauge fragments+ Fragment (..)+ , Profile (..)+ , zeroProfile++ -- * Fragment features+ , Feature (..)+ , Features (..)+ , zeroFeatures++ -- * Compliance+ , complies+ , compliesWithEnvs+ , Complies+ , Error (..))+where+import DDC.Core.Fragment.Feature+import DDC.Core.Fragment.Compliance+import DDC.Core.Fragment.Error+import DDC.Core.Fragment.Profile+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Lexer+import DDC.Data.Token+++-- Fragment -------------------------------------------------------------------+-- | Carries all the information we need to work on a particular +-- fragment of the Disciple Core language.+data Fragment n (err :: * -> *)+ = Fragment+ { -- | Language profile for this fragment.+ fragmentProfile :: Profile n++ -- | File extension to use when dumping modules in this fragment.+ , fragmentExtension :: String++ -- | Read a name.+ , fragmentReadName :: String -> Maybe n+ + -- | Lex module source into tokens,+ -- given the source name and starting line number. + , fragmentLexModule :: String -> Int -> String -> [Token (Tok n)]++ -- | Lex expression source into tokens,+ -- given the source name and starting line number.+ , fragmentLexExp :: String -> Int -> String -> [Token (Tok n)]++ -- | Perform language fragment specific checks on a module.+ , fragmentCheckModule :: forall a. Module a n -> Maybe (err a)++ -- | Perform language fragment specific checks on an expression.+ , fragmentCheckExp :: forall a. Exp a n -> Maybe (err a) }+++instance Show (Fragment n err) where+ show frag+ = profileName $ fragmentProfile frag+
+ DDC/Core/Fragment/Compliance.hs view
@@ -0,0 +1,388 @@++module DDC.Core.Fragment.Compliance+ ( complies+ , compliesWithEnvs+ , Complies)+where+import DDC.Core.Fragment.Feature+import DDC.Core.Fragment.Profile+import DDC.Core.Fragment.Error+import DDC.Core.Compounds+import DDC.Core.Predicates+import DDC.Core.Module+import DDC.Core.Exp+import Control.Monad+import Data.Maybe+import DDC.Type.Env (Env)+import Data.Set (Set)+import qualified DDC.Type.Env as Env+import qualified Data.Set as Set+import qualified Data.Map.Strict as Map+++-- | Check whether a core thing complies with a language fragment profile.+complies + :: (Ord n, Show n, Complies c)+ => Profile n -- ^ Fragment profile giving the supported+ -- language features and primitive operators.+ -> c a n -- ^ The thing to check.+ -> Maybe (Error n)++complies profile thing+ = compliesWithEnvs profile+ (profilePrimKinds profile)+ (profilePrimTypes profile)+ thing+++-- | Like `complies` but with some starting environments.+compliesWithEnvs+ :: (Ord n, Show n, Complies c)+ => Profile n -- ^ Fragment profile giving the supported+ -- language features and primitive operators.+ -> Env.KindEnv n -- ^ Starting kind environment.+ -> Env.TypeEnv n -- ^ Starting type environment.+ -> c a n -- ^ The thing to check.+ -> Maybe (Error n)++compliesWithEnvs profile kenv tenv thing+ = let merr = result + $ compliesX profile + kenv tenv+ contextTop thing+ in case merr of+ Left err -> Just err+ Right _ -> Nothing++++-- Complies -------------------------------------------------------------------+-- | Class of things we can check language fragment compliance for.+class Complies (c :: * -> * -> *) where+ -- Check compliance of a well typed term with a language profile.+ -- If it is not well typed then this can return a bad result.+ compliesX+ :: (Ord n, Show n)+ => Profile n -- ^ Fragment profile giving the supported+ -- language features and primitive operators.+ -> Env n -- ^ Starting Kind environment.+ -> Env n -- ^ Starting Type environment.+ -> Context+ -> c a n + -> CheckM n+ (Set n, Set n) -- Used type and value names.+++instance Complies Module where+ compliesX profile kenv tenv context mm+ = do let bs = [ BName n t + | (n, (_, t)) <- Map.toList $ moduleImportTypes mm ]+ let tenv' = Env.extends bs tenv+ compliesX profile kenv tenv' context (moduleBody mm)+++-- We'll mark type vars that only appear in types of binders as unused.+instance Complies Exp where+ compliesX profile kenv tenv context xx+ = let has f = f $ profileFeatures profile+ ok = return (Set.empty, Set.empty)+ in case xx of++ -- variables ----------------------------+ XVar _ u@(UName n)+ | not $ Env.member u tenv+ , not $ has featuresUnboundLevel0Vars + -> throw $ ErrorUndefinedVar n++ | args <- fromMaybe 0 $ contextFunArgs context+ , Just t <- Env.lookup u tenv+ , arity <- arityOfType t+ , args < arity+ , not $ has featuresPartialApplication+ -> throw $ ErrorUnsupported PartialApplication++ | otherwise+ -> return (Set.empty, Set.singleton n)++ XVar _ u@(UPrim n t)+ | not $ Env.member u (profilePrimTypes profile)+ -> throw $ ErrorUndefinedPrim n++ | args <- fromMaybe 0 $ contextFunArgs context+ , arity <- arityOfType t+ , args < arity+ , not $ has featuresPartialPrims+ -> throw $ ErrorUnsupported PartialPrims++ | otherwise+ -> return (Set.empty, Set.empty)++ XVar{} -> ok++ -- constructors -------------------------+ XCon{} -> ok++ -- spec binders -------------------------+ XLAM _ b x+ | contextAbsBody context+ , not $ has featuresNestedFunctions+ -> throw $ ErrorUnsupported NestedFunctions++ | otherwise+ -> do + -- If the body isn't another lambda then remember+ -- that we've entered into a function.+ let context'+ | isXLAM x || isXLam x = context+ | otherwise = setBody context++ (tUsed, vUsed) <- compliesX profile + (Env.extend b kenv) tenv + context' x++ tUsed' <- checkBind profile kenv b tUsed+ return (tUsed', vUsed)++ -- value and witness abstraction --------+ XLam _ b x+ | contextAbsBody context+ , not $ has featuresNestedFunctions+ -> throw $ ErrorUnsupported NestedFunctions++ | otherwise+ -> do + -- If the body isn't another lambda then remember+ -- that we've entered into a function.+ let context'+ | isXLAM x || isXLam x = context+ | otherwise = setBody context++ (tUsed, vUsed) <- compliesX profile + kenv (Env.extend b tenv)+ context' x++ vUsed' <- checkBind profile tenv b vUsed+ return (tUsed, vUsed')+ + -- application --------------------------+ XApp _ x1 (XType t2)+ | profileTypeIsUnboxed profile t2+ , Nothing <- takeXPrimApps xx+ -> throw $ ErrorUnsupported UnboxedInstantiation++ | otherwise+ -> do checkFunction profile x1+ compliesX profile kenv tenv (addArg context) x1++ XApp _ x1 XWitness{}+ -> do checkFunction profile x1+ compliesX profile kenv tenv (addArg context) x1++ XApp _ x1 x2+ -> do checkFunction profile x1+ (tUsed1, vUsed1) <- compliesX profile kenv tenv (addArg context) x1+ (tUsed2, vUsed2) <- compliesX profile kenv tenv context x2+ return ( Set.union tUsed1 tUsed2+ , Set.union vUsed1 vUsed2)++ -- let ----------------------------------+ XLet _ (LLet mode b1 x1) x2+ -> do let tenv' = Env.extend b1 tenv+ (tUsed1, vUsed1) <- compliesX profile kenv tenv (reset context) x1+ (tUsed2, vUsed2) <- compliesX profile kenv tenv' (reset context) x2+ vUsed2' <- checkBind profile tenv b1 vUsed2++ -- Check for unsupported lazy bindings.+ (case mode of+ LetStrict -> return ()+ LetLazy _ + | has featuresLazyBindings -> return ()+ | otherwise + -> throw $ ErrorUnsupported LazyBindings)++ return ( Set.union tUsed1 tUsed2+ , Set.union vUsed1 vUsed2')++ XLet _ (LRec bxs) x2+ -> do let (bs, xs) = unzip bxs+ let tenv' = Env.extends bs tenv++ (tUseds1, vUseds1) + <- liftM unzip+ $ mapM (compliesX profile kenv tenv' (reset context)) + xs++ (tUsed2, vUsed2) <- compliesX profile kenv tenv' (reset context) x2+ let tUseds = Set.unions (tUsed2 : tUseds1)+ let vUseds = Set.unions (vUsed2 : vUseds1)++ vUseds' <- checkBinds profile tenv bs vUseds+ return (tUseds, vUseds')+++ XLet _ (LLetRegions rs bs) x2+ -> do (tUsed2, vUsed2) + <- compliesX profile (Env.extends rs kenv) + (Env.extends bs tenv) + (reset context) x2+ return (tUsed2, vUsed2)++ XLet _ (LWithRegion _) x2+ -> do (tUsed2, vUsed2) <- compliesX profile kenv tenv + (reset context) x2+ return (tUsed2, vUsed2)++ -- case ---------------------------------+ XCase _ x1 alts+ -> do (tUsed1, vUsed1) + <- compliesX profile kenv tenv (reset context) x1++ (tUseds2, vUseds2) <- liftM unzip + $ mapM (compliesX profile kenv tenv (reset context)) alts++ return ( Set.unions $ tUsed1 : tUseds2+ , Set.unions $ vUsed1 : vUseds2)+++ -- cast ---------------------------------+ XCast _ _ x -> compliesX profile kenv tenv (reset context) x++ -- type and witness ---------------------+ XType t -> throw $ ErrorNakedType t+ XWitness w -> throw $ ErrorNakedWitness w+++instance Complies Alt where+ compliesX profile kenv tenv context aa+ = case aa of+ AAlt PDefault x+ -> do (tUsed1, vUsed1) <- compliesX profile kenv tenv + (reset context) x+ return (tUsed1, vUsed1)++ AAlt (PData _ bs) x+ -> do (tUsed1, vUsed1) <- compliesX profile kenv (Env.extends bs tenv) + (reset context) x+ vUsed1' <- checkBinds profile tenv bs vUsed1 + return (tUsed1, vUsed1')+++-- Bind -----------------------------------------------------------------------+-- | Check for compliance violations at a binding site.+checkBind + :: Ord n + => Profile n -- ^ The current language profile.+ -> Env n -- ^ The current environment+ -> Bind n -- ^ The binder at this site.+ -> Set n -- ^ Names used under the binder.+ -> CheckM n (Set n) -- ^ Names used above the binder.++checkBind profile env bb used+ = let has f = f $ profileFeatures profile+ in case bb of+ BName n _+ | not $ Set.member n used+ , not $ has featuresUnusedBindings + -> throw $ ErrorUnusedBind n++ | Env.memberBind bb env+ , not $ has featuresNameShadowing + -> throw $ ErrorShadowedBind n++ | otherwise+ -> return $ Set.delete n used++ BAnon{}+ | not $ has featuresDebruijnBinders+ -> throw $ ErrorUnsupported DebruijnBinders++ _ -> return used+++-- | Check for compliance violations at a binding site.+-- The binders must all be at the same level.+checkBinds + :: Ord n + => Profile n + -> Env n -> [Bind n] -> Set n + -> CheckM n (Set n)++checkBinds profile env bs used+ = case bs of+ [] -> return used+ (b : bs') + -> do used' <- checkBinds profile env bs' used+ checkBind profile env b used'+++-- Function -------------------------------------------------------------------+-- | Check the function part of an application.+checkFunction :: Profile n -> Exp a n -> CheckM n ()+checkFunction profile xx + = let has f = f $ profileFeatures profile+ ok = return ()+ in case xx of+ XVar{} -> ok+ XCon{} -> ok+ XApp{} -> ok+ XCast{} -> ok+ _+ | has featuresGeneralApplication -> return ()+ | otherwise -> throw $ ErrorUnsupported GeneralApplication+++-- Context --------------------------------------------------------------------+data Context+ = Context+ { contextAbsBody :: Bool + , contextFunArgs :: Maybe Int }+ deriving (Eq, Show)+++-- | The top level context, used at the top-level scope of a module.+contextTop :: Context+contextTop+ = Context+ { contextAbsBody = False+ , contextFunArgs = Nothing }+++-- | Record that we've entered into an abstraction body.+setBody :: Context -> Context+setBody context = context { contextAbsBody = True }+++-- | Record that the expression is being directly applied to an argument.+addArg :: Context -> Context+addArg context+ = case contextFunArgs context of+ Nothing -> context { contextFunArgs = Just 1 }+ Just args -> context { contextFunArgs = Just (args + 1) }+++-- | Reset the argument counter of a context.+reset :: Context -> Context+reset context = context { contextFunArgs = Nothing } +++-- Monad ----------------------------------------------------------------------+-- | Compliance checking monad.+data CheckM n x+ = CheckM (Either (Error n) x)++instance Monad (CheckM n) where+ return x = CheckM (Right x)+ (>>=) m f + = case m of+ CheckM (Left err) -> CheckM (Left err)+ CheckM (Right x) -> f x+++-- | Throw an error in the monad.+throw :: Error n -> CheckM n x+throw e = CheckM $ Left e+++-- | Take the result from a check monad.+result :: CheckM n x -> Either (Error n) x+result (CheckM r) = r
+ DDC/Core/Fragment/Error.hs view
@@ -0,0 +1,59 @@++module DDC.Core.Fragment.Error+ (Error(..))+where+import DDC.Core.Fragment.Feature+import DDC.Core.Exp+import DDC.Core.Pretty+++-- | Language fragment compliance violations.+data Error n+ -- | Found an unsupported language feature.+ = ErrorUnsupported !Feature++ -- | Found an undefined primitive operator.+ | ErrorUndefinedPrim !n ++ -- | Found an unbound variable.+ | ErrorUndefinedVar !n++ -- | Found a variable binder that shadows another one at a higher scope,+ -- but the profile doesn't permit this.+ | ErrorShadowedBind !n++ -- | Found a bound variable with no uses,+ -- but the profile doesn't permit this.+ | ErrorUnusedBind !n++ -- | Found a naked type that isn't used as a function argument.+ | ErrorNakedType !(Type n)++ -- | Found a naked witness that isn't used as a function argument.+ | ErrorNakedWitness !(Witness n)+ deriving (Eq, Show)+++instance (Pretty n, Eq n) => Pretty (Error n) where+ ppr err+ = case err of+ ErrorUnsupported feature+ -> vcat [ text "Unsupported feature: " <> text (show feature) ]++ ErrorUndefinedPrim n+ -> vcat [ text "Undefined primitive: " <> ppr n ]++ ErrorUndefinedVar n+ -> vcat [ text "Undefined variable: " <> ppr n ]++ ErrorShadowedBind n+ -> vcat [ text "Binding shadows existing name: " <> ppr n ]++ ErrorUnusedBind n+ -> vcat [ text "Bound name is not used: " <> ppr n ]++ ErrorNakedType t+ -> vcat [ text "Naked type is not a function argument: " <> ppr t]++ ErrorNakedWitness w+ -> vcat [ text "Naked witness is not a function argument: " <> ppr w ]
+ DDC/Core/Fragment/Feature.hs view
@@ -0,0 +1,63 @@++module DDC.Core.Fragment.Feature+ (Feature(..))+where+++-- | Language feature supported by a fragment.+data Feature+ -- Type system features ---------------------------+ -- | Assume all functions perform global side effects, + -- and don't generate effect terms in types.+ = UntrackedEffects++ -- | Assume all functions share data invisibly,+ -- and don't generate closure terms in types.+ | UntrackedClosures++ -- General features -------------------------------+ -- | Partially applied primitive operators.+ | PartialPrims++ -- | Partially applied functions+ | PartialApplication++ -- | Function application where the thing being applied+ -- is not a variable.+ -- Most backend languages (like LLVM) don't support this.+ | GeneralApplication++ -- | Nested function bindings.+ -- The output of the lambda-lifter should not contain these.+ | NestedFunctions++ -- | Lazy let-bindings.+ -- Turning this off means the runtime system won't need to build+ -- suspensions.+ | LazyBindings++ -- | Debruijn binders.+ -- Most backends will want to use real names, instead of indexed+ -- binders.+ | DebruijnBinders++ -- | Allow data and witness vars without binding occurrences if+ -- they are annotated directly with their types. This lets+ -- us work with open terms.+ | UnboundLevel0Vars++ -- | Allow non-primitive functions to be instantiated at unboxed types.+ -- Our existing backends can't handle this, because boxed and unboxed+ -- objects have different representations.+ | UnboxedInstantiation++ -- Sanity -----------------------------------------+ -- | Allow name shadowing.+ | NameShadowing++ -- | Allow unused named data and witness bindings.+ | UnusedBindings++ -- | Allow unused named matches.+ | UnusedMatches+ deriving (Eq, Ord, Show)
+ DDC/Core/Fragment/Profile.hs view
@@ -0,0 +1,111 @@++-- | A fragment profile determines what features a program can use.+module DDC.Core.Fragment.Profile+ ( Profile (..)+ , zeroProfile++ , Features(..)+ , zeroFeatures+ , setFeature)+where+import DDC.Core.Fragment.Feature+import DDC.Type.DataDef+import DDC.Type.Exp+import DDC.Type.Env (KindEnv, TypeEnv)+import qualified DDC.Type.Env as Env+++-- | The fragment profile describes the language features and +-- primitive operators available in the language.+data Profile n+ = Profile+ { -- | The name of this profile.+ profileName :: !String++ -- | Permitted language features.+ , profileFeatures :: !Features++ -- | Primitive data type declarations.+ , profilePrimDataDefs :: !(DataDefs n)++ -- | Kinds of primitive types.+ , profilePrimKinds :: !(KindEnv n)++ -- | Types of primitive operators.+ , profilePrimTypes :: !(TypeEnv n)++ -- | Check whether a type is an unboxed type.+ -- Some fragments limit how these can be used.+ , profileTypeIsUnboxed :: !(Type n -> Bool) }+++-- | A language profile with no features or primitive operators.+--+-- This provides a simple first-order language.+zeroProfile :: Profile n+zeroProfile+ = Profile+ { profileName = "Zero"+ , profileFeatures = zeroFeatures+ , profilePrimDataDefs = emptyDataDefs+ , profilePrimKinds = Env.empty+ , profilePrimTypes = Env.empty+ , profileTypeIsUnboxed = const False }+++-- | A flattened set of features, for easy lookup.+data Features + = Features+ { featuresUntrackedEffects :: Bool+ , featuresUntrackedClosures :: Bool+ , featuresPartialPrims :: Bool+ , featuresPartialApplication :: Bool+ , featuresGeneralApplication :: Bool+ , featuresNestedFunctions :: Bool+ , featuresLazyBindings :: Bool+ , featuresDebruijnBinders :: Bool+ , featuresUnboundLevel0Vars :: Bool+ , featuresUnboxedInstantiation :: Bool+ , featuresNameShadowing :: Bool+ , featuresUnusedBindings :: Bool+ , featuresUnusedMatches :: Bool+ }+++-- | An emtpy feature set, with all flags set to `False`.+zeroFeatures :: Features+zeroFeatures+ = Features+ { featuresUntrackedEffects = False+ , featuresUntrackedClosures = False+ , featuresPartialPrims = False+ , featuresPartialApplication = False+ , featuresGeneralApplication = False+ , featuresNestedFunctions = False+ , featuresLazyBindings = False+ , featuresDebruijnBinders = False+ , featuresUnboundLevel0Vars = False+ , featuresUnboxedInstantiation = False+ , featuresNameShadowing = False+ , featuresUnusedBindings = False+ , featuresUnusedMatches = False }+++-- | Set a language `Flag` in the `Profile`.+setFeature :: Feature -> Bool -> Features -> Features+setFeature feature val features+ = case feature of+ UntrackedEffects -> features { featuresUntrackedEffects = val }+ UntrackedClosures -> features { featuresUntrackedClosures = val }+ PartialPrims -> features { featuresPartialPrims = val }+ PartialApplication -> features { featuresPartialApplication = val }+ GeneralApplication -> features { featuresGeneralApplication = val }+ NestedFunctions -> features { featuresNestedFunctions = val }+ LazyBindings -> features { featuresLazyBindings = val }+ DebruijnBinders -> features { featuresDebruijnBinders = val }+ UnboundLevel0Vars -> features { featuresUnboundLevel0Vars = val }+ UnboxedInstantiation -> features { featuresUnboxedInstantiation = val }+ NameShadowing -> features { featuresNameShadowing = val }+ UnusedBindings -> features { featuresUnusedBindings = val }+ UnusedMatches -> features { featuresUnusedMatches = val }+
+ DDC/Core/Lexer.hs view
@@ -0,0 +1,215 @@++-- | Reference lexer for core langauge parser. Slow but Simple.+--+-- The lexers here all use 'String' in place of a real name type.+-- After applying these functions to the program text, we need+-- to use `renameTok` tok convert the strings in `TokNamed` tokens+-- into the name type specific to the langauge fragment to be parsed.+--+module DDC.Core.Lexer+ ( module DDC.Core.Lexer.Tokens+ , module DDC.Core.Lexer.Names++ -- * Lexer+ , lexModuleWithOffside+ , lexExp)+where+import DDC.Core.Lexer.Offside+import DDC.Core.Lexer.Comments+import DDC.Core.Lexer.Names+import DDC.Core.Lexer.Tokens+import DDC.Data.SourcePos+import DDC.Data.Token+import Data.Char+++-- Module ---------------------------------------------------------------------+-- | Lex a module and apply the offside rule.+--+-- Automatically drop comments from the token stream along the way.+--+lexModuleWithOffside + :: FilePath -- ^ Path to source file, for error messages.+ -> Int -- ^ Starting line number.+ -> String -- ^ String containing program text.+ -> [Token (Tok String)]++lexModuleWithOffside sourceName lineStart str+ = {-# SCC lexWithOffside #-}+ applyOffside [] + $ addStarts+ $ dropComments + $ lexString sourceName lineStart str+++-- Exp ------------------------------------------------------------------------+-- | Lex a string into tokens.+--+-- Automatically drop comments from the token stream along the way.+--+lexExp :: FilePath -- ^ Path to source file, for error messages.+ -> Int -- ^ Starting line number.+ -> String -- ^ String containing program text.+ -> [Token (Tok String)]++lexExp sourceName lineStart str+ = {-# SCC lexExp #-}+ dropNewLines+ $ dropComments+ $ lexString sourceName lineStart str+++-- Generic --------------------------------------------------------------------+lexString :: String -> Int -> String -> [Token (Tok String)]+lexString sourceName lineStart str+ = lexWord lineStart 1 str+ where + lexWord :: Int -> Int -> String -> [Token (Tok String)]+ lexWord line column w+ = let tok t = Token t (SourcePos sourceName line column)+ tokM = tok . KM+ tokA = tok . KA+ tokN = tok . KN++ lexMore n rest+ = lexWord line (column + n) rest++ in case w of+ [] -> [] ++ -- Whitespace+ ' ' : w' -> lexMore 1 w'+ '\t' : w' -> lexMore 8 w'++ -- Literal values+ -- This needs to come before the rule for '-'+ c : cs+ | isDigit c+ , (body, rest) <- span isLitBody cs+ -> tokN (KLit (c:body)) : lexMore (length (c:body)) rest++ '-' : c : cs+ | isDigit c+ , (body, rest) <- span isLitBody cs+ -> tokN (KLit ('-':c:body)) : lexMore (length (c:body)) rest++ -- Meta tokens+ '{' : '-' : w' -> tokM KCommentBlockStart : lexMore 2 w'+ '-' : '}' : w' -> tokM KCommentBlockEnd : lexMore 2 w'+ '-' : '-' : w' -> tokM KCommentLineStart : lexMore 2 w'+ '\n' : w' -> tokM KNewLine : lexWord (line + 1) 1 w'+++ -- The unit data constructor+ '(' : ')' : w' -> tokA KDaConUnit : lexMore 2 w'++ -- Compound Parens+ '[' : ':' : w' -> tokA KSquareColonBra : lexMore 2 w'+ ':' : ']' : w' -> tokA KSquareColonKet : lexMore 2 w'+ '<' : ':' : w' -> tokA KAngleColonBra : lexMore 2 w'+ ':' : '>' : w' -> tokA KAngleColonKet : lexMore 2 w'++ -- Function Constructors+ '~' : '>' : w' -> tokA KArrowTilde : lexMore 2 w'+ '-' : '>' : w' -> tokA KArrowDash : lexMore 2 w'+ '<' : '-' : w' -> tokA KArrowDashLeft : lexMore 2 w'+ '=' : '>' : w' -> tokA KArrowEquals : lexMore 2 w'++ -- Compound symbols+ ':' : ':' : w' -> tokA KColonColon : lexMore 2 w'+ '/' : '\\' : w' -> tokA KBigLambda : lexMore 2 w'++ -- Debruijn indices+ '^' : cs+ | (ds, rest) <- span isDigit cs+ , length ds >= 1+ -> tokA (KIndex (read ds)) : lexMore (1 + length ds) rest ++ -- Parens+ '(' : w' -> tokA KRoundBra : lexMore 1 w'+ ')' : w' -> tokA KRoundKet : lexMore 1 w'+ '[' : w' -> tokA KSquareBra : lexMore 1 w'+ ']' : w' -> tokA KSquareKet : lexMore 1 w'+ '{' : w' -> tokA KBraceBra : lexMore 1 w'+ '}' : w' -> tokA KBraceKet : lexMore 1 w'+ '<' : w' -> tokA KAngleBra : lexMore 1 w'+ '>' : w' -> tokA KAngleKet : lexMore 1 w' ++ -- Punctuation+ '.' : w' -> tokA KDot : lexMore 1 w'+ '|' : w' -> tokA KBar : lexMore 1 w'+ '^' : w' -> tokA KHat : lexMore 1 w'+ '+' : w' -> tokA KPlus : lexMore 1 w'+ ':' : w' -> tokA KColon : lexMore 1 w'+ ',' : w' -> tokA KComma : lexMore 1 w'+ '\\' : w' -> tokA KBackSlash : lexMore 1 w'+ ';' : w' -> tokA KSemiColon : lexMore 1 w'+ '_' : w' -> tokA KUnderscore : lexMore 1 w'+ '=' : w' -> tokA KEquals : lexMore 1 w'+ '&' : w' -> tokA KAmpersand : lexMore 1 w'+ '-' : w' -> tokA KDash : lexMore 1 w'+ + -- Bottoms+ '!' : '0' : w' -> tokA KBotEffect : lexMore 2 w'+ '$' : '0' : w' -> tokA KBotClosure : lexMore 2 w'++ -- Sort Constructors+ '*' : '*' : w' -> tokA KSortComp : lexMore 2 w'+ '@' : '@' : w' -> tokA KSortProp : lexMore 2 w' ++ -- Kind Constructors+ '*' : w' -> tokA KKindValue : lexMore 1 w'+ '%' : w' -> tokA KKindRegion : lexMore 1 w'+ '!' : w' -> tokA KKindEffect : lexMore 1 w'+ '$' : w' -> tokA KKindClosure : lexMore 1 w'+ '@' : w' -> tokA KKindWitness : lexMore 1 w'+ ++ -- Named Constructors+ c : cs+ | isConStart c+ , (body, rest) <- span isConBody cs+ , (body', rest') <- case rest of+ '#' : rest' -> (body ++ "#", rest')+ _ -> (body, rest)+ -> let readNamedCon s+ | Just twcon <- readTwConBuiltin s+ = tokA (KTwConBuiltin twcon) : lexMore (length s) rest'+ + | Just tccon <- readTcConBuiltin s+ = tokA (KTcConBuiltin tccon) : lexMore (length s) rest'+ + | Just con <- readCon s+ = tokN (KCon con) : lexMore (length s) rest'+ + | otherwise + = [tok (KJunk [c])]+ + in readNamedCon (c : body')++ -- Keywords, Named Variables and Witness constructors+ c : cs+ | isVarStart c+ , (body, rest) <- span isVarBody cs+ , (body', rest') <- case rest of+ '#' : rest' -> (body ++ "#", rest')+ _ -> (body, rest)+ -> let readNamedVar s+ | Just t <- lookup s keywords+ = tok t : lexMore (length s) rest'++ | Just wc <- readWbConBuiltin s+ = tokA (KWbConBuiltin wc) : lexMore (length s) rest'+ + | Just v <- readVar s+ = tokN (KVar v) : lexMore (length s) rest'++ | otherwise+ = [tok (KJunk [c])]++ in readNamedVar (c : body')++ -- Some unrecognised character.+ -- We still need to keep lexing as this may be in a comment.+ c : cs -> (tok $ KJunk [c]) : lexMore 1 cs+
+ DDC/Core/Lexer/Comments.hs view
@@ -0,0 +1,64 @@++module DDC.Core.Lexer.Comments+ ( dropComments+ , dropNewLines)+where+import DDC.Core.Lexer.Tokens+import DDC.Data.Token+import DDC.Data.SourcePos+++-- | Drop all the comments and newline tokens in this stream.+dropComments + :: Eq n => [Token (Tok n)] -> [Token (Tok n)]++dropComments [] = []+dropComments (t@(Token tok sourcePos) : xs)+ = case tok of+ KM KCommentLineStart + -> dropComments $ dropWhile (\t' -> not $ isToken t' (KM KNewLine)) xs++ KM KCommentBlockStart + -> dropComments $ dropCommentBlock sourcePos xs t++ _ -> t : dropComments xs+++-- | Drop block comments form a token stream.+dropCommentBlock + :: Eq n+ => SourcePos -- ^ Position of outer-most block comment start.+ -> [Token (Tok n)] + -> Token (Tok n) + -> [Token (Tok n)]++dropCommentBlock spStart [] _terr+ = [Token (KM KCommentUnterminated) spStart]++dropCommentBlock spStart (t@(Token tok _) : xs) terr+ = case tok of+ -- enter into nested block comments.+ KM KCommentBlockStart+ -> dropCommentBlock spStart (dropCommentBlock spStart xs t) terr++ -- outer-most block comment has ended.+ KM KCommentBlockEnd+ -> xs++ _ -> dropCommentBlock spStart xs terr+++-- | Drop newline tokens from this list.+dropNewLines :: Eq n => [Token (Tok n)] -> [Token (Tok n)]+dropNewLines [] = []+dropNewLines (t:ts)+ | isToken t (KM KNewLine)+ = dropNewLines ts++ | otherwise+ = t : dropNewLines ts+++isToken :: Eq n => Token (Tok n) -> Tok n -> Bool+isToken (Token tok _) tok2 = tok == tok2+
+ DDC/Core/Lexer/Names.hs view
@@ -0,0 +1,226 @@++module DDC.Core.Lexer.Names+ ( -- * Keywords+ keywords++ -- * Builtin constructors+ , readTwConBuiltin+ , readTcConBuiltin+ , readWbConBuiltin++ -- * Variable names+ , isVarName+ , isVarStart+ , isVarBody+ , readVar++ -- * Constructor names+ , isConName+ , isConStart+ , isConBody+ , readCon++ -- * Literal names+ , isLitName+ , isLitStart+ , isLitBody)+where+import DDC.Core.Exp+import DDC.Core.Lexer.Tokens+import DDC.Data.ListUtils+import Data.Char+import Data.List+++-- | Textual keywords in the core language.+keywords :: [(String, Tok n)]+keywords+ = [ ("module", KA KModule)+ , ("imports", KA KImports)+ , ("exports", KA KExports)+ , ("in", KA KIn)+ , ("of", KA KOf) + , ("letrec", KA KLetRec)+ , ("letregions", KA KLetRegions)+ , ("letregion", KA KLetRegion)+ , ("withregion", KA KWithRegion)+ , ("let", KA KLet)+ , ("lazy", KA KLazy)+ , ("case", KA KCase)+ , ("purify", KA KPurify)+ , ("forget", KA KForget)+ , ("type", KA KType)+ , ("weakeff", KA KWeakEff)+ , ("weakclo", KA KWeakClo)+ , ("with", KA KWith)+ , ("where", KA KWhere) + , ("do", KA KDo)+ , ("match", KA KMatch)+ , ("else", KA KElse) ]+++-- | Read a named `TwCon`. +readTwConBuiltin :: String -> Maybe TwCon+readTwConBuiltin ss+ = case ss of+ "Global" -> Just TwConGlobal+ "DeepGlobal" -> Just TwConDeepGlobal+ "Const" -> Just TwConConst+ "DeepConst" -> Just TwConDeepConst+ "Mutable" -> Just TwConMutable+ "DeepMutable" -> Just TwConDeepMutable+ "Lazy" -> Just TwConLazy+ "HeadLazy" -> Just TwConHeadLazy+ "Manifest" -> Just TwConManifest+ "Pure" -> Just TwConPure+ "Empty" -> Just TwConEmpty+ "Disjoint" -> Just TwConDisjoint+ "Distinct" -> Just (TwConDistinct 2)+ _ -> readTwConWithArity ss+++readTwConWithArity :: String -> Maybe TwCon+readTwConWithArity ss+ | Just n <- stripPrefix "Distinct" ss + , all isDigit n+ = Just (TwConDistinct $ read n)+ | otherwise = Nothing+ + +-- | Read a builtin `TcCon` with a non-symbolic name, +-- ie not '->'.+readTcConBuiltin :: String -> Maybe TcCon+readTcConBuiltin ss+ = case ss of+ "Unit" -> Just TcConUnit+ "Read" -> Just TcConRead+ "HeadRead" -> Just TcConHeadRead+ "DeepRead" -> Just TcConDeepRead+ "Write" -> Just TcConWrite+ "DeepWrite" -> Just TcConDeepWrite+ "Alloc" -> Just TcConAlloc+ "DeepAlloc" -> Just TcConDeepAlloc+ "Use" -> Just TcConUse+ "DeepUse" -> Just TcConDeepUse+ _ -> Nothing+++-- | Read a `WbCon`.+readWbConBuiltin :: String -> Maybe WbCon+readWbConBuiltin ss+ = case ss of+ "pure" -> Just WbConPure+ "empty" -> Just WbConEmpty+ "use" -> Just WbConUse+ "read" -> Just WbConRead+ "alloc" -> Just WbConAlloc+ _ -> Nothing+++-- Variable names -------------------------------------------------------------+-- | String is a variable name+isVarName :: String -> Bool+isVarName str+ = case str of+ [] -> False+ c : cs + | isVarStart c + , and (map isVarBody cs)+ -> True+ + | _ : _ <- cs+ , Just initCs <- takeInit cs+ , isVarStart c+ , and (map isVarBody initCs)+ , last cs == '#'+ -> True++ | otherwise+ -> False+++-- | Charater can start a variable name.+isVarStart :: Char -> Bool+isVarStart = isLower+ ++-- | Character can be part of a variable body.+isVarBody :: Char -> Bool+isVarBody c+ = isUpper c || isLower c || isDigit c || c == '_' || c == '\''+++-- | Read a named, user defined variable.+readVar :: String -> Maybe String+readVar ss+ | isVarName ss = Just ss+ | otherwise = Nothing+++-- Constructor names ----------------------------------------------------------+-- | String is a constructor name.+isConName :: String -> Bool+isConName str+ = case str of+ [] -> False+ c : cs + | isConStart c + , and (map isConBody cs)+ -> True+ + | _ : _ <- cs+ , Just initCs <- takeInit cs+ , isConStart c+ , and (map isConBody initCs)+ , last cs == '#'+ -> True++ | otherwise+ -> False++-- | Character can start a constructor name.+isConStart :: Char -> Bool+isConStart = isUpper+++-- | Charater can be part of a constructor body.+isConBody :: Char -> Bool+isConBody c = isUpper c || isLower c || isDigit c || c == '_'+ +++-- | Read a named, user defined `TcCon`.+readCon :: String -> Maybe String+readCon ss+ | isConName ss = Just ss+ | otherwise = Nothing+++-- Literal names --------------------------------------------------------------+-- | String is the name of a literal.+isLitName :: String -> Bool+isLitName str+ = case str of+ [] -> False+ c : cs+ | isLitStart c+ , and (map isLitBody cs)+ -> True++ | otherwise+ -> False++-- | Character can start a literal.+isLitStart :: Char -> Bool+isLitStart c+ = isDigit c+ || c == '-'++-- | Character can be part of a literal body.+isLitBody :: Char -> Bool+isLitBody c+ = isDigit c+ || c == 'b' || c == 'o' || c == 'x'+ || c == 'w' || c == 'i' + || c == '#'+
+ DDC/Core/Lexer/Offside.hs view
@@ -0,0 +1,265 @@++-- | Apply the offside rule to a token stream to add braces.+module DDC.Core.Lexer.Offside+ ( Lexeme (..)+ , applyOffside+ , addStarts)+where+import DDC.Core.Lexer.Tokens+import DDC.Data.SourcePos+import DDC.Data.Token+++-- | Holds a real token or start symbol which is used to apply the offside rule.+data Lexeme n+ = LexemeToken (Token (Tok n))+ | LexemeStartLine Int++ -- | Signal that we're starting a block in this column.+ | LexemeStartBlock Int+ deriving (Eq, Show)++type Context+ = Int++-- | Apply the offside rule to this token stream.+-- It should have been processed with addStarts first to add the+-- LexemeStartLine/LexemeStartLine tokens.+--+applyOffside + :: (Eq n, Show n) + => [Context] + -> [Lexeme n] + -> [Token (Tok n)]++-- Wait for the module header before we start applying the real offside rule. +-- This allows us to write 'module Name with letrec' all on the same line.+applyOffside [] (LexemeToken t : ts) + | isToken t (KA KModule)+ || isKNToken t+ = t : applyOffside [] ts++-- When we see the top-level letrec then enter into the outer-most context.+applyOffside [] (LexemeToken t1 : (LexemeStartBlock n) : ls)+ | isToken t1 (KA KLetRec)+ || isToken t1 (KA KExports)+ || isToken t1 (KA KImports)+ = t1 : newCBra ls : applyOffside [n] ls ++-- At top level without a context.+-- Skip over everything until we get the 'with' in 'module Name with ...''+applyOffside [] (LexemeStartLine _ : ts)+ = applyOffside [] ts ++applyOffside [] (LexemeStartBlock _ : ts)+ = applyOffside [] ts+++-- line start+applyOffside mm@(m : ms) (t@(LexemeStartLine n) : ts)+ -- add semicolon to get to the next statement in this block+ | m == n+ = newSemiColon ts : applyOffside mm ts++ -- end a block+ -- we keep the StartLine token in the recursion in case we're ending+ -- multiple blocks difference from Haskell98: add a semicolon as well+ | n < m + = newSemiColon ts : newCKet ts : applyOffside ms (t : ts)++ -- indented continuation of this statement+ | otherwise+ = applyOffside mm ts+++-- block start+applyOffside mm@(m : ms) (LexemeStartBlock n : ts)+ -- enter into a nested context+ | n > m+ = newCBra ts : applyOffside (n : m : ms) ts ++ -- new context starts less than the current one.+ -- This should never happen, + -- provided addStarts works.+ | tNext : _ <- dropNewLinesLexeme ts+ = error $ "DDC.Core.Lexer.Tokens.Offside: layout error on " ++ show tNext ++ "."++ -- new context cannot be less indented than outer one+ -- This should never happen,+ -- as there is no lexeme to start a new context at the end of the file+ | [] <- dropNewLinesLexeme ts+ = error "DDC.Core.Lexer.Tokens.Offside: tried to start new context at end of file."++ -- an empty block+ | otherwise+ = newCBra ts : newCKet ts : applyOffside mm (LexemeStartLine n : ts)+++-- pop contexts from explicit close braces+applyOffside mm (LexemeToken t@Token { tokenTok = KA KBraceKet } : ts) ++ -- make sure that explict open braces match explicit close braces+ | 0 : ms <- mm+ = t : applyOffside ms ts++ -- nup+ | _tNext : _ <- dropNewLinesLexeme ts+ = [newOffsideClosingBrace ts]+++-- push contexts for explicit open braces+applyOffside ms (LexemeToken t@Token { tokenTok = KA KBraceBra } : ts)+ = t : applyOffside (0 : ms) ts++applyOffside ms (LexemeToken t : ts) + = t : applyOffside ms ts++applyOffside [] [] = []++-- close off remaining contexts once we've reached the end of the stream.+applyOffside (_ : ms) [] = newCKet [] : applyOffside ms []+++-- addStarts ------------------------------------------------------------------+-- | Add block and line start tokens to this stream.+-- This is lifted straight from the Haskell98 report.+addStarts :: Eq n => [Token (Tok n)] -> [Lexeme n]+addStarts ts+ = case dropNewLines ts of++ -- If the first lexeme of a module is not '{' then start a new block.+ (t1 : tsRest)+ | not $ or $ map (isToken t1) [KA KBraceBra]+ -> LexemeStartBlock (tokenColumn t1) : addStarts' (t1 : tsRest)++ | otherwise+ -> addStarts' (t1 : tsRest)++ -- empty file+ [] -> []+++addStarts' :: Eq n => [Token (Tok n)] -> [Lexeme n]+addStarts' [] = []+addStarts' (t1 : ts) ++ -- We're starting a block+ | isBlockStart t1+ , [] <- dropNewLines ts+ = LexemeToken t1 : [LexemeStartBlock 0]++ | isBlockStart t1+ , t2 : tsRest <- dropNewLines ts+ , not $ isToken t2 (KA KBraceBra)+ = LexemeToken t1 : LexemeStartBlock (tokenColumn t2)+ : addStarts' (t2 : tsRest)++ -- check for start of list+ | isToken t1 (KA KBraceBra)+ = LexemeToken t1 : addStarts' ts++ -- check for end of list+ | isToken t1 (KA KBraceKet)+ = LexemeToken t1 : addStarts' ts++ -- check for start of new line+ | isToken t1 (KM KNewLine)+ , t2 : tsRest <- dropNewLines ts+ , not $ isToken t2 (KA KBraceBra)+ = LexemeStartLine (tokenColumn t2) + : addStarts' (t2 : tsRest)++ -- eat up trailine newlines+ | isToken t1 (KM KNewLine)+ = addStarts' ts++ -- a regular token+ | otherwise+ = LexemeToken t1 : addStarts' ts+++-- | Drop newline tokens at the front fo this stream.+dropNewLines :: Eq n => [Token (Tok n)] -> [Token (Tok n)]+dropNewLines [] = []+dropNewLines (t1:ts)+ | isToken t1 (KM KNewLine)+ = dropNewLines ts++ | otherwise+ = t1 : ts+++-- | Drop newline tokens at the front fo this stream.+dropNewLinesLexeme :: Eq n => [Lexeme n] -> [Lexeme n]+dropNewLinesLexeme ll+ = case ll of+ [] -> []+ LexemeToken t1 : ts+ | isToken t1 (KM KNewLine)+ -> dropNewLinesLexeme ts++ l : ls+ -> l : dropNewLinesLexeme ls+++-- | Check if a token is one that starts a block of statements.+isBlockStart :: Token (Tok n) -> Bool+isBlockStart Token { tokenTok = tok }+ = case tok of+ KA KDo -> True+ KA KOf -> True+ KA KLetRec -> True+ KA KWhere -> True+ KA KExports -> True+ KA KImports -> True+ _ -> False+++-- Utils ----------------------------------------------------------------------+-- | Test whether this wrapper token matches.+isToken :: Eq n => Token (Tok n) -> Tok n -> Bool+isToken (Token tok _) tok2 = tok == tok2+++-- | Test whether this wrapper token matches.+isKNToken :: Eq n => Token (Tok n) -> Bool+isKNToken (Token (KN _) _) = True+isKNToken _ = False+++-- | When generating new source tokens, take the position from the first+-- non-newline token in this list+newCBra :: [Lexeme n] -> Token (Tok n)+newCBra ts+ = (takeTok ts) { tokenTok = KA KBraceBra }+++newCKet :: [Lexeme n] -> Token (Tok n)+newCKet ts+ = (takeTok ts) { tokenTok = KA KBraceKet }+++newSemiColon :: [Lexeme n] -> Token (Tok n)+newSemiColon ts + = (takeTok ts) { tokenTok = KA KSemiColon }+++-- | This is injected by `applyOffside` when it finds an explit close+-- brace in a position where it would close a synthetic one.+newOffsideClosingBrace :: [Lexeme n] -> Token (Tok n)+newOffsideClosingBrace ts+ = (takeTok ts) { tokenTok = KM KOffsideClosingBrace }+++takeTok :: [Lexeme n] -> Token (Tok n)+takeTok [] + = Token (KJunk "") (SourcePos "" 0 0)++takeTok (l : ls)+ = case l of+ LexemeToken (Token { tokenTok = KM KNewLine })+ -> takeTok ls++ LexemeToken t -> t+ LexemeStartLine _ -> takeTok ls+ LexemeStartBlock _ -> takeTok ls
+ DDC/Core/Lexer/Tokens.hs view
@@ -0,0 +1,347 @@++module DDC.Core.Lexer.Tokens+ ( -- * Tokens+ Tok (..)+ , renameTok+ , describeTok++ -- * Meta Tokens+ , TokMeta (..)+ , describeTokMeta++ -- * Atomic Tokens+ , TokAtom (..)+ , describeTokAtom++ -- * Named Tokens+ , TokNamed (..)+ , describeTokNamed)+where+import DDC.Core.Pretty+import DDC.Core.Exp+import Control.Monad+++-- TokenFamily ----------------------------------------------------------------+-- | The family of a token.+-- This is used to help generate parser error messages,+-- so we can say ''the constructor Cons''+-- and ''the keyword case'' etc.+data TokenFamily+ = Symbol+ | Keyword+ | Constructor+ | Index+ | Variable+++-- | Describe a token family, for parser error messages.+describeTokenFamily :: TokenFamily -> String+describeTokenFamily tf+ = case tf of+ Symbol -> "symbol"+ Keyword -> "keyword"+ Constructor -> "constructor"+ Index -> "index"+ Variable -> "variable"+++-- Tok ------------------------------------------------------------------------+-- | Tokens accepted by the core language parser.+data Tok n+ -- | Some junk symbol that isn't part of the language.+ = KJunk String++ -- | Meta tokens contain out-of-band information that is eliminated+ -- before parsing proper.+ | KM !TokMeta++ -- | Atomic tokens are keywords, punctuation and baked-in + -- constructor names.+ | KA !TokAtom ++ -- | A named token that is specific to the language fragment + -- (maybe it's a primop), or a user defined name.+ | KN !(TokNamed n)+ deriving (Eq, Show)+++-- | Apply a function to all the names in a `Tok`.+renameTok+ :: Ord n2+ => (n1 -> Maybe n2) + -> Tok n1 + -> Maybe (Tok n2)++renameTok f kk+ = case kk of+ KJunk s -> Just $ KJunk s+ KM t -> Just $ KM t+ KA t -> Just $ KA t+ KN t -> liftM KN $ renameTokNamed f t+++-- | Describe a token for parser error messages.+describeTok :: Pretty n => Tok n -> String+describeTok kk+ = case kk of+ KJunk c -> "character " ++ show c+ KM tm -> describeTokMeta tm+ KA ta -> describeTokAtom ta+ KN tn -> describeTokNamed tn+++-- TokMeta --------------------------------------------------------------------+-- | Meta tokens contain out-of-band information that is +-- eliminated before parsing proper.+data TokMeta+ = KNewLine+ | KCommentLineStart+ | KCommentBlockStart+ | KCommentBlockEnd++ -- | This is injected by `dropCommentBlock` when it finds+ -- an unterminated block comment.+ | KCommentUnterminated++ -- | This is injected by `applyOffside` when it finds an explit close+ -- brace in a position where it would close a synthetic one.+ | KOffsideClosingBrace+ deriving (Eq, Show)+++-- | Describe a TokMeta, for lexer error messages.+describeTokMeta :: TokMeta -> String+describeTokMeta tm+ = case tm of+ KNewLine -> "new line"+ KCommentLineStart -> "comment start"+ KCommentBlockStart -> "block comment start"+ KCommentBlockEnd -> "block comment end"+ KCommentUnterminated -> "unterminated block comment"+ KOffsideClosingBrace -> "closing brace"+++-- TokAtom --------------------------------------------------------------------+-- | Atomic tokens are keywords, punctuation and baked-in constructor names.+-- They don't contain user-defined names or primops specific to the +-- language fragment.+data TokAtom+ -- parens+ = KRoundBra+ | KRoundKet+ | KSquareBra+ | KSquareKet+ | KBraceBra+ | KBraceKet+ | KAngleBra+ | KAngleKet++ -- compound parens+ | KSquareColonBra+ | KSquareColonKet+ | KAngleColonBra+ | KAngleColonKet++ -- punctuation+ | KDot+ | KBar+ | KHat+ | KPlus+ | KColon+ | KComma+ | KBackSlash+ | KSemiColon+ | KUnderscore+ | KEquals+ | KAmpersand+ | KDash+ | KColonColon+ | KBigLambda++ -- symbolic constructors+ | KSortComp+ | KSortProp+ | KKindValue+ | KKindRegion+ | KKindEffect+ | KKindClosure+ | KKindWitness+ | KArrowTilde+ | KArrowDash+ | KArrowDashLeft+ | KArrowEquals++ -- bottoms+ | KBotEffect+ | KBotClosure++ -- core keywords+ | KModule+ | KImports+ | KExports+ | KWith+ | KWhere+ | KIn+ | KLet+ | KLazy+ | KLetRec+ | KLetRegions+ | KLetRegion+ | KWithRegion+ | KCase+ | KOf+ | KType+ | KWeakEff+ | KWeakClo+ | KPurify+ | KForget++ -- sugar keywords+ | KDo+ | KMatch+ | KElse++ -- debruijn indices+ | KIndex Int++ -- builtin names ------------+ -- the unit data constructor.+ | KDaConUnit++ -- witness type constructors.+ | KTwConBuiltin TwCon++ -- witness constructors.+ | KWbConBuiltin WbCon++ -- other builtin spec constructors.+ | KTcConBuiltin TcCon+ deriving (Eq, Show)+++-- | Describe a `TokAtom`, for parser error messages.+describeTokAtom :: TokAtom -> String+describeTokAtom ta+ = let (family, str) = describeTokAtom' ta+ in describeTokenFamily family ++ " " ++ show str++describeTokAtom' :: TokAtom -> (TokenFamily, String)+describeTokAtom' ta+ = case ta of+ -- parens+ KRoundBra -> (Symbol, "(")+ KRoundKet -> (Symbol, ")")+ KSquareBra -> (Symbol, "[")+ KSquareKet -> (Symbol, "]")+ KBraceBra -> (Symbol, "{")+ KBraceKet -> (Symbol, "}")+ KAngleBra -> (Symbol, "<")+ KAngleKet -> (Symbol, ">")++ -- compound parens+ KSquareColonBra -> (Symbol, "[:")+ KSquareColonKet -> (Symbol, ":]")+ KAngleColonBra -> (Symbol, "<:")+ KAngleColonKet -> (Symbol, ":>")++ -- punctuation+ KDot -> (Symbol, ".")+ KBar -> (Symbol, "|")+ KHat -> (Symbol, "^")+ KPlus -> (Symbol, "+")+ KColon -> (Symbol, ":")+ KComma -> (Symbol, ",")+ KBackSlash -> (Symbol, "\\")+ KSemiColon -> (Symbol, ";")+ KUnderscore -> (Symbol, "_")+ KEquals -> (Symbol, "=")+ KAmpersand -> (Symbol, "&")+ KDash -> (Symbol, "-")+ KColonColon -> (Symbol, "::")+ KBigLambda -> (Symbol, "/\\")++ -- symbolic constructors+ KSortComp -> (Constructor, "**")+ KSortProp -> (Constructor, "@@")+ KKindValue -> (Constructor, "*")+ KKindRegion -> (Constructor, "%")+ KKindEffect -> (Constructor, "!")+ KKindClosure -> (Constructor, "$")+ KKindWitness -> (Constructor, "@")+ KArrowTilde -> (Constructor, "~>")+ KArrowDash -> (Constructor, "->")+ KArrowDashLeft -> (Constructor, "<-")+ KArrowEquals -> (Constructor, "=>")++ -- bottoms+ KBotEffect -> (Constructor, "!0")+ KBotClosure -> (Constructor, "!$")++ -- expression keywords+ KModule -> (Keyword, "module")+ KImports -> (Keyword, "imports")+ KExports -> (Keyword, "exports")+ KWith -> (Keyword, "with")+ KWhere -> (Keyword, "where")+ KIn -> (Keyword, "in")+ KLet -> (Keyword, "let")+ KLazy -> (Keyword, "lazy")+ KLetRec -> (Keyword, "letrec")+ KLetRegions -> (Keyword, "letregions")+ KLetRegion -> (Keyword, "letregion")+ KWithRegion -> (Keyword, "withregion")+ KCase -> (Keyword, "case")+ KOf -> (Keyword, "of")+ KType -> (Keyword, "type")+ KWeakEff -> (Keyword, "weakeff")+ KWeakClo -> (Keyword, "weakclo")+ KPurify -> (Keyword, "purify")+ KForget -> (Keyword, "forget")++ -- sugar keywords+ KDo -> (Keyword, "do")+ KMatch -> (Keyword, "match")+ KElse -> (Keyword, "else")++ -- debruijn indices+ KIndex i -> (Index, "^" ++ show i)++ -- builtin names+ KDaConUnit -> (Constructor, "()")+ KTwConBuiltin tw -> (Constructor, renderPlain $ ppr tw)+ KWbConBuiltin wi -> (Constructor, renderPlain $ ppr wi)+ KTcConBuiltin tc -> (Constructor, renderPlain $ ppr tc)+++-- TokNamed -------------------------------------------------------------------+-- | A token with a user-defined name.+data TokNamed n+ = KCon n+ | KVar n+ | KLit n+ deriving (Eq, Show)+++-- | Describe a `TokNamed`, for parser error messages.+describeTokNamed :: Pretty n => TokNamed n -> String+describeTokNamed tn+ = case tn of+ KCon n -> renderPlain $ text "constructor" <+> (dquotes $ ppr n)+ KVar n -> renderPlain $ text "variable" <+> (dquotes $ ppr n)+ KLit n -> renderPlain $ text "literal" <+> (dquotes $ ppr n)+++-- | Apply a function to all the names in a `TokNamed`.+renameTokNamed + :: Ord n2+ => (n1 -> Maybe n2) + -> TokNamed n1 + -> Maybe (TokNamed n2)++renameTokNamed f kk+ = case kk of+ KCon c -> liftM KCon $ f c+ KVar c -> liftM KVar $ f c+ KLit c -> liftM KLit $ f c+
+ DDC/Core/Load.hs view
@@ -0,0 +1,240 @@++-- | \"Loading\" refers to the combination of parsing and type checking.+-- This is the easiest way to turn source tokens into a type-checked +-- abstract syntax tree.+module DDC.Core.Load+ ( C.AnTEC (..)+ , Error (..)+ , loadModuleFromFile+ , loadModuleFromString+ , loadModuleFromTokens+ , loadExp+ , loadType+ , loadWitness)+where+import DDC.Core.Transform.SpreadX+import DDC.Core.Fragment.Profile+import DDC.Core.Lexer.Tokens+import DDC.Core.Exp+import DDC.Type.Transform.SpreadT+import DDC.Core.Module+import DDC.Base.Pretty+import DDC.Data.Token+import qualified DDC.Core.Fragment as I+import qualified DDC.Core.Parser as C+import qualified DDC.Core.Check as C+import qualified DDC.Type.Check as T+import qualified DDC.Base.Parser as BP+import Data.Map.Strict (Map)+import System.Directory+++-- | Things that can go wrong when loading a core thing.+data Error n+ = ErrorRead !String+ | ErrorParser !BP.ParseError+ | ErrorCheckType !(T.Error n) + | ErrorCheckExp !(C.Error () n)+ | ErrorCompliance !(I.Error n)+ deriving Show+++instance (Eq n, Show n, Pretty n) => Pretty (Error n) where+ ppr err+ = case err of+ ErrorRead str+ -> vcat [ text "While reading."+ , indent 2 $ text str ]++ ErrorParser err' + -> vcat [ text "While parsing."+ , indent 2 $ ppr err' ]++ ErrorCheckType err'+ -> vcat [ text "When checking type."+ , indent 2 $ ppr err' ]+++ ErrorCheckExp err' + -> vcat [ text "When checking expression."+ , indent 2 $ ppr err' ]++ ErrorCompliance err' + -> vcat [ text "During fragment compliance check."+ , indent 2 $ ppr err' ]+++-- Module ---------------------------------------------------------------------+-- | Parse and type check a core module from a file.+loadModuleFromFile + :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> (String -> [Token (Tok n)]) -- ^ Function to lex the source file.+ -> FilePath -- ^ File containing source code.+ -> IO (Either (Error n)+ (Module (C.AnTEC () n) n))++loadModuleFromFile profile lexSource filePath+ = do + -- Check whether the file exists.+ exists <- doesFileExist filePath+ if not exists + then return $ Left $ ErrorRead "Cannot read file."+ else do+ -- Read the source file.+ src <- readFile filePath++ -- Lex the source.+ let toks = lexSource src++ return $ loadModuleFromTokens profile filePath toks++-- | Parse and type check a core module from a string.+loadModuleFromString+ :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> (String -> [Token (Tok n)]) -- ^ Function to lex the source file.+ -> FilePath -- ^ Path to source file for error messages.+ -> String -- ^ Program text.+ -> Either (Error n) (Module (C.AnTEC () n) n)++loadModuleFromString profile lexSource filePath src+ = loadModuleFromTokens profile filePath (lexSource src)+++-- | Parse and type check a core module.+loadModuleFromTokens+ :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> FilePath -- ^ Path to source file for error messages.+ -> [Token (Tok n)] -- ^ Source tokens.+ -> Either (Error n) (Module (C.AnTEC () n) n)++loadModuleFromTokens profile sourceName toks'+ = goParse toks'+ where + -- Type checker config kind and type environments.+ config = C.configOfProfile profile+ kenv = profilePrimKinds profile+ tenv = profilePrimTypes profile++ -- Parse the tokens.+ goParse toks + = case BP.runTokenParser describeTok sourceName C.pModule toks of+ Left err -> Left (ErrorParser err)+ Right mm -> goCheckType (spreadX kenv tenv mm)++ -- Check that the module is type sound.+ goCheckType mm+ = case C.checkModule config mm of+ Left err -> Left (ErrorCheckExp err)+ Right mm' -> goCheckCompliance mm'++ -- Check that the module compiles with the language fragment.+ goCheckCompliance mm+ = case I.complies profile mm of+ Just err -> Left (ErrorCompliance err)+ Nothing -> Right mm+++-- Exp ------------------------------------------------------------------------+-- | Parse and check an expression+-- returning it along with its spec, effect and closure+loadExp+ :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> Map ModuleName (Module (C.AnTEC () n) n)+ -- ^ Other modules currently in scope.+ -- We add their exports to the environment.+ -> FilePath -- ^ Path to source file for error messages.+ -> [Token (Tok n)] -- ^ Source tokens.+ -> Either (Error n) + (Exp (C.AnTEC () n) n)++loadExp profile modules sourceName toks'+ = goParse toks'+ where + -- Type checker profile, kind and type environments.+ config = C.configOfProfile profile+ kenv = modulesExportKinds modules $ profilePrimKinds profile+ tenv = modulesExportTypes modules $ profilePrimTypes profile++ -- Parse the tokens.+ goParse toks + = case BP.runTokenParser describeTok sourceName C.pExp toks of+ Left err -> Left (ErrorParser err)+ Right t -> goCheckType (spreadX kenv tenv t)++ -- Check the kind of the type.+ goCheckType x+ = case C.checkExp config kenv tenv x of+ Left err -> Left (ErrorCheckExp err)+ Right (x', _, _, _) -> goCheckCompliance x'++ -- Check that the module compiles with the language fragment.+ goCheckCompliance x + = case I.compliesWithEnvs profile kenv tenv x of+ Just err -> Left (ErrorCompliance err)+ Nothing -> Right x+++-- Type -----------------------------------------------------------------------+-- | Parse and check a type,+-- returning it along with its kind.+loadType+ :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> FilePath -- ^ Path to source file for error messages.+ -> [Token (Tok n)] -- ^ Source tokens.+ -> Either (Error n) + (Type n, Kind n)++loadType profile sourceName toks'+ = goParse toks'+ where defs = profilePrimDataDefs profile+ kenv = profilePrimKinds profile++ -- Parse the tokens.+ goParse toks + = case BP.runTokenParser describeTok sourceName C.pType toks of+ Left err -> Left (ErrorParser err)+ Right t -> goCheckType (spreadT kenv t)++ -- Check the kind of the type.+ goCheckType t+ = case T.checkType defs kenv t of+ Left err -> Left (ErrorCheckType err)+ Right k -> Right (t, k)+ +++-- Witness --------------------------------------------------------------------+-- | Parse and check a witness,+-- returning it along with its type.+loadWitness+ :: (Eq n, Ord n, Show n, Pretty n)+ => Profile n -- ^ Language fragment profile.+ -> FilePath -- ^ Path to source file for error messages.+ -> [Token (Tok n)] -- ^ Source tokens.+ -> Either (Error n) + (Witness n, Type n)++loadWitness profile sourceName toks'+ = goParse toks'+ where -- Type checker config, kind and type environments.+ config = C.configOfProfile profile+ kenv = profilePrimKinds profile+ tenv = profilePrimTypes profile++ -- Parse the tokens.+ goParse toks + = case BP.runTokenParser describeTok sourceName C.pWitness toks of+ Left err -> Left (ErrorParser err)+ Right t -> goCheckType (spreadX kenv tenv t)++ -- Check the kind of the type.+ goCheckType w+ = case C.checkWitness config kenv tenv w of+ Left err -> Left (ErrorCheckExp err)+ Right k -> Right (w, k)+
+ DDC/Core/Module.hs view
@@ -0,0 +1,147 @@++module DDC.Core.Module+ ( -- * Modules+ Module (..)+ , isMainModule+ , moduleKindEnv+ , moduleTypeEnv+ , modulesGetBinds++ -- * Module maps+ , ModuleMap+ , modulesExportKinds+ , modulesExportTypes++ -- * Module Names.+ , QualName (..)+ , ModuleName (..)+ , isMainModuleName)+where+import DDC.Core.Exp+import Data.Typeable+import Data.Map.Strict (Map)+import DDC.Type.Env as Env+import qualified Data.Map.Strict as Map+import Control.DeepSeq+++-- Module ---------------------------------------------------------------------+-- | A module can be mutually recursive with other modules.+data Module a n+ = ModuleCore+ { -- | Name of this module.+ moduleName :: !ModuleName++ -- Exports ------------------+ -- | Kinds of exported types.+ , moduleExportKinds :: !(Map n (Kind n))++ -- | Types of exported values.+ , moduleExportTypes :: !(Map n (Type n))++ -- Imports ------------------+ -- | Kinds of imported types,+ -- along with the name of the module they are from.+ , moduleImportKinds :: !(Map n (QualName n, Kind n))++ -- | Types of imported values,+ -- along with the name of the module they are from.+ , moduleImportTypes :: !(Map n (QualName n, Type n))++ -- Local --------------------+ -- | The module body consists of some let-bindings+ -- wrapping a unit data constructor.+ -- + -- We're only interested in the bindings, + -- with the unit being just a place-holder.+ , moduleBody :: !(Exp a n)+ }+ deriving (Show, Typeable)+++instance (NFData a, NFData n) => NFData (Module a n) where+ rnf !mm+ = rnf (moduleName mm)+ `seq` rnf (moduleExportKinds mm)+ `seq` rnf (moduleExportTypes mm)+ `seq` rnf (moduleImportKinds mm)+ `seq` rnf (moduleImportTypes mm)+ `seq` rnf (moduleBody mm)+++-- | Check if this is the `Main` module.+isMainModule :: Module a n -> Bool+isMainModule mm+ = isMainModuleName + $ moduleName mm+++-- | Get the top-level kind environment of a module,+-- from its imported types.+moduleKindEnv :: Ord n => Module a n -> KindEnv n+moduleKindEnv mm+ = Env.fromList + $ [BName n k | (n, (_, k)) <- Map.toList $ moduleImportKinds mm]+++-- | Get the top-level type environment of a module,+-- from its imported values.+moduleTypeEnv :: Ord n => Module a n -> TypeEnv n+moduleTypeEnv mm+ = Env.fromList + $ [BName n k | (n, (_, k)) <- Map.toList $ moduleImportTypes mm]+++-- ModuleMap ------------------------------------------------------------------+-- | Map of module names to modules.+type ModuleMap a n + = Map ModuleName (Module a n)++modulesGetBinds m + = Env.fromList $ map (uncurry BName) (Map.assocs m)+++-- | Add the kind environment exported by all these modules to the given one.+modulesExportKinds :: Ord n => ModuleMap a n -> KindEnv n -> KindEnv n+modulesExportKinds mods base+ = foldl Env.union base + $ map (modulesGetBinds.moduleExportKinds) (Map.elems mods)+++-- | Add the type environment exported by all these modules to the given one.+modulesExportTypes :: Ord n => ModuleMap a n -> TypeEnv n -> TypeEnv n++modulesExportTypes mods base+ = foldl Env.union base + $ map (modulesGetBinds.moduleExportTypes) (Map.elems mods)+++-- ModuleName -----------------------------------------------------------------+-- | A hierarchical module name.+data ModuleName+ = ModuleName [String]+ deriving (Show, Eq, Ord, Typeable)++instance NFData ModuleName where+ rnf (ModuleName ss)+ = rnf ss+ ++-- | A fully qualified name, +-- including the name of the module it is from.+data QualName n+ = QualName ModuleName n+ deriving Show++instance NFData n => NFData (QualName n) where+ rnf (QualName mn n)+ = rnf mn `seq` rnf n+++-- | Check whether this is the name of the \"Main\" module.+isMainModuleName :: ModuleName -> Bool+isMainModuleName mn+ = case mn of+ ModuleName ["Main"] -> True+ _ -> False+
DDC/Core/Parser.hs view
@@ -1,631 +1,44 @@ -- | Core language parser. module DDC.Core.Parser- ( module DDC.Base.Parser- , Parser- , pExp- , pWitness)- -where-import DDC.Core.Exp-import DDC.Core.Parser.Tokens-import DDC.Base.Parser ((<?>))-import DDC.Type.Parser (pTok)-import qualified DDC.Base.Parser as P-import qualified DDC.Type.Compounds as T-import qualified DDC.Type.Parser as T-import Control.Monad.Error----- | A parser of core language tokens.-type Parser n a- = P.Parser (Tok n) a----- Expressions ------------------------------------------------------------------- | Parse a core language expression.-pExp :: Ord n => Parser n (Exp () n)-pExp - = P.choice- -- Level-0 lambda abstractions- -- \(x1 x2 ... : TYPE) (y1 y2 ... : TYPE) ... . EXP- [ do pTok KBackSlash-- bs <- liftM concat- $ P.many1 - $ do pTok KRoundBra- bs' <- P.many1 T.pBinder- pTok KColon- t <- T.pType- pTok KRoundKet- return (map (\b -> T.makeBindFromBinder b t) bs')-- pTok KDot- xBody <- pExp- return $ foldr (XLam ()) xBody bs-- -- Level-1 lambda abstractions.- -- /\(x1 x2 ... : TYPE) (y1 y2 ... : TYPE) ... . EXP- , do pTok KBigLambda-- bs <- liftM concat- $ P.many1 - $ do pTok KRoundBra- bs' <- P.many1 T.pBinder- pTok KColon- t <- T.pType- pTok KRoundKet- return (map (\b -> T.makeBindFromBinder b t) bs')-- pTok KDot- xBody <- pExp- return $ foldr (XLAM ()) xBody bs--- -- let expression- , do pTok KLet- (mode1, b1, x1) <- pLetBinding- pTok KIn- x2 <- pExp- return $ XLet () (LLet mode1 b1 x1) x2--- -- letrec expression- , do pTok KLetRec-- P.choice- -- Multiple bindings in braces- [ do pTok KBraceBra- lets <- P.sepEndBy1 pLetRecBinding (pTok KSemiColon)- pTok KBraceKet- pTok KIn- x <- pExp- return $ XLet () (LRec lets) x-- -- A single binding without braces.- , do ll <- pLetRecBinding- pTok KIn- x <- pExp- return $ XLet () (LRec [ll]) x- ] --- -- Local region binding.- -- letregion BINDER with { BINDER : TYPE ... } in EXP- -- letregion BINDER in EXP- , do pTok KLetRegion- br <- T.pBinder- let b = T.makeBindFromBinder br T.kRegion-- P.choice - [ do pTok KWith- pTok KBraceBra- wits <- P.sepBy- (do w <- pVar- pTok KColon- t <- T.pTypeApp- return (BName w t))- (pTok KSemiColon)- pTok KBraceKet- pTok KIn- x <- pExp - return $ XLet () (LLetRegion b wits) x -- , do pTok KIn- x <- pExp- return $ XLet () (LLetRegion b []) x ]--- -- withregion CON in EXP- , do pTok KWithRegion- n <- pVar- pTok KIn- x <- pExp- let u = UName n (T.tBot T.kRegion)- return $ XLet () (LWithRegion u) x--- -- case EXP of { ALTS }- , do pTok KCase- x <- pExp- pTok KOf - pTok KBraceBra- alts <- P.sepEndBy1 pAlt (pTok KSemiColon)- pTok KBraceKet- return $ XCase () x alts--- -- weakeff [TYPE] in EXP- , do pTok KWeakEff- pTok KSquareBra- t <- T.pType- pTok KSquareKet- pTok KIn- x <- pExp- return $ XCast () (CastWeakenEffect t) x--- -- weakclo [TYPE] in EXP- , do pTok KWeakClo- pTok KSquareBra- t <- T.pType- pTok KSquareKet- pTok KIn- x <- pExp- return $ XCast () (CastWeakenClosure t) x--- -- purify <WITNESS> in EXP- , do pTok KPurify- pTok KAngleBra- w <- pWitness- pTok KAngleKet- pTok KIn- x <- pExp- return $ XCast () (CastPurify w) x--- -- forget <WITNESS> in EXP- , do pTok KForget- pTok KAngleBra- w <- pWitness- pTok KAngleKet- pTok KIn- x <- pExp- return $ XCast () (CastForget w) x-- -- APP- , do pExpApp- ]-- <?> "an expression"----- Applications.-pExpApp :: Ord n => Parser n (Exp () n)-pExpApp - = do x1 <- pExp0- - P.choice- [ do xs <- liftM concat $ P.many1 pArgs- return $ foldl (XApp ()) x1 xs-- , return x1]-- <?> "an expression or application"----- Comp, Witness or Spec arguments.-pArgs :: Ord n => Parser n [Exp () n]-pArgs - = P.choice- -- [TYPE]- [ do pTok KSquareBra- t <- T.pType - pTok KSquareKet- return [XType t]-- -- [: TYPE0 TYPE0 ... :]- , do pTok KSquareColonBra- ts <- P.many1 T.pTypeAtom- pTok KSquareColonKet- return $ map XType ts- - -- <WITNESS>- , do pTok KAngleBra- w <- pWitness- pTok KAngleKet- return [XWitness w]- - -- <: WITNESS0 WITNESS0 ... :>- , do pTok KAngleColonBra- ws <- P.many1 pWitnessAtom- pTok KAngleColonKet- return $ map XWitness ws- - -- EXP0- , do x <- pExp0- return [x]- ]- <?> "a type, witness or expression argument"----- Atomics-pExp0 :: Ord n => Parser n (Exp () n)-pExp0 - = P.choice- -- (EXP2)- [ do pTok KRoundBra- t <- pExp- pTok KRoundKet- return $ t- - -- Named constructors- , do con <- pCon- return $ XCon () (UName con (T.tBot T.kData)) -- -- Literals- , do lit <- pLit- return $ XCon () (UName lit (T.tBot T.kData))-- -- Debruijn indices- , do i <- T.pIndex- return $ XVar () (UIx i (T.tBot T.kData))-- -- Variables- , do var <- pVar- return $ XVar () (UName var (T.tBot T.kData)) - ]-- <?> "a variable, constructor, or parenthesised type"----- Case alternatives.-pAlt :: Ord n => Parser n (Alt () n)-pAlt- = do p <- pPat- pTok KArrowDash- x <- pExp- return $ AAlt p x----- Patterns.-pPat :: Ord n => Parser n (Pat n)-pPat- = P.choice- [ -- Wildcard- do pTok KUnderscore- return $ PDefault-- -- LIT- , do nLit <- pLit- return $ PData (UName nLit (T.tBot T.kData)) []-- -- CON BIND BIND ...- , do nCon <- pCon - bs <- P.many pBindPat- return $ PData (UName nCon (T.tBot T.kData)) bs]----- Binds in patterns can have no type annotation,--- or can have an annotation if the whole thing is in parens.-pBindPat :: Ord n => Parser n (Bind n)-pBindPat - = P.choice- -- Plain binder.- [ do b <- T.pBinder- return $ T.makeBindFromBinder b (T.tBot T.kData)-- -- Binder with type, wrapped in parens.- , do pTok KRoundBra- b <- T.pBinder- pTok KColon- t <- T.pType- pTok KRoundKet- return $ T.makeBindFromBinder b t- ]----- Bindings ---------------------------------------------------------------------- | A binding for let expression.-pLetBinding :: Ord n => Parser n (LetMode n, Bind n, Exp () n)-pLetBinding - = do b <- T.pBinder-- P.choice- [ do -- Binding with full type signature.- -- BINDER : TYPE = EXP- pTok KColon- t <- T.pType- mode <- pLetMode- pTok KEquals- xBody <- pExp-- return $ (mode, T.makeBindFromBinder b t, xBody) --- , do -- Non-function binding with no type signature.- -- This form can't be used with letrec as we can't use it- -- to build the full type sig for the let-bound variable.- -- BINDER = EXP- mode <- pLetMode- pTok KEquals- xBody <- pExp- let t = T.tBot T.kData- return $ (mode, T.makeBindFromBinder b t, xBody)--- , do -- Binding using function syntax.- ps <- liftM concat - $ P.many pBindParamSpec - - P.choice- [ do -- Function syntax with a return type.- -- We can make the full type sig for the let-bound variable.- -- BINDER PARAM1 PARAM2 .. PARAMN : TYPE = EXP- pTok KColon- tBody <- T.pType- mode <- pLetMode- pTok KEquals- xBody <- pExp-- let x = expOfParams () ps xBody- let t = funTypeOfParams ps tBody- return (mode, T.makeBindFromBinder b t, x)-- -- Function syntax with no return type.- -- We can't make the type sig for the let-bound variable,- -- but we can create lambda abstractions with the given - -- parameter types.- -- BINDER PARAM1 PARAM2 .. PARAMN = EXP- , do mode <- pLetMode- pTok KEquals- xBody <- pExp-- let x = expOfParams () ps xBody- let t = T.tBot T.kData- return (mode, T.makeBindFromBinder b t, x) ]- ]---- | Parse a let mode specifier.--- Only allow the lazy specifier with non-recursive bindings.--- We don't support value recursion, so the right of all recursive--- bindings must be explicit lambda abstractions anyway, so there's --- no point suspending them.-pLetMode :: Ord n => Parser n (LetMode n)-pLetMode- = do P.choice- -- lazy <WITNESS>- [ do pTok KLazy-- P.choice- [ do pTok KAngleBra- w <- pWitness- pTok KAngleKet- return $ LetLazy (Just w)- - , do return $ LetLazy Nothing ]-- , do return $ LetStrict ]----- | Letrec bindings must have a full type signature, --- or use function syntax with a return type so that we can make one.-pLetRecBinding :: Ord n => Parser n (Bind n, Exp () n)-pLetRecBinding - = do b <- T.pBinder-- P.choice- [ do -- Binding with full type signature.- -- BINDER : TYPE = EXP- pTok KColon- t <- T.pType- pTok KEquals- xBody <- pExp-- return $ (T.makeBindFromBinder b t, xBody) --- , do -- Binding using function syntax.- -- BINDER PARAM1 PARAM2 .. PARAMN : TYPE = EXP- ps <- liftM concat - $ P.many pBindParamSpec - - pTok KColon- tBody <- T.pType- let t = funTypeOfParams ps tBody-- pTok KEquals- xBody <- pExp- let x = expOfParams () ps xBody-- return (T.makeBindFromBinder b t, x) ]----- | Parse a parameter specification.------ [BIND1 BIND2 .. BINDN : TYPE]--- or (BIND : TYPE)--- or (BIND : TYPE) { EFFECT | CLOSURE }----pBindParamSpec :: Ord n => Parser n [ParamSpec n]-pBindParamSpec- = P.choice- -- Type parameter- -- [BIND1 BIND2 .. BINDN : TYPE]- [ do pTok KSquareBra- bs <- P.many1 T.pBinder- pTok KColon- t <- T.pType- pTok KSquareKet- return [ ParamType b - | b <- zipWith T.makeBindFromBinder bs (repeat t)]--- -- Witness parameter- -- <BIND : TYPE>- , do pTok KAngleBra- b <- T.pBinder- pTok KColon- t <- T.pType- pTok KAngleKet- return [ ParamWitness $ T.makeBindFromBinder b t]-- -- Value parameter- -- (BIND : TYPE) - -- (BIND : TYPE) { TYPE | TYPE }- , do pTok KRoundBra- b <- T.pBinder- pTok KColon- t <- T.pType- pTok KRoundKet-- (eff, clo) - <- P.choice- [ do pTok KBraceBra- eff' <- T.pType- pTok KBar- clo' <- T.pType- pTok KBraceKet- return (eff', clo')- - , do return (T.tBot T.kEffect, T.tBot T.kClosure) ]- -- return $ [ParamValue (T.makeBindFromBinder b t) eff clo]- ]----- | Specification of a function parameter.--- We can determine the contribution to the type of the function, --- as well as its expression based on the parameter.-data ParamSpec n- = ParamType (Bind n)- | ParamWitness (Bind n)- | ParamValue (Bind n) (Type n) (Type n)----- | Build the type of a function from specifications of its parameters,--- and the type of the body.-funTypeOfParams - :: [ParamSpec n] -- ^ Spec of parameters.- -> Type n -- ^ Type of body.- -> Type n -- ^ Type of whole function.--funTypeOfParams [] tBody = tBody-funTypeOfParams (p:ps) tBody- = case p of- ParamType b - -> TForall b - $ funTypeOfParams ps tBody-- ParamWitness b- -> T.tImpl (T.typeOfBind b)- $ funTypeOfParams ps tBody-- ParamValue b eff clo- -> T.tFun (T.typeOfBind b) eff clo - $ funTypeOfParams ps tBody----- | Build the expression of a function from specifications of its parameters,--- and the expression for the body.-expOfParams - :: a- -> [ParamSpec n] -- ^ Spec of parameters.- -> Exp a n -- ^ Body of function.- -> Exp a n -- ^ Expression of whole function.--expOfParams _ [] xBody = xBody-expOfParams a (p:ps) xBody- = case p of- ParamType b - -> XLAM a b $ expOfParams a ps xBody- - ParamWitness b- -> XLam a b $ expOfParams a ps xBody-- ParamValue b _ _- -> XLam a b $ expOfParams a ps xBody------ Witnesses --------------------------------------------------------------------- | Parse a witness expression.-pWitness :: Ord n => Parser n (Witness n)-pWitness = pWitnessJoin----- Witness Joining-pWitnessJoin :: Ord n => Parser n (Witness n)-pWitnessJoin - -- WITNESS or WITNESS & WITNESS- = do w1 <- pWitnessApp- P.choice - [ do pTok KAmpersand- w2 <- pWitnessJoin- return (WJoin w1 w2)-- , do return w1 ]----- Applications-pWitnessApp :: Ord n => Parser n (Witness n)-pWitnessApp - = do (x:xs) <- P.many1 pWitnessArg- return $ foldl WApp x xs-- <?> "a witness expression or application"----- Function argument-pWitnessArg :: Ord n => Parser n (Witness n)-pWitnessArg - = P.choice- [ -- [TYPE]- do pTok KSquareBra- t <- T.pType- pTok KSquareKet- return $ WType t-- -- WITNESS- , do pWitnessAtom ]----- Atomics-pWitnessAtom :: Ord n => Parser n (Witness n)-pWitnessAtom - = P.choice- -- (WITNESS)- [ do pTok KRoundBra- w <- pWitness- pTok KRoundKet- return $ w-- -- Named constructors- , do con <- pCon- return $ WCon (WiConBound $ UName con (T.tBot T.kWitness)) -- -- Baked-in witness constructors.- , do wb <- pWbCon- return $ WCon (WiConBuiltin wb)-- - -- Debruijn indices- , do i <- T.pIndex- return $ WVar (UIx i (T.tBot T.kWitness))-- -- Variables- , do var <- pVar- return $ WVar (UName var (T.tBot T.kWitness)) ]+ ( Parser - <?> "a witness"+ -- * Modules+ , pModule + -- * Expressions+ , pExp+ , pExpApp+ , pExpAtom ----------------------------------------------------------------------------------- | Parse a builtin named `WiCon`-pWbCon :: Parser n WbCon-pWbCon = P.pTokMaybe f- where f (KA (KWbConBuiltin wb)) = Just wb- f _ = Nothing+ -- * Types+ , pType+ , pTypeApp+ , pTypeAtom + -- * Witnesses+ , pWitness+ , pWitnessApp+ , pWitnessAtom --- | Parse a variable name-pVar :: Parser n n-pVar = P.pTokMaybe f- where f (KN (KVar n)) = Just n- f _ = Nothing+ -- * Constructors+ , pCon+ , pLit + -- * Variables+ , pBinder+ , pIndex+ , pVar+ , pName --- | Parse a constructor name-pCon :: Parser n n-pCon = P.pTokMaybe f- where f (KN (KCon n)) = Just n- f _ = Nothing+ -- * Raw Tokens+ , pTok+ , pTokAs) +where+import DDC.Core.Parser.Base+import DDC.Core.Parser.Witness+import DDC.Core.Parser.Type+import DDC.Core.Parser.Exp+import DDC.Core.Parser.Module --- | Parse a literal-pLit :: Parser n n-pLit = P.pTokMaybe f- where f (KN (KLit n)) = Just n- f _ = Nothing
+ DDC/Core/Parser/Base.hs view
@@ -0,0 +1,98 @@++module DDC.Core.Parser.Base+ ( Parser+ , pWbCon+ , pModuleName+ , pQualName+ , pName+ , pCon+ , pLit+ , pIndex+ , pVar+ , pTok+ , pTokAs)+where+import DDC.Base.Pretty+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Lexer.Tokens+import DDC.Base.Parser ((<?>))+import qualified DDC.Base.Parser as P+++-- | A parser of core language tokens.+type Parser n a+ = P.Parser (Tok n) a+++-- | Parse a builtin named `WiCon`+pWbCon :: Parser n WbCon+pWbCon = P.pTokMaybe f+ where f (KA (KWbConBuiltin wb)) = Just wb+ f _ = Nothing+++-- | Parse a module name. +-- +--- ISSUE #273: Handle hierarchical module names.+-- Accept hierachical names, and reject hashes at the end of a name.+-- Hashes can be at the end of constructor name, but not module names.+pModuleName :: Pretty n => Parser n ModuleName+pModuleName = P.pTokMaybe f+ where f (KN (KCon n)) = Just $ ModuleName [renderPlain $ ppr n]+ f _ = Nothing+++-- | Parse a qualified variable or constructor name.+pQualName :: Pretty n => Parser n (QualName n)+pQualName+ = do mn <- pModuleName+ pTok KDot+ n <- pName+ return $ QualName mn n+++-- | Parse a constructor or variable name.+pName :: Parser n n+pName = P.choice [pCon, pVar]+++-- | Parse a constructor name.+pCon :: Parser n n+pCon = P.pTokMaybe f+ where f (KN (KCon n)) = Just n+ f _ = Nothing+++-- | Parse a literal+pLit :: Parser n n+pLit = P.pTokMaybe f+ where f (KN (KLit n)) = Just n+ f _ = Nothing+++-- | Parse a variable.+pVar :: Parser n n+pVar = P.pTokMaybe f+ <?> "a variable"+ where f (KN (KVar n)) = Just n+ f _ = Nothing+++-- | Parse a deBruijn index+pIndex :: Parser n Int+pIndex = P.pTokMaybe f+ <?> "an index"+ where f (KA (KIndex i)) = Just i+ f _ = Nothing+++-- | Parse an atomic token.+pTok :: TokAtom -> Parser n ()+pTok k = P.pTok (KA k)+++-- | Parse an atomic token and return some value.+pTokAs :: TokAtom -> a -> Parser n a+pTokAs k x = P.pTokAs (KA k) x+
+ DDC/Core/Parser/Exp.hs view
@@ -0,0 +1,547 @@++-- | Core language parser.+module DDC.Core.Parser.Exp+ ( pExp+ , pExpApp+ , pExpAtom+ , pLets+ , pType+ , pTypeApp+ , pTypeAtom)+where+import DDC.Core.Exp+import DDC.Core.Parser.Witness+import DDC.Core.Parser.Param+import DDC.Core.Parser.Type+import DDC.Core.Parser.Base+import DDC.Core.Lexer.Tokens+import DDC.Core.Compounds+import DDC.Base.Parser ((<?>))+import qualified DDC.Base.Parser as P+import qualified DDC.Type.Compounds as T+import Control.Monad.Error+++-- Expressions ----------------------------------------------------------------+-- | Parse a core language expression.+pExp :: Ord n => Parser n (Exp () n)+pExp + = P.choice+ -- Level-0 lambda abstractions+ -- \(x1 x2 ... : TYPE) (y1 y2 ... : TYPE) ... . EXP+ [ do pTok KBackSlash++ bs <- liftM concat+ $ P.many1 + $ do pTok KRoundBra+ bs' <- P.many1 pBinder+ pTok KColon+ t <- pType+ pTok KRoundKet+ return (map (\b -> T.makeBindFromBinder b t) bs')++ pTok KDot+ xBody <- pExp+ return $ foldr (XLam ()) xBody bs++ -- Level-1 lambda abstractions.+ -- /\(x1 x2 ... : TYPE) (y1 y2 ... : TYPE) ... . EXP+ , do pTok KBigLambda++ bs <- liftM concat+ $ P.many1 + $ do pTok KRoundBra+ bs' <- P.many1 pBinder+ pTok KColon+ t <- pType+ pTok KRoundKet+ return (map (\b -> T.makeBindFromBinder b t) bs')++ pTok KDot+ xBody <- pExp+ return $ foldr (XLAM ()) xBody bs+++ -- let expression+ , do lts <- pLets+ pTok KIn+ x2 <- pExp+ return $ XLet () lts x2+++ -- do { STMTS }+ -- Sugar for a let-expression.+ , do pTok KDo+ pTok KBraceBra+ xx <- pStmts+ pTok KBraceKet+ return $ xx+++ -- withregion CON in EXP+ , do pTok KWithRegion+ u <- P.choice + [ do n <- pVar+ return $ UName n++ , do n <- pCon+ return $ UPrim n kRegion]+ pTok KIn+ x <- pExp+ return $ XLet () (LWithRegion u) x+++ -- case EXP of { ALTS }+ , do pTok KCase+ x <- pExp+ pTok KOf + pTok KBraceBra+ alts <- P.sepEndBy1 pAlt (pTok KSemiColon)+ pTok KBraceKet+ return $ XCase () x alts+++ -- match PAT <- EXP else EXP in EXP+ -- Sugar for a case-expression.+ , do pTok KMatch+ p <- pPat+ pTok KArrowDashLeft+ x1 <- pExp + pTok KElse+ x2 <- pExp + pTok KIn+ x3 <- pExp+ return $ XCase () x1 [AAlt p x3, AAlt PDefault x2]+++ -- weakeff [TYPE] in EXP+ , do pTok KWeakEff+ pTok KSquareBra+ t <- pType+ pTok KSquareKet+ pTok KIn+ x <- pExp+ return $ XCast () (CastWeakenEffect t) x+++ -- weakclo {EXP;+} in EXP+ , do pTok KWeakClo+ pTok KBraceBra+ xs <- liftM concat $ P.sepEndBy1 pArgs (pTok KSemiColon)+ pTok KBraceKet+ pTok KIn+ x <- pExp+ return $ XCast () (CastWeakenClosure xs) x+++ -- purify <WITNESS> in EXP+ , do pTok KPurify+ pTok KAngleBra+ w <- pWitness+ pTok KAngleKet+ pTok KIn+ x <- pExp+ return $ XCast () (CastPurify w) x+++ -- forget <WITNESS> in EXP+ , do pTok KForget+ pTok KAngleBra+ w <- pWitness+ pTok KAngleKet+ pTok KIn+ x <- pExp+ return $ XCast () (CastForget w) x++ -- APP+ , do pExpApp+ ]++ <?> "an expression"+++-- Applications.+pExpApp :: Ord n => Parser n (Exp () n)+pExpApp + = do x1 <- pExpAtom+ + P.choice+ [ do xs <- liftM concat $ P.many1 pArgs+ return $ foldl (XApp ()) x1 xs++ , return x1]++ <?> "an expression or application"+++-- Comp, Witness or Spec arguments.+pArgs :: Ord n => Parser n [Exp () n]+pArgs + = P.choice+ -- [TYPE]+ [ do pTok KSquareBra+ t <- pType + pTok KSquareKet+ return [XType t]++ -- [: TYPE0 TYPE0 ... :]+ , do pTok KSquareColonBra+ ts <- P.many1 pTypeAtom+ pTok KSquareColonKet+ return $ map XType ts+ + -- <WITNESS>+ , do pTok KAngleBra+ w <- pWitness+ pTok KAngleKet+ return [XWitness w]+ + -- <: WITNESS0 WITNESS0 ... :>+ , do pTok KAngleColonBra+ ws <- P.many1 pWitnessAtom+ pTok KAngleColonKet+ return $ map XWitness ws+ + -- EXP0+ , do x <- pExpAtom+ return [x]+ ]+ <?> "a type, witness or expression argument"+++-- | Parse a variable, constructor or parenthesised expression.+pExpAtom :: Ord n => Parser n (Exp () n)+pExpAtom + = P.choice+ -- (EXP2)+ [ do pTok KRoundBra+ t <- pExp+ pTok KRoundKet+ return $ t+ + -- The unit data constructor. + , do pTok KDaConUnit+ return $ XCon () dcUnit++ -- Named algebraic constructors.+ -- We just fill-in the type with tBot for now, and leave it to + -- the spreader to attach the real type.+ , do con <- pCon+ return $ XCon () (mkDaConAlg con (T.tBot T.kData))++ -- Literals.+ -- We just fill-in the type with tBot for now, and leave it to+ -- the spreader to attach the real type.+ -- We also set the literal as being algebraic, which may not be+ -- true (as for Floats). The spreader also needs to fix this.+ , do lit <- pLit+ return $ XCon () (mkDaConAlg lit (T.tBot T.kData))++ -- Debruijn indices+ , do i <- pIndex+ return $ XVar () (UIx i)++ -- Variables+ , do var <- pVar+ return $ XVar () (UName var) + ]++ <?> "a variable, constructor, or parenthesised type"+++-- Alternatives ---------------------------------------------------------------+-- Case alternatives.+pAlt :: Ord n => Parser n (Alt () n)+pAlt+ = do p <- pPat+ pTok KArrowDash+ x <- pExp+ return $ AAlt p x+++-- Patterns.+pPat :: Ord n => Parser n (Pat n)+pPat+ = P.choice+ [ -- Wildcard+ do pTok KUnderscore+ return $ PDefault++ -- LIT+ , do nLit <- pLit+ return $ PData (mkDaConAlg nLit (T.tBot T.kData)) []++ -- Unit+ , do pTok KDaConUnit+ return $ PData dcUnit []++ -- CON BIND BIND ...+ , do nCon <- pCon + bs <- P.many pBindPat+ return $ PData (mkDaConAlg nCon (T.tBot T.kData)) bs]+++-- Binds in patterns can have no type annotation,+-- or can have an annotation if the whole thing is in parens.+pBindPat :: Ord n => Parser n (Bind n)+pBindPat + = P.choice+ -- Plain binder.+ [ do b <- pBinder+ return $ T.makeBindFromBinder b (T.tBot T.kData)++ -- Binder with type, wrapped in parens.+ , do pTok KRoundBra+ b <- pBinder+ pTok KColon+ t <- pType+ pTok KRoundKet+ return $ T.makeBindFromBinder b t+ ]+++-- Bindings -------------------------------------------------------------------+pLets :: Ord n => Parser n (Lets () n)+pLets+ = P.choice+ [ -- non-recursive let.+ do pTok KLet+ (mode1, b1, x1) <- pLetBinding+ return $ LLet mode1 b1 x1++ -- recursive let.+ , do pTok KLetRec+ P.choice+ -- Multiple bindings in braces+ [ do pTok KBraceBra+ lets <- P.sepEndBy1 pLetRecBinding (pTok KSemiColon)+ pTok KBraceKet+ return $ LRec lets++ -- A single binding without braces.+ , do ll <- pLetRecBinding+ return $ LRec [ll]+ ] ++ -- Local region binding.+ -- letregions [BINDER] with { BINDER : TYPE ... } in EXP+ -- letregions [BINDER] in EXP+ , do pTok KLetRegions+ brs <- P.manyTill pBinder (P.try $ P.lookAhead $ P.choice [pTok KIn, pTok KWith])+ let bs = map (flip T.makeBindFromBinder T.kRegion) brs+ pLetWits bs+ + , do pTok KLetRegion+ br <- pBinder+ let b = T.makeBindFromBinder br T.kRegion+ pLetWits [b]+ + ]+ + +pLetWits :: Ord n => [Bind n] -> Parser n (Lets () n)+pLetWits bs+ = P.choice + [ do pTok KWith+ pTok KBraceBra+ wits <- P.sepBy+ (do b <- pBinder+ pTok KColon+ t <- pTypeApp+ return $ T.makeBindFromBinder b t)+ (pTok KSemiColon)+ pTok KBraceKet+ return (LLetRegions bs wits)+ + , do return (LLetRegions bs [])+ ]+++-- | A binding for let expression.+pLetBinding :: Ord n => Parser n (LetMode n, Bind n, Exp () n)+pLetBinding + = do b <- pBinder++ P.choice+ [ do -- Binding with full type signature.+ -- BINDER : TYPE = EXP+ pTok KColon+ t <- pType+ mode <- pLetMode+ pTok KEquals+ xBody <- pExp++ return $ (mode, T.makeBindFromBinder b t, xBody) +++ , do -- Non-function binding with no type signature.+ -- This form can't be used with letrec as we can't use it+ -- to build the full type sig for the let-bound variable.+ -- BINDER = EXP+ mode <- pLetMode+ pTok KEquals+ xBody <- pExp+ let t = T.tBot T.kData+ return $ (mode, T.makeBindFromBinder b t, xBody)+++ , do -- Binding using function syntax.+ ps <- liftM concat + $ P.many pBindParamSpec + + P.choice+ [ do -- Function syntax with a return type.+ -- We can make the full type sig for the let-bound variable.+ -- BINDER PARAM1 PARAM2 .. PARAMN : TYPE = EXP+ pTok KColon+ tBody <- pType+ mode <- pLetMode+ pTok KEquals+ xBody <- pExp++ let x = expOfParams () ps xBody+ let t = funTypeOfParams ps tBody+ return (mode, T.makeBindFromBinder b t, x)++ -- Function syntax with no return type.+ -- We can't make the type sig for the let-bound variable,+ -- but we can create lambda abstractions with the given + -- parameter types.+ -- BINDER PARAM1 PARAM2 .. PARAMN = EXP+ , do mode <- pLetMode+ pTok KEquals+ xBody <- pExp++ let x = expOfParams () ps xBody+ let t = T.tBot T.kData+ return (mode, T.makeBindFromBinder b t, x) ]+ ]++-- | Parse a let mode specifier.+-- Only allow the lazy specifier with non-recursive bindings.+-- We don't support value recursion, so the right of all recursive+-- bindings must be explicit lambda abstractions anyway, so there's +-- no point suspending them.+pLetMode :: Ord n => Parser n (LetMode n)+pLetMode+ = do P.choice+ -- lazy <WITNESS>+ [ do pTok KLazy++ P.choice+ [ do pTok KAngleBra+ w <- pWitness+ pTok KAngleKet+ return $ LetLazy (Just w)+ + , do return $ LetLazy Nothing ]++ , do return $ LetStrict ]+++-- | Letrec bindings must have a full type signature, +-- or use function syntax with a return type so that we can make one.+pLetRecBinding :: Ord n => Parser n (Bind n, Exp () n)+pLetRecBinding + = do b <- pBinder++ P.choice+ [ do -- Binding with full type signature.+ -- BINDER : TYPE = EXP+ pTok KColon+ t <- pType+ pTok KEquals+ xBody <- pExp++ return $ (T.makeBindFromBinder b t, xBody) +++ , do -- Binding using function syntax.+ -- BINDER PARAM1 PARAM2 .. PARAMN : TYPE = EXP+ ps <- liftM concat + $ P.many pBindParamSpec + + pTok KColon+ tBody <- pType+ let t = funTypeOfParams ps tBody++ pTok KEquals+ xBody <- pExp+ let x = expOfParams () ps xBody++ return (T.makeBindFromBinder b t, x) ]+++-- Statements -----------------------------------------------------------------+data Stmt n+ = StmtBind (Bind n) (Exp () n)+ | StmtMatch (Pat n) (Exp () n) (Exp () n)+ | StmtNone (Exp () n)+++-- | Parse a single statement.+pStmt :: Ord n => Parser n (Stmt n)+pStmt + = P.choice+ [ -- BINDER = EXP ;+ -- We need the 'try' because a VARIABLE binders can also be parsed+ -- as a function name in a non-binding statement.+ -- + P.try $ + do br <- pBinder+ pTok KEquals+ x1 <- pExp+ let t = T.tBot T.kData+ let b = T.makeBindFromBinder br t+ return $ StmtBind b x1++ -- PAT <- EXP else EXP;+ -- Sugar for a case-expression.+ -- We need the 'try' because the PAT can also be parsed+ -- as a function name in a non-binding statement.+ , P.try $+ do p <- pPat+ pTok KArrowDashLeft+ x1 <- pExp + pTok KElse+ x2 <- pExp + return $ StmtMatch p x1 x2++ -- EXP+ , do x <- pExp+ return $ StmtNone x+ ]+++-- | Parse some statements.+pStmts :: Ord n => Parser n (Exp () n)+pStmts+ = do stmts <- P.sepEndBy1 pStmt (pTok KSemiColon)+ case makeStmts stmts of+ Nothing -> P.unexpected "do-block must end with a statement"+ Just x -> return x+++-- | Make an expression from some statements.+makeStmts :: [Stmt n] -> Maybe (Exp () n)+makeStmts ss+ = case ss of+ [StmtNone x] + -> Just x++ StmtNone x1 : rest+ | Just x2 <- makeStmts rest+ -> Just $ XLet () (LLet LetStrict (BNone (T.tBot T.kData)) x1) x2++ StmtBind b x1 : rest+ | Just x2 <- makeStmts rest+ -> Just $ XLet () (LLet LetStrict b x1) x2++ StmtMatch p x1 x2 : rest+ | Just x3 <- makeStmts rest+ -> Just $ XCase () x1 + [ AAlt p x3+ , AAlt PDefault x2]++ _ -> Nothing+
− DDC/Core/Parser/Lexer.hs
@@ -1,293 +0,0 @@---- | Reference lexer for core langauge parser. Slow but Simple.-module DDC.Core.Parser.Lexer- ( -- * Constructors- isConName, isConStart, isConBody- , readTwConBuiltin- , readTcConBuiltin- , readWbConBuiltin- , readCon- - -- * Variables- , isVarName, isVarStart, isVarBody- , readVar-- -- * Lexer- , lexExp)-where-import DDC.Base.Lexer-import DDC.Core.Exp-import DDC.Core.Parser.Tokens-import Data.Char----- WbCon names ------------------------------------------------------------------- | Read a `WbCon`.-readWbConBuiltin :: String -> Maybe WbCon-readWbConBuiltin ss- = case ss of- "pure" -> Just WbConPure- "empty" -> Just WbConEmpty- "use" -> Just WbConUse- "read" -> Just WbConRead- "alloc" -> Just WbConAlloc- _ -> Nothing----- | Textual keywords in the core language.-keywords :: [(String, Tok n)]-keywords- = [ ("in", KA KIn)- , ("of", KA KOf) - , ("letrec", KA KLetRec)- , ("letregion", KA KLetRegion)- , ("withregion", KA KWithRegion)- , ("let", KA KLet)- , ("lazy", KA KLazy)- , ("case", KA KCase)- , ("purify", KA KPurify)- , ("forget", KA KForget)- , ("weakeff", KA KWeakEff)- , ("weakclo", KA KWeakClo)- , ("with", KA KWith)- , ("where", KA KWhere) ]------------------------------------------------------------------------------------- | Lex a string into tokens.----lexExp :: Int -> String -> [Token (Tok String)]-lexExp lineStart str- = lexWord lineStart 1 str- where -- lexWord :: Int -> Int -> String -> [Token (Tok String)]- lexWord line column w- = let tok t = Token t (SourcePos Nothing line column)- tokA = tok . KA- tokN = tok . KN-- lexMore n rest- = lexWord line (column + n) rest-- in case w of- [] -> [] -- ' ' : w' -> lexMore 1 w'- '\t' : w' -> lexMore 8 w'- '\n' : w' -> lexWord (line + 1) 1 w'--- -- The unit data constructor- '(' : ')' : w' -> tokN (KCon "()") : lexMore 2 w'-- -- Compound Parens- '[' : ':' : w' -> tokA KSquareColonBra : lexMore 2 w'- ':' : ']' : w' -> tokA KSquareColonKet : lexMore 2 w'- '<' : ':' : w' -> tokA KAngleColonBra : lexMore 2 w'- ':' : '>' : w' -> tokA KAngleColonKet : lexMore 2 w'-- -- Function Constructors- '~' : '>' : w' -> tokA KArrowTilde : lexMore 2 w'- '-' : '>' : w' -> tokA KArrowDash : lexMore 2 w'- '=' : '>' : w' -> tokA KArrowEquals : lexMore 2 w'-- -- Compound symbols- ':' : ':' : w' -> tokA KColonColon : lexMore 2 w'- '/' : '\\' : w' -> tokA KBigLambda : lexMore 2 w'-- -- Debruijn indices- '^' : cs- | (ds, rest) <- span isDigit cs- , length ds >= 1- -> tokA (KIndex (read ds)) : lexMore (1 + length ds) rest -- -- Parens- '(' : w' -> tokA KRoundBra : lexMore 1 w'- ')' : w' -> tokA KRoundKet : lexMore 1 w'- '[' : w' -> tokA KSquareBra : lexMore 1 w'- ']' : w' -> tokA KSquareKet : lexMore 1 w'- '{' : w' -> tokA KBraceBra : lexMore 1 w'- '}' : w' -> tokA KBraceKet : lexMore 1 w'- '<' : w' -> tokA KAngleBra : lexMore 1 w'- '>' : w' -> tokA KAngleKet : lexMore 1 w' -- -- Punctuation- '.' : w' -> tokA KDot : lexMore 1 w'- '|' : w' -> tokA KBar : lexMore 1 w'- '^' : w' -> tokA KHat : lexMore 1 w'- '+' : w' -> tokA KPlus : lexMore 1 w'- ':' : w' -> tokA KColon : lexMore 1 w'- ',' : w' -> tokA KComma : lexMore 1 w'- '\\' : w' -> tokA KBackSlash : lexMore 1 w'- ';' : w' -> tokA KSemiColon : lexMore 1 w'- '_' : w' -> tokA KUnderscore : lexMore 1 w'- '=' : w' -> tokA KEquals : lexMore 1 w'- '&' : w' -> tokA KAmpersand : lexMore 1 w'- '-' : w' -> tokA KDash : lexMore 1 w'- - -- Bottoms- '!' : '0' : w' -> tokA KBotEffect : lexMore 2 w'- '$' : '0' : w' -> tokA KBotClosure : lexMore 2 w'-- -- Sort Constructors- '*' : '*' : w' -> tokA KSortComp : lexMore 2 w'- '@' : '@' : w' -> tokA KSortProp : lexMore 2 w' -- -- Kind Constructors- '*' : w' -> tokA KKindValue : lexMore 1 w'- '%' : w' -> tokA KKindRegion : lexMore 1 w'- '!' : w' -> tokA KKindEffect : lexMore 1 w'- '$' : w' -> tokA KKindClosure : lexMore 1 w'- '@' : w' -> tokA KKindWitness : lexMore 1 w'- - -- Literal values- c : cs- | isDigit c- , (body, rest) <- span isDigit cs- -> tokN (KLit (c:body)) : lexMore (length (c:body)) rest- - -- Named Constructors- c : cs- | isConStart c- , (body, rest) <- span isConBody cs- , (body', rest') <- case rest of- '#' : rest' -> (body ++ "#", rest')- _ -> (body, rest)- -> let readNamedCon s- | Just twcon <- readTwConBuiltin s- = tokA (KTwConBuiltin twcon) : lexMore (length s) rest'- - | Just tccon <- readTcConBuiltin s- = tokA (KTcConBuiltin tccon) : lexMore (length s) rest'- - | Just con <- readCon s- = tokN (KCon con) : lexMore (length s) rest'- - | otherwise - = [tok (KJunk c)]- - in readNamedCon (c : body')-- -- Keywords, Named Variables and Witness constructors- c : cs- | isVarStart c- , (body, rest) <- span isVarBody cs- -> let readNamedVar s- | Just t <- lookup s keywords- = tok t : lexMore (length s) rest-- | Just wc <- readWbConBuiltin s- = tokA (KWbConBuiltin wc) : lexMore (length s) rest- - | Just v <- readVar s- = tokN (KVar v) : lexMore (length s) rest-- | otherwise- = [tok (KJunk c)]-- in readNamedVar (c : body)-- -- Error- c : _ -> [tok $ KJunk c]- ---- TyCon names ------------------------------------------------------------------- | String is a constructor name.-isConName :: String -> Bool-isConName str- = case str of- [] -> False- (c:cs) - | isConStart c - , and (map isConBody cs)- -> True- - | _ : _ <- cs- , isConStart c- , and (map isConBody (init cs))- , last cs == '#'- -> True-- | otherwise- -> False---- | Character can start a constructor name.-isConStart :: Char -> Bool-isConStart = isUpper----- | Charater can be part of a constructor body.-isConBody :: Char -> Bool-isConBody c = isUpper c || isLower c || isDigit c || c == '_'- ---- | Read a named `TwCon`. -readTwConBuiltin :: String -> Maybe TwCon-readTwConBuiltin ss- = case ss of- "Global" -> Just TwConGlobal- "DeepGlobal" -> Just TwConDeepGlobal- "Const" -> Just TwConConst- "DeepConst" -> Just TwConDeepConst- "Mutable" -> Just TwConMutable- "DeepMutable" -> Just TwConDeepMutable- "Lazy" -> Just TwConLazy- "HeadLazy" -> Just TwConHeadLazy- "Manifest" -> Just TwConManifest- "Pure" -> Just TwConPure- "Empty" -> Just TwConEmpty- _ -> Nothing----- | Read a builtin `TcCon` with a non-symbolic name, --- ie not '->'.-readTcConBuiltin :: String -> Maybe TcCon-readTcConBuiltin ss- = case ss of- "Read" -> Just TcConRead- "HeadRead" -> Just TcConHeadRead- "DeepRead" -> Just TcConDeepRead- "Write" -> Just TcConWrite- "DeepWrite" -> Just TcConDeepWrite- "Alloc" -> Just TcConAlloc- "DeepAlloc" -> Just TcConDeepAlloc- "Use" -> Just TcConUse- "DeepUse" -> Just TcConDeepUse- _ -> Nothing----- | Read a named, user defined `TcCon`.------ We won't know its kind, so fill this in with the Bottom element for --- computatation kinds (**0).-readCon :: String -> Maybe String-readCon ss- | isConName ss = Just ss- | otherwise = Nothing----- TyVar names ------------------------------------------------------------------- | String is a variable name.-isVarName :: String -> Bool-isVarName [] = False-isVarName (c:cs) = isVarStart c && (and $ map isVarBody cs)----- | Charater can start a variable name.-isVarStart :: Char -> Bool-isVarStart = isLower- ---- | Character can be part of a variable body.-isVarBody :: Char -> Bool-isVarBody c- = isUpper c || isLower c || isDigit c || c == '_' || c == '\''----- | Read a named, user defined variable.-readVar :: String -> Maybe String-readVar ss- | isVarName ss = Just ss- | otherwise = Nothing-
+ DDC/Core/Parser/Module.hs view
@@ -0,0 +1,125 @@++module DDC.Core.Parser.Module+ (pModule)+where+import DDC.Core.Module+import DDC.Core.Exp+import DDC.Core.Parser.Type+import DDC.Core.Parser.Exp+import DDC.Core.Parser.Base+import DDC.Core.Lexer.Tokens+import DDC.Core.Compounds+import DDC.Base.Pretty+import qualified DDC.Base.Parser as P+import qualified Data.Map as Map+++-- Module ---------------------------------------------------------------------+-- | Parse a core module.+pModule :: (Ord n, Pretty n) + => Parser n (Module () n)+pModule + = do pTok KModule+ name <- pModuleName++ -- exports { SIG;+ }+ tExports + <- P.choice+ [do pTok KExports+ pTok KBraceBra+ sigs <- P.sepEndBy1 pTypeSig (pTok KSemiColon)+ pTok KBraceKet+ return sigs++ , return []]++ -- imports { SIG;+ }+ tImportKindsTypes+ <- P.choice+ [do pTok KImports+ pTok KBraceBra+ importKinds <- P.sepEndBy pImportKindSpec (pTok KSemiColon)+ importTypes <- P.sepEndBy pImportTypeSpec (pTok KSemiColon)+ pTok KBraceKet+ return (importKinds, importTypes)++ , return ([], [])]++ let (tImportKinds, tImportTypes)+ = tImportKindsTypes++ pTok KWith++ -- LET;++ lts <- P.sepBy1 pLets (pTok KIn)++ -- The body of the module consists of the top-level bindings wrapped+ -- around a unit constructor place-holder.+ let body = xLets () lts (xUnit ())++ -- ISSUE #295: Check for duplicate exported names in module parser.+ -- The names are added to a unique map, so later ones with the same+ -- name will replace earlier ones.+ return $ ModuleCore+ { moduleName = name+ , moduleExportKinds = Map.empty+ , moduleExportTypes = Map.fromList tExports+ , moduleImportKinds = Map.fromList tImportKinds+ , moduleImportTypes = Map.fromList tImportTypes+ , moduleBody = body }+++-- | Parse a type signature.+pTypeSig :: Ord n => Parser n (n, Type n) +pTypeSig+ = do var <- pVar+ pTok KColonColon+ t <- pType+ return (var, t)+++-- | Parse the type signature of an imported variable.+pImportKindSpec + :: (Ord n, Pretty n) + => Parser n (n, (QualName n, Kind n))++pImportKindSpec + = pTok KType+ >> P.choice+ [ -- Import with an explicit external name.+ -- Module.varExternal with varLocal+ do qn <- pQualName+ pTok KWith+ n <- pName+ pTok KColonColon+ k <- pType+ return (n, (qn, k))++ , do n <- pName+ pTok KColonColon+ k <- pType+ return (n, (QualName (ModuleName []) n, k))+ ] +++-- | Parse the type signature of an imported variable.+pImportTypeSpec + :: (Ord n, Pretty n) + => Parser n (n, (QualName n, Type n))++pImportTypeSpec + = P.choice+ [ -- Import with an explicit external name.+ -- Module.varExternal with varLocal+ do qn <- pQualName+ pTok KWith+ n <- pName+ pTok KColonColon+ t <- pType+ return (n, (qn, t))++ , do n <- pName+ pTok KColonColon+ t <- pType+ return (n, (QualName (ModuleName []) n, t))+ ]
+ DDC/Core/Parser/Param.hs view
@@ -0,0 +1,122 @@++module DDC.Core.Parser.Param+ ( ParamSpec (..)+ , funTypeOfParams+ , expOfParams+ , pBindParamSpec)+where+import DDC.Core.Exp+import DDC.Core.Parser.Type+import DDC.Core.Parser.Base (Parser)+import DDC.Core.Lexer.Tokens+import qualified DDC.Base.Parser as P+import qualified DDC.Type.Compounds as T+++-- | Specification of a function parameter.+-- We can determine the contribution to the type of the function, +-- as well as its expression based on the parameter.+data ParamSpec n+ = ParamType (Bind n)+ | ParamWitness (Bind n)+ | ParamValue (Bind n) (Type n) (Type n)+++-- | Build the type of a function from specifications of its parameters,+-- and the type of the body.+funTypeOfParams + :: [ParamSpec n] -- ^ Spec of parameters.+ -> Type n -- ^ Type of body.+ -> Type n -- ^ Type of whole function.++funTypeOfParams [] tBody = tBody+funTypeOfParams (p:ps) tBody+ = case p of+ ParamType b + -> TForall b + $ funTypeOfParams ps tBody++ ParamWitness b+ -> T.tImpl (T.typeOfBind b)+ $ funTypeOfParams ps tBody++ ParamValue b eff clo+ -> T.tFun (T.typeOfBind b) eff clo + $ funTypeOfParams ps tBody+++-- | Build the expression of a function from specifications of its parameters,+-- and the expression for the body.+expOfParams + :: a+ -> [ParamSpec n] -- ^ Spec of parameters.+ -> Exp a n -- ^ Body of function.+ -> Exp a n -- ^ Expression of whole function.++expOfParams _ [] xBody = xBody+expOfParams a (p:ps) xBody+ = case p of+ ParamType b + -> XLAM a b $ expOfParams a ps xBody+ + ParamWitness b+ -> XLam a b $ expOfParams a ps xBody++ ParamValue b _ _+ -> XLam a b $ expOfParams a ps xBody+++-- | Parse a parameter specification.+--+-- [BIND1 BIND2 .. BINDN : TYPE]+-- or (BIND : TYPE)+-- or (BIND : TYPE) { EFFECT | CLOSURE }+--+pBindParamSpec :: Ord n => Parser n [ParamSpec n]+pBindParamSpec+ = P.choice+ -- Type parameter+ -- [BIND1 BIND2 .. BINDN : TYPE]+ [ do pTok KSquareBra+ bs <- P.many1 pBinder+ pTok KColon+ t <- pType+ pTok KSquareKet+ return [ ParamType b + | b <- zipWith T.makeBindFromBinder bs (repeat t)]+++ -- Witness parameter+ -- <BIND : TYPE>+ , do pTok KAngleBra+ b <- pBinder+ pTok KColon+ t <- pType+ pTok KAngleKet+ return [ ParamWitness $ T.makeBindFromBinder b t]++ -- Value parameter+ -- (BIND : TYPE) + -- (BIND : TYPE) { TYPE | TYPE }+ , do pTok KRoundBra+ b <- pBinder+ pTok KColon+ t <- pType+ pTok KRoundKet++ (eff, clo) + <- P.choice+ [ do pTok KBraceBra+ eff' <- pType+ pTok KBar+ clo' <- pType+ pTok KBraceKet+ return (eff', clo')+ + , do return (T.tBot T.kEffect, T.tBot T.kClosure) ]+ ++ return $ [ParamValue (T.makeBindFromBinder b t) eff clo]+ ]++
− DDC/Core/Parser/Tokens.hs
@@ -1,263 +0,0 @@--module DDC.Core.Parser.Tokens- ( Tok (..)- , describeTok- , renameTok-- , TokAtom (..)- , describeTokAtom-- , TokNamed (..)- , describeTokNamed)-where-import DDC.Core.Pretty-import DDC.Core.Exp----- TokenFamily ------------------------------------------------------------------- | The family of a token.--- This is used to help generate parser error messages,--- so we can say ''the constructor Cons''--- and ''the keyword case'' etc.-data TokenFamily- = Symbol- | Keyword- | Constructor- | Index- | Variable----- | Describe a token family, for parser error messages.-describeTokenFamily :: TokenFamily -> String-describeTokenFamily tf- = case tf of- Symbol -> "symbol"- Keyword -> "keyword"- Constructor -> "constructor"- Index -> "index"- Variable -> "variable"----- Tok --------------------------------------------------------------------------- | Tokens accepted by the core language parser.-data Tok n- -- Some junk symbol that isn't part of the language.- = KJunk Char-- -- An atomic token.- | KA !TokAtom -- -- A named token.- | KN !(TokNamed n)- deriving (Eq, Show)----- | Describe a token for parser error messages.-describeTok :: Pretty n => Tok n -> String-describeTok kk- = case kk of- KJunk c -> "character " ++ show c- KA ta -> describeTokAtom ta- KN tn -> describeTokNamed tn----- | Apply a function to all the names in a `Tok`.-renameTok- :: Ord n2- => (n1 -> n2) -> Tok n1 -> Tok n2--renameTok f kk- = case kk of- KJunk s -> KJunk s- KA t -> KA t- KN t -> KN $ renameTokNamed f t----- TokAtom ----------------------------------------------------------------------- | Atomic tokens, that don't contain user-defined names.-data TokAtom- -- parens- = KRoundBra- | KRoundKet- | KSquareBra- | KSquareKet- | KBraceBra- | KBraceKet- | KAngleBra- | KAngleKet-- -- compound parens- | KSquareColonBra- | KSquareColonKet- | KAngleColonBra- | KAngleColonKet-- -- punctuation- | KDot- | KBar- | KHat- | KPlus- | KColon- | KComma- | KBackSlash- | KSemiColon- | KUnderscore- | KEquals- | KAmpersand- | KDash- | KColonColon- | KBigLambda-- -- symbolic constructors- | KSortComp- | KSortProp- | KKindValue- | KKindRegion- | KKindEffect- | KKindClosure- | KKindWitness- | KArrowTilde- | KArrowDash- | KArrowEquals-- -- bottoms- | KBotEffect- | KBotClosure-- -- expression keywords- | KWith- | KWhere- | KIn- | KLet- | KLazy- | KLetRec- | KLetRegion- | KWithRegion- | KCase- | KOf- | KWeakEff- | KWeakClo- | KPurify- | KForget-- -- debruijn indices- | KIndex Int-- -- builtin names- | KTwConBuiltin TwCon- | KWbConBuiltin WbCon- | KTcConBuiltin TcCon- deriving (Eq, Show)----- | Describe a `TokAtom`, for parser error messages.-describeTokAtom :: TokAtom -> String-describeTokAtom ta- = let (family, str) = describeTokAtom' ta- in describeTokenFamily family ++ " " ++ show str--describeTokAtom' :: TokAtom -> (TokenFamily, String)-describeTokAtom' ta- = case ta of- -- parens- KRoundBra -> (Symbol, "(")- KRoundKet -> (Symbol, ")")- KSquareBra -> (Symbol, "[")- KSquareKet -> (Symbol, "]")- KBraceBra -> (Symbol, "{")- KBraceKet -> (Symbol, "}")- KAngleBra -> (Symbol, "<")- KAngleKet -> (Symbol, ">")-- -- compound parens- KSquareColonBra -> (Symbol, "[:")- KSquareColonKet -> (Symbol, ":]")- KAngleColonBra -> (Symbol, "<:")- KAngleColonKet -> (Symbol, ":>")-- -- punctuation- KDot -> (Symbol, ".")- KBar -> (Symbol, "|")- KHat -> (Symbol, "^")- KPlus -> (Symbol, "+")- KColon -> (Symbol, ":")- KComma -> (Symbol, ",")- KBackSlash -> (Symbol, "\\")- KSemiColon -> (Symbol, ";")- KUnderscore -> (Symbol, "_")- KEquals -> (Symbol, "=")- KAmpersand -> (Symbol, "&")- KDash -> (Symbol, "-")- KColonColon -> (Symbol, "::")- KBigLambda -> (Symbol, "/\\")-- -- symbolic constructors- KSortComp -> (Constructor, "**")- KSortProp -> (Constructor, "@@")- KKindValue -> (Constructor, "*")- KKindRegion -> (Constructor, "%")- KKindEffect -> (Constructor, "!")- KKindClosure -> (Constructor, "$")- KKindWitness -> (Constructor, "@")- KArrowTilde -> (Constructor, "~>")- KArrowDash -> (Constructor, "->")- KArrowEquals -> (Constructor, "=>")-- -- bottoms- KBotEffect -> (Constructor, "!0")- KBotClosure -> (Constructor, "!$")-- -- expression keywords- KWith -> (Keyword, "with")- KWhere -> (Keyword, "where")- KIn -> (Keyword, "in")- KLet -> (Keyword, "let")- KLazy -> (Keyword, "lazy")- KLetRec -> (Keyword, "letrec")- KLetRegion -> (Keyword, "letregion")- KWithRegion -> (Keyword, "withregion")- KCase -> (Keyword, "case")- KOf -> (Keyword, "of")- KWeakEff -> (Keyword, "weakeff")- KWeakClo -> (Keyword, "weakclo")- KPurify -> (Keyword, "purify")- KForget -> (Keyword, "forget")- - -- debruijn indices- KIndex i -> (Index, "^" ++ show i)-- -- builtin names- KTwConBuiltin tw -> (Constructor, renderPlain $ ppr tw)- KWbConBuiltin wi -> (Constructor, renderPlain $ ppr wi)- KTcConBuiltin tc -> (Constructor, renderPlain $ ppr tc)----- TokNamed ---------------------------------------------------------------------- | A token witn a user-defined name.-data TokNamed n- = KCon n- | KVar n- | KLit n- deriving (Eq, Show)----- | Describe a `TokNamed`, for parser error messages.-describeTokNamed :: Pretty n => TokNamed n -> String-describeTokNamed tn- = case tn of- KCon n -> renderPlain $ text "constructor" <+> (dquotes $ ppr n)- KVar n -> renderPlain $ text "variable" <+> (dquotes $ ppr n)- KLit n -> renderPlain $ text "literal" <+> (dquotes $ ppr n)----- | Apply a function to all the names in a `TokNamed`.-renameTokNamed - :: Ord n2- => (n1 -> n2) -> TokNamed n1 -> TokNamed n2--renameTokNamed f kk- = case kk of- KCon c -> KCon $ f c- KVar c -> KVar $ f c- KLit c -> KLit $ f c-
+ DDC/Core/Parser/Type.hs view
@@ -0,0 +1,209 @@++-- | Parser for type expressions.+module DDC.Core.Parser.Type+ ( pType+ , pTypeAtom+ , pTypeApp+ , pBinder+ , pIndex+ , pTok+ , pTokAs)+where+import DDC.Core.Parser.Base+import DDC.Core.Lexer.Tokens +import DDC.Type.Exp+import DDC.Type.Compounds+import DDC.Base.Parser ((<?>))+import qualified DDC.Base.Parser as P+import qualified DDC.Type.Sum as TS+++-- | Parse a type.+pType :: Ord n => Parser n (Type n)+pType = pTypeSum+ <?> "a type"+++-- | Parse a type sum.+pTypeSum :: Ord n => Parser n (Type n)+pTypeSum + = do t1 <- pTypeForall+ P.choice + [ -- Type sums.+ -- T2 + T3+ do pTok KPlus+ t2 <- pTypeSum+ return $ TSum $ TS.fromList (tBot sComp) [t1, t2]+ + , do return t1 ]+ <?> "a type"+++-- | Parse a binder.+pBinder :: Ord n => Parser n (Binder n)+pBinder+ = P.choice+ -- Named binders.+ [ do v <- pVar+ return $ RName v+ + -- Anonymous binders.+ , do pTok KHat+ return $ RAnon + + -- Vacant binders.+ , do pTok KUnderscore+ return $ RNone ]+ <?> "a binder"+ +-- | Parse a quantified type.+pTypeForall :: Ord n => Parser n (Type n)+pTypeForall+ = P.choice+ [ -- Universal quantification.+ -- [v1 v1 ... vn : T1]. T2+ do pTok KSquareBra+ bs <- P.many1 pBinder+ pTok KColon+ k <- pTypeSum+ pTok KSquareKet+ pTok KDot++ body <- pTypeForall++ return $ foldr TForall body + $ map (\b -> makeBindFromBinder b k) bs++ -- Body type+ , do pTypeFun]+ <?> "a type"+++-- | Parse a function type.+pTypeFun :: Ord n => Parser n (Type n)+pTypeFun+ = do t1 <- pTypeApp+ P.choice + [ -- T1 ~> T2+ do pTok KArrowTilde+ t2 <- pTypeFun+ return $ TApp (TApp (TCon (TyConKind KiConFun)) t1) t2++ -- T1 => T2+ , do pTok KArrowEquals+ t2 <- pTypeFun+ return $ TApp (TApp (TCon (TyConWitness TwConImpl)) t1) t2++ -- T1 -> T2+ , do pTok KArrowDash+ t2 <- pTypeFun+ return $ t1 `tFunPE` t2++ -- T1 -(TSUM | TSUM)> t2+ , do pTok KDash+ pTok KRoundBra+ eff <- pTypeSum+ pTok KBar+ clo <- pTypeSum+ pTok KRoundKet+ pTok KAngleKet+ t2 <- pTypeFun+ return $ tFun t1 eff clo t2+++ -- Body type+ , do return t1 ]+ <?> "an atomic type or type application"+++-- | Parse a type application.+pTypeApp :: Ord n => Parser n (Type n)+pTypeApp + = do (t:ts) <- P.many1 pTypeAtom+ return $ foldl TApp t ts+ <?> "an atomic type or type application"+++-- | Parse a variable, constructor or parenthesised type.+pTypeAtom :: Ord n => Parser n (Type n)+pTypeAtom + = P.choice+ -- (~>) and (=>) and (->) and (TYPE2)+ [ do pTok KRoundBra+ P.choice+ [ do pTok KArrowTilde+ pTok KRoundKet+ return (TCon $ TyConKind KiConFun)++ , do pTok KArrowEquals+ pTok KRoundKet+ return (TCon $ TyConWitness TwConImpl)++ , do pTok KArrowDash+ pTok KRoundKet+ return (TCon $ TyConSpec TcConFun)++ , do t <- pTypeSum+ pTok KRoundKet+ return t + ]++ -- Named type constructors+ , do tc <- pTcCon+ return $ TCon (TyConSpec tc)++ , do tc <- pTwCon+ return $ TCon (TyConWitness tc)++ , do tc <- pTyConNamed+ return $ TCon tc++ -- Symbolic constructors.+ , do pTokAs KSortComp (TCon $ TyConSort SoConComp)+ , do pTokAs KSortProp (TCon $ TyConSort SoConProp) + , do pTokAs KKindValue (TCon $ TyConKind KiConData)+ , do pTokAs KKindRegion (TCon $ TyConKind KiConRegion) + , do pTokAs KKindEffect (TCon $ TyConKind KiConEffect) + , do pTokAs KKindClosure (TCon $ TyConKind KiConClosure) + , do pTokAs KKindWitness (TCon $ TyConKind KiConWitness) + + -- Bottoms.+ , do pTokAs KBotEffect (tBot kEffect)+ , do pTokAs KBotClosure (tBot kClosure)+ + -- Bound occurrence of a variable.+ -- We don't know the kind of this variable yet, so fill in the+ -- field with the bottom element of computation kinds. This isn't+ -- really part of the language, but makes sense implentation-wise.+ , do v <- pVar+ return $ TVar (UName v)++ , do i <- pIndex+ return $ TVar (UIx (fromIntegral i))+ ]+ <?> "an atomic type"+++-------------------------------------------------------------------------------+-- | Parse a builtin `TcCon`+pTcCon :: Parser n TcCon+pTcCon = P.pTokMaybe f+ <?> "a type constructor"+ where f (KA (KTcConBuiltin c)) = Just c+ f _ = Nothing ++-- | Parse a builtin `TwCon`+pTwCon :: Parser n TwCon+pTwCon = P.pTokMaybe f+ <?> "a witness constructor"+ where f (KA (KTwConBuiltin c)) = Just c+ f _ = Nothing++-- | Parse a user `TcCon`+pTyConNamed :: Parser n (TyCon n)+pTyConNamed + = P.pTokMaybe f+ <?> "a type constructor"+ where f (KN (KCon n)) = Just (TyConBound (UName n) (tBot kData))+ f _ = Nothing+
+ DDC/Core/Parser/Witness.hs view
@@ -0,0 +1,84 @@++module DDC.Core.Parser.Witness+ ( pWitness+ , pWitnessApp+ , pWitnessAtom) +where+import DDC.Core.Parser.Type+import DDC.Core.Parser.Base+import DDC.Core.Lexer.Tokens+import DDC.Core.Exp+import DDC.Base.Parser ((<?>))+import qualified DDC.Base.Parser as P+import qualified DDC.Type.Compounds as T+ ++-- | Parse a witness expression.+pWitness :: Ord n => Parser n (Witness n)+pWitness = pWitnessJoin+++-- | Parse a witness join.+pWitnessJoin :: Ord n => Parser n (Witness n)+pWitnessJoin + -- WITNESS or WITNESS & WITNESS+ = do w1 <- pWitnessApp+ P.choice + [ do pTok KAmpersand+ w2 <- pWitnessJoin+ return (WJoin w1 w2)++ , do return w1 ]+++-- | Parse a witness application.+pWitnessApp :: Ord n => Parser n (Witness n)+pWitnessApp + = do (x:xs) <- P.many1 pWitnessArg+ return $ foldl WApp x xs++ <?> "a witness expression or application"+++-- | Parse a witness argument.+pWitnessArg :: Ord n => Parser n (Witness n)+pWitnessArg + = P.choice+ [ -- [TYPE]+ do pTok KSquareBra+ t <- pType+ pTok KSquareKet+ return $ WType t++ -- WITNESS+ , do pWitnessAtom ]+++-- | Parse a variable, constructor or parenthesised witness.+pWitnessAtom :: Ord n => Parser n (Witness n)+pWitnessAtom + = P.choice+ -- (WITNESS)+ [ do pTok KRoundBra+ w <- pWitness+ pTok KRoundKet+ return $ w++ -- Named constructors+ , do con <- pCon+ return $ WCon (WiConBound (UName con) (T.tBot T.kWitness))++ -- Baked-in witness constructors.+ , do wb <- pWbCon+ return $ WCon (WiConBuiltin wb)++ + -- Debruijn indices+ , do i <- pIndex+ return $ WVar (UIx i)++ -- Variables+ , do var <- pVar+ return $ WVar (UName var) ]++ <?> "a witness"
DDC/Core/Predicates.hs view
@@ -1,10 +1,12 @@ -- | Simple predicates on core expressions. module DDC.Core.Predicates- ( -- * Atoms- isXVar, isXCon- , isAtomW, isAtomX+ ( module DDC.Type.Predicates + -- * Atoms+ , isXVar, isXCon+ , isAtomX, isAtomW+ -- * Lambdas , isXLAM, isXLam , isLambdaX@@ -12,6 +14,10 @@ -- * Applications , isXApp + -- * Types and Witnesses+ , isXType+ , isXWitness+ -- * Patterns , isPDefault) where@@ -36,15 +42,6 @@ _ -> False --- | Check whether a witness is a `WVar` or `WCon`.-isAtomW :: Witness n -> Bool-isAtomW ww- = case ww of- WVar{} -> True- WCon{} -> True- _ -> False-- -- | Check whether an expression is a `XVar` or an `XCon`, -- or some type or witness atom. isAtomX :: Exp a n -> Bool@@ -57,6 +54,15 @@ _ -> False +-- | Check whether a witness is a `WVar` or `WCon`.+isAtomW :: Witness n -> Bool+isAtomW ww+ = case ww of+ WVar{} -> True+ WCon{} -> True+ _ -> False++ -- Lambdas -------------------------------------------------------------------- -- | Check whether an expression is a spec abstraction (level-1). isXLAM :: Exp a n -> Bool@@ -87,6 +93,23 @@ = case xx of XApp{} -> True _ -> False+++-- Type and Witness -----------------------------------------------------------+-- | Check whether an expression is an `XType`+isXType :: Exp a n -> Bool+isXType xx+ = case xx of+ XType{} -> True+ _ -> False+++-- | Check whether an expression is an `XWitness`+isXWitness :: Exp a n -> Bool+isXWitness xx+ = case xx of+ XWitness{} -> True+ _ -> False -- Patterns -------------------------------------------------------------------
DDC/Core/Pretty.hs view
@@ -1,43 +1,94 @@--- | Pretty printing for core expressions.++-- | Provides pretty printing for core modules and expressions. module DDC.Core.Pretty ( module DDC.Type.Pretty , module DDC.Base.Pretty) where-import DDC.Core.Exp import DDC.Core.Compounds import DDC.Core.Predicates+import DDC.Core.Module+import DDC.Core.Exp import DDC.Type.Pretty-import DDC.Type.Compounds-import DDC.Type.Predicates import DDC.Base.Pretty+import Data.List+import qualified Data.Map.Strict as Map --- Binder ------------------------------------------------------------------------ | Pretty print a binder, adding spaces after names.--- The RAnon and None binders don't need spaces, as they're single symbols.-pprBinderSep :: Pretty n => Binder n -> Doc-pprBinderSep bb- = case bb of- RName v -> ppr v- RAnon -> text "^"- RNone -> text "_"+-- ModuleName -----------------------------------------------------------------+instance Pretty ModuleName where+ ppr (ModuleName parts)+ = text $ intercalate "." parts --- | Print a group of binders with the same type.-pprBinderGroup - :: (Pretty n, Eq n) - => Doc -> ([Binder n], Type n) -> Doc+-- Module ---------------------------------------------------------------------+instance (Pretty n, Eq n) => Pretty (Module a n) where+ ppr ModuleCore + { moduleName = name+ , moduleExportKinds = exportKinds+ , moduleExportTypes = exportTypes+ , moduleImportKinds = importKinds+ , moduleImportTypes = importTypes+ , moduleBody = body }+ = {-# SCC "ppr[Module]" #-}+ let + (lts, _) = splitXLets body -pprBinderGroup lam (rs, t)- = lam <> parens ((cat $ map pprBinderSep rs) <+> text ":" <+> ppr t) <> dot+ docsExportKinds+ | Map.null exportKinds = empty+ | otherwise + = nest 8 $ line + <> vcat [ text "type" <+> ppr n <+> text "::" <+> ppr t <> semi+ | (n, t) <- Map.toList exportKinds ] + docsExportTypes + | Map.null exportTypes = empty+ | otherwise+ = nest 8 $ line+ <> vcat [ ppr n <+> text "::" <+> ppr t <> semi+ | (n, t) <- Map.toList exportTypes ] + docsImportKinds+ | Map.null importKinds = empty+ | otherwise + = nest 8 $ line + <> vcat [ text "type" <+> ppr n <+> text "::" <+> ppr t <> semi+ | (n, (_, t)) <- Map.toList importKinds ]++ docsImportTypes + | Map.null importTypes = empty+ | otherwise+ = nest 8 $ line+ <> vcat [ ppr n <+> text "::" <+> ppr t <> semi+ | (n, (_, t)) <- Map.toList importTypes ]++ in text "module" <+> ppr name + <+> (if Map.null exportKinds && Map.null exportTypes+ then empty+ else line+ <> text "exports" <+> lbrace+ <> docsExportKinds+ <> docsExportTypes+ <> line + <> rbrace <> space)++ <> (if Map.null importKinds && Map.null importTypes+ then empty+ else line + <> text "imports" <+> lbrace + <> docsImportKinds+ <> docsImportTypes+ <> line + <> rbrace <> space)+ <> text "with" <$$> (vcat $ map ppr lts)++ -- Exp ------------------------------------------------------------------------ instance (Pretty n, Eq n) => Pretty (Exp a n) where pprPrec d xx- = case xx of+ = {-# SCC "ppr[Exp]" #-}+ case xx of XVar _ u -> ppr u- XCon _ tc -> ppr tc+ XCon _ dc -> ppr dc XLAM{} -> let Just (bs, xBody) = takeXLAMs xx@@ -107,15 +158,25 @@ = ppr p <+> nest 1 (line <> nest 3 (text "->" <+> ppr x)) +-- DaCon ----------------------------------------------------------------------+instance (Pretty n, Eq n) => Pretty (DaCon n) where+ ppr dc+ = case daConName dc of+ DaConUnit -> text "()"+ DaConNamed n -> ppr n++ -- Cast ------------------------------------------------------------------------instance (Pretty n, Eq n) => Pretty (Cast n) where+instance (Pretty n, Eq n) => Pretty (Cast a n) where ppr cc = case cc of CastWeakenEffect eff -> text "weakeff" <+> brackets (ppr eff) - CastWeakenClosure clo- -> text "weakclo" <+> brackets (ppr clo)+ CastWeakenClosure xs+ -> text "weakclo" + <+> braces (hcat $ punctuate (semi <> space) + $ map ppr xs) CastPurify w -> text "purify" <+> angles (ppr w)@@ -152,17 +213,27 @@ $ map pprLetRecBind bxs))) <$> rbrace -- LLetRegion b []+ + LLetRegions [b] [] -> text "letregion" <+> ppr (binderOfBind b)-- LLetRegion b bs+ + LLetRegions [b] bs -> text "letregion" <+> ppr (binderOfBind b) <+> text "with" <+> braces (cat $ punctuate (text "; ") $ map ppr bs) + LLetRegions b []+ -> text "letregions"+ <+> (hcat $ punctuate space (map (ppr . binderOfBind) b))++ LLetRegions b bs+ -> text "letregions"+ <+> (hcat $ punctuate space (map (ppr . binderOfBind) b))+ <+> text "with"+ <+> braces (cat $ punctuate (text "; ") $ map ppr bs)+ LWithRegion b -> text "withregion" <+> ppr b@@ -195,8 +266,8 @@ instance (Pretty n, Eq n) => Pretty (WiCon n) where ppr wc = case wc of- WiConBuiltin wb -> ppr wb- WiConBound u -> ppr u+ WiConBuiltin wb -> ppr wb+ WiConBound u _ -> ppr u instance Pretty WbCon where@@ -207,6 +278,24 @@ WbConUse -> text "use" WbConRead -> text "read" WbConAlloc -> text "alloc"+++-- Binder ---------------------------------------------------------------------+pprBinder :: Pretty n => Binder n -> Doc+pprBinder bb+ = case bb of+ RName v -> ppr v+ RAnon -> text "^"+ RNone -> text "_"+++-- | Print a group of binders with the same type.+pprBinderGroup + :: (Pretty n, Eq n) + => Doc -> ([Binder n], Type n) -> Doc++pprBinderGroup lam (rs, t)+ = lam <> parens ((hsep $ map pprBinder rs) <+> text ":" <+> ppr t) <> dot -- Utils ----------------------------------------------------------------------
+ DDC/Core/Transform/LiftT.hs view
@@ -0,0 +1,107 @@++module DDC.Core.Transform.LiftT+ ( liftT, liftAtDepthT+ , MapBoundT(..))+where+import DDC.Core.Exp+import DDC.Type.Transform.LiftT+++instance Ord n => MapBoundT (Exp a) n where+ mapBoundAtDepthT f d xx+ = let down = mapBoundAtDepthT f d+ in case xx of+ XVar a u -> XVar a u+ XCon{} -> xx+ XApp a x1 x2 -> XApp a (down x1) (down x2)+ XLAM a b x -> XLAM a b (mapBoundAtDepthT f (d + countBAnons [b]) x)+ XLam a b x -> XLam a (down b) (down x)+ + XLet a lets x + -> let (lets', levels) = mapBoundAtDepthTLets f d lets + in XLet a lets' (mapBoundAtDepthT f (d + levels) x)++ XCase a x alts -> XCase a (down x) (map down alts)+ XCast a cc x -> XCast a (down cc) (down x)+ XType t -> XType (down t)+ XWitness w -> XWitness (down w)+++instance Ord n => MapBoundT LetMode n where+ mapBoundAtDepthT f d m+ = case m of+ LetStrict -> m+ LetLazy Nothing -> m+ LetLazy (Just w) -> LetLazy (Just $ mapBoundAtDepthT f d w)++ +instance Ord n => MapBoundT Witness n where+ mapBoundAtDepthT f d ww+ = let down = mapBoundAtDepthT f d+ in case ww of+ WVar u -> WVar (down u)+ WCon _ -> ww+ WApp w1 w2 -> WApp (down w1) (down w2)+ WJoin w1 w2 -> WJoin (down w1) (down w2)+ WType t -> WType (down t)+++instance Ord n => MapBoundT (Cast a) n where+ mapBoundAtDepthT f d cc+ = let down = mapBoundAtDepthT f d+ in case cc of+ CastWeakenEffect t + -> CastWeakenEffect (down t)++ CastWeakenClosure xs + -> CastWeakenClosure (map down xs)++ CastPurify w+ -> CastPurify (down w)++ CastForget w+ -> CastForget (down w)+++instance Ord n => MapBoundT (Alt a) n where+ mapBoundAtDepthT f d (AAlt p x)+ = let down = mapBoundAtDepthT f d+ in case p of+ PDefault + -> AAlt PDefault (down x)++ PData dc bs+ -> AAlt (PData dc (map down bs)) (down x) + ++mapBoundAtDepthTLets+ :: Ord n+ => (Int -> Bound n -> Bound n) -- ^ Number of levels to lift.+ -> Int -- ^ Current binding depth.+ -> Lets a n -- ^ Lift exp indices in this thing.+ -> (Lets a n, Int) -- ^ Lifted, and how much to increase depth by++mapBoundAtDepthTLets f d lts+ = let down = mapBoundAtDepthT f d+ in case lts of+ LLet m b x+ -> ( LLet (down m) (down b) (down x)+ , 0)++ LRec bs+ -> let bs' = [ (b, mapBoundAtDepthT f d x) | (b, x) <- bs ]+ in (LRec bs', 0)++ LLetRegions bsT bsX+ -> let inc = countBAnons bsT+ bsX' = map (mapBoundAtDepthT f (d + inc)) bsX+ in ( LLetRegions bsT bsX'+ , inc)++ LWithRegion _+ -> (lts, 0)+++countBAnons = length . filter isAnon+ where isAnon (BAnon _) = True+ isAnon _ = False
− DDC/Core/Transform/LiftW.hs
@@ -1,116 +0,0 @@---- | Lift deBruijn indices in witnesses.-module DDC.Core.Transform.LiftW- (LiftW(..))-where-import DDC.Core.Exp---class LiftW (c :: * -> *) where- -- | Lift indices that are at least a the given depth by some number- -- of levels- liftAtDepthW- :: forall n. Ord n- => Int -- ^ Number of levels to lift.- -> Int -- ^ Current binding depth.- -> c n -- ^ Lift witness variable indices in this thing.- -> c n- - -- | Wrapper for `liftAtDepthX` that starts at depth 0. - liftW :: forall n. Ord n- => Int -- ^ Number of levels to lift.- -> c n -- ^ Lift witness variable indices in this thing.- -> c n- - liftW n xx = liftAtDepthW n 0 xx- --instance LiftW Bound where- liftAtDepthW n d uu- = case uu of- UName{} -> uu- UPrim{} -> uu- UIx i t - | d <= i -> UIx (i + n) t- | otherwise -> uu---instance LiftW (Exp a) where- liftAtDepthW n d xx- = let down = liftAtDepthW n d- in case xx of- XVar{} -> xx- XCon{} -> xx- XApp a x1 x2 -> XApp a (down x1) (down x2)- XLAM a b x -> XLAM a b (down x)- XLam a b x -> XLam a b (liftAtDepthW n (d + 1) x)- - XLet a lets x - -> let (lets', levels) = liftAtDepthXLets n d lets - in XLet a lets' (liftAtDepthW n (d + levels) x)-- XCase a x alts -> XCase a (down x) (map down alts)- XCast a cc x -> XCast a cc (down x)- XType{} -> xx- XWitness w -> XWitness (down w)- --instance LiftW LetMode where- liftAtDepthW n d m- = case m of- LetStrict -> m- LetLazy Nothing -> m- LetLazy (Just w) -> LetLazy (Just $ liftAtDepthW n d w)---instance LiftW (Alt a) where- liftAtDepthW n d (AAlt p x)- = case p of- PDefault - -> AAlt PDefault (liftAtDepthW n d x)-- PData _ bs - -> let d' = d + countBAnons bs- in AAlt p (liftAtDepthW n d' x)---instance LiftW Witness where- liftAtDepthW n d ww- = let down = liftAtDepthW n d- in case ww of- WVar u -> WVar (down u)- WCon{} -> ww- WApp w1 w2 -> WApp (down w1) (down w2)- WJoin w1 w2 -> WJoin (down w1) (down w2)- WType{} -> ww- --liftAtDepthXLets- :: forall a n. Ord n- => Int -- ^ Number of levels to lift.- -> Int -- ^ Current binding depth.- -> Lets a n -- ^ Lift exp indices in this thing.- -> (Lets a n, Int) -- ^ Lifted, and how much to increase depth by--liftAtDepthXLets n d lts- = case lts of- LLet m b x- -> let m' = liftAtDepthW n d m- inc = countBAnons [b]- x' = liftAtDepthW n (d+inc) x- in (LLet m' b x', inc)-- LRec bs- -> let inc = countBAnons (map fst bs)- bs' = map (\(b,e) -> (b, liftAtDepthW n (d+inc) e)) bs- in (LRec bs', inc)-- LLetRegion _b bs -> (lts, countBAnons bs)- LWithRegion _ -> (lts, 0)---countBAnons = length . filter isAnon- where isAnon (BAnon _) = True- isAnon _ = False--
DDC/Core/Transform/LiftX.hs view
@@ -1,92 +1,176 @@ --- | Lift deBruijn indices in expressions.+-- | Lifting and lowering level-0 deBruijn indices in core things.+-- +-- Level-0 indices are used for both value and witness variables. module DDC.Core.Transform.LiftX- (LiftX(..))+ ( liftX, liftAtDepthX+ , lowerX, lowerAtDepthX+ , MapBoundX(..)) where import DDC.Core.Exp -class LiftX (c :: * -> *) where- -- | Lift indices that are at least the given depth by some number- -- of levels.- liftAtDepthX- :: forall n. Ord n+-- Lift -----------------------------------------------------------------------+-- | Lift debruijn indices less than or equal to the given depth.+liftAtDepthX + :: MapBoundX c n => Int -- ^ Number of levels to lift. -> Int -- ^ Current binding depth. -> c n -- ^ Lift expression indices in this thing. -> c n- - -- | Wrapper for `liftAtDepthX` that starts at depth 0. - liftX :: forall n. Ord n- => Int -- ^ Number of levels to lift.- -> c n -- ^ Lift expression indices in this thing.++liftAtDepthX n d+ = {-# SCC liftAtDepthX #-} + mapBoundAtDepthX liftU d+ where + liftU d' u+ = case u of+ UName{} -> u+ UPrim{} -> u+ UIx i+ | d' <= i -> UIx (i + n)+ | otherwise -> u+++-- | Wrapper for `liftAtDepthX` that starts at depth 0. +liftX :: MapBoundX c n => Int -> c n -> c n+liftX n xx = liftAtDepthX n 0 xx+++-- Lower ----------------------------------------------------------------------+-- | Lower debruijn indices less than or equal to the given depth.+lowerAtDepthX + :: MapBoundX c n+ => Int -- ^ Number of levels to lower.+ -> Int -- ^ Current binding depth.+ -> c n -- ^ Lower expression indices in this thing. -> c n- - liftX n xx = liftAtDepthX n 0 xx- -instance LiftX Bound where- liftAtDepthX n d uu- = case uu of- UName{} -> uu- UPrim{} -> uu- UIx i t - | d <= i -> UIx (i + n) t- | otherwise -> uu+lowerAtDepthX n d+ = {-# SCC lowerAtDepthX #-}+ mapBoundAtDepthX liftU d+ where + liftU d' u+ = case u of+ UName{} -> u+ UPrim{} -> u+ UIx i+ | d' <= i -> UIx (i - n)+ | otherwise -> u -instance LiftX (Exp a) where- liftAtDepthX n d xx- = let down = liftAtDepthX n d+-- | Wrapper for `lowerAtDepthX` that starts at depth 0. +lowerX :: MapBoundX c n => Int -> c n -> c n+lowerX n xx = lowerAtDepthX n 0 xx+++-- MapBoundX ------------------------------------------------------------------+class MapBoundX (c :: * -> *) n where+ -- | Apply a function to all bound variables in the program.+ -- The function is passed the current binding depth.+ -- This is used to defined both `liftX` and `lowerX`.+ mapBoundAtDepthX+ :: (Int -> Bound n -> Bound n) -- ^ Function to apply to the bound occ.+ -- It is passed the current binding depth.+ -> Int -- ^ Current binding depth.+ -> c n -- ^ Lift expression indices in this thing.+ -> c n+++instance MapBoundX Bound n where+ mapBoundAtDepthX f d u+ = f d u+++instance MapBoundX (Exp a) n where+ mapBoundAtDepthX f d xx+ = let down = mapBoundAtDepthX f d in case xx of- XVar a u -> XVar a (down u)+ XVar a u -> XVar a (f d u) XCon{} -> xx XApp a x1 x2 -> XApp a (down x1) (down x2) XLAM a b x -> XLAM a b (down x)- XLam a b x -> XLam a b (liftAtDepthX n (d + 1) x)+ XLam a b x -> XLam a b (mapBoundAtDepthX f (d + countBAnons [b]) x) XLet a lets x - -> let (lets', levels) = liftAtDepthXLets n d lets - in XLet a lets' (liftAtDepthX n (d + levels) x)+ -> let (lets', levels) = mapBoundAtDepthXLets f d lets + in XLet a lets' (mapBoundAtDepthX f (d + levels) x) - XCase a x alts -> XCase a (down x) (map down alts)- XCast a cc x -> XCast a cc (down x)+ XCase a x alts -> XCase a (down x) (map down alts)+ XCast a cc x -> XCast a (down cc) (down x) XType{} -> xx- XWitness{} -> xx+ XWitness w -> XWitness (down w)+++instance MapBoundX LetMode n where+ mapBoundAtDepthX f d m+ = case m of+ LetStrict -> m+ LetLazy Nothing -> m+ LetLazy (Just w) -> LetLazy (Just $ mapBoundAtDepthX f d w)+ +instance MapBoundX Witness n where+ mapBoundAtDepthX f d ww+ = let down = mapBoundAtDepthX f d+ in case ww of+ WVar u -> WVar (down u)+ WCon _ -> ww+ WApp w1 w2 -> WApp (down w1) (down w2)+ WJoin w1 w2 -> WJoin (down w1) (down w2)+ WType _ -> ww -instance LiftX (Alt a) where- liftAtDepthX n d (AAlt p x)++instance MapBoundX (Cast a) n where+ mapBoundAtDepthX f d cc+ = case cc of+ CastWeakenEffect{}+ -> cc++ CastWeakenClosure xs + -> CastWeakenClosure (map (mapBoundAtDepthX f d) xs)++ CastPurify w+ -> CastPurify w++ CastForget w+ -> CastForget w+++instance MapBoundX (Alt a) n where+ mapBoundAtDepthX f d (AAlt p x) = case p of PDefault - -> AAlt PDefault (liftAtDepthX n d x)+ -> AAlt PDefault (mapBoundAtDepthX f d x) PData _ bs -> let d' = d + countBAnons bs- in AAlt p (liftAtDepthX n d' x)+ in AAlt p (mapBoundAtDepthX f d' x) -liftAtDepthXLets- :: forall a n. Ord n- => Int -- ^ Number of levels to lift.- -> Int -- ^ Current binding depth.- -> Lets a n -- ^ Lift exp indices in this thing.- -> (Lets a n, Int) -- ^ Lifted, and how much to increase depth by+mapBoundAtDepthXLets+ :: (Int -> Bound n -> Bound n) -- ^ Number of levels to lift.+ -> Int -- ^ Current binding depth.+ -> Lets a n -- ^ Lift exp indices in this thing.+ -> (Lets a n, Int) -- ^ Lifted, and how much to increase depth by -liftAtDepthXLets n d lts+mapBoundAtDepthXLets f d lts = case lts of LLet m b x -> let inc = countBAnons [b]- x' = liftAtDepthX n (d+inc) x- in (LLet m b x', inc)+ m' = mapBoundAtDepthX f d m + -- non-recursive binding: do not increase x's depth+ x' = mapBoundAtDepthX f d x+ in (LLet m' b x', inc)+ LRec bs -> let inc = countBAnons (map fst bs)- bs' = map (\(b,e) -> (b, liftAtDepthX n (d+inc) e)) bs+ bs' = map (\(b,e) -> (b, mapBoundAtDepthX f (d+inc) e)) bs in (LRec bs', inc) - LLetRegion _b bs -> (lts, countBAnons bs)- LWithRegion _ -> (lts, 0)+ LLetRegions _b bs -> (lts, countBAnons bs)+ LWithRegion _ -> (lts, 0) countBAnons = length . filter isAnon
+ DDC/Core/Transform/Reannotate.hs view
@@ -0,0 +1,68 @@++module DDC.Core.Transform.Reannotate+ (Reannotate (..))+where+import DDC.Core.Module+import DDC.Core.Exp+++-- | Apply the given function to every annotation in a core thing.+class Reannotate c where+ reannotate :: (a -> b) -> c a n -> c b n+++instance Reannotate Module where+ reannotate f+ (ModuleCore name + exportKinds exportTypes + importKinds importTypes+ body)+ = ModuleCore name+ exportKinds exportTypes+ importKinds importTypes+ (reannotate f body)+++instance Reannotate Exp where+ reannotate f xx+ = {-# SCC reannotate #-}+ let down x = reannotate f x+ in case xx of+ XVar a u -> XVar (f a) u+ XCon a u -> XCon (f a) u+ XLAM a b x -> XLAM (f a) b (down x)+ XLam a b x -> XLam (f a) b (down x)+ XApp a x1 x2 -> XApp (f a) (down x1) (down x2)+ XLet a lts x -> XLet (f a) (down lts) (down x)+ XCase a x alts -> XCase (f a) (down x) (map down alts)+ XCast a c x -> XCast (f a) (down c) (down x)+ XType t -> XType t+ XWitness w -> XWitness w+++instance Reannotate Lets where+ reannotate f xx+ = let down x = reannotate f x+ in case xx of+ LLet m b x -> LLet m b (down x)+ LRec bxs -> LRec [(b, down x) | (b, x) <- bxs]+ LLetRegions b bs -> LLetRegions b bs+ LWithRegion b -> LWithRegion b+++instance Reannotate Alt where+ reannotate f aa+ = case aa of+ AAlt w x -> AAlt w (reannotate f x)+++instance Reannotate Cast where+ reannotate f cc+ = let down x = reannotate f x+ in case cc of+ CastWeakenEffect eff -> CastWeakenEffect eff+ CastWeakenClosure xs -> CastWeakenClosure (map down xs)+ CastPurify w -> CastPurify w+ CastForget w -> CastForget w++
+ DDC/Core/Transform/Rename.hs view
@@ -0,0 +1,41 @@++module DDC.Core.Transform.Rename+ ( Rename(..)++ -- * Substitution states+ , Sub(..)++ -- * Binding stacks+ , BindStack(..)+ , pushBind+ , pushBinds+ , substBound++ -- * Rewriting binding occurences+ , bind1, bind1s, bind0, bind0s++ -- * Rewriting bound occurences+ , use1, use0)+where+import DDC.Core.Exp+import DDC.Type.Transform.Rename+++instance Rename LetMode where+ renameWith sub lm+ = case lm of+ LetStrict -> lm+ LetLazy (Just t) -> LetLazy (Just $ renameWith sub t) + LetLazy Nothing -> LetLazy Nothing+++instance Rename Witness where+ renameWith sub ww+ = let down x = renameWith x+ in case ww of+ WVar u -> WVar (use0 sub u)+ WCon{} -> ww+ WApp w1 w2 -> WApp (down sub w1) (down sub w2)+ WJoin w1 w2 -> WJoin (down sub w1) (down sub w2)+ WType t -> WType (down sub t)+
DDC/Core/Transform/SpreadX.hs view
@@ -1,15 +1,14 @@ --- | Spread type annotations from binders and the environment into bound--- occurrences of variables and constructors. module DDC.Core.Transform.SpreadX (SpreadX(..)) where+import DDC.Core.Module import DDC.Core.Exp import DDC.Core.Compounds import DDC.Type.Transform.SpreadT import DDC.Type.Env (Env) import qualified DDC.Type.Env as Env-+import qualified Data.Map as Map class SpreadX (c :: * -> *) where @@ -22,9 +21,24 @@ => Env n -> Env n -> c n -> c n +-- Module ---------------------------------------------------------------------+instance SpreadX (Module a) where+ spreadX kenv tenv mm@ModuleCore{}+ = mm+ { moduleExportKinds = Map.map (spreadT kenv) (moduleExportKinds mm)+ , moduleExportTypes = Map.map (spreadT kenv) (moduleExportTypes mm)+ , moduleImportKinds = Map.map (liftSnd (spreadT kenv)) (moduleImportKinds mm)+ , moduleImportTypes = Map.map (liftSnd (spreadT kenv)) (moduleImportTypes mm)+ , moduleBody = spreadX kenv tenv (moduleBody mm) }++ where liftSnd f (x, y) = (x, f y)+ ++------------------------------------------------------------------------------- instance SpreadX (Exp a) where spreadX kenv tenv xx - = let down = spreadX kenv tenv + = {-# SCC spreadX #-}+ let down x = spreadX kenv tenv x in case xx of XVar a u -> XVar a (down u) XCon a u -> XCon a (down u)@@ -50,19 +64,37 @@ XWitness w -> XWitness (down w) -instance SpreadX Cast where+instance SpreadX DaCon where+ spreadX _kenv tenv dc+ = case daConName dc of+ DaConUnit -> dc++ DaConNamed n+ -> let u | Env.isPrim tenv n = UPrim n (daConType dc)+ | otherwise = UName n++ in case Env.lookup u tenv of+ Just t' -> dc { daConType = t' }++ -- Primitive constructors won't be in the type environment.+ -- But we leave it to checkExp to worry about whether a constructor+ -- is primitive or simply undefined.+ Nothing -> dc+++instance SpreadX (Cast a) where spreadX kenv tenv cc- = let down = spreadX kenv tenv + = let down x = spreadX kenv tenv x in case cc of- CastWeakenEffect eff -> CastWeakenEffect (spreadT kenv eff)- CastWeakenClosure clo -> CastWeakenClosure (spreadT kenv clo)- CastPurify w -> CastPurify (down w)- CastForget w -> CastForget (down w)+ CastWeakenEffect eff -> CastWeakenEffect (spreadT kenv eff)+ CastWeakenClosure xs -> CastWeakenClosure (map down xs)+ CastPurify w -> CastPurify (down w)+ CastForget w -> CastForget (down w) instance SpreadX Pat where spreadX kenv tenv pat- = let down = spreadX kenv tenv+ = let down x = spreadX kenv tenv x in case pat of PDefault -> PDefault PData u bs -> PData (down u) (map down bs)@@ -79,7 +111,7 @@ instance SpreadX (Lets a) where spreadX kenv tenv lts- = let down = spreadX kenv tenv+ = let down x = spreadX kenv tenv x in case lts of LLet m b x -> LLet (down m) (down b) (down x) @@ -90,11 +122,11 @@ xs' = map (spreadX kenv tenv') xs in LRec (zip bs' xs') - LLetRegion b bs- -> let b' = spreadT kenv b- kenv' = Env.extend b' kenv+ LLetRegions b bs+ -> let b' = map (spreadT kenv) b+ kenv' = Env.extends b' kenv bs' = map (spreadX kenv' tenv) bs- in LLetRegion b' bs'+ in LLetRegions b' bs' LWithRegion b -> LWithRegion (spreadX kenv tenv b)@@ -121,12 +153,17 @@ instance SpreadX WiCon where spreadX kenv tenv wc- = let down = spreadX kenv tenv- in case wc of- WiConBound u -> WiConBound (down u)- WiConBuiltin{} -> wc+ = case wc of+ WiConBound (UName n) _+ -> case Env.envPrimFun tenv n of+ Nothing -> wc+ Just t + -> let t' = spreadT kenv t+ in WiConBound (UPrim n t') t' + _ -> wc + instance SpreadX Bind where spreadX kenv _tenv bb = case bb of@@ -139,13 +176,14 @@ spreadX kenv tenv uu | Just t' <- Env.lookup uu tenv = case uu of- UIx ix _ -> UIx ix t'- UPrim n _ -> UPrim n t'+ UIx ix -> UIx ix - UName n _+ UName n -> if Env.isPrim tenv n then UPrim n (spreadT kenv t')- else UName n (spreadT kenv t')+ else UName n++ UPrim n _ -> UPrim n t' | otherwise = uu
DDC/Core/Transform/SubstituteTX.hs view
@@ -3,17 +3,18 @@ -- -- If a binder would capture a variable then it is anonymized -- to deBruijn form.+-- module DDC.Core.Transform.SubstituteTX- ( substituteTX+ ( SubstituteTX(..)+ , substituteTX , substituteTXs- , substituteBoundTX- , SubstituteTX(..))+ , substituteBoundTX) where import DDC.Core.Collect import DDC.Core.Exp import DDC.Type.Compounds import DDC.Type.Transform.SubstituteT-import DDC.Type.Rewrite+import DDC.Type.Transform.Rename import Data.Maybe import qualified Data.Set as Set import qualified DDC.Type.Env as Env@@ -64,9 +65,10 @@ instance SubstituteTX (Exp a) where substituteWithTX tArg sub xx- = let down = substituteWithTX tArg+ = {-# SCC substituteWithTX #-}+ let down x = substituteWithTX tArg x in case xx of- XVar a u -> XVar a (down sub u)+ XVar a u -> XVar a u XCon{} -> xx XApp a x1 x2 -> XApp a (down sub x1) (down sub x2) @@ -94,11 +96,11 @@ x2' = down sub1 x2 in XLet a (LRec (zip bs' xs')) x2' - XLet a (LLetRegion b bs) x2- -> let (sub1, b') = bind1 sub b+ XLet a (LLetRegions b bs) x2+ -> let (sub1, b') = bind1s sub b (sub2, bs') = bind0s sub1 (map (down sub1) bs) x2' = down sub2 x2- in XLet a (LLetRegion b' bs') x2'+ in XLet a (LLetRegions b' bs') x2' XLet a (LWithRegion uR) x2 -> XLet a (LWithRegion uR) (down sub x2)@@ -111,7 +113,7 @@ instance SubstituteTX LetMode where substituteWithTX tArg sub lm- = let down = substituteWithTX tArg+ = let down x = substituteWithTX tArg x in case lm of LetStrict -> lm LetLazy Nothing -> lm@@ -120,7 +122,7 @@ instance SubstituteTX (Alt a) where substituteWithTX tArg sub aa- = let down = substituteWithTX tArg+ = let down x = substituteWithTX tArg x in case aa of AAlt PDefault xBody -> AAlt PDefault $ down sub xBody@@ -131,21 +133,21 @@ in AAlt (PData uCon bs') x' -instance SubstituteTX Cast where+instance SubstituteTX (Cast a) where substituteWithTX tArg sub cc- = let down = substituteWithTX tArg+ = let down x = substituteWithTX tArg x in case cc of CastWeakenEffect eff -> CastWeakenEffect (down sub eff)- CastWeakenClosure clo -> CastWeakenClosure (down sub clo)+ CastWeakenClosure clo -> CastWeakenClosure (map (down sub) clo) CastPurify w -> CastPurify (down sub w) CastForget w -> CastForget (down sub w) instance SubstituteTX Witness where substituteWithTX tArg sub ww- = let down = substituteWithTX tArg+ = let down x = substituteWithTX tArg x in case ww of- WVar u -> WVar (down sub u)+ WVar u -> WVar u WCon{} -> ww WApp w1 w2 -> WApp (down sub w1) (down sub w2) WJoin w1 w2 -> WJoin (down sub w1) (down sub w2)@@ -155,11 +157,6 @@ instance SubstituteTX Bind where substituteWithTX tArg sub bb = replaceTypeOfBind (substituteWithTX tArg sub (typeOfBind bb)) bb---instance SubstituteTX Bound where- substituteWithTX tArg sub uu- = replaceTypeOfBound (substituteWithTX tArg sub (typeOfBound uu)) uu instance SubstituteTX Type where
DDC/Core/Transform/SubstituteWX.hs view
@@ -3,6 +3,7 @@ -- -- If a binder would capture a variable then it is anonymized -- to deBruijn form.+-- module DDC.Core.Transform.SubstituteWX ( SubstituteWX(..) , substituteWX@@ -10,15 +11,15 @@ where import DDC.Core.Exp import DDC.Core.Collect-import DDC.Core.Transform.LiftW+import DDC.Core.Transform.Rename+import DDC.Core.Transform.LiftX import DDC.Type.Compounds-import DDC.Type.Rewrite import Data.Maybe import qualified DDC.Type.Env as Env import qualified Data.Set as Set --- | Wrapper for `substituteWithW` that determines the set of free names in the+-- | Wrapper for `substituteWithWX` that determines the set of free names in the -- type being substituted, and starts with an empty binder stack. substituteWX :: (Ord n, SubstituteWX c) @@ -52,7 +53,7 @@ | otherwise = xx --- | Wrapper for `substituteW` to substitute multiple things.+-- | Wrapper for `substituteWithWX` to substitute multiple things. substituteWXs :: (Ord n, SubstituteWX c) => [(Bind n, Witness n)] -> c n -> c n@@ -60,12 +61,8 @@ = foldr (uncurry substituteWX) x bts +------------------------------------------------------------------------------- class SubstituteWX (c :: * -> *) where-- -- | Substitute a witness into some thing.- -- In the target, if we find a named binder that would capture a free variable- -- in the type to substitute, then we rewrite that binder to anonymous form,- -- avoiding the capture. substituteWithWX :: forall n. Ord n => Witness n -> Sub n -> c n -> c n@@ -73,10 +70,11 @@ instance SubstituteWX (Exp a) where substituteWithWX wArg sub xx- = let down = substituteWithWX wArg- into = rewriteWith+ = {-# SCC substituteWithWX #-}+ let down s x = substituteWithWX wArg s x+ into s x = renameWith s x in case xx of- XVar a u -> XVar a (into sub u)+ XVar a u -> XVar a u XCon{} -> xx XApp a x1 x2 -> XApp a (down sub x1) (down sub x2) @@ -104,11 +102,11 @@ x2' = down sub1 x2 in XLet a (LRec (zip bs' xs')) x2' - XLet a (LLetRegion b bs) x2- -> let (sub1, b') = bind1 sub b+ XLet a (LLetRegions b bs) x2+ -> let (sub1, b') = bind1s sub b (sub2, bs') = bind0s sub1 bs x2' = down sub2 x2- in XLet a (LLetRegion b' bs') x2'+ in XLet a (LLetRegions b' bs') x2' XLet a (LWithRegion uR) x2 -> XLet a (LWithRegion uR) (down sub x2)@@ -122,7 +120,7 @@ instance SubstituteWX LetMode where substituteWithWX wArg sub lm- = let down = substituteWithWX wArg+ = let down s x = substituteWithWX wArg s x in case lm of LetStrict -> lm LetLazy Nothing -> LetLazy Nothing@@ -131,7 +129,7 @@ instance SubstituteWX (Alt a) where substituteWithWX wArg sub aa- = let down = substituteWithWX wArg+ = let down s x = substituteWithWX wArg s x in case aa of AAlt PDefault xBody -> AAlt PDefault $ down sub xBody@@ -142,25 +140,25 @@ in AAlt (PData uCon bs') x' -instance SubstituteWX Cast where+instance SubstituteWX (Cast a) where substituteWithWX wArg sub cc- = let down = substituteWithWX wArg- into = rewriteWith+ = let down s x = substituteWithWX wArg s x+ into s x = renameWith s x in case cc of CastWeakenEffect eff -> CastWeakenEffect (into sub eff)- CastWeakenClosure clo -> CastWeakenClosure (into sub clo)+ CastWeakenClosure xs -> CastWeakenClosure (map (down sub) xs) CastPurify w -> CastPurify (down sub w) CastForget w -> CastForget (down sub w) instance SubstituteWX Witness where substituteWithWX wArg sub ww- = let down = substituteWithWX wArg- into = rewriteWith+ = let down s x = substituteWithWX wArg s x+ into s x = renameWith s x in case ww of WVar u -> case substW wArg sub u of- Left u' -> WVar (into sub u')+ Left u' -> WVar u' Right w -> w WCon{} -> ww@@ -175,8 +173,8 @@ substW wArg sub u = case substBound (subStack0 sub) (subBound sub) u of- Left u' -> Left (rewriteWith sub u')+ Left u' -> Left u' Right n - | not $ subShadow0 sub -> Right (liftW n wArg)- | otherwise -> Left (rewriteWith sub u)+ | not $ subShadow0 sub -> Right (liftX n wArg)+ | otherwise -> Left u
DDC/Core/Transform/SubstituteXX.hs view
@@ -3,6 +3,7 @@ -- -- If a binder would capture a variable then it is anonymized -- to deBruijn form.+-- module DDC.Core.Transform.SubstituteXX ( SubstituteXX(..) , substituteXX@@ -17,7 +18,7 @@ import DDC.Core.Transform.SubstituteWX import DDC.Core.Transform.SubstituteTX import DDC.Type.Transform.SubstituteT-import DDC.Type.Rewrite+import DDC.Type.Transform.Rename import Data.Maybe import qualified DDC.Type.Env as Env import qualified Data.Set as Set@@ -41,7 +42,7 @@ , subConflict1 = Set.fromList $ (mapMaybe takeNameOfBound $ Set.toList $ freeT Env.empty xArg) - ++ (mapMaybe takeNameOfBind $ collectSpecBinds xArg)+ ++ (mapMaybe takeNameOfBind $ fst $ collectBinds xArg) -- Rewrite level-0 binders that have the same name as any -- of the free variables in the expression to substitute.@@ -99,12 +100,13 @@ instance SubstituteXX Exp where substituteWithXX xArg sub xx- = let down = substituteWithXX xArg- into = rewriteWith+ = {-# SCC substituteWithXX #-}+ let down s x = substituteWithXX xArg s x+ into s x = renameWith s x in case xx of XVar a u -> case substX xArg sub u of- Left u' -> XVar a (into sub u')+ Left u' -> XVar a u' Right x -> x XCon{} -> xx@@ -134,24 +136,24 @@ x2' = down sub1 x2 in XLet a (LRec (zip bs' xs')) x2' - XLet a (LLetRegion b bs) x2- -> let (sub1, b') = bind1 sub b+ XLet a (LLetRegions b bs) x2+ -> let (sub1, b') = bind1s sub b (sub2, bs') = bind0s sub1 bs x2' = down sub2 x2- in XLet a (LLetRegion b' bs') x2'+ in XLet a (LLetRegions b' bs') x2' XLet a (LWithRegion uR) x2 -> XLet a (LWithRegion uR) (down sub x2) XCase a x1 alts -> XCase a (down sub x1) (map (down sub) alts)- XCast a cc x1 -> XCast a (into sub cc) (down sub x1)+ XCast a cc x1 -> XCast a (down sub cc) (down sub x1) XType t -> XType (into sub t) XWitness w -> XWitness (into sub w) instance SubstituteXX Alt where substituteWithXX xArg sub aa- = let down = substituteWithXX xArg+ = let down s x = substituteWithXX xArg s x in case aa of AAlt PDefault xBody -> AAlt PDefault $ down sub xBody@@ -162,15 +164,26 @@ in AAlt (PData uCon bs') x' +instance SubstituteXX Cast where+ substituteWithXX xArg sub cc+ = let down s x = substituteWithXX xArg s x+ into s x = renameWith s x+ in case cc of+ CastWeakenEffect eff -> CastWeakenEffect (into sub eff)+ CastWeakenClosure xs -> CastWeakenClosure (map (down sub) xs)+ CastPurify w -> CastPurify (into sub w)+ CastForget w -> CastForget (into sub w)++ -- | Rewrite or substitute into an expression variable. substX :: Ord n => Exp a n -> Sub n -> Bound n -> Either (Bound n) (Exp a n) substX xArg sub u = case substBound (subStack0 sub) (subBound sub) u of- Left u' -> Left (rewriteWith sub u')+ Left u' -> Left u' Right n | not $ subShadow0 sub -> Right (liftX n xArg)- | otherwise -> Left (rewriteWith sub u)+ | otherwise -> Left u
+ DDC/Core/Transform/Trim.hs view
@@ -0,0 +1,112 @@++-- | Trim the expressions passed to @weakclo@ casts to just those terms+-- that can affect the closure of the body. +--+module DDC.Core.Transform.Trim+ ( trimX, trimClosures )+where+import DDC.Core.Collect()+import DDC.Type.Collect+import DDC.Core.Exp+import DDC.Type.Env+import DDC.Core.Transform.Reannotate+import Data.List (nubBy)+++-- | Trim the expressions of a weaken closure @(XCast CastWeakenClosure)@+-- into only the free variables.+--+-- For example,+-- @trimClosures [build (\k z. something k), else]+-- = [build, something, else]+-- @+trimClosures+ :: (Ord n)+ => a+ -> [Exp a n]+ -> [Exp a n]++trimClosures a xs+ = {-# SCC trimClosures #-}+ nub' $ concatMap (freeExp a empty empty) xs+ where nub' = nubBy (\x y -> reannotate (const ()) x == reannotate (const ()) y)+++-- | Trim an expression if it is a @weakclo@ cast. +--+-- Non-recursive version. If you want to recursively trim closures,+-- use @transformUpX' (const trimX)@.+trimX :: (Ord n)+ => Exp a n+ -> Exp a n+trimX (XCast a (CastWeakenClosure ws) in_)+ = XCast a (CastWeakenClosure $ trimClosures a ws) in_++trimX x+ = x+++-- freeExp --------------------------------------------------------------------+-- | Collect all the free variables, but return them all as expressions:+-- eg+-- @+-- freeExp +-- (let i = 5 [R0#] () in+-- updateInt [:R0# R1#:] <w> i ...)+--+-- will return something like+-- [ XType (TCon R0#)+-- , XVar updateInt+-- , XType (TCon R0#)+-- , XType (TCon R1#)+-- , XWitness w ]+-- @+freeExp :: (BindStruct c, Ord n) + => a+ -> Env n+ -> Env n+ -> c n+ -> [Exp a n]+freeExp a kenv tenv xx + = concatMap (freeOfTreeExp a kenv tenv) $ slurpBindTree xx++freeOfTreeExp+ :: Ord n+ => a+ -> Env n+ -> Env n+ -> BindTree n+ -> [Exp a n]+freeOfTreeExp a kenv tenv tt+ = case tt of+ BindDef way bs ts+ | isBoundExpWit $ boundLevelOfBindWay way+ , tenv' <- extends bs tenv+ -> concatMap (freeOfTreeExp a kenv tenv') ts++ BindDef way bs ts+ | BoundSpec <- boundLevelOfBindWay way+ , kenv' <- extends bs kenv+ -> concatMap (freeOfTreeExp a kenv' tenv) ts++ BindDef _ _ ts+ -> concatMap (freeOfTreeExp a kenv tenv) ts++ BindUse BoundExp u+ | member u tenv -> []+ | otherwise -> [XVar a u]++ BindUse BoundWit u+ | member u tenv -> []+ | otherwise -> [XWitness (WVar u)]++ BindUse BoundSpec u+ | member u kenv -> []+ | otherwise -> [XType (TVar u)]++ BindCon BoundSpec u (Just k)+ | member u kenv -> []+ | otherwise -> [XType (TCon (TyConBound u k))]++ _ -> []+
+ DDC/Type/Bind.hs view
@@ -0,0 +1,31 @@++module DDC.Type.Bind+ (getBindType)+where+import DDC.Type.Exp+++-- | Lookup the type of a bound thing from the binder stack.+-- The binder stack contains the binders of all the `TForall`s we've+-- entered under so far.+getBindType :: Eq n => [Bind n] -> Bound n -> Maybe (Int, Type n)+getBindType bs' u'+ = go 0 u' bs'+ where go n u (BName n1 t : bs)+ | UName n2 <- u+ , n1 == n2 = Just (n, t)++ | otherwise = go (n + 1) u bs++ go n (UIx i) (BAnon t : bs)+ | i < 0 = Nothing+ | i == 0 = Just (n, t)+ | otherwise = go (n + 1) (UIx (i - 1)) bs++ go n u (BAnon _ : bs)+ | otherwise = go (n + 1) u bs++ go n u (BNone _ : bs)+ = go (n + 1) u bs++ go _ _ [] = Nothing
DDC/Type/Check.hs view
@@ -12,23 +12,23 @@ -- * Errors , Error(..)) where-import DDC.Type.Check.CheckError+import DDC.Type.DataDef+import DDC.Type.Check.Error+import DDC.Type.Check.ErrorMessage () import DDC.Type.Check.CheckCon import DDC.Type.Compounds import DDC.Type.Predicates-import DDC.Type.Transform.LiftT-import DDC.Core.DataDef import DDC.Type.Exp import DDC.Base.Pretty import Data.List import Control.Monad-import DDC.Type.Check.Monad (throw, result)-import DDC.Type.Pretty ()-import DDC.Type.Env (Env)-import qualified DDC.Type.Sum as TS-import qualified DDC.Type.Env as Env-import qualified DDC.Type.Check.Monad as G-import qualified Data.Map as Map+import DDC.Type.Pretty ()+import DDC.Type.Env (KindEnv)+import DDC.Control.Monad.Check (throw, result)+import qualified DDC.Control.Monad.Check as G+import qualified DDC.Type.Sum as TS+import qualified DDC.Type.Env as Env+import qualified Data.Map as Map -- | The type checker monad.@@ -37,9 +37,9 @@ -- Wrappers ------------------------------------------------------------------- -- | Check a type in the given environment, returning an error or its kind.-checkType :: (Ord n, Pretty n) +checkType :: (Ord n, Show n, Pretty n) => DataDefs n - -> Env n + -> KindEnv n -> Type n -> Either (Error n) (Kind n) @@ -48,7 +48,7 @@ -- | Check a type in an empty environment, returning an error or its kind.-kindOfType :: (Ord n, Pretty n) +kindOfType :: (Ord n, Show n, Pretty n) => DataDefs n -> Type n -> Either (Error n) (Kind n)@@ -65,55 +65,22 @@ -- that need to be compared up to alpha-equivalence, nor do they contain -- crushable components terms. checkTypeM - :: (Ord n, Pretty n) + :: (Ord n, Show n, Pretty n) => DataDefs n- -> Env n+ -> KindEnv n -> Type n -> CheckM n (Kind n) checkTypeM defs env tt = -- trace (pretty $ text "checkTypeM:" <+> ppr tt) $+ {-# SCC checkTypeM #-} checkTypeM' defs env tt -- Variables ------------------ checkTypeM' _defs env (TVar u)- = do let tBound = typeOfBound u- let mtEnv = Env.lookup u env-- let mkResult- -- If the annot is Bot then just use the type- -- from the environment.- | Just tEnv <- mtEnv- , isBot tBound- = return tEnv-- -- The bound has an explicit type annotation,- -- which matches the one from the environment.- -- - -- When the bound is a deBruijn index we need to lift the- -- annotation on the original binder through any lambdas- -- between the binding occurrence and the use.- | Just tEnv <- mtEnv- , UIx i _ <- u- , tBound == liftT (i + 1) tEnv- = return tBound-- -- The bound has an explicit type annotation,- -- that matches the one from the environment.- | Just tEnv <- mtEnv- , tBound == tEnv- = return tBound-- -- The bound has an explicit type annotation,- -- that does not match the one from the environment. - | Just tEnv <- mtEnv- = throw $ ErrorVarAnnotMismatch u tEnv-- -- Type variables must be in the environment.- | _ <- mtEnv- = throw $ ErrorUndefined u-- mkResult+ = case Env.lookup u env of+ Just t -> return t+ Nothing -> throw $ ErrorUndefined u -- Constructors --------------- checkTypeM' defs _env tt@(TCon tc)@@ -132,17 +99,17 @@ TyConSpec tcc -> return $ kindOfTcCon tcc -- User defined type constructors need to be in the set of data defs.- TyConBound u + TyConBound u k -> case u of- UName n _+ UName n | Just _ <- Map.lookup n (dataDefsTypes defs)- -> return $ typeOfBound u+ -> return k | otherwise -> throw $ ErrorUndefinedCtor u - UPrim{} -> return $ typeOfBound u- UIx{} -> error "sorry"+ UPrim{} -> return k+ UIx{} -> throw $ ErrorUndefinedCtor u -- Quantifiers ----------------
DDC/Type/Check/CheckCon.hs view
@@ -14,18 +14,18 @@ takeKindOfTyCon tt = case tt of -- Sorts don't have a higher classification.- TyConSort _ -> Nothing+ TyConSort _ -> Nothing - TyConKind kc -> takeSortOfKiCon kc- TyConWitness tc -> Just $ kindOfTwCon tc- TyConSpec tc -> Just $ kindOfTcCon tc- TyConBound u -> Just $ typeOfBound u+ TyConKind kc -> takeSortOfKiCon kc+ TyConWitness tc -> Just $ kindOfTwCon tc+ TyConSpec tc -> Just $ kindOfTcCon tc+ TyConBound _u k -> Just k -- | Take the superkind of an atomic kind constructor. ----- * Yields `Nothing` for the kind function (~>) as it doesn't have a sort--- without being fully applied.+-- Yields `Nothing` for the kind function (~>) as it doesn't have a sort+-- without being fully applied. takeSortOfKiCon :: KiCon -> Maybe (Sort n) takeSortOfKiCon kc = case kc of@@ -41,24 +41,27 @@ kindOfTwCon :: TwCon -> Kind n kindOfTwCon tc = case tc of- TwConImpl -> kWitness `kFun` (kWitness `kFun` kWitness)- TwConPure -> kEffect `kFun` kWitness- TwConEmpty -> kClosure `kFun` kWitness- TwConGlobal -> kRegion `kFun` kWitness- TwConDeepGlobal -> kData `kFun` kWitness- TwConConst -> kRegion `kFun` kWitness- TwConDeepConst -> kData `kFun` kWitness- TwConMutable -> kRegion `kFun` kWitness- TwConDeepMutable-> kData `kFun` kWitness- TwConLazy -> kRegion `kFun` kWitness- TwConHeadLazy -> kData `kFun` kWitness- TwConManifest -> kRegion `kFun` kWitness+ TwConImpl -> kWitness `kFun` kWitness `kFun` kWitness+ TwConPure -> kEffect `kFun` kWitness+ TwConEmpty -> kClosure `kFun` kWitness+ TwConGlobal -> kRegion `kFun` kWitness+ TwConDeepGlobal -> kData `kFun` kWitness+ TwConConst -> kRegion `kFun` kWitness+ TwConDeepConst -> kData `kFun` kWitness+ TwConMutable -> kRegion `kFun` kWitness+ TwConDeepMutable-> kData `kFun` kWitness+ TwConLazy -> kRegion `kFun` kWitness+ TwConHeadLazy -> kData `kFun` kWitness+ TwConManifest -> kRegion `kFun` kWitness+ TwConDisjoint -> kEffect `kFun` kEffect `kFun` kWitness+ TwConDistinct n -> (replicate n kRegion) `kFuns` kWitness -- | Take the kind of a computation type constructor. kindOfTcCon :: TcCon -> Kind n kindOfTcCon tc = case tc of+ TcConUnit -> kData TcConFun -> [kData, kEffect, kClosure, kData] `kFuns` kData TcConRead -> kRegion `kFun` kEffect TcConHeadRead -> kData `kFun` kEffect
− DDC/Type/Check/CheckError.hs
@@ -1,141 +0,0 @@-{-# OPTIONS_HADDOCK hide #-}--- | Errors produced when checking types.-module DDC.Type.Check.CheckError- (Error(..))-where-import DDC.Type.Exp-import DDC.Type.Compounds-import DDC.Type.Pretty----- Error --------------------------------------------------------------------------------------------- | Type errors.-data Error n-- -- | An undefined type variable.- = ErrorUndefined - { errorBound :: Bound n }-- -- | An undefined type constructor.- | ErrorUndefinedCtor- { errorBound :: Bound n }-- -- | The kind annotation on the variables does not match the one in the environment.- | ErrorVarAnnotMismatch- { errorBound :: Bound n- , errorTypeEnv :: Type n }-- -- | Found a naked sort constructor.- | ErrorNakedSort- { errorSort :: Sort n }-- -- | Found an unapplied kind function constructor.- | ErrorUnappliedKindFun -- -- | A type application where the parameter and argument kinds don't match.- | ErrorAppArgMismatch - { errorChecking :: Type n- , errorParamKind :: Kind n- , errorArgKind :: Kind n }-- -- | A type application where the thing being applied is not a function.- | ErrorAppNotFun- { errorChecking :: Type n- , errorFunType :: Type n- , errorFunTypeKind :: Kind n- , errorArgType :: Type n- , errorArgTypeKind :: Kind n }-- -- | A type sum where the components have differing kinds.- | ErrorSumKindMismatch- { errorKindExpected :: Kind n- , errorTypeSum :: TypeSum n- , errorKinds :: [Kind n] }- - -- | A type sum that does not have effect or closure kind.- | ErrorSumKindInvalid- { errorCheckingSum :: TypeSum n- , errorKind :: Kind n }-- -- | A forall where the body does not have data or witness kind.- | ErrorForallKindInvalid- { errorChecking :: Type n- , errorBody :: Type n- , errorKind :: Kind n }-- -- | A witness implication where the premise or conclusion has an invalid kind.- | ErrorWitnessImplInvalid- { errorChecking :: Type n- , errorLeftType :: Type n- , errorLeftKind :: Kind n- , errorRightType :: Type n- , errorRightKind :: Kind n }- deriving Show---instance (Eq n, Pretty n) => Pretty (Error n) where- ppr err- = case err of- ErrorUndefined u- -> text "Undefined type variable: " <> ppr u-- ErrorUndefinedCtor u- -> text "Undefined type constructor: " <> ppr u-- ErrorUnappliedKindFun - -> text "Can't take sort of unapplied kind function constructor."- - ErrorNakedSort s- -> text "Can't check a naked sort: " <> ppr s- - ErrorVarAnnotMismatch u t- -> vcat [ text "Type mismatch in annotation."- , text " Variable: " <> ppr u- , text " has annotation: " <> (ppr $ typeOfBound u)- , text " which conflicts with: " <> ppr t- , text " from environment." ]- - ErrorAppArgMismatch tt t1 t2- -> vcat [ text "Core type mismatch in application."- , text " type: " <> ppr t1- , text " does not match: " <> ppr t2- , text " in application: " <> ppr tt ]- - ErrorAppNotFun tt t1 k1 t2 k2- -> vcat [ text "Core type mismatch in application."- , text " cannot apply type: " <> ppr t2- , text " of kind: " <> ppr k2- , text " to non-function type: " <> ppr t1- , text " of kind: " <> ppr k1- , text " in appliction: " <> ppr tt]- - ErrorSumKindMismatch k ts ks- -> vcat - $ [ text "Core type mismatch in sum."- , text " found multiple types: " <> ppr ts- , text " with differing kinds: " <> ppr ks ]- ++ (if k /= tBot sComp- then [text " expected kind: " <> ppr k ]- else [])- - ErrorSumKindInvalid ts k- -> vcat [ text "Invalid kind for type sum."- , text " the type sum: " <> ppr ts- , text " has kind: " <> ppr k- , text " but it must be ! or $" ]-- ErrorForallKindInvalid tt t k- -> vcat [ text "Invalid kind for body of quantified type."- , text " the body type: " <> ppr t- , text " has kind: " <> ppr k- , text " but it must be * or @" - , text " when checking: " <> ppr tt ]- - ErrorWitnessImplInvalid tt t1 k1 t2 k2- -> vcat [ text "Invalid args for witness implication."- , text " left type: " <> ppr t1- , text " has kind: " <> ppr k1- , text " right type: " <> ppr t2- , text " has kind: " <> ppr k2 - , text " when checking: " <> ppr tt ]-
+ DDC/Type/Check/Error.hs view
@@ -0,0 +1,71 @@++-- | Errors produced when checking types.+module DDC.Type.Check.Error+ (Error(..))+where+import DDC.Type.Exp+++-- | Things that can go wrong when checking the kind of at type.+data Error n++ -- | An undefined type variable.+ = ErrorUndefined + { errorBound :: Bound n }++ -- | An undefined type constructor.+ | ErrorUndefinedCtor+ { errorBound :: Bound n }++ -- | The kind annotation on the variables does not match the one in the environment.+ | ErrorVarAnnotMismatch+ { errorBound :: Bound n+ , errorTypeEnv :: Type n }++ -- | Found a naked sort constructor.+ | ErrorNakedSort+ { errorSort :: Sort n }++ -- | Found an unapplied kind function constructor.+ | ErrorUnappliedKindFun ++ -- | A type application where the parameter and argument kinds don't match.+ | ErrorAppArgMismatch + { errorChecking :: Type n+ , errorParamKind :: Kind n+ , errorArgKind :: Kind n }++ -- | A type application where the thing being applied is not a function.+ | ErrorAppNotFun+ { errorChecking :: Type n+ , errorFunType :: Type n+ , errorFunTypeKind :: Kind n+ , errorArgType :: Type n+ , errorArgTypeKind :: Kind n }++ -- | A type sum where the components have differing kinds.+ | ErrorSumKindMismatch+ { errorKindExpected :: Kind n+ , errorTypeSum :: TypeSum n+ , errorKinds :: [Kind n] }+ + -- | A type sum that does not have effect or closure kind.+ | ErrorSumKindInvalid+ { errorCheckingSum :: TypeSum n+ , errorKind :: Kind n }++ -- | A forall where the body does not have data or witness kind.+ | ErrorForallKindInvalid+ { errorChecking :: Type n+ , errorBody :: Type n+ , errorKind :: Kind n }++ -- | A witness implication where the premise or conclusion has an invalid kind.+ | ErrorWitnessImplInvalid+ { errorChecking :: Type n+ , errorLeftType :: Type n+ , errorLeftKind :: Kind n+ , errorRightType :: Type n+ , errorRightKind :: Kind n }+ deriving Show+
+ DDC/Type/Check/ErrorMessage.hs view
@@ -0,0 +1,75 @@++-- | Errors produced when checking types.+module DDC.Type.Check.ErrorMessage+where+import DDC.Type.Check.Error+import DDC.Type.Compounds+import DDC.Type.Pretty+++instance (Eq n, Show n, Pretty n) => Pretty (Error n) where+ ppr err+ = case err of+ ErrorUndefined u+ -> text "Undefined type variable: " <> ppr u++ ErrorUndefinedCtor u+ -> text "Undefined type constructor: " <> ppr u++ ErrorUnappliedKindFun + -> text "Can't take sort of unapplied kind function constructor."+ + ErrorNakedSort s+ -> text "Can't check a naked sort: " <> ppr s+ + ErrorVarAnnotMismatch u t+ -> vcat [ text "Type mismatch in annotation."+ , text " Variable: " <> ppr u+ , text " has annotation: " <> ppr u+ , text " which conflicts with: " <> ppr t+ , text " from environment." ]+ + ErrorAppArgMismatch tt t1 t2+ -> vcat [ text "Core type mismatch in application."+ , text " type: " <> ppr t1+ , text " does not match: " <> ppr t2+ , text " in application: " <> ppr tt ]+ + ErrorAppNotFun tt t1 k1 t2 k2+ -> vcat [ text "Core type mismatch in application."+ , text " cannot apply type: " <> ppr t2+ , text " of kind: " <> ppr k2+ , text " to non-function type: " <> ppr t1+ , text " of kind: " <> ppr k1+ , text " in appliction: " <> ppr tt]+ + ErrorSumKindMismatch k ts ks+ -> vcat + $ [ text "Core type mismatch in sum."+ , text " found multiple types: " <> ppr ts+ , text " with differing kinds: " <> ppr ks ]+ ++ (if k /= tBot sComp+ then [text " expected kind: " <> ppr k ]+ else [])+ + ErrorSumKindInvalid ts k+ -> vcat [ text "Invalid kind for type sum."+ , text " the type sum: " <> ppr ts+ , text " has kind: " <> ppr k+ , text " but it must be ! or $" ]++ ErrorForallKindInvalid tt t k+ -> vcat [ text "Invalid kind for body of quantified type."+ , text " the body type: " <> ppr t+ , text " has kind: " <> ppr k+ , text " but it must be * or @" + , text " when checking: " <> ppr tt ]+ + ErrorWitnessImplInvalid tt t1 k1 t2 k2+ -> vcat [ text "Invalid args for witness implication."+ , text " left type: " <> ppr t1+ , text " has kind: " <> ppr k1+ , text " right type: " <> ppr t2+ , text " has kind: " <> ppr k2 + , text " when checking: " <> ppr tt ]+
− DDC/Type/Check/Monad.hs
@@ -1,28 +0,0 @@--module DDC.Type.Check.Monad- ( CheckM (..)- , throw- , result)-where---- | Type checking monad.-data CheckM err a- = CheckM (Either err a)--instance Monad (CheckM err) where- return x = CheckM (Right x)- (>>=) m f - = case m of- CheckM (Left err) -> CheckM (Left err)- CheckM (Right x) -> f x-- --- | Throw a type error in the monad.-throw :: err -> CheckM err a-throw e = CheckM $ Left e----- | Take the result from a check monad.-result :: CheckM err a -> Either err a-result (CheckM r) = r-
+ DDC/Type/Collect.hs view
@@ -0,0 +1,185 @@++-- | Collecting sets of variables and constructors.+module DDC.Type.Collect+ ( freeT+ , collectBound+ , collectBinds+ , BindTree (..)+ , BindWay (..)+ , BindStruct (..)++ , BoundLevel (..)+ , isBoundExpWit+ , boundLevelOfBindWay+ , bindDefT)+where+import DDC.Type.Exp+import DDC.Type.Env (Env)+import qualified DDC.Type.Env as Env+import qualified DDC.Type.Sum as Sum+import qualified Data.Set as Set+import Data.Set (Set)+++-- freeT ----------------------------------------------------------------------+-- | Collect the free Spec variables in a thing (level-1).+freeT :: (BindStruct c, Ord n) + => Env n -> c n -> Set (Bound n)+freeT tenv xx = Set.unions $ map (freeOfTreeT tenv) $ slurpBindTree xx++freeOfTreeT :: Ord n => Env n -> BindTree n -> Set (Bound n)+freeOfTreeT kenv tt+ = case tt of+ BindDef way bs ts+ | BoundSpec <- boundLevelOfBindWay way+ , kenv' <- Env.extends bs kenv+ -> Set.unions $ map (freeOfTreeT kenv') ts++ BindDef _ _ ts+ -> Set.unions $ map (freeOfTreeT kenv) ts++ BindUse BoundSpec u+ | Env.member u kenv -> Set.empty+ | otherwise -> Set.singleton u+ _ -> Set.empty+++-- collectBound ---------------------------------------------------------------+-- | Collect all the bound variables in a thing, +-- independent of whether they are free or not.+collectBound :: (BindStruct c, Ord n) => c n -> Set (Bound n)+collectBound + = Set.unions . map collectBoundOfTree . slurpBindTree ++collectBoundOfTree :: Ord n => BindTree n -> Set (Bound n)+collectBoundOfTree tt+ = case tt of+ BindDef _ _ ts -> Set.unions $ map collectBoundOfTree ts+ BindUse _ u -> Set.singleton u+ BindCon _ u _ -> Set.singleton u+++-- collectSpecBinds -----------------------------------------------------------+-- | Collect all the spec and exp binders in a thing.+collectBinds + :: (BindStruct c, Ord n) + => c n + -> ([Bind n], [Bind n])++collectBinds thing+ = let tree = slurpBindTree thing+ in ( concatMap collectSpecBindsOfTree tree+ , concatMap collectExpBindsOfTree tree)+ ++collectSpecBindsOfTree :: Ord n => BindTree n -> [Bind n]+collectSpecBindsOfTree tt+ = case tt of+ BindDef way bs ts+ | BoundSpec <- boundLevelOfBindWay way+ -> concat ( bs+ : map collectSpecBindsOfTree ts)++ | otherwise+ -> concatMap collectSpecBindsOfTree ts++ _ -> []+++collectExpBindsOfTree :: Ord n => BindTree n -> [Bind n]+collectExpBindsOfTree tt+ = case tt of+ BindDef way bs ts+ | BoundExp <- boundLevelOfBindWay way+ -> concat ( bs+ : map collectExpBindsOfTree ts)++ | otherwise+ -> concatMap collectExpBindsOfTree ts++ _ -> []+++-------------------------------------------------------------------------------+-- | A description of the binding structure of some type or expression.+data BindTree n+ -- | An abstract binding expression.+ = BindDef BindWay [Bind n] [BindTree n]++ -- | Use of a variable.+ | BindUse BoundLevel (Bound n)++ -- | Use of a constructor.+ | BindCon BoundLevel (Bound n) (Maybe (Kind n))+ deriving (Eq, Show)+++-- | Describes how a variable was bound.+data BindWay+ = BindForall+ | BindLAM+ | BindLam+ | BindLet+ | BindLetRec+ | BindLetRegions+ | BindLetRegionWith+ | BindCasePat+ deriving (Eq, Show)+++-- | What level this binder is at.+data BoundLevel+ = BoundSpec+ | BoundExp+ | BoundWit+ deriving (Eq, Show)+++-- | Check if a boundlevel is expression or witness+isBoundExpWit :: BoundLevel -> Bool+isBoundExpWit BoundExp = True+isBoundExpWit BoundWit = True+isBoundExpWit _ = False+++-- | Get the `BoundLevel` corresponding to a `BindWay`.+boundLevelOfBindWay :: BindWay -> BoundLevel+boundLevelOfBindWay way+ = case way of+ BindForall -> BoundSpec+ BindLAM -> BoundSpec+ BindLam -> BoundExp+ BindLet -> BoundExp+ BindLetRec -> BoundExp+ BindLetRegions -> BoundSpec+ BindLetRegionWith -> BoundExp+ BindCasePat -> BoundExp+++-- BindStruct -----------------------------------------------------------------+class BindStruct (c :: * -> *) where+ slurpBindTree :: c n -> [BindTree n]+++instance BindStruct Type where+ slurpBindTree tt+ = case tt of+ TVar u -> [BindUse BoundSpec u]+ TCon tc -> slurpBindTree tc+ TForall b t -> [bindDefT BindForall [b] [t]]+ TApp t1 t2 -> slurpBindTree t1 ++ slurpBindTree t2+ TSum ts -> concatMap slurpBindTree $ Sum.toList ts+++instance BindStruct TyCon where+ slurpBindTree tc+ = case tc of+ TyConBound u k -> [BindCon BoundSpec u (Just k)]+ _ -> []+++-- | Helper for constructing the `BindTree` for a type binder.+bindDefT :: BindStruct c+ => BindWay -> [Bind n] -> [c n] -> BindTree n+bindDefT way bs xs+ = BindDef way bs $ concatMap slurpBindTree xs
+ DDC/Type/Collect/FreeT.hs view
@@ -0,0 +1,47 @@++module DDC.Type.Collect.FreeT+ (FreeVarConT(..))+where+import DDC.Type.Exp+import Data.Set (Set)+import DDC.Type.Env (KindEnv)+import qualified DDC.Type.Env as Env+import qualified DDC.Type.Sum as Sum+import qualified Data.Set as Set+++class FreeVarConT (c :: * -> *) where+ -- | Collect the free type variables and constructors used in a thing.+ freeVarConT + :: Ord n + => KindEnv n -> c n + -> (Set (Bound n), Set (Bound n))+++instance FreeVarConT Type where+ freeVarConT kenv tt+ = case tt of+ TVar u + -> if Env.member u kenv+ then (Set.empty, Set.empty)+ else (Set.singleton u, Set.empty)++ TCon tc+ | TyConBound u _ <- tc -> (Set.empty, Set.singleton u)+ | otherwise -> (Set.empty, Set.empty)++ TForall b t+ -> freeVarConT (Env.extend b kenv) t++ TApp t1 t2+ -> let (vs1, cs1) = freeVarConT kenv t1+ (vs2, cs2) = freeVarConT kenv t2+ in ( Set.union vs1 vs2+ , Set.union cs1 cs2)++ TSum ts+ -> let (vss, css) = unzip $ map (freeVarConT kenv) + $ Sum.toList ts+ in (Set.unions vss, Set.unions css)++
DDC/Type/Compounds.hs view
@@ -1,6 +1,6 @@ {-# OPTIONS -fno-warn-missing-signatures #-} module DDC.Type.Compounds- ( -- * Binds+ ( -- * Binds takeNameOfBind , typeOfBind , replaceTypeOfBind@@ -11,31 +11,53 @@ , partitionBindsByType -- * Bounds- , typeOfBound , takeNameOfBound- , replaceTypeOfBound , boundMatchesBind , namedBoundMatchesBind , takeSubstBoundOfBind+ , takeSubstBoundsOfBinds - -- * Type structure- , tIx- , tApp, ($:)- , tApps, takeTApps- , takeTyConApps, takeDataTyConApps+ -- * Kinds+ , kFun+ , kFuns+ , takeKFun+ , takeKFuns+ , takeKFuns'+ , takeResultKind++ -- * Quantifiers , tForall- , tForalls, takeTForalls+ , tForalls, takeTForalls, eraseTForalls++ -- * Sums , tBot , tSum - -- * Function type construction- , kFun- , kFuns, takeKFun- , takeKFuns, takeKFuns', takeResultKind- , tFun, takeTFun, takeTFunArgResult+ -- * Applications+ , tApp, ($:)+ , tApps, takeTApps+ , takeTyConApps+ , takePrimTyConApps+ , takeDataTyConApps+ , takePrimeRegion++ -- * Functions+ , tFun , tFunPE+ , takeTFun+ , takeTFunArgResult+ , takeTFunWitArgResult+ , arityOfType++ -- * Implications , tImpl + -- * Units+ , tUnit++ -- * Variables+ , tIx+ -- * Sort construction , sComp, sProp @@ -47,15 +69,16 @@ , tWrite, tDeepWrite , tAlloc, tDeepAlloc - -- * Closure type constructors.+ -- * Closure type constructors , tUse, tDeepUse - -- * Witness type constructors.+ -- * Witness type constructors , tPure , tEmpty , tGlobal, tDeepGlobal , tConst, tDeepConst , tMutable, tDeepMutable+ , tDistinct , tLazy, tHeadLazy , tManifest , tConData0, tConData1)@@ -123,32 +146,14 @@ -- Bounds ------------------------------------------------------------------------ | Take the type of a bound variable.-typeOfBound :: Bound n -> Type n-typeOfBound uu- = case uu of- UName _ t -> t- UPrim _ t -> t- UIx _ t -> t-- -- | Take the name of bound variable. -- If this is a deBruijn index then there won't be a name. takeNameOfBound :: Bound n -> Maybe n takeNameOfBound uu = case uu of- UName n _ -> Just n+ UName n -> Just n UPrim n _ -> Just n- UIx _ _ -> Nothing----- | Replace the type of a bound with a new one.-replaceTypeOfBound :: Type n -> Bound n -> Bound n-replaceTypeOfBound t uu- = case uu of- UName n _ -> UName n t- UPrim n _ -> UPrim n t- UIx i _ -> UIx i t+ UIx{} -> Nothing -- | Check whether a bound maches a bind.@@ -158,9 +163,9 @@ boundMatchesBind :: Eq n => Bound n -> Bind n -> Bool boundMatchesBind u b = case (u, b) of- (UName n1 _, BName n2 _) -> n1 == n2- (UIx 0 _, BAnon _ ) -> True- _ -> False+ (UName n1, BName n2 _) -> n1 == n2+ (UIx 0, BAnon _) -> True+ _ -> False -- | Check whether a named bound matches a named bind. @@ -168,27 +173,36 @@ namedBoundMatchesBind :: Eq n => Bound n -> Bind n -> Bool namedBoundMatchesBind u b = case (u, b) of- (UName n1 _, BName n2 _) -> n1 == n2- _ -> False-+ (UName n1, BName n2 _) -> n1 == n2+ _ -> False --- | Convert a `Bound` to a `Bind`, ready for substitution.+-- | Convert a `Bind` to a `Bound`, ready for substitution. -- -- Returns `UName` for `BName`, @UIx 0@ for `BAnon` -- and `Nothing` for `BNone`, because there's nothing to substitute. takeSubstBoundOfBind :: Bind n -> Maybe (Bound n) takeSubstBoundOfBind bb = case bb of- BName n t -> Just $ UName n t- BAnon t -> Just $ UIx 0 t+ BName n _ -> Just $ UName n + BAnon _ -> Just $ UIx 0 BNone _ -> Nothing +-- | Convert some `Bind`s to `Bounds`+takeSubstBoundsOfBinds :: [Bind n] -> [Bound n]+takeSubstBoundsOfBinds bs+ = go 0 bs+ where go _level [] = []+ go level (BName n _ : bs') = UName n : go level bs'+ go level (BAnon _ : bs') = UIx level : go (level + 1) bs'+ go level (BNone _ : bs') = go level bs'++ -- Variables ------------------------------------------------------------------ -- | Construct a deBruijn index. tIx :: Kind n -> Int -> Type n-tIx k i = TVar (UIx i k)+tIx _ i = TVar (UIx i) -- Applications ---------------------------------------------------------------@@ -226,35 +240,58 @@ -- | Flatten a sequence of type applications, returning the type constructor+-- and arguments, if there is one. Only accept primitive type constructors.+takePrimTyConApps :: Type n -> Maybe (n, [Type n])+takePrimTyConApps tt+ = case takeTApps tt of+ TCon tc : args + | TyConBound (UPrim n _) _ <- tc+ -> Just (n, args)++ _ -> Nothing+++-- | Flatten a sequence of type applications, returning the type constructor -- and arguments, if there is one. Only accept data type constructors. takeDataTyConApps :: Type n -> Maybe (TyCon n, [Type n]) takeDataTyConApps tt = case takeTApps tt of TCon tc : args - | TyConBound (UName _ t) <- tc- , TCon (TyConKind KiConData) <- takeResultKind t+ | TyConBound (UName _) k <- tc+ , TCon (TyConKind KiConData) <- takeResultKind k -> Just (tc, args) - | TyConBound (UPrim _ t) <- tc- , TCon (TyConKind KiConData) <- takeResultKind t+ | TyConBound UPrim{} k <- tc+ , TCon (TyConKind KiConData) <- takeResultKind k -> Just (tc, args) _ -> Nothing +-- | Take the prime region variable of a data type.+-- This corresponds to the region the outermost constructor is allocated into.+takePrimeRegion :: Type n -> Maybe (Type n)+takePrimeRegion tt+ = case takeTApps tt of+ TCon _ : tR@(TVar _) : _+ -> Just tR++ _ -> Nothing++ -- Foralls -------------------------------------------------------------------- -- | Build an anonymous type abstraction, with a single parameter. tForall :: Kind n -> (Type n -> Type n) -> Type n tForall k f- = TForall (BAnon k) (f (TVar (UIx 0 k)))+ = TForall (BAnon k) (f (TVar (UIx 0))) -- | Build an anonymous type abstraction, with several parameters. tForalls :: [Kind n] -> ([Type n] -> Type n) -> Type n tForalls ks f = let bs = [BAnon k | k <- ks]- us = reverse [TVar (UIx n k) | k <- ks | n <- [0..]]- in foldr TForall (f us) bs+ us = map (\i -> TVar (UIx i)) [0.. (length ks - 1)]+ in foldr TForall (f $ reverse us) bs -- | Split nested foralls from the front of a type, @@ -268,17 +305,33 @@ (bs, body) -> Just (bs, body) +-- | Erase all `TForall` quantifiers from a type.+eraseTForalls :: Ord n => Type n -> Type n+eraseTForalls tt+ = case tt of+ TVar{} -> tt+ TCon{} -> tt+ TForall _ t -> eraseTForalls t+ TApp t1 t2 -> TApp (eraseTForalls t1) (eraseTForalls t2)+ TSum ts -> TSum $ Sum.fromList (Sum.kindOfSum ts) + $ map eraseTForalls $ Sum.toList ts++ -- Sums ----------------------------------------------------------------------- tSum :: Ord n => Kind n -> [Type n] -> Type n tSum k ts = TSum (Sum.fromList k ts) +-- Unit -----------------------------------------------------------------------+tUnit :: Type n+tUnit = TCon (TyConSpec TcConUnit)++ -- Function Constructors ------------------------------------------------------ -- | Construct a kind function. kFun :: Kind n -> Kind n -> Kind n kFun k1 k2 = ((TCon $ TyConKind KiConFun)`TApp` k1) `TApp` k2- infixr `kFun` @@ -330,7 +383,6 @@ tFun :: Type n -> Effect n -> Closure n -> Type n -> Type n tFun t1 eff clo t2 = (TCon $ TyConSpec TcConFun) `tApps` [t1, eff, clo, t2]- infixr `tFun` @@ -343,8 +395,8 @@ _ -> Nothing --- | Destruct the type of a value function, returning just the argument--- and result types.+-- | Destruct the type of a function,+-- returning just the argument and result types. takeTFunArgResult :: Type n -> ([Type n], Type n) takeTFunArgResult tt = case tt of@@ -354,17 +406,40 @@ _ -> ([], tt) +-- | Destruct the type of a function,+-- returning the witness argument, value argument and result types.+-- The function type must have the witness implications before +-- the value arguments, eg @T1 => T2 -> T3 -> T4 -> T5@.+takeTFunWitArgResult :: Type n -> ([Type n], [Type n], Type n)+takeTFunWitArgResult tt+ = case tt of+ TApp (TApp (TCon (TyConWitness TwConImpl)) t1) t2+ -> let (twsMore, tvsMore, tResult) = takeTFunWitArgResult t2+ in (t1 : twsMore, tvsMore, tResult) + _ -> let (tvsMore, tResult) = takeTFunArgResult tt+ in ([], tvsMore, tResult)+++-- | Determine the arity of an expression by looking at its type.+-- Count all the function arrows, and foralls.+arityOfType :: Type n -> Int+arityOfType tt+ = case tt of+ TForall _ t -> 1 + arityOfType t+ t -> length $ fst $ takeTFunArgResult t++ -- | Construct a pure and empty value type function. tFunPE :: Type n -> Type n -> Type n tFunPE t1 t2 = tFun t1 (tBot kEffect) (tBot kClosure) t2+infixr `tFunPE` -- | Construct a witness implication type. tImpl :: Type n -> Type n -> Type n tImpl t1 t2 = ((TCon $ TyConWitness TwConImpl) `tApp` t1) `tApp` t2- infixr `tImpl` @@ -405,6 +480,7 @@ tDeepConst = twCon1 TwConDeepConst tMutable = twCon1 TwConMutable tDeepMutable = twCon1 TwConDeepMutable+tDistinct n = twCon2 (TwConDistinct n) tLazy = twCon1 TwConLazy tHeadLazy = twCon1 TwConHeadLazy tManifest = twCon1 TwConManifest@@ -412,14 +488,16 @@ tcCon1 tc t = (TCon $ TyConSpec tc) `tApp` t twCon1 tc t = (TCon $ TyConWitness tc) `tApp` t +twCon2 tc ts = tApps (TCon $ TyConWitness tc) ts + -- | Build a nullary type constructor of the given kind. tConData0 :: n -> Kind n -> Type n-tConData0 n k = TCon (TyConBound (UName n k))+tConData0 n k = TCon (TyConBound (UName n) k) -- | Build a type constructor application of one argumnet. tConData1 :: n -> Kind n -> Type n -> Type n-tConData1 n k t1 = TApp (TCon (TyConBound (UName n k))) t1+tConData1 n k t1 = TApp (TCon (TyConBound (UName n) k)) t1
+ DDC/Type/DataDef.hs view
@@ -0,0 +1,142 @@++-- | Algebraic data type definitions.+module DDC.Type.DataDef+ ( DataDef (..)++ -- * Data type definition table+ , DataDefs (..)+ , DataMode (..)+ , DataType (..)+ , DataCtor (..)++ , emptyDataDefs+ , insertDataDef+ , fromListDataDefs+ , lookupModeOfDataType)+where+import DDC.Type.Exp+import Data.Map (Map)+import qualified Data.Map.Strict as Map+import Data.Maybe+import Control.Monad+++-- | The definition of a single data type.+data DataDef n+ = DataDef+ { -- | Name of the data type.+ dataDefTypeName :: !n++ -- | Kinds of type parameters.+ , dataDefParamKinds :: ![Kind n]++ -- | Constructors of the data type, or Nothing if there are+ -- too many to list (like with `Int`).+ , dataDefCtors :: !(Maybe [(n, [Type n])]) }+ deriving Show+++-- DataDefs -------------------------------------------------------------------+-- | A table of data type definitions,+-- unpacked into type and data constructors so we can find them easily.+data DataDefs n+ = DataDefs+ { dataDefsTypes :: !(Map n (DataType n))+ , dataDefsCtors :: !(Map n (DataCtor n)) }+ deriving Show+++-- | The mode of a data type records how many data constructors there are.+-- This can be set to 'Large' for large primitive types like Int and Float.+-- In this case we don't ever expect them all to be enumerated+-- as case alternatives.+data DataMode n+ = DataModeSmall ![n]+ | DataModeLarge+ deriving Show+++-- | Describes a data type constructor, used in the `DataDefs` table.+data DataType n+ = DataType + { -- | Name of data type constructor.+ dataTypeName :: !n++ -- | Kinds of type parameters to constructor.+ , dataTypeParamKinds :: ![Kind n]++ -- | Names of data constructors of this data type,+ -- or `Nothing` if it has infinitely many constructors.+ , dataTypeMode :: !(DataMode n) }+ deriving Show+++-- | Describes a data constructor, used in the `DataDefs` table.+data DataCtor n+ = DataCtor+ { -- | Name of data constructor.+ dataCtorName :: !n++ -- | Tag of constructor (order in data type declaration)+ , dataCtorTag :: !Integer++ -- | Field types of constructor.+ , dataCtorFieldTypes :: ![Type n]++ -- | Name of result type of constructor.+ , dataCtorTypeName :: !n }+ deriving Show+++-- | An empty table of data type definitions.+emptyDataDefs :: DataDefs n+emptyDataDefs+ = DataDefs+ { dataDefsTypes = Map.empty+ , dataDefsCtors = Map.empty }+++-- | Insert a data type definition into some DataDefs.+insertDataDef :: Ord n => DataDef n -> DataDefs n -> DataDefs n+insertDataDef (DataDef nType ks mCtors) dataDefs+ = let defType = DataType+ { dataTypeName = nType+ , dataTypeParamKinds = ks+ , dataTypeMode = defMode }++ defMode = case mCtors of+ Nothing -> DataModeLarge+ Just ctors -> DataModeSmall (map fst ctors)++ makeDefCtor tag (nCtor, tsFields)+ = DataCtor+ { dataCtorName = nCtor+ , dataCtorTag = tag+ , dataCtorFieldTypes = tsFields+ , dataCtorTypeName = nType }++ defCtors = case mCtors of+ Nothing -> Nothing+ Just cs -> Just $ zipWith makeDefCtor [0..] cs++ in dataDefs+ { dataDefsTypes = Map.insert nType defType (dataDefsTypes dataDefs)+ , dataDefsCtors = Map.union (dataDefsCtors dataDefs)+ $ Map.fromList [(n, def) + | def@(DataCtor n _ _ _) <- concat $ maybeToList defCtors ]}+++-- | Build a `DataDefs` table from a list of `DataDef`+fromListDataDefs :: Ord n => [DataDef n] -> DataDefs n+fromListDataDefs defs+ = foldr insertDataDef emptyDataDefs defs++++-- | Yield the list of data constructor names for some data type, +-- or `Nothing` for large types with too many constructors to list.+lookupModeOfDataType :: Ord n => n -> DataDefs n -> Maybe (DataMode n)+lookupModeOfDataType n defs+ = liftM dataTypeMode $ Map.lookup n (dataDefsTypes defs)++
DDC/Type/Env.hs view
@@ -8,24 +8,43 @@ -- module DDC.Type.Env ( Env(..)+ , KindEnv+ , TypeEnv++ -- * Construction , empty- , extend, extends- , setPrimFun, isPrim- , fromList+ , extend+ , extends , union- , member, memberBind- , lookup, lookupName++ -- * Conversion+ , fromList+ , fromTypeMap++ -- * Projetions , depth- , lift- , wrapTForalls)+ , member+ , memberBind+ , lookup+ , lookupName++ -- * Primitives+ , setPrimFun+ , isPrim++ -- * Lifting+ , wrapTForalls++ -- * Wrapping+ , lift) where import DDC.Type.Exp import DDC.Type.Transform.LiftT import Data.Maybe-import Data.Map (Map)-import Prelude hiding (lookup)-import qualified Data.Map as Map-import qualified Prelude as P+import Data.Map (Map)+import Prelude hiding (lookup)+import qualified Data.Map.Strict as Map+import qualified Prelude as P import Control.Monad @@ -33,18 +52,26 @@ data Env n = Env { -- | Types of named binders.- envMap :: Map n (Type n)+ envMap :: !(Map n (Type n)) -- | Types of anonymous deBruijn binders.- , envStack :: [Type n] + , envStack :: ![Type n] -- | The length of the above stack.- , envStackLength :: Int+ , envStackLength :: !Int -- | Types of baked in, primitive names.- , envPrimFun :: n -> Maybe (Type n) }+ , envPrimFun :: !(n -> Maybe (Type n)) } +-- | Type synonym to improve readability.+type KindEnv n = Env n+++-- | Type synonym to improve readability.+type TypeEnv n = Env n++ -- | An empty environment. empty :: Env n empty = Env@@ -90,6 +117,12 @@ = foldr extend empty bs +-- | Convert a map of names to types to a environment.+fromTypeMap :: Map n (Type n) -> Env n+fromTypeMap m+ = empty { envMap = m}++ -- | Combine two environments. -- If both environments have a binding with the same name, -- then the one in the second environment takes preference.@@ -121,15 +154,12 @@ lookup :: Ord n => Bound n -> Env n -> Maybe (Type n) lookup uu env = case uu of- UName n _+ UName n -> Map.lookup n (envMap env) `mplus` envPrimFun env n - UIx i _ - -> P.lookup i (zip [0..] (envStack env))-- UPrim n _- -> envPrimFun env n+ UIx i -> P.lookup i (zip [0..] (envStack env))+ UPrim n _ -> envPrimFun env n -- | Lookup a bound name from an environment.@@ -144,8 +174,13 @@ -- | Lift all free deBruijn indices in the environment by the given number of steps.--- TODO: Delay this, only lift when we extract the final type.--- will also need to update the 'member' function.+---+-- ISSUE #276: Delay lifting of indices in type environments.+-- The 'lift' function on type environments applies to every member of+-- the environment. We'd get better complexity by recording how many+-- levels all types should be lifted by, and only applying the real lift+-- function when the type is finally extracted.+-- lift :: Ord n => Int -> Env n -> Env n lift n env = Env
DDC/Type/Equiv.hs view
@@ -1,13 +1,12 @@ module DDC.Type.Equiv- (equivT)+ ( equivT+ , equivWithBindsT) where-import DDC.Type.Exp-import DDC.Type.Compounds import DDC.Type.Transform.Crush-import DDC.Type.Transform.Trim-import DDC.Base.Pretty-import Data.Maybe+import DDC.Type.Compounds+import DDC.Type.Bind+import DDC.Type.Exp import qualified DDC.Type.Sum as Sum @@ -22,33 +21,42 @@ -- bound variables match the binders. If this is not the case then you get -- an indeterminate result. ---equivT :: (Ord n, Pretty n) => Type n -> Type n -> Bool+equivT :: Ord n => Type n -> Type n -> Bool equivT t1 t2- = equivT' [] 0 [] 0 t1 t2-+ = equivWithBindsT [] [] t1 t2 -equivT' :: (Ord n, Pretty n)- => [Bind n] -> Int- -> [Bind n] -> Int- -> Type n -> Type n+-- | Like `equivT` but take the initial stacks of type binders.+equivWithBindsT+ :: Ord n+ => [Bind n]+ -> [Bind n]+ -> Type n+ -> Type n -> Bool -equivT' stack1 depth1 stack2 depth2 t1 t2+equivWithBindsT stack1 stack2 t1 t2 = let t1' = unpackSumT $ crushSomeT t1 t2' = unpackSumT $ crushSomeT t2 in case (t1', t2') of (TVar u1, TVar u2)- -- Bound variables are name-equivalent.- | u1 == u2 -> True+ -- Free variables are name-equivalent, bound variables aren't:+ -- (forall a. a) != (forall b. a)+ | Nothing <- getBindType stack1 u1+ , Nothing <- getBindType stack2 u2+ , u1 == u2 -> checkBounds u1 u2 True - -- Variables aren't name equivalent, - -- but would be equivalent if we renamed them.- | depth1 == depth2- , Just (ix1, t1a) <- getBindType stack1 u1+ -- Both variables are bound in foralls, so check the stack+ -- to see if they would be equivalent if we named them.+ | Just (ix1, t1a) <- getBindType stack1 u1 , Just (ix2, t2a) <- getBindType stack2 u2 , ix1 == ix2- -> equivT' stack1 depth1 stack2 depth2 t1a t2a+ -> checkBounds u1 u2 + $ equivWithBindsT stack1 stack2 t1a t2a + | otherwise+ -> checkBounds u1 u2+ $ False+ -- Constructor names must be equal. (TCon tc1, TCon tc2) -> tc1 == tc2@@ -56,31 +64,34 @@ -- Push binders on the stack as we enter foralls. (TForall b11 t12, TForall b21 t22) | equivT (typeOfBind b11) (typeOfBind b21)- -> equivT' (b11 : stack1) (depth1 + 1) - (b21 : stack2) (depth2 + 1) - t12 t22+ -> equivWithBindsT+ (b11 : stack1)+ (b21 : stack2)+ t12 t22 -- Decend into applications. (TApp t11 t12, TApp t21 t22)- -> equivT' stack1 depth1 stack2 depth2 t11 t21- && equivT' stack1 depth1 stack2 depth2 t12 t22+ -> equivWithBindsT stack1 stack2 t11 t21+ && equivWithBindsT stack1 stack2 t12 t22 -- Sums are equivalent if all of their components are. (TSum ts1, TSum ts2) -> let ts1' = Sum.toList ts1 ts2' = Sum.toList ts2- equiv = equivT' stack1 depth1 stack2 depth2 -- If all the components of the sum were in the element -- arrays then they come out of Sum.toList sorted -- and we can compare corresponding pairs.- checkFast = and $ zipWith equiv ts1' ts2'+ checkFast = and $ zipWith (equivWithBindsT stack1 stack2) ts1' ts2' -- If any of the components use a higher kinded type variable -- like (c : % ~> !) then they won't nessesarally be sorted, -- so we need to do this slower O(n^2) check.- checkSlow = and [ or (map (equiv t1c) ts2') | t1c <- ts1' ]- && and [ or (map (equiv t2c) ts1') | t2c <- ts2' ]+ -- Make sure to get the bind stacks the right way around here.+ checkSlow = and [ or (map (equivWithBindsT stack1 stack2 t1c) ts2') + | t1c <- ts1' ]+ && and [ or (map (equivWithBindsT stack2 stack1 t2c) ts1') + | t2c <- ts2' ] in (length ts1' == length ts2') && (checkFast || checkSlow)@@ -88,62 +99,30 @@ (_, _) -> False --- | Unpack single element sums into plain types.-unpackSumT :: Type n -> Type n-unpackSumT (TSum ts)- | [t] <- Sum.toList ts = t-unpackSumT tt = tt----- | Crush compound effects and closure terms.--- We check for a crushable term before calling crushT because that function--- will recursively crush the components. --- As equivT is already recursive, we don't want a doubly-recursive function--- that tries to re-crush the same non-crushable type over and over.----crushSomeT :: (Ord n, Pretty n) => Type n -> Type n-crushSomeT tt- = case tt of- (TApp (TCon tc) _)- -> case tc of- TyConSpec TcConDeepRead -> crushEffect tt- TyConSpec TcConDeepWrite -> crushEffect tt- TyConSpec TcConDeepAlloc -> crushEffect tt-- -- If a closure is miskinded then 'trimClosure' - -- can return Nothing, so we just leave the term untrimmed.- TyConSpec TcConDeepUse -> fromMaybe tt (trimClosure tt)-- TyConWitness TwConDeepGlobal -> crushEffect tt- _ -> tt-- _ -> tt----- | Lookup the type of a bound thing from the binder stack.--- The binder stack contains the binders of all the `TForall`s we've--- entered under so far.-getBindType :: Eq n => [Bind n] -> Bound n -> Maybe (Int, Type n)-getBindType bs' u- = go 0 bs'- where go n (BName n1 t : bs)- | UName n2 _ <- u- , n1 == n2 = Just (n, t)- | otherwise = go (n + 1) bs--- go n (BAnon t : bs)- | UIx i _ <- u- , i == 0 = Just (n, t)+-- | If we have a UName and UPrim with the same name then these won't match+-- even though they pretty print the same. This will only happen due to +-- a compiler bugs, but is very confusing when it does, so we check for+-- this case explicitly.+checkBounds :: Eq n => Bound n -> Bound n -> a -> a+checkBounds u1 u2 x+ = case (u1, u2) of+ (UName n2, UPrim n1 _)+ | n1 == n2 -> die - | UIx i _ <- u- , i < 0 = Nothing+ (UPrim n1 _, UName n2)+ | n1 == n2 -> die - | otherwise = go (n + 1) bs+ _ -> x+ where+ die = error $ unlines+ [ "DDC.Type.Equiv"+ , " Found a primitive and non-primitive bound variable with the same name."] - go n (BNone _ : bs)- = go (n + 1) bs+-- | Unpack single element sums into plain types.+unpackSumT :: Type n -> Type n+unpackSumT (TSum ts)+ | [t] <- Sum.toList ts = t+unpackSumT tt = tt - go _ [] = Nothing
DDC/Type/Exp.hs view
@@ -1,10 +1,7 @@ module DDC.Type.Exp ( -- * Types, Kinds, and Sorts- Binder (..)- , Bind (..)- , Bound (..)- , Type (..)+ Type (..) , Kind, Sort , Region, Effect, Closure , TypeSum (..), TyConHash(..), TypeSumVarCon(..)@@ -12,260 +9,11 @@ , SoCon (..) , KiCon (..) , TwCon (..)- , TcCon (..))+ , TcCon (..)+ , Binder (..)+ , Bind (..)+ , Bound (..)) where-import Data.Array-import Data.Map (Map)-import Data.Set (Set)----- Bind -------------------------------------------------------------------------- | A variable binder.-data Binder n- = RNone- | RAnon- | RName n- deriving Show----- | A variable binder with its type.-data Bind n- -- | A variable with no uses in the body doesn't need a name.- = BNone (Type n)-- -- | Nameless variable on the deBruijn stack.- | BAnon (Type n)-- -- | Named variable in the environment.- | BName n (Type n)- deriving Show------ | A bound occurrence of a variable, with its type.------ If variable hasn't been annotated with its real type then this --- can be `tBot` (an empty sum).--data Bound n- -- | Nameless variable that should be on the deBruijn stack.- = UIx Int (Type n) -- -- | Named variable that should be in the environment.- | UName n (Type n)-- -- | Named primitive that is not bound in the environment.- -- Prims aren't every counted as being free.- | UPrim n (Type n) - deriving Show----- Types ------------------------------------------------------------------------- | A value type, kind, or sort.------ We use the same data type to represent all three universes, as they have--- a similar algebraic structure.----data Type n- -- | Variable.- = TVar (Bound n)-- -- | Constructor.- | TCon (TyCon n)-- -- | Abstraction.- | TForall (Bind n) (Type n)- - -- | Application.- | TApp (Type n) (Type n)-- -- | Least upper bound.- | TSum (TypeSum n)- deriving Show---type Sort n = Type n-type Kind n = Type n-type Region n = Type n-type Effect n = Type n-type Closure n = Type n----- Type Sums --------------------------------------------------------------------- | A least upper bound of several types.--- --- We keep type sums in this normalised format instead of joining them--- together with a binary operator (like @(+)@). This makes sums easier to work--- with, as a given sum type often only has a single physical representation.-data TypeSum n- = TypeSum- { -- | The kind of the elements in this sum.- typeSumKind :: Kind n-- -- | Where we can see the outer constructor of a type, its argument- -- is inserted into this array. This handles common cases like- -- Read, Write, Alloc effects.- , typeSumElems :: Array TyConHash (Set (TypeSumVarCon n))-- -- | A map for named type variables.- , typeSumBoundNamed :: Map n (Kind n)-- -- | A map for anonymous type variables.- , typeSumBoundAnon :: Map Int (Kind n)-- -- | Types that can't be placed in the other fields go here.- -- - -- INVARIANT: this list doesn't contain more `TSum`s.- , typeSumSpill :: [Type n] }- deriving (Show)- ---- | Hash value used to insert types into the `typeSumElems` array of a `TypeSum`.-data TyConHash - = TyConHash !Int- deriving (Eq, Show, Ord, Ix)----- | Wraps a variable or constructor that can be added the `typeSumElems` array.-data TypeSumVarCon n- = TypeSumVar (Bound n)- | TypeSumCon (Bound n)- deriving Show----- TyCon ------------------------------------------------------------------------- | Kind, type and witness constructors.------ These are grouped to make it easy to determine the universe that they--- belong to.--- -data TyCon n- -- | (level 3) Builtin Sort constructors.- = TyConSort SoCon-- -- | (level 2) Builtin Kind constructors.- | TyConKind KiCon-- -- | (level 1) Builtin Spec constructors for the types of witnesses.- | TyConWitness TwCon-- -- | (level 1) Builtin Spec constructors for types of other kinds.- | TyConSpec TcCon-- -- | User defined and primitive constructors.- | TyConBound (Bound n)- deriving Show----- | Sort constructor.-data SoCon- -- | Sort of witness kinds.- = SoConProp -- '@@'-- -- | Sort of computation kinds.- | SoConComp -- '**'- deriving (Eq, Show)----- | Kind constructor.-data KiCon- -- | Function kind constructor.- -- This is only well formed when it is fully applied.- = KiConFun -- (~>)-- -- Witness kinds ------------------------- -- | Kind of witnesses.- | KiConWitness -- '@ :: @@'-- -- Computation kinds ---------------------- -- | Kind of data values.- | KiConData -- '* :: **'-- -- | Kind of regions.- | KiConRegion -- '% :: **'-- -- | Kind of effects.- | KiConEffect -- '! :: **'-- -- | Kind of closures.- | KiConClosure -- '$ :: **'- deriving (Eq, Show)----- | Witness type constructors.-data TwCon- -- Witness implication.- = TwConImpl -- :: '(=>) :: * ~> *'-- -- | Purity of some effect.- | TwConPure -- :: ! ~> @-- -- | Emptiness of some closure.- | TwConEmpty -- :: $ ~> @-- -- | Globalness of some region.- | TwConGlobal -- :: % ~> @-- -- | Globalness of material regions in some type.- | TwConDeepGlobal -- :: * ~> @- - -- | Constancy of some region.- | TwConConst -- :: % ~> @-- -- | Constancy of material regions in some type- | TwConDeepConst -- :: * ~> @-- -- | Mutability of some region.- | TwConMutable -- :: % ~> @-- -- | Mutability of material regions in some type.- | TwConDeepMutable -- :: * ~> @-- -- | Laziness of some region.- | TwConLazy -- :: % ~> @-- -- | Laziness of the primary region in some type.- | TwConHeadLazy -- :: * ~> @-- -- | Manifestness of some region (not lazy).- | TwConManifest -- :: % ~> @- deriving (Eq, Show)----- | Other constructors at the spec level.-data TcCon- -- Data type constructors ---------------- -- | The function type constructor is baked in so we - -- represent it separately.- = TcConFun -- '(->) :: * ~> * ~> ! ~> $ ~> *'-- -- Effect type constructors -------------- -- | Read of some region.- | TcConRead -- :: '% ~> !'-- -- | Read the head region in a data type.- | TcConHeadRead -- :: '* ~> !'-- -- | Read of all material regions in a data type.- | TcConDeepRead -- :: '* ~> !'- - -- | Write of some region.- | TcConWrite -- :: '% ~> !'-- -- | Write to all material regions in some data type.- | TcConDeepWrite -- :: '* ~> !'- - -- | Allocation into some region.- | TcConAlloc -- :: '% ~> !'-- -- | Allocation into all material regions in some data type.- | TcConDeepAlloc -- :: '* ~> !'- - -- Closure type constructors ------------- -- | Region is captured in a closure.- | TcConUse -- :: '% ~> $'- - -- | All material regions in a data type are captured in a closure.- | TcConDeepUse -- :: '* ~> $'- deriving (Eq, Show)+import DDC.Type.Exp.Base+import DDC.Type.Exp.NFData ()
+ DDC/Type/Exp/Base.hs view
@@ -0,0 +1,267 @@++module DDC.Type.Exp.Base where+import Data.Array+import Data.Map.Strict (Map)+import Data.Set (Set)+++-- Bind -----------------------------------------------------------------------+-- | A variable binder.+data Binder n+ = RNone+ | RAnon+ | RName !n+ deriving Show+++-- | A variable binder with its type.+data Bind n+ -- | A variable with no uses in the body doesn't need a name.+ = BNone !(Type n)++ -- | Nameless variable on the deBruijn stack.+ | BAnon !(Type n)++ -- | Named variable in the environment.+ | BName n !(Type n)+ deriving Show++++-- | A bound occurrence of a variable, with its type.+--+-- If variable hasn't been annotated with its real type then this +-- can be `tBot` (an empty sum).++data Bound n+ -- | Nameless variable that should be on the deBruijn stack.+ = UIx !Int ++ -- | Named variable that should be in the environment.+ | UName !n++ -- | Named primitive that has its type attached to it.+ -- The types of primitives must be closed.+ | UPrim !n !(Type n)+ deriving Show+++-- Types ----------------------------------------------------------------------+-- | A value type, kind, or sort.+--+-- We use the same data type to represent all three universes, as they have+-- a similar algebraic structure.+--+data Type n+ -- | Variable.+ = TVar !(Bound n)++ -- | Constructor.+ | TCon !(TyCon n)++ -- | Abstraction.+ | TForall !(Bind n) !(Type n)+ + -- | Application.+ | TApp !(Type n) !(Type n)++ -- | Least upper bound.+ | TSum !(TypeSum n)+ deriving Show+++type Sort n = Type n+type Kind n = Type n+type Region n = Type n+type Effect n = Type n+type Closure n = Type n+++-- Type Sums ------------------------------------------------------------------+-- | A least upper bound of several types.+-- +-- We keep type sums in this normalised format instead of joining them+-- together with a binary operator (like @(+)@). This makes sums easier to work+-- with, as a given sum type often only has a single physical representation.+data TypeSum n+ = TypeSumBot+ { typeSumKind :: !(Kind n) }++ | TypeSumSet+ { -- | The kind of the elements in this sum.+ typeSumKind :: !(Kind n)++ -- | Where we can see the outer constructor of a type, its argument+ -- is inserted into this array. This handles common cases like+ -- Read, Write, Alloc effects.+ , typeSumElems :: !(Array TyConHash (Set (TypeSumVarCon n)))++ -- | A map for named type variables.+ , typeSumBoundNamed :: !(Map n (Kind n))++ -- | A map for anonymous type variables.+ , typeSumBoundAnon :: !(Map Int (Kind n))++ -- | Types that can't be placed in the other fields go here.+ -- + -- INVARIANT: this list doesn't contain more `TSum`s.+ , typeSumSpill :: ![Type n] }+ deriving (Show)+ ++-- | Hash value used to insert types into the `typeSumElems` array of a `TypeSum`.+data TyConHash + = TyConHash !Int+ deriving (Eq, Show, Ord, Ix)+++-- | Wraps a variable or constructor that can be added the `typeSumElems` array.+data TypeSumVarCon n+ = TypeSumVar !(Bound n)+ | TypeSumCon !(Bound n) !(Type n)+ deriving Show+++-- TyCon ----------------------------------------------------------------------+-- | Kind, type and witness constructors.+--+-- These are grouped to make it easy to determine the universe that they+-- belong to.+-- +data TyCon n+ -- | (level 3) Builtin Sort constructors.+ = TyConSort !SoCon++ -- | (level 2) Builtin Kind constructors.+ | TyConKind !KiCon++ -- | (level 1) Builtin Spec constructors for the types of witnesses.+ | TyConWitness !TwCon++ -- | (level 1) Builtin Spec constructors for types of other kinds.+ | TyConSpec !TcCon++ -- | User defined and primitive constructors.+ | TyConBound !(Bound n) !(Kind n)+ deriving Show+++-- | Sort constructor.+data SoCon+ -- | Sort of witness kinds.+ = SoConProp -- '@@'++ -- | Sort of computation kinds.+ | SoConComp -- '**'+ deriving (Eq, Show)+++-- | Kind constructor.+data KiCon+ -- | Function kind constructor.+ -- This is only well formed when it is fully applied.+ = KiConFun -- (~>)++ -- Witness kinds ------------------------+ -- | Kind of witnesses.+ | KiConWitness -- '@ :: @@'++ -- Computation kinds ---------------------+ -- | Kind of data values.+ | KiConData -- '* :: **'++ -- | Kind of regions.+ | KiConRegion -- '% :: **'++ -- | Kind of effects.+ | KiConEffect -- '! :: **'++ -- | Kind of closures.+ | KiConClosure -- '$ :: **'+ deriving (Eq, Show)+++-- | Witness type constructors.+data TwCon+ -- Witness implication.+ = TwConImpl -- :: '(=>) :: @ ~> *'++ -- | Purity of some effect.+ | TwConPure -- :: ! ~> @++ -- | Emptiness of some closure.+ | TwConEmpty -- :: $ ~> @++ -- | Globalness of some region.+ | TwConGlobal -- :: % ~> @++ -- | Globalness of material regions in some type.+ | TwConDeepGlobal -- :: * ~> @+ + -- | Constancy of some region.+ | TwConConst -- :: % ~> @++ -- | Constancy of material regions in some type+ | TwConDeepConst -- :: * ~> @++ -- | Mutability of some region.+ | TwConMutable -- :: % ~> @++ -- | Mutability of material regions in some type.+ | TwConDeepMutable -- :: * ~> @++ -- | Distinctness of some n regions+ | TwConDistinct Int -- :: * ~> [%] ~> @+ + -- | Laziness of some region.+ | TwConLazy -- :: % ~> @++ -- | Laziness of the primary region in some type.+ | TwConHeadLazy -- :: * ~> @++ -- | Manifestness of some region (not lazy).+ | TwConManifest -- :: % ~> @++ -- | Non-interfering effects are disjoint. Used for rewrite rules.+ | TwConDisjoint -- :: ! ~> ! ~> @+ deriving (Eq, Show)+++-- | Other constructors at the spec level.+data TcCon+ -- Data type constructors ---------------+ -- | The unit data type constructor is baked in.+ = TcConUnit -- 'Unit :: *'++ -- | The function type constructor is baked in.+ | TcConFun -- '(->) :: * ~> * ~> ! ~> $ ~> *'++ -- Effect type constructors -------------+ -- | Read of some region.+ | TcConRead -- :: '% ~> !'++ -- | Read the head region in a data type.+ | TcConHeadRead -- :: '* ~> !'++ -- | Read of all material regions in a data type.+ | TcConDeepRead -- :: '* ~> !'+ + -- | Write of some region.+ | TcConWrite -- :: '% ~> !'++ -- | Write to all material regions in some data type.+ | TcConDeepWrite -- :: '* ~> !'+ + -- | Allocation into some region.+ | TcConAlloc -- :: '% ~> !'++ -- | Allocation into all material regions in some data type.+ | TcConDeepAlloc -- :: '* ~> !'+ + -- Closure type constructors ------------+ -- | Region is captured in a closure.+ | TcConUse -- :: '% ~> $'+ + -- | All material regions in a data type are captured in a closure.+ | TcConDeepUse -- :: '* ~> $'+ deriving (Eq, Show)
+ DDC/Type/Exp/NFData.hs view
@@ -0,0 +1,81 @@++module DDC.Type.Exp.NFData where+import DDC.Type.Exp.Base+import Control.DeepSeq+++instance NFData n => NFData (Binder n) where+ rnf bb+ = case bb of+ RNone -> ()+ RAnon -> ()+ RName n -> rnf n+++instance NFData n => NFData (Bind n) where+ rnf bb+ = case bb of+ BNone t -> rnf t+ BAnon t -> rnf t+ BName n t -> rnf n `seq` rnf t+++instance NFData n => NFData (Bound n) where+ rnf uu+ = case uu of+ UIx i -> rnf i+ UName n -> rnf n+ UPrim u t -> rnf u `seq` rnf t+++instance NFData n => NFData (Type n) where+ rnf tt+ = case tt of+ TVar u -> rnf u+ TCon tc -> rnf tc+ TForall b t -> rnf b `seq` rnf t+ TApp t1 t2 -> rnf t1 `seq` rnf t2+ TSum ts -> rnf ts+++instance NFData n => NFData (TypeSum n) where+ rnf !ts+ = case ts of+ TypeSumBot{}+ -> rnf (typeSumKind ts)++ TypeSumSet{} + -> rnf (typeSumKind ts)+ `seq` rnf (typeSumElems ts)+ `seq` rnf (typeSumBoundNamed ts)+ `seq` rnf (typeSumBoundAnon ts)+ `seq` rnf (typeSumSpill ts)+++instance NFData TyConHash where+ rnf (TyConHash i)+ = rnf i+++instance NFData n => NFData (TypeSumVarCon n) where+ rnf ts+ = case ts of+ TypeSumVar u -> rnf u+ TypeSumCon u t -> rnf u `seq` rnf t+++instance NFData n => NFData (TyCon n) where+ rnf tc+ = case tc of+ TyConSort con -> rnf con+ TyConKind con -> rnf con+ TyConWitness con -> rnf con+ TyConSpec con -> rnf con+ TyConBound con k -> rnf con `seq` rnf k+++instance NFData SoCon+instance NFData KiCon+instance NFData TwCon+instance NFData TcCon+
− DDC/Type/Parser.hs
@@ -1,236 +0,0 @@---- | Parser for type expressions.-module DDC.Type.Parser- ( module DDC.Base.Parser- , Parser- , pType, pTypeAtom, pTypeApp- , pBinder- , pIndex- , pTok, pTokAs)-where-import DDC.Core.Parser.Tokens -import DDC.Type.Exp-import DDC.Type.Compounds-import DDC.Base.Parser ((<?>))-import qualified DDC.Base.Parser as P-import qualified DDC.Type.Sum as TS----- | Parser of type tokens.-type Parser n a- = P.Parser (Tok n) a----- | Top level parser for types.-pType :: Ord n => Parser n (Type n)-pType = pTypeSum- <?> "a type"----- | Parse a type sum.-pTypeSum :: Ord n => Parser n (Type n)-pTypeSum - = do t1 <- pTypeForall- P.choice - [ -- Type sums.- -- T2 + T3- do pTok KPlus- t2 <- pTypeSum- return $ TSum $ TS.fromList (tBot sComp) [t1, t2]- - , do return t1 ]- <?> "a type"----- | Parse a binder.-pBinder :: Ord n => Parser n (Binder n)-pBinder- = P.choice- -- Named binders.- [ do v <- pVar- return $ RName v- - -- Anonymous binders.- , do pTok KHat- return $ RAnon - - -- Vacant binders.- , do pTok KUnderscore- return $ RNone ]- <?> "a binder"----- | Parse a quantified type.-pTypeForall :: Ord n => Parser n (Type n)-pTypeForall- = P.choice- [ -- Universal quantification.- -- [v1 v1 ... vn : T1]. T2- do pTok KSquareBra- bs <- P.many1 pBinder- pTok KColon- k <- pTypeSum- pTok KSquareKet- pTok KDot-- body <- pTypeForall-- return $ foldr TForall body - $ map (\b -> makeBindFromBinder b k) bs-- -- Body type- , do pTypeFun]- <?> "a type"----- | Parse a function type.-pTypeFun :: Ord n => Parser n (Type n)-pTypeFun- = do t1 <- pTypeApp- P.choice - [ -- T1 ~> T2- do pTok KArrowTilde- t2 <- pTypeFun- return $ TApp (TApp (TCon (TyConKind KiConFun)) t1) t2-- -- T1 => T2- , do pTok KArrowEquals- t2 <- pTypeFun- return $ TApp (TApp (TCon (TyConWitness TwConImpl)) t1) t2-- -- T1 -> T2- , do pTok KArrowDash- t2 <- pTypeFun- return $ t1 `tFunPE` t2-- -- T1 -(TSUM | TSUM)> t2- , do pTok KDash- pTok KRoundBra- eff <- pTypeSum- pTok KBar- clo <- pTypeSum- pTok KRoundKet- pTok KAngleKet- t2 <- pTypeFun- return $ tFun t1 eff clo t2--- -- Body type- , do return t1 ]- <?> "an atomic type or type application"----- | Parse a type application.-pTypeApp :: Ord n => Parser n (Type n)-pTypeApp - = do (t:ts) <- P.many1 pTypeAtom- return $ foldl TApp t ts- <?> "an atomic type or type application"----- | Parse a variable, constructor or parenthesised type.-pTypeAtom :: Ord n => Parser n (Type n)-pTypeAtom - = P.choice- -- (~>) and (=>) and (->) and (TYPE2)- [ do pTok KRoundBra- P.choice- [ do pTok KArrowTilde- pTok KRoundKet- return (TCon $ TyConKind KiConFun)-- , do pTok KArrowEquals- pTok KRoundKet- return (TCon $ TyConWitness TwConImpl)-- , do pTok KArrowDash- pTok KRoundKet- return (TCon $ TyConSpec TcConFun)-- , do t <- pTypeSum- pTok KRoundKet- return t - ]-- -- Named type constructors- , do tc <- pTcCon- return $ TCon (TyConSpec tc)-- , do tc <- pTwCon- return $ TCon (TyConWitness tc)-- , do tc <- pTyConNamed- return $ TCon tc-- -- Symbolic constructors.- , do pTokAs KSortComp (TCon $ TyConSort SoConComp)- , do pTokAs KSortProp (TCon $ TyConSort SoConProp) - , do pTokAs KKindValue (TCon $ TyConKind KiConData)- , do pTokAs KKindRegion (TCon $ TyConKind KiConRegion) - , do pTokAs KKindEffect (TCon $ TyConKind KiConEffect) - , do pTokAs KKindClosure (TCon $ TyConKind KiConClosure) - , do pTokAs KKindWitness (TCon $ TyConKind KiConWitness) - - -- Bottoms.- , do pTokAs KBotEffect (tBot kEffect)- , do pTokAs KBotClosure (tBot kClosure)- - -- Bound occurrence of a variable.- -- We don't know the kind of this variable yet, so fill in the- -- field with the bottom element of computation kinds. This isn't- -- really part of the language, but makes sense implentation-wise.- , do v <- pVar- return $ TVar (UName v (tBot sComp))-- , do i <- pIndex- return $ TVar (UIx (fromIntegral i) (tBot sComp))- ]- <?> "an atomic type"------------------------------------------------------------------------------------- | Parse a builtin `TcCon`-pTcCon :: Parser n TcCon-pTcCon = P.pTokMaybe f- <?> "a type constructor"- where f (KA (KTcConBuiltin c)) = Just c- f _ = Nothing ---- | Parse a builtin `TwCon`-pTwCon :: Parser n TwCon-pTwCon = P.pTokMaybe f- <?> "a witness constructor"- where f (KA (KTwConBuiltin c)) = Just c- f _ = Nothing---- | Parse a user `TcCon`-pTyConNamed :: Parser n (TyCon n)-pTyConNamed - = P.pTokMaybe f- <?> "a type constructor"- where f (KN (KCon n)) = Just (TyConBound (UName n (tBot kData)))- f _ = Nothing---- | Parse a variable.-pVar :: Parser n n-pVar = P.pTokMaybe f- <?> "a variable"- where f (KN (KVar n)) = Just n- f _ = Nothing---- | Parse a deBruijn index-pIndex :: Parser n Int-pIndex = P.pTokMaybe f- <?> "an index"- where f (KA (KIndex i)) = Just i- f _ = Nothing---- | Parse an atomic token.-pTok :: TokAtom -> Parser n ()-pTok k = P.pTok (KA k)----- | Parse an atomic token and return some value.-pTokAs :: TokAtom -> a -> Parser n a-pTokAs k x = P.pTokAs (KA k) x-
DDC/Type/Predicates.hs view
@@ -1,21 +1,71 @@ -- | Predicates on type expressions. module DDC.Type.Predicates- ( isBot+ ( -- * Binders+ isBNone+ , isBAnon+ , isBName++ -- * Atoms+ , isTVar+ , isBot , isAtomT++ -- * Kinds , isDataKind , isRegionKind , isEffectKind , isClosureKind , isWitnessKind- , isAlgDataType)++ -- * Data Types+ , isAlgDataType+ , isWitnessType+ , isConstWitType+ , isMutableWitType+ , isDistinctWitType++ -- * Effect Types+ , isReadEffect+ , isWriteEffect+ , isAllocEffect+ , isSomeReadEffect+ , isSomeWriteEffect+ , isSomeAllocEffect) where import DDC.Type.Exp import DDC.Type.Compounds import qualified DDC.Type.Sum as T +-- Binders --------------------------------------------------------------------+isBNone :: Bind n -> Bool+isBNone bb+ = case bb of+ BNone{} -> True+ _ -> False++isBAnon :: Bind n -> Bool+isBAnon bb+ = case bb of+ BAnon{} -> True+ _ -> False++isBName :: Bind n -> Bool+isBName bb+ = case bb of+ BName{} -> True+ _ -> False++ -- Atoms ----------------------------------------------------------------------+-- | Check whether a type is a `TVar`+isTVar :: Type n -> Bool+isTVar tt+ = case tt of+ TVar{} -> True+ _ -> False+ -- | Test if some type is an empty TSum isBot :: Type n -> Bool isBot tt@@ -82,17 +132,114 @@ -- It needs to have an explicit data constructor out the front, -- and not a type variable. The constructor must not be the function -- constructor, and must return a value of kind '*'.---- Algebraic data types are all built from constructors--- that have '*' as their result kind.--- The function constructor (->) also has this result kind,--- but it is in `TyConComp`, so is easy to ignore.+---+-- The function constructor (->) also has this result kind,+-- but it is in `TyConComp`, so is easy to ignore. isAlgDataType :: Eq n => Type n -> Bool isAlgDataType tt- | Just (tc, _) <- takeTyConApps tt- , TyConBound u <- tc- = takeResultKind (typeOfBound u) == kData+ | Just (tc, _) <- takeTyConApps tt+ , TyConBound _ k <- tc+ = takeResultKind k == kData | otherwise = False++-- | Check whether type is a witness constructor+isWitnessType :: Eq n => Type n -> Bool+isWitnessType tt+ = case takeTyConApps tt of+ Just (TyConWitness _, _) -> True+ _ -> False+ ++-- | Check whether this is the type of a @Const@ witness.+isConstWitType :: Eq n => Type n -> Bool+isConstWitType tt+ = case takeTyConApps tt of+ Just (TyConWitness TwConConst, _) -> True+ _ -> False+++-- | Check whether this is the type of a @Mutable@ witness.+isMutableWitType :: Eq n => Type n -> Bool+isMutableWitType tt+ = case takeTyConApps tt of+ Just (TyConWitness TwConMutable, _) -> True+ _ -> False+++-- | Check whether this is the type of a @Distinct@ witness.+isDistinctWitType :: Eq n => Type n -> Bool+isDistinctWitType tt+ = case takeTyConApps tt of+ Just (TyConWitness (TwConDistinct _), _) -> True+ _ -> False+ ++-- Effects --------------------------------------------------------------------+-- | Check whether this is an atomic read effect.+isReadEffect :: Effect n -> Bool+isReadEffect eff+ = case eff of+ TApp (TCon (TyConSpec TcConRead)) _ -> True+ _ -> False+++-- | Check whether this is an atomic write effect.+isWriteEffect :: Effect n -> Bool+isWriteEffect eff+ = case eff of+ TApp (TCon (TyConSpec TcConWrite)) _ -> True+ _ -> False+++-- | Check whether this is an atomic alloc effect.+isAllocEffect :: Effect n -> Bool+isAllocEffect eff+ = case eff of+ TApp (TCon (TyConSpec TcConAlloc)) _ -> True+ _ -> False+++-- | Check whether an effect is some sort of read effect.+-- Matches @Read@ @HeadRead@ and @DeepRead@.+isSomeReadEffect :: Effect n -> Bool+isSomeReadEffect tt+ = case tt of+ TApp (TCon (TyConSpec con)) _+ -> case con of+ TcConRead -> True+ TcConHeadRead -> True+ TcConDeepRead -> True+ _ -> False++ _ -> False+++-- | Check whether an effect is some sort of allocation effect.+-- Matches @Alloc@ and @DeepAlloc@+isSomeWriteEffect :: Effect n -> Bool+isSomeWriteEffect tt+ = case tt of+ TApp (TCon (TyConSpec con)) _+ -> case con of+ TcConWrite -> True+ TcConDeepWrite -> True+ _ -> False++ _ -> False+++-- | Check whether an effect is some sort of allocation effect.+-- Matches @Alloc@ and @DeepAlloc@+isSomeAllocEffect :: Effect n -> Bool+isSomeAllocEffect tt+ = case tt of+ TApp (TCon (TyConSpec con)) _+ -> case con of+ TcConAlloc -> True+ TcConDeepAlloc -> True+ _ -> False++ _ -> False
DDC/Type/Pretty.hs view
@@ -49,13 +49,9 @@ instance (Pretty n, Eq n) => Pretty (Bound n) where ppr nn = case nn of--- UName n t -> parens (ppr n <> text ":" <> ppr t)- UName n _ -> ppr n--- UPrim n _ -> ppr n--- UIx i t -> parens (text "^" <> ppr i <> text ":" <> ppr t)- UIx i _ -> text "^" <> ppr i+ UName n -> ppr n+ UPrim n _ -> ppr n+ UIx i -> text "^" <> ppr i -- Type -----------------------------------------------------------------------@@ -127,7 +123,7 @@ TyConKind kc -> ppr kc TyConWitness tc -> ppr tc TyConSpec tc -> ppr tc- TyConBound u -> ppr u+ TyConBound u _ -> ppr u instance Pretty SoCon where@@ -160,14 +156,17 @@ TwConDeepConst -> text "DeepConst" TwConMutable -> text "Mutable" TwConDeepMutable-> text "DeepMutable"+ TwConDistinct n -> text "Distinct" <> ppr n TwConLazy -> text "Lazy" TwConHeadLazy -> text "HeadLazy" TwConManifest -> text "Manifest"+ TwConDisjoint -> text "Disjoint" instance Pretty TcCon where ppr tc = case tc of+ TcConUnit -> text "Unit" TcConFun -> text "(->)" TcConRead -> text "Read" TcConHeadRead -> text "HeadRead"
− DDC/Type/Rewrite.hs
@@ -1,264 +0,0 @@---- | Rewriting of variable binders to anonymous form to avoid capture.-module DDC.Type.Rewrite- ( Rewrite(..)- , Sub(..)- , BindStack(..)- , pushBind- , pushBinds- , substBound-- , bind1, bind0, bind0s- , use1, use0)-where-import DDC.Core.Exp-import DDC.Type.Compounds-import Data.List-import Data.Set (Set)-import qualified DDC.Type.Sum as Sum-import qualified Data.Set as Set----- | Substitution state.--- Keeps track of the binders in the environment that have been rewrittten--- to avoid variable capture or spec binder shadowing.-data Sub n- = Sub- { -- | Bound variable that we're substituting for.- subBound :: Bound n-- -- | We've decended past a binder that shadows the one that we're- -- substituting for. We're no longer substituting, but still may- -- need to anonymise variables in types. - -- This can only happen for level-0 named binders.- , subShadow0 :: Bool -- -- | Level-1 names that need to be rewritten to avoid capture.- , subConflict1 :: Set n-- -- | Level-0 names that need to be rewritten to avoid capture.- , subConflict0 :: Set n -- -- | Rewriting stack for level-1 names.- , subStack1 :: BindStack n-- -- | Rewriting stack for level-0 names.- , subStack0 :: BindStack n }----- | Stack of anonymous binders that we've entered under during substitution. -data BindStack n- = BindStack- { -- | Holds anonymous binders that were already in the program,- -- as well as named binders that are being rewritten to anonymous ones.- -- In the resulting expression all these binders will be anonymous.- stackBinds :: [Bind n]-- -- | Holds all binders, independent of whether they are being rewritten or not.- , stackAll :: [Bind n] -- -- | Number of `BAnon` in `stackBinds`.- , stackAnons :: Int-- -- | Number of `BName` in `stackBinds`.- , stackNamed :: Int }----- | Push several binds onto the bind stack,--- anonymyzing them if need be to avoid variable capture.-pushBinds :: Ord n => Set n -> BindStack n -> [Bind n] -> (BindStack n, [Bind n])-pushBinds fns stack bs- = mapAccumL (pushBind fns) stack bs----- | Push a bind onto a bind stack, --- anonymizing it if need be to avoid variable capture.-pushBind- :: Ord n- => Set n -- ^ Names that need to be rewritten.- -> BindStack n -- ^ Current bind stack.- -> Bind n -- ^ Bind to push.- -> (BindStack n, Bind n) -- ^ New stack and possibly anonymised bind.--pushBind fns bs@(BindStack stack env dAnon dName) bb- = case bb of- -- Push already anonymous bind on stack.- BAnon t - -> ( BindStack (BAnon t : stack) (BAnon t : env) (dAnon + 1) dName- , BAnon t)- - -- If the binder needs to be rewritten then push the original name on the- -- 'stackBinds' to remember this.- BName n t- | Set.member n fns - -> ( BindStack (BName n t : stack) (BAnon t : env) dAnon (dName + 1)- , BAnon t)-- | otherwise- -> ( BindStack stack (BName n t : env) dAnon dName- , bb)-- -- Binder was a wildcard.- _ -> (bs, bb)------ | Compare a `Bound` against the one we're substituting for.-substBound- :: Ord n- => BindStack n -- ^ Current Bind stack during substitution.- -> Bound n -- ^ Bound we're substituting for.- -> Bound n -- ^ Bound we're looking at now.- -> Either - (Bound n) -- Bound doesn't match, but replace with this one.- Int -- Bound matches, drop the thing being substituted and - -- and lift indices this many steps.--substBound (BindStack binds _ dAnon dName) u u'- -- Bound name matches the one that we're substituting for.- | UName n1 _ <- u- , UName n2 _ <- u'- , n1 == n2- = Right (dAnon + dName)-- -- Bound index matches the one that we're substituting for.- | UIx i1 _ <- u- , UIx i2 _ <- u'- , i1 + dAnon == i2 - = Right (dAnon + dName)-- -- The Bind for this name was rewritten to avoid variable capture,- -- so we also have to update the bound occurrence.- | UName _ t <- u'- , Just ix <- findIndex (boundMatchesBind u') binds- = Left $ UIx ix t-- -- Bound index doesn't match, but lower this index by one to account- -- for the removal of the outer binder.- | UIx i2 t <- u'- , i2 > dAnon- , cutOffset <- case u of- UIx{} -> 1- _ -> 0- = Left $ UIx (i2 + dName - cutOffset) t-- -- Some name that didn't match.- | otherwise- = Left u'------------------------------------------------------------------------------------- | Push a level-1 binder on the rewrite stack.-bind1 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)-bind1 sub b - = let (stackT', b') = pushBind (subConflict1 sub) (subStack1 sub) b- in (sub { subStack1 = stackT' }, b')----- | Push a level-0 binder on the rewrite stack.-bind0 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)-bind0 sub b - = let b1 = rewriteWith sub b- (stackX', b2) = pushBind (subConflict0 sub) (subStack0 sub) b1- in ( sub { subStack0 = stackX'- , subShadow0 = subShadow0 sub - || namedBoundMatchesBind (subBound sub) b2 }- , b2)----- | Push some level-0 binders on the rewrite stack.-bind0s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])-bind0s = mapAccumL bind0----- | Rewrite a use of a level-1 binder if need be.-use1 :: Ord n => Sub n -> Bound n -> Bound n-use1 sub u- | UName _ t <- u- , BindStack binds _ _ _ <- subStack1 sub- , Just ix <- findIndex (boundMatchesBind u) binds- = UIx ix t-- | otherwise- = u----- | Rewrite the use of a level-0 binder if need be.-use0 :: Ord n => Sub n -> Bound n -> Bound n-use0 sub u- | UName _ t <- u- , BindStack binds _ _ _ <- subStack0 sub- , Just ix <- findIndex (boundMatchesBind u) binds- = UIx ix (rewriteWith sub t)-- | otherwise- = rewriteWith sub u-----------------------------------------------------------------------------------class Rewrite (c :: * -> *) where- -- | Rewrite names in some thing to anonymous form if they conflict with--- any names in the `Sub` state.- rewriteWith :: Ord n => Sub n -> c n -> c n ---instance Rewrite Bind where- rewriteWith sub bb- = replaceTypeOfBind (rewriteWith sub (typeOfBind bb)) bb---instance Rewrite Bound where- rewriteWith sub uu- = replaceTypeOfBound (rewriteWith sub (typeOfBound uu)) uu---instance Rewrite LetMode where- rewriteWith sub lm- = case lm of- LetStrict -> lm- LetLazy (Just t) -> LetLazy (Just $ rewriteWith sub t) - LetLazy Nothing -> LetLazy Nothing---instance Rewrite Cast where- rewriteWith sub cc- = let down = rewriteWith sub - in case cc of- CastWeakenEffect eff -> CastWeakenEffect (down eff)- CastWeakenClosure clo -> CastWeakenClosure (down clo)- CastPurify w -> CastPurify (down w)- CastForget w -> CastForget (down w)---instance Rewrite Type where- rewriteWith sub tt - = let down = rewriteWith - in case tt of- TVar u -> TVar (use1 sub u)- TCon{} -> tt-- TForall b t- -> let (sub1, b') = bind1 sub b- t' = down sub1 t- in TForall b' t'-- TApp t1 t2 -> TApp (down sub t1) (down sub t2)- TSum ts -> TSum (down sub ts)---instance Rewrite TypeSum where- rewriteWith sub ts- = Sum.fromList (Sum.kindOfSum ts)- $ map (rewriteWith sub)- $ Sum.toList ts---instance Rewrite Witness where- rewriteWith sub ww- = let down = rewriteWith - in case ww of- WVar u -> WVar (use0 sub u)- WCon{} -> ww- WApp w1 w2 -> WApp (down sub w1) (down sub w2)- WJoin w1 w2 -> WJoin (down sub w1) (down sub w2)- WType t -> WType (down sub t)
DDC/Type/Sum.hs view
@@ -2,32 +2,48 @@ -- | Utilities for working with `TypeSum`s. -- module DDC.Type.Sum - ( empty+ ( -- * Constructors+ empty , singleton- , elem- , insert- , delete , union , unions- , difference+ , insert++ -- * Conversion+ , toList+ , fromList++ -- * Projection , kindOfSum- , toList, fromList- , hashTyCon, hashTyConRange- , unhashTyCon- , takeSumArrayElem- , makeSumArrayElem)+ , elem++ -- * Deletion+ , delete+ , difference++ -- * Hashing+ , hashTyCon+ , hashTyConRange+ , unhashTyCon) where import DDC.Type.Exp import Data.Array-import qualified Data.List as L-import qualified Data.Map as Map-import qualified Data.Set as Set-import Prelude hiding (elem)+import qualified Data.List as L+import qualified Data.Map.Strict as Map+import qualified Data.Set as Set+import Prelude hiding (elem) -- | Construct an empty type sum of the given kind. empty :: Kind n -> TypeSum n-empty k = TypeSum+empty k = TypeSumBot k+++-- | Construct an empty type sum of the given kind, but in `TypeSumSet` form.+-- This isn't exported.+emptySet :: Kind n -> TypeSum n+emptySet k + = TypeSumSet { typeSumKind = k , typeSumElems = listArray hashTyConRange (repeat Set.empty) , typeSumBoundNamed = Map.empty@@ -50,11 +66,12 @@ -- * May return False if the first argument is miskinded but still -- alpha-equivalent to some component of the sum. elem :: (Eq n, Ord n) => Type n -> TypeSum n -> Bool-elem t ts +elem _ TypeSumBot{} = False+elem t ts@TypeSumSet{} = case t of- TVar (UName n _) -> Map.member n (typeSumBoundNamed ts)+ TVar (UName n) -> Map.member n (typeSumBoundNamed ts)+ TVar (UIx i) -> Map.member i (typeSumBoundAnon ts) TVar (UPrim n _) -> Map.member n (typeSumBoundNamed ts)- TVar (UIx i _) -> Map.member i (typeSumBoundAnon ts) TCon{} -> L.elem t (typeSumSpill ts) -- Foralls can't be a part of well-kinded sums.@@ -86,17 +103,19 @@ -- | Insert a new element into a sum. insert :: Ord n => Type n -> TypeSum n -> TypeSum n-insert t ts- = case t of- TVar (UName n k) -> ts { typeSumBoundNamed = Map.insert n k (typeSumBoundNamed ts) }- TVar (UPrim n k) -> ts { typeSumBoundNamed = Map.insert n k (typeSumBoundNamed ts) }- TVar (UIx i k) -> ts { typeSumBoundAnon = Map.insert i k (typeSumBoundAnon ts) }- TCon{} -> ts { typeSumSpill = t : typeSumSpill ts }+insert t (TypeSumBot k) = insert t (emptySet k)+insert t ts@TypeSumSet{}+ = let k = typeSumKind ts+ in case t of+ TVar (UName n) -> ts { typeSumBoundNamed = Map.insert n k (typeSumBoundNamed ts) }+ TVar (UIx i) -> ts { typeSumBoundAnon = Map.insert i k (typeSumBoundAnon ts) }+ TVar (UPrim n _)-> ts { typeSumBoundNamed = Map.insert n k (typeSumBoundNamed ts) }+ TCon{} -> ts { typeSumSpill = L.nub $ t : typeSumSpill ts } -- Foralls can't be part of well-kinded sums. -- Just add them to the splill lists so that we can still -- pretty print such mis-kinded types.- TForall{} -> ts { typeSumSpill = t : typeSumSpill ts }+ TForall{} -> ts { typeSumSpill = L.nub $ t : typeSumSpill ts } TApp (TCon _) _ | Just (h, vc) <- takeSumArrayElem t@@ -105,20 +124,21 @@ then ts else ts { typeSumElems = (typeSumElems ts) // [(h, Set.insert vc tsThere)] } - TApp{} -> ts { typeSumSpill = t : typeSumSpill ts }+ TApp{} -> ts { typeSumSpill = L.nub $ t : typeSumSpill ts } TSum ts' -> foldr insert ts (toList ts') -- | Delete an element from a sum. delete :: Ord n => Type n -> TypeSum n -> TypeSum n-delete t ts+delete _ ts@TypeSumBot{} = ts+delete t ts@TypeSumSet{} = case t of- TVar (UName n _) -> ts { typeSumBoundNamed = Map.delete n (typeSumBoundNamed ts) }- TVar (UPrim n _) -> ts { typeSumBoundNamed = Map.delete n (typeSumBoundNamed ts) }- TVar (UIx i _) -> ts { typeSumBoundAnon = Map.delete i (typeSumBoundAnon ts) }- TCon{} -> ts { typeSumSpill = L.delete t (typeSumSpill ts) }- TForall{} -> ts { typeSumSpill = L.delete t (typeSumSpill ts) }+ TVar (UName n) -> ts { typeSumBoundNamed = Map.delete n (typeSumBoundNamed ts) }+ TVar (UIx i) -> ts { typeSumBoundAnon = Map.delete i (typeSumBoundAnon ts) }+ TVar (UPrim n _)-> ts { typeSumBoundNamed = Map.delete n (typeSumBoundNamed ts) }+ TCon{} -> ts { typeSumSpill = L.delete t (typeSumSpill ts) }+ TForall{} -> ts { typeSumSpill = L.delete t (typeSumSpill ts) } TApp (TCon _) _ | Just (h, vc) <- takeSumArrayElem t@@ -157,7 +177,10 @@ -- | Flatten out a sum, yielding a list of individual terms. toList :: TypeSum n -> [Type n]-toList TypeSum+toList TypeSumBot{} + = []++toList TypeSumSet { typeSumKind = _kind , typeSumElems = sumElems , typeSumBoundNamed = named@@ -166,8 +189,8 @@ = [ makeSumArrayElem h vc | (h, ts) <- assocs sumElems, vc <- Set.toList ts] - ++ [TVar $ UName n k | (n, k) <- Map.toList named]- ++ [TVar $ UIx i k | (i, k) <- Map.toList anon]+ ++ [TVar $ UName n | (n, _) <- Map.toList named]+ ++ [TVar $ UIx i | (i, _) <- Map.toList anon] ++ spill @@ -231,7 +254,7 @@ | Just h <- hashTyCon tc = case t2 of TVar u -> Just (h, TypeSumVar u)- TCon (TyConBound u) -> Just (h, TypeSumCon u)+ TCon (TyConBound u k) -> Just (h, TypeSumCon u k) _ -> Nothing takeSumArrayElem _ = Nothing@@ -243,7 +266,7 @@ = let tc = unhashTyCon h in case vc of TypeSumVar u -> TApp (TCon tc) (TVar u)- TypeSumCon u -> TApp (TCon tc) (TCon (TyConBound u))+ TypeSumCon u k -> TApp (TCon tc) (TCon (TyConBound u k)) -- Type Equality --------------------------------------------------------------@@ -268,6 +291,7 @@ -- Unwrap single element sums into plain types. where normalise (TSum ts) | [t'] <- toList ts = t'+ | [] <- toList ts = TSum $ empty (typeSumKind ts) normalise t' = t' @@ -280,25 +304,47 @@ , [] <- toList ts2 = typeSumKind ts1 == typeSumKind ts2 - -- If the sum has elements, then compare them directly and ignore the+ | TypeSumBot{} <- normalise ts1+ , TypeSumBot{} <- normalise ts2+ = typeSumKind ts1 == typeSumKind ts2++ -- If both sums have elements, then compare them directly and ignore the -- kind. This allows us to use (tBot sComp) as the typeSumKind field -- when we want to compute the real kind based on the elements. - | otherwise+ | TypeSumSet{} <- ts1+ , TypeSumSet{} <- ts2 = typeSumElems ts1 == typeSumElems ts2 && typeSumBoundNamed ts1 == typeSumBoundNamed ts2 && typeSumBoundAnon ts1 == typeSumBoundAnon ts2 && typeSumSpill ts1 == typeSumSpill ts2 + -- One is a set and one is bottom, so they are not equal.+ | otherwise+ = False + where normalise ts+ | [] <- toList ts = empty (typeSumKind ts)+ normalise ts = ts++ instance Ord n => Ord (Bound n) where- compare (UName n1 _) (UName n2 _) = compare n1 n2- compare (UIx i1 _) (UIx i2 _) = compare i1 i2- compare (UPrim n1 _) (UPrim n2 _) = compare n1 n2- compare (UIx _ _) _ = LT- compare (UName _ _) (UIx _ _) = GT- compare (UName _ _) (UPrim _ _) = LT- compare (UPrim _ _) _ = GT+ compare (UName n1) (UName n2) = compare n1 n2+ compare (UIx i1) (UIx i2) = compare i1 i2+ compare (UPrim n1 _) (UPrim n2 _) = compare n1 n2+ compare UIx{} _ = LT+ compare UName{} UIx{} = GT+ compare UName{} UPrim{} = LT+ compare UPrim{} _ = GT -deriving instance Eq n => Eq (TypeSumVarCon n)-deriving instance Ord n => Ord (TypeSumVarCon n)++instance Eq n => Eq (TypeSumVarCon n) where+ (==) (TypeSumVar u1) (TypeSumVar u2) = u1 == u2+ (==) (TypeSumCon u1 _) (TypeSumCon u2 _) = u1 == u2+ (==) _ _ = False++instance Ord n => Ord (TypeSumVarCon n) where+ compare (TypeSumVar u1) (TypeSumVar u2) = compare u1 u2+ compare (TypeSumCon u1 _) (TypeSumCon u2 _) = compare u1 u2+ compare (TypeSumVar _) _ = LT+ compare (TypeSumCon _ _) _ = GT
DDC/Type/Transform/Crush.hs view
@@ -1,12 +1,41 @@ module DDC.Type.Transform.Crush- (crushEffect)+ ( crushSomeT+ , crushEffect ) where import DDC.Type.Predicates import DDC.Type.Compounds+import DDC.Type.Transform.Trim import DDC.Type.Exp import qualified DDC.Type.Sum as Sum+import Data.Maybe +-- | Crush compound effects and closure terms.+-- We check for a crushable term before calling crushT because that function+-- will recursively crush the components. +-- As equivT is already recursive, we don't want a doubly-recursive function+-- that tries to re-crush the same non-crushable type over and over.+--+crushSomeT :: Ord n => Type n -> Type n+crushSomeT tt+ = {-# SCC crushSomeT #-}+ case tt of+ (TApp (TCon tc) _)+ -> case tc of+ TyConSpec TcConDeepRead -> crushEffect tt+ TyConSpec TcConDeepWrite -> crushEffect tt+ TyConSpec TcConDeepAlloc -> crushEffect tt++ -- If a closure is miskinded then 'trimClosure' + -- can return Nothing, so we just leave the term untrimmed.+ TyConSpec TcConDeepUse -> fromMaybe tt (trimClosure tt)++ TyConWitness TwConDeepGlobal -> crushEffect tt+ _ -> tt++ _ -> tt++ -- | Crush compound effect terms into their components. -- -- This is like `trimClosure` but for effects instead of closures.@@ -15,7 +44,8 @@ -- crushEffect :: Ord n => Effect n -> Effect n crushEffect tt- = case tt of+ = {-# SCC crushEffect #-}+ case tt of TVar{} -> tt TCon{} -> tt TForall b t@@ -33,14 +63,15 @@ -> case takeTyConApps t of -- Type has a head region.- Just (TyConBound u, (tR : _)) - | (k1 : _, _) <- takeKFuns (typeOfBound u)+ Just (TyConBound _ k, (tR : _)) + | (k1 : _, _) <- takeKFuns k , isRegionKind k1 -> tRead tR -- Type has no head region. -- This happens with case () of { ... }- Just (TyConBound _, []) -> tBot kEffect+ Just (TyConSpec TcConUnit, []) -> tBot kEffect+ Just (TyConBound _ _, []) -> tBot kEffect _ -> tt @@ -48,8 +79,8 @@ -- See Note: Crushing with higher kinded type vars. | Just (TyConSpec TcConDeepRead, [t]) <- takeTyConApps tt -> case takeTyConApps t of- Just (TyConBound u, ts)- | (ks, _) <- takeKFuns (typeOfBound u)+ Just (TyConBound _ k, ts)+ | (ks, _) <- takeKFuns k , length ks == length ts , Just effs <- sequence $ zipWith makeDeepRead ks ts -> crushEffect $ TSum $ Sum.fromList kEffect effs@@ -60,8 +91,8 @@ -- See Note: Crushing with higher kinded type vars. | Just (TyConSpec TcConDeepWrite, [t]) <- takeTyConApps tt -> case takeTyConApps t of- Just (TyConBound u, ts)- | (ks, _) <- takeKFuns (typeOfBound u)+ Just (TyConBound _ k, ts)+ | (ks, _) <- takeKFuns k , length ks == length ts , Just effs <- sequence $ zipWith makeDeepWrite ks ts -> crushEffect $ TSum $ Sum.fromList kEffect effs@@ -72,22 +103,24 @@ -- See Note: Crushing with higher kinded type vars. | Just (TyConSpec TcConDeepAlloc, [t]) <- takeTyConApps tt -> case takeTyConApps t of- Just (TyConBound u, ts)- | (ks, _) <- takeKFuns (typeOfBound u)+ Just (TyConBound _ k, ts)+ | (ks, _) <- takeKFuns k , length ks == length ts , Just effs <- sequence $ zipWith makeDeepAlloc ks ts -> crushEffect $ TSum $ Sum.fromList kEffect effs _ -> tt - -- TODO: we're hijacking crushEffect to work on witnesses as well.- -- we should split this into another function. -- Deep Global -- See Note: Crushing with higher kinded type vars.+ --+ -- NOTE: We're hijacking crushEffect to work on witnesses as well.+ -- It would be better to split this into another function.+ -- | Just (TyConWitness TwConDeepGlobal, [t]) <- takeTyConApps tt -> case takeTyConApps t of- Just (TyConBound u, ts)- | (ks, _) <- takeKFuns (typeOfBound u)+ Just (TyConBound _ k, ts)+ | (ks, _) <- takeKFuns k , length ks == length ts , Just props <- sequence $ zipWith makeDeepGlobal ks ts -> crushEffect $ TSum $ Sum.fromList kWitness props
DDC/Type/Transform/Instantiate.hs view
@@ -10,7 +10,12 @@ -- | Instantiate a type with an argument. -- The type to be instantiated must have an outer forall, else `Nothing`.-instantiateT :: (Ord n, Pretty n) => Type n -> Type n -> Maybe (Type n)+instantiateT + :: (Ord n, Pretty n) + => Type n -- ^ Type to instantiate.+ -> Type n -- ^ Argument type.+ -> Maybe (Type n)+ instantiateT (TForall b tBody) t2 = Just $ substituteT b t2 tBody instantiateT _ _ = Nothing @@ -18,7 +23,12 @@ -- | Instantiate a type with several arguments. -- The type to be instantiated must have at least as many outer foralls -- as provided type arguments, else `Nothing`.-instantiateTs :: (Ord n, Pretty n) => Type n -> [Type n] -> Maybe (Type n)+instantiateTs + :: (Ord n, Pretty n) + => Type n -- ^ Type to instantiate.+ -> [Type n] -- ^ Argument types.+ -> Maybe (Type n)+ instantiateTs t [] = Just t instantiateTs t (tArg:tsArgs) = case instantiateT t tArg of
DDC/Type/Transform/LiftT.hs view
@@ -1,63 +1,109 @@ -- | Lifting of deBruijn indices in a type.------- TODO: merge this code with LowerT module DDC.Type.Transform.LiftT- (LiftT(..))+ ( liftT, liftAtDepthT+ , lowerT, lowerAtDepthT+ , MapBoundT(..)) where import DDC.Type.Exp import DDC.Type.Compounds import qualified DDC.Type.Sum as Sum -class LiftT (c :: * -> *) where-- -- | Lift type indices that are at least a certain depth by the given number of levels.- liftAtDepthT - :: forall n. Ord n+-- Lift -----------------------------------------------------------------------+-- | Lift debruijn indices less than or equal to the given depth.+liftAtDepthT+ :: MapBoundT c n => Int -- ^ Number of levels to lift. -> Int -- ^ Current binding depth.- -> c n -- ^ Lift type indices in this thing.+ -> c n -- ^ Lift expression indices in this thing. -> c n- - -- | Wrapper for `liftAtDepthT` that starts at depth 0. - liftT :: forall n. Ord n- => Int -- ^ Number of levels to lift- -> c n -- ^ Lift type indices in this thing.++liftAtDepthT n d+ = mapBoundAtDepthT liftU d+ where + liftU d' u+ = case u of+ UName{} -> u+ UPrim{} -> u+ UIx i+ | d' <= i -> UIx (i + n)+ | otherwise -> u+++-- | Wrapper for `liftAtDepthX` that starts at depth 0. +liftT :: MapBoundT c n => Int -> c n -> c n+liftT n xx = liftAtDepthT n 0 xx+++-- Lower ----------------------------------------------------------------------+-- | Lower debruijn indices less than or equal to the given depth.+lowerAtDepthT+ :: MapBoundT c n+ => Int -- ^ Number of levels to lower.+ -> Int -- ^ Current binding depth.+ -> c n -- ^ Lower expression indices in this thing. -> c n- - liftT n xx = liftAtDepthT n 0 xx- -instance LiftT Bind where- liftAtDepthT n d bb- = replaceTypeOfBind (liftAtDepthT n d $ typeOfBind bb) bb- +lowerAtDepthT n d+ = mapBoundAtDepthT lowerU d+ where + lowerU d' u+ = case u of+ UName{} -> u+ UPrim{} -> u+ UIx i+ | d' <= i -> UIx (i - n)+ | otherwise -> u -instance LiftT Bound where- liftAtDepthT n d uu- = case uu of- UName{} -> uu- UPrim{} -> uu- UIx i t - | d <= i -> UIx (i + n) t- | otherwise -> uu- -instance LiftT Type where- liftAtDepthT n d tt- = let down = liftAtDepthT n+-- | Wrapper for `lowerAtDepthX` that starts at depth 0. +lowerT :: MapBoundT c n => Int -> c n -> c n+lowerT n xx = lowerAtDepthT n 0 xx+++-- MapBoundT ------------------------------------------------------------------+class MapBoundT (c :: * -> *) n where+ -- | Apply a function to all bound variables in the program.+ -- The function is passed the current binding depth.+ -- This is used to defined both `liftT` and `lowerT`.+ mapBoundAtDepthT+ :: (Int -> Bound n -> Bound n) + -- ^ Function to apply to the bound occ.+ -- It is passed the current binding depth.+ -> Int -- ^ Current binding depth.+ -> c n -- ^ Lift expression indices in this thing.+ -> c n+++instance Ord n => MapBoundT Bind n where+ mapBoundAtDepthT f d bb+ = replaceTypeOfBind (mapBoundAtDepthT f d $ typeOfBind bb) bb+++instance MapBoundT Bound n where+ mapBoundAtDepthT f d u+ = f d u+++instance Ord n => MapBoundT Type n where+ mapBoundAtDepthT f d tt+ = let down = mapBoundAtDepthT f d in case tt of- TVar u -> TVar (down d u)+ TVar u -> TVar (f d u) TCon{} -> tt- TForall b t -> TForall (down d b) (down (d + 1) t)- TApp t1 t2 -> TApp (down d t1) (down d t2)- TSum ss -> TSum (down d ss)+ TForall b t -> TForall b (mapBoundAtDepthT f (d + countBAnons [b]) t)+ TApp t1 t2 -> TApp (down t1) (down t2)+ TSum ss -> TSum (down ss) -instance LiftT TypeSum where- liftAtDepthT n d ss- = Sum.fromList (liftAtDepthT n d $ Sum.kindOfSum ss)- $ map (liftAtDepthT n d)+instance Ord n => MapBoundT TypeSum n where+ mapBoundAtDepthT f d ss+ = Sum.fromList (Sum.kindOfSum ss)+ $ map (mapBoundAtDepthT f d) $ Sum.toList ss++countBAnons = length . filter isAnon+ where isAnon (BAnon _) = True+ isAnon _ = False
− DDC/Type/Transform/LowerT.hs
@@ -1,63 +0,0 @@---- | Lowering of deBruijn indices in a type.------- TODO: merge this code with LiftT.-module DDC.Type.Transform.LowerT- (LowerT(..))-where-import DDC.Type.Exp-import DDC.Type.Compounds-import qualified DDC.Type.Sum as Sum---class LowerT (c :: * -> *) where-- -- | Lower type indices that are at least a certain depth by the given number of levels.- lowerAtDepthT - :: forall n. Ord n- => Int -- ^ Number of levels to lower.- -> Int -- ^ Current binding depth.- -> c n -- ^ Lower type indices in this thing.- -> c n- - -- | Wrapper for `lowerAtDepthT` that starts at depth 0. - lowerT :: forall n. Ord n- => Int -- ^ Number of levels to lower.- -> c n -- ^ Lower type indices in this thing.- -> c n- - lowerT n xx = lowerAtDepthT n 0 xx- --instance LowerT Bind where- lowerAtDepthT n d bb- = replaceTypeOfBind (lowerAtDepthT n d $ typeOfBind bb) bb- --instance LowerT Bound where- lowerAtDepthT n d uu- = case uu of- UName{} -> uu- UPrim{} -> uu- UIx i t - | d <= i -> UIx (i - n) t- | otherwise -> uu- --instance LowerT Type where- lowerAtDepthT n d tt- = let down = lowerAtDepthT n - in case tt of- TVar uu -> TVar (down d uu)- TCon{} -> tt- TForall b t -> TForall (down d b) (down (d + 1) t)- TApp t1 t2 -> TApp (down d t1) (down d t2)- TSum ss -> TSum (down d ss)---instance LowerT TypeSum where- lowerAtDepthT n d ss- = Sum.fromList (lowerAtDepthT n d $ Sum.kindOfSum ss)- $ map (lowerAtDepthT n d)- $ Sum.toList ss-
+ DDC/Type/Transform/Rename.hs view
@@ -0,0 +1,246 @@++-- | Renaming of variable binders to anonymous form to avoid capture.+module DDC.Type.Transform.Rename+ ( Rename(..)++ -- * Substitution states+ , Sub(..)++ -- * Binding stacks+ , BindStack(..)+ , pushBind+ , pushBinds+ , substBound++ -- * Rewriting binding occurences+ , bind1, bind1s, bind0, bind0s++ -- * Rewriting bound occurences+ , use1, use0)+where+import DDC.Type.Compounds+import DDC.Type.Exp+import Data.List+import Data.Set (Set)+import qualified DDC.Type.Sum as Sum+import qualified Data.Set as Set+++-------------------------------------------------------------------------------+class Rename (c :: * -> *) where+ -- | Rewrite names in some thing to anonymous form if they conflict with+-- any names in the `Sub` state. We use this to avoid variable capture+-- during substitution.+ renameWith :: Ord n => Sub n -> c n -> c n +++instance Rename Type where+ renameWith sub tt + = {-# SCC renameWith #-}+ let down = renameWith + in case tt of+ TVar u -> TVar (use1 sub u)+ TCon{} -> tt++ TForall b t+ -> let (sub1, b') = bind1 sub b+ t' = down sub1 t+ in TForall b' t'++ TApp t1 t2 -> TApp (down sub t1) (down sub t2)+ TSum ts -> TSum (down sub ts)+++instance Rename TypeSum where+ renameWith sub ts+ = Sum.fromList (Sum.kindOfSum ts)+ $ map (renameWith sub)+ $ Sum.toList ts+++instance Rename Bind where+ renameWith sub bb+ = replaceTypeOfBind (renameWith sub (typeOfBind bb)) bb+++-------------------------------------------------------------------------------+-- | Substitution state.+-- Keeps track of the binders in the environment that have been rewrittten+-- to avoid variable capture or spec binder shadowing.+data Sub n+ = Sub+ { -- | Bound variable that we're substituting for.+ subBound :: !(Bound n)++ -- | We've decended past a binder that shadows the one that we're+ -- substituting for. We're no longer substituting, but still may+ -- need to anonymise variables in types. + -- This can only happen for level-0 named binders.+ , subShadow0 :: !Bool ++ -- | Level-1 names that need to be rewritten to avoid capture.+ , subConflict1 :: !(Set n)++ -- | Level-0 names that need to be rewritten to avoid capture.+ , subConflict0 :: !(Set n)++ -- | Rewriting stack for level-1 names.+ , subStack1 :: !(BindStack n)++ -- | Rewriting stack for level-0 names.+ , subStack0 :: !(BindStack n) }+++-- | Stack of anonymous binders that we've entered under during substitution. +data BindStack n+ = BindStack+ { -- | Holds anonymous binders that were already in the program,+ -- as well as named binders that are being rewritten to anonymous ones.+ -- In the resulting expression all these binders will be anonymous.+ stackBinds :: ![Bind n]++ -- | Holds all binders, independent of whether they are being rewritten or not.+ , stackAll :: ![Bind n] ++ -- | Number of `BAnon` in `stackBinds`.+ , stackAnons :: !Int++ -- | Number of `BName` in `stackBinds`.+ , stackNamed :: !Int }+++-- | Push several binds onto the bind stack,+-- anonymyzing them if need be to avoid variable capture.+pushBinds :: Ord n => Set n -> BindStack n -> [Bind n] -> (BindStack n, [Bind n])+pushBinds fns stack bs+ = mapAccumL (pushBind fns) stack bs+++-- | Push a bind onto a bind stack, +-- anonymizing it if need be to avoid variable capture.+pushBind+ :: Ord n+ => Set n -- ^ Names that need to be rewritten.+ -> BindStack n -- ^ Current bind stack.+ -> Bind n -- ^ Bind to push.+ -> (BindStack n, Bind n) -- ^ New stack and possibly anonymised bind.++pushBind fns bs@(BindStack stack env dAnon dName) bb+ = case bb of+ -- Push already anonymous bind on stack.+ BAnon t + -> ( BindStack (BAnon t : stack) (BAnon t : env) (dAnon + 1) dName+ , BAnon t)+ + -- If the binder needs to be rewritten then push the original name on the+ -- 'stackBinds' to remember this.+ BName n t+ | Set.member n fns + -> ( BindStack (BName n t : stack) (BAnon t : env) dAnon (dName + 1)+ , BAnon t)++ | otherwise+ -> ( BindStack stack (BName n t : env) dAnon dName+ , bb)++ -- Binder was a wildcard.+ _ -> (bs, bb)++++-- | Compare a `Bound` against the one we're substituting for.+substBound+ :: Ord n+ => BindStack n -- ^ Current Bind stack during substitution.+ -> Bound n -- ^ Bound we're substituting for.+ -> Bound n -- ^ Bound we're looking at now.+ -> Either + (Bound n) -- Bound doesn't match, but replace with this one.+ Int -- Bound matches, drop the thing being substituted and + -- and lift indices this many steps.++substBound (BindStack binds _ dAnon dName) u u'+ -- Bound name matches the one that we're substituting for.+ | UName n1 <- u+ , UName n2 <- u'+ , n1 == n2+ = Right (dAnon + dName)++ -- Bound index matches the one that we're substituting for.+ | UIx i1 <- u+ , UIx i2 <- u'+ , i1 + dAnon == i2 + = Right (dAnon + dName)++ -- The Bind for this name was rewritten to avoid variable capture,+ -- so we also have to update the bound occurrence.+ | UName _ <- u'+ , Just ix <- findIndex (boundMatchesBind u') binds+ = Left $ UIx ix++ -- Bound index doesn't match, but lower this index by one to account+ -- for the removal of the outer binder.+ | UIx i2 <- u'+ , i2 > dAnon+ , cutOffset <- case u of+ UIx{} -> 1+ _ -> 0+ = Left $ UIx (i2 + dName - cutOffset)++ -- Some name that didn't match.+ | otherwise+ = Left u'+++-------------------------------------------------------------------------------+-- | Push a level-1 binder on the rewrite stack.+bind1 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)+bind1 sub b + = let (stackT', b') = pushBind (subConflict1 sub) (subStack1 sub) b+ in (sub { subStack1 = stackT' }, b')+++-- | Push some level-1 binders on the rewrite stack.+bind1s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])+bind1s = mapAccumL bind1+++-- | Push a level-0 binder on the rewrite stack.+bind0 :: Ord n => Sub n -> Bind n -> (Sub n, Bind n)+bind0 sub b + = let b1 = renameWith sub b+ (stackX', b2) = pushBind (subConflict0 sub) (subStack0 sub) b1+ in ( sub { subStack0 = stackX'+ , subShadow0 = subShadow0 sub + || namedBoundMatchesBind (subBound sub) b2 }+ , b2)+++-- | Push some level-0 binders on the rewrite stack.+bind0s :: Ord n => Sub n -> [Bind n] -> (Sub n, [Bind n])+bind0s = mapAccumL bind0+++-- | Rewrite the use of a level-1 binder if need be.+use1 :: Ord n => Sub n -> Bound n -> Bound n+use1 sub u+ | UName _ <- u+ , BindStack binds _ _ _ <- subStack1 sub+ , Just ix <- findIndex (boundMatchesBind u) binds+ = UIx ix++ | otherwise+ = u+++-- | Rewrite the use of a level-0 binder if need be.+use0 :: Ord n => Sub n -> Bound n -> Bound n+use0 sub u+ | UName _ <- u+ , BindStack binds _ _ _ <- subStack0 sub+ , Just ix <- findIndex (boundMatchesBind u) binds+ = UIx ix++ | otherwise+ = u+
DDC/Type/Transform/SpreadT.hs view
@@ -3,17 +3,19 @@ (SpreadT(..)) where import DDC.Type.Exp-import DDC.Type.Env (Env)+import DDC.Type.Env (TypeEnv) import qualified DDC.Type.Env as Env import qualified DDC.Type.Sum as T class SpreadT (c :: * -> *) where - -- | Spread type annotations from variable binders in to the bound- -- occurrences.+ -- | Rewrite `UName` bounds to `UPrim` bounds and attach their types.+ -- Primitives have their types attached because they are so common in the+ -- language, their types are closed, and we don't want to keep having to+ -- look them up from the environment. spreadT :: forall n. Ord n - => Env n -> c n -> c n+ => TypeEnv n -> c n -> c n instance SpreadT Type where@@ -47,21 +49,23 @@ instance SpreadT Bound where spreadT kenv uu- | Just t' <- Env.lookup uu kenv = case uu of- UIx ix _ -> UIx ix t'- UPrim n _ -> UPrim n t'- UName n _- -> if Env.isPrim kenv n - then UPrim n t'- else UName n t'- - | otherwise = uu+ UIx{} -> uu+ UPrim{} -> uu + UName n+ -> case Env.envPrimFun kenv n of+ Nothing -> UName n+ Just t -> UPrim n t+ instance SpreadT TyCon where spreadT kenv tc = case tc of- TyConBound u -> TyConBound (spreadT kenv u)+ TyConBound (UName n) _+ -> case Env.envPrimFun kenv n of+ Nothing -> tc+ Just t -> TyConBound (UPrim n t) t+ _ -> tc
DDC/Type/Transform/SubstituteT.hs view
@@ -1,23 +1,23 @@ -- | Capture avoiding substitution of types in types. module DDC.Type.Transform.SubstituteT- ( SubstituteT(..)- , substituteT+ ( substituteT , substituteTs , substituteBoundT+ , SubstituteT(..) , BindStack(..) , pushBind , pushBinds , substBound) where-import DDC.Type.Exp+import DDC.Type.Collect import DDC.Type.Compounds-import DDC.Core.Collect import DDC.Type.Transform.LiftT import DDC.Type.Transform.Crush import DDC.Type.Transform.Trim-import DDC.Type.Rewrite+import DDC.Type.Transform.Rename+import DDC.Type.Exp import Data.Maybe import qualified DDC.Type.Sum as Sum import qualified DDC.Type.Env as Env
DDC/Type/Transform/Trim.hs view
@@ -2,7 +2,7 @@ module DDC.Type.Transform.Trim (trimClosure) where-import DDC.Core.Collect+import DDC.Type.Collect import DDC.Type.Check.CheckCon import DDC.Type.Exp import DDC.Type.Compounds@@ -18,19 +18,22 @@ -- -- This is like `crushEffect`, but for closures instead of effects. ----- For example, trimming @Int r2 -(Read r1 | Use r1)> Int r2@ yields just @Use r1@. +-- For example, trimming @DeepUse (Int r2 -(Read r1 | Use r1)> Int r2)@ yields+-- just @Use r1@. -- Only @r1@ might contain an actual store object that is reachable from a function -- closure with such a type. -- -- This function assumes the closure is well-kinded, and may return `Nothing` if -- this is not the case.+-- trimClosure :: Ord n => Closure n -> Maybe (Closure n) trimClosure cc- = liftM TSum $ trimToSumC cc+ = {-# SCC trimClosure #-}+ liftM TSum $ trimToSumC cc -- | Trim a closure down to a closure sum.
DDC/Type/Universe.hs view
@@ -1,5 +1,4 @@ --- | Universes of the Disciple Core language. module DDC.Type.Universe ( Universe(..) , universeFromType3@@ -8,7 +7,8 @@ , universeOfType) where import DDC.Type.Exp-import DDC.Type.Compounds+import DDC.Base.Pretty+import DDC.Type.Env as Env import qualified DDC.Type.Sum as T @@ -45,6 +45,16 @@ deriving (Show, Eq) +instance Pretty Universe where+ ppr u+ = case u of+ UniverseSort -> text "Sort"+ UniverseKind -> text "Kind"+ UniverseSpec -> text "Spec"+ UniverseWitness -> text "Witness"+ UniverseData -> text "Data"++ -- | Given the type of the type of the type of some thing (up three levels), -- yield the universe of the original thing, or `Nothing` it was badly formed. universeFromType3 :: Type n -> Maybe Universe@@ -69,9 +79,9 @@ KiConData -> Just UniverseData _ -> Nothing - TCon (TyConWitness _) -> Nothing- TCon (TyConSpec _) -> Nothing- TCon (TyConBound _) -> Nothing+ TCon TyConWitness{} -> Nothing+ TCon TyConSpec{} -> Nothing+ TCon TyConBound{} -> Nothing TForall _ _ -> Nothing TApp _ t2 -> universeFromType2 t2 TSum _ -> Nothing@@ -79,38 +89,47 @@ -- | Given the type of some thing (up one level), -- yield the universe of the original thing, or `Nothing` if it was badly formed.-universeFromType1 :: Type n -> Maybe Universe-universeFromType1 tt+universeFromType1 :: Ord n => Env n -> Type n -> Maybe Universe+universeFromType1 kenv tt = case tt of- TVar u -> universeFromType2 (typeOfBound u)- TCon (TyConSort _) -> Just UniverseKind- TCon (TyConKind _) -> Just UniverseSpec- TCon (TyConWitness _) -> Just UniverseWitness- TCon (TyConSpec TcConFun) -> Just UniverseData- TCon (TyConSpec _) -> Nothing- TCon (TyConBound u) -> universeFromType2 (typeOfBound u)- TForall _ t2 -> universeFromType1 t2- TApp _ t2 -> universeFromType1 t2- TSum _ -> Nothing+ TVar n+ -> case Env.lookup n kenv of+ Nothing -> Nothing+ Just k -> universeFromType2 k + TCon (TyConSort _) -> Just UniverseKind+ TCon (TyConKind _) -> Just UniverseSpec+ TCon (TyConWitness _) -> Just UniverseWitness+ TCon (TyConSpec TcConFun) -> Just UniverseData+ TCon (TyConSpec TcConUnit) -> Just UniverseData+ TCon (TyConSpec _) -> Nothing+ TCon (TyConBound _ k) -> universeFromType2 k+ TForall b t2 -> universeFromType1 (Env.extend b kenv) t2+ TApp t1 _ -> universeFromType1 kenv t1+ TSum _ -> Nothing + -- | Yield the universe of some type. -- -- @ universeOfType (tBot kEffect) = UniverseSpec -- universeOfType kRegion = UniverseKind -- @ ---universeOfType :: Type n -> Maybe Universe-universeOfType tt+universeOfType :: Ord n => Env n -> Type n -> Maybe Universe+universeOfType kenv tt = case tt of- TVar u -> universeFromType1 (typeOfBound u)+ TVar n+ -> case Env.lookup n kenv of+ Nothing -> Nothing+ Just k -> universeFromType1 kenv k+ TCon (TyConSort _) -> Just UniverseSort TCon (TyConKind _) -> Just UniverseKind TCon (TyConWitness _) -> Just UniverseSpec TCon (TyConSpec _) -> Just UniverseSpec- TCon (TyConBound u) -> universeFromType1 (typeOfBound u)- TForall _ t2 -> universeOfType t2- TApp _ t2 -> universeOfType t2- TSum ss -> universeFromType1 (T.kindOfSum ss)+ TCon (TyConBound _ k) -> universeFromType1 kenv k+ TForall b t2 -> universeOfType (Env.extend b kenv) t2+ TApp _ t2 -> universeOfType kenv t2+ TSum ss -> universeFromType1 kenv (T.kindOfSum ss)
ddc-core.cabal view
@@ -1,5 +1,5 @@ Name: ddc-core-Version: 0.2.1.2+Version: 0.3.1.1 License: MIT License-file: LICENSE Author: The Disciplined Disciple Compiler Strike Force@@ -10,73 +10,116 @@ Category: Compilers/Interpreters Homepage: http://disciple.ouroborus.net Bug-reports: disciple@ouroborus.net-Synopsis: Disciple Core language and type checker.+Synopsis: Disciplined Disciple Compiler core language and type checker. Description: Disciple Core is an explicitly typed language based on System-F2, intended- as an intermediate representation for a compiler. In addition to the features of + as an intermediate representation for a compiler. In addition to the polymorphism of System-F2 it supports region, effect and closure typing. Evaluation order is left-to-right call-by-value by default, but explicit lazy evaluation is also supported.- There is also a capability system to track whether objects are mutable or constant,+ There is a capability system to track whether objects are mutable or constant, and to ensure that computations that perform visible side effects are not suspended with lazy evaluation. - See the @ddci-core@ package for a user-facing interpreter.+ See the @ddc-tools@ package for a user-facing interpreter and compiler. Library Build-Depends: base == 4.6.*,+ deepseq == 1.3.*, containers == 0.5.*, array == 0.4.*,+ directory == 1.2.*, transformers == 0.3.*, mtl == 2.1.*,- ddc-base == 0.2.1.*+ ddc-base == 0.3.1.* Exposed-modules:- DDC.Core.Check.CheckExp- DDC.Core.Check.CheckWitness- DDC.Core.Check.Error- DDC.Core.Check.TaggedClosure- DDC.Core.Parser.Lexer- DDC.Core.Parser.Tokens- DDC.Core.Transform.LiftW+ DDC.Core.Lexer.Names+ DDC.Core.Lexer.Tokens++ DDC.Core.Transform.LiftT DDC.Core.Transform.LiftX+ DDC.Core.Transform.Reannotate+ DDC.Core.Transform.Rename DDC.Core.Transform.SpreadX DDC.Core.Transform.SubstituteTX DDC.Core.Transform.SubstituteWX DDC.Core.Transform.SubstituteXX+ DDC.Core.Transform.Trim+ DDC.Core.Check DDC.Core.Collect DDC.Core.Compounds- DDC.Core.DataDef+ DDC.Core.DaCon DDC.Core.Exp- DDC.Core.Pretty- DDC.Core.Predicates+ DDC.Core.Fragment+ DDC.Core.Lexer+ DDC.Core.Load+ DDC.Core.Module DDC.Core.Parser- DDC.Type.Check.Monad+ DDC.Core.Predicates+ DDC.Core.Pretty+ DDC.Type.Transform.Crush DDC.Type.Transform.Instantiate DDC.Type.Transform.LiftT- DDC.Type.Transform.LowerT+ DDC.Type.Transform.Rename DDC.Type.Transform.SpreadT DDC.Type.Transform.SubstituteT DDC.Type.Transform.Trim+ DDC.Type.Bind DDC.Type.Check+ DDC.Type.Collect DDC.Type.Compounds+ DDC.Type.DataDef DDC.Type.Env DDC.Type.Equiv DDC.Type.Exp- DDC.Type.Parser DDC.Type.Predicates- DDC.Type.Rewrite+ DDC.Type.Pretty DDC.Type.Subsumes DDC.Type.Sum DDC.Type.Universe Other-modules:+ DDC.Core.Check.CheckDaCon+ DDC.Core.Check.CheckExp+ DDC.Core.Check.CheckModule+ DDC.Core.Check.CheckWitness DDC.Core.Check.ErrorMessage+ DDC.Core.Check.Error+ DDC.Core.Check.TaggedClosure++ DDC.Core.Collect.Support+ DDC.Core.Collect.Free++ DDC.Core.Exp.Base+ DDC.Core.Exp.NFData++ DDC.Core.Fragment.Compliance+ DDC.Core.Fragment.Error+ DDC.Core.Fragment.Feature+ DDC.Core.Fragment.Profile++ DDC.Core.Lexer.Comments+ DDC.Core.Lexer.Offside++ DDC.Core.Parser.Base+ DDC.Core.Parser.Exp+ DDC.Core.Parser.Module+ DDC.Core.Parser.Param+ DDC.Core.Parser.Type+ DDC.Core.Parser.Witness+ DDC.Type.Check.CheckCon- DDC.Type.Check.CheckError- DDC.Type.Pretty+ DDC.Type.Check.Error+ DDC.Type.Check.ErrorMessage++ DDC.Type.Collect.FreeT++ DDC.Type.Exp.Base+ DDC.Type.Exp.NFData+ GHC-options: -Wall@@ -85,6 +128,7 @@ -fno-warn-unused-do-bind Extensions:+ BangPatterns ParallelListComp PatternGuards RankNTypes@@ -97,4 +141,6 @@ ScopedTypeVariables StandaloneDeriving DoAndIfThenElse- + DeriveDataTypeable+ ViewPatterns+