@@ -50,6 +50,10 @@ deriveInstance mn ds (TypeInstanceDeclaration nm deps className tys@[ty] Derived
50 , Just (Qualified mn' tyCon, args) <- unwrapTypeConstructor ty
50 , Just (Qualified mn' tyCon, args) <- unwrapTypeConstructor ty
51 , mn == fromMaybe mn mn'
51 , mn == fromMaybe mn mn'
52 = TypeInstanceDeclaration nm deps className tys . ExplicitInstance <$> deriveGeneric mn ds tyCon args
52 = TypeInstanceDeclaration nm deps className tys . ExplicitInstance <$> deriveGeneric mn ds tyCon args
53+ | className == Qualified (Just (ModuleName [ ProperName "Prelude" ])) eq
54+ , Just (Qualified mn' tyCon, _) <- unwrapTypeConstructor ty
55+ , mn == fromMaybe mn mn'
56+ = TypeInstanceDeclaration nm deps className tys . ExplicitInstance <$> deriveEq mn ds tyCon
53deriveInstance _ _ (TypeInstanceDeclaration _ _ className tys DerivedInstance)
57deriveInstance _ _ (TypeInstanceDeclaration _ _ className tys DerivedInstance)
54 = throwError . errorMessage $ CannotDerive className tys
58 = throwError . errorMessage $ CannotDerive className tys
55deriveInstance mn ds (PositionedDeclaration pos com d) = PositionedDeclaration pos com <$> deriveInstance mn ds d
59deriveInstance mn ds (PositionedDeclaration pos com d) = PositionedDeclaration pos com <$> deriveInstance mn ds d
@@ -73,22 +77,193 @@ dataMaybe = ModuleName [ ProperName "Data", ProperName "Maybe" ]
73typesProxy :: ModuleName
77typesProxy :: ModuleName
74typesProxy = ModuleName [ ProperName "Type", ProperName "Proxy" ]
78typesProxy = ModuleName [ ProperName "Type", ProperName "Proxy" ]
80+eq :: ProperName 'ClassName
76deriveGeneric
83deriveGeneric
77− :: (Functor m, MonadError MultipleErrors m, MonadSupply m)
84+ :: forall m. (Functor m, MonadError MultipleErrors m, MonadSupply m)
78 => ModuleName
85 => ModuleName
79 -> [Declaration]
86 -> [Declaration]
80 -> ProperName 'TypeName
87 -> ProperName 'TypeName
82 -> m [Declaration]
89 -> m [Declaration]
83−deriveGeneric mn ds tyConNm args = do
90+deriveGeneric mn ds tyConNm dargs = do
84 tyCon <- findTypeDecl tyConNm ds
91 tyCon <- findTypeDecl tyConNm ds
85− toSpine <- mkSpineFunction mn tyCon
92+ toSpine <- mkSpineFunction tyCon
86− fromSpine <- mkFromSpineFunction mn tyCon
93+ fromSpine <- mkFromSpineFunction tyCon
87− let toSignature = mkSignatureFunction mn tyCon args
94+ let toSignature = mkSignatureFunction tyCon dargs
88 return [ ValueDeclaration (Ident C.toSpine) Public [] (Right toSpine)
95 return [ ValueDeclaration (Ident C.toSpine) Public [] (Right toSpine)
89 , ValueDeclaration (Ident C.fromSpine) Public [] (Right fromSpine)
96 , ValueDeclaration (Ident C.fromSpine) Public [] (Right fromSpine)
90 , ValueDeclaration (Ident C.toSignature) Public [] (Right toSignature)
97 , ValueDeclaration (Ident C.toSignature) Public [] (Right toSignature)
100+ mkSpineFunction :: Declaration -> m Expr
101+ mkSpineFunction (DataDeclaration _ _ _ args) = lamCase "$x" <$> mapM mkCtorClause args
103+ prodConstructor :: Expr -> Expr
104+ prodConstructor = App (Constructor (Qualified (Just dataGeneric) (ProperName "SProd")))
106+ recordConstructor :: Expr -> Expr
107+ recordConstructor = App (Constructor (Qualified (Just dataGeneric) (ProperName "SRecord")))
109+ mkCtorClause :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative
110+ mkCtorClause (ctorName, tys) = do
111+ idents <- replicateM (length tys) freshIdent'
112+ return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right (caseResult idents))
115+ App (prodConstructor (StringLiteral . showQualified runProperName $ Qualified (Just mn) ctorName))
117+ $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys
119+ toSpineFun :: Expr -> Type -> Expr
120+ toSpineFun i r | Just rec <- objectType r =
121+ lamNull . recordConstructor . ArrayLiteral .
122+ map (\(str,typ) -> ObjectLiteral [("recLabel", StringLiteral str), ("recValue", toSpineFun (Accessor str i) typ)])
124+ toSpineFun i _ = lamNull $ App (mkGenVar C.toSpine) i
125+ mkSpineFunction (PositionedDeclaration _ _ d) = mkSpineFunction d
126+ mkSpineFunction _ = internalError "mkSpineFunction: expected DataDeclaration"
128+ mkSignatureFunction :: Declaration -> [Type] -> Expr
129+ mkSignatureFunction (DataDeclaration _ name tyArgs args) classArgs = lamNull . mkSigProd $ map mkProdClause args
131+ mkSigProd :: [Expr] -> Expr
132+ mkSigProd = App (App (Constructor (Qualified (Just dataGeneric) (ProperName "SigProd")))
133+ (StringLiteral (showQualified runProperName (Qualified (Just mn) name)))
136+ mkSigRec :: [Expr] -> Expr
137+ mkSigRec = App (Constructor (Qualified (Just dataGeneric) (ProperName "SigRecord"))) . ArrayLiteral
139+ proxy :: Type -> Type
140+ proxy = TypeApp (TypeConstructor (Qualified (Just typesProxy) (ProperName "Proxy")))
142+ mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr
143+ mkProdClause (ctorName, tys) =
145+ [ ("sigConstructor", StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName)))
146+ , ("sigValues", ArrayLiteral . map (mkProductSignature . instantiate) $ tys)
149+ mkProductSignature :: Type -> Expr
150+ mkProductSignature r | Just rec <- objectType r =
151+ lamNull . mkSigRec $ [ ObjectLiteral [ ("recLabel", StringLiteral str)
152+ , ("recValue", mkProductSignature typ)
154+ | (str, typ) <- decomposeRec rec
156+ mkProductSignature typ = lamNull $ App (mkGenVar C.toSignature)
157+ (TypedValue False (mkGenVar "anyProxy") (proxy typ))
158+ instantiate = replaceAllTypeVars (zipWith (\(arg, _) ty -> (arg, ty)) tyArgs classArgs)
159+ mkSignatureFunction (PositionedDeclaration _ _ d) classArgs = mkSignatureFunction d classArgs
160+ mkSignatureFunction _ _ = internalError "mkSignatureFunction: expected DataDeclaration"
162+ mkFromSpineFunction :: Declaration -> m Expr
163+ mkFromSpineFunction (DataDeclaration _ _ _ args) = lamCase "$x" <$> (addCatch <$> mapM mkAlternative args)
165+ mkJust :: Expr -> Expr
166+ mkJust = App (Constructor (Qualified (Just dataMaybe) (ProperName "Just")))
169+ mkNothing = Constructor (Qualified (Just dataMaybe) (ProperName "Nothing"))
171+ prodBinder :: [Binder] -> Binder
172+ prodBinder = ConstructorBinder (Qualified (Just dataGeneric) (ProperName "SProd"))
174+ recordBinder :: [Binder] -> Binder
175+ recordBinder = ConstructorBinder (Qualified (Just dataGeneric) (ProperName "SRecord"))
177+ mkAlternative :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative
178+ mkAlternative (ctorName, tys) = do
179+ idents <- replicateM (length tys) freshIdent'
180+ return $ CaseAlternative [ prodBinder [ StringBinder (showQualified runProperName (Qualified (Just mn) ctorName)), ArrayBinder (map VarBinder idents)]]
182+ $ liftApplicative (mkJust $ Constructor (Qualified (Just mn) ctorName))
183+ (zipWith fromSpineFun (map (Var . Qualified Nothing) idents) tys)
185+ addCatch :: [CaseAlternative] -> [CaseAlternative]
186+ addCatch = (++ [catchAll])
188+ catchAll = CaseAlternative [NullBinder] (Right mkNothing)
191+ | Just rec <- objectType r
192+ = App (lamCase "r" [ mkRecCase (decomposeRec rec)
193+ , CaseAlternative [NullBinder] (Right mkNothing)
195+ (App e (mkPrelVar "unit"))
197+ fromSpineFun e _ = App (mkGenVar C.fromSpine) (App e (mkPrelVar "unit"))
199+ mkRecCase rs = CaseAlternative [ recordBinder [ ArrayBinder (map (VarBinder . Ident . fst) rs)
203+ $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar x)) y) rs)
205+ mkRecFun :: [(String, Type)] -> Expr
206+ mkRecFun xs = mkJust $ foldr lam recLiteral (map fst xs)
207+ where recLiteral = ObjectLiteral $ map (\(s,_) -> (s,mkVar s)) xs
208+ mkFromSpineFunction (PositionedDeclaration _ _ d) = mkFromSpineFunction d
209+ mkFromSpineFunction _ = internalError "mkFromSpineFunction: expected DataDeclaration"
213+ liftApplicative :: Expr -> [Expr] -> Expr
214+ liftApplicative = foldl' (\x e -> App (App (mkPrelVar "apply") x) e)
216+ mkPrelVar :: String -> Expr
217+ mkPrelVar = mkVarMn (Just (ModuleName [ProperName C.prelude]))
219+ mkGenVar :: String -> Expr
220+ mkGenVar = mkVarMn (Just (ModuleName [ProperName "Data", ProperName C.generic]))
223+ forall m. (Functor m, MonadError MultipleErrors m, MonadSupply m)
226+ -> ProperName 'TypeName
228+deriveEq mn ds tyConNm = do
229+ tyCon <- findTypeDecl tyConNm ds
230+ eqFun <- mkEqFunction tyCon
231+ return [ ValueDeclaration (Ident C.eq) Public [] (Right eqFun) ]
233+ mkEqFunction :: Declaration -> m Expr
234+ mkEqFunction (DataDeclaration _ _ _ args) = lamCase2 "$x" "$y" <$> (addCatch <$> mapM mkCtorClause args)
235+ mkEqFunction (PositionedDeclaration _ _ d) = mkEqFunction d
236+ mkEqFunction _ = internalError "mkEqFunction: expected DataDeclaration"
238+ preludeConj :: Expr -> Expr -> Expr
239+ preludeConj = App . App (Var (Qualified (Just (ModuleName [ProperName C.prelude])) (Ident C.conj)))
241+ preludeEq :: Expr -> Expr -> Expr
242+ preludeEq = App . App (Var (Qualified (Just (ModuleName [ProperName C.prelude])) (Ident C.eq)))
244+ addCatch :: [CaseAlternative] -> [CaseAlternative]
245+ addCatch = (++ [catchAll])
247+ catchAll = CaseAlternative [NullBinder, NullBinder] (Right (BooleanLiteral False))
249+ mkCtorClause :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative
250+ mkCtorClause (ctorName, tys) = do
251+ [identsL, identsR] <- replicateM 2 (replicateM (length tys) freshIdent')
252+ let tests = zipWith3 toEqTest (map (Var . Qualified Nothing) identsL) (map (Var . Qualified Nothing) identsR) tys
253+ return $ CaseAlternative [caseBinder identsL, caseBinder identsR] (Right (conjAll tests))
255+ caseBinder idents = ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)
257+ conjAll :: [Expr] -> Expr
258+ conjAll [] = BooleanLiteral True
259+ conjAll xs = foldl1 preludeConj xs
261+ toEqTest :: Expr -> Expr -> Type -> Expr
262+ toEqTest l r ty | Just rec <- objectType ty =
264+ . map (\(str, typ) -> toEqTest (Accessor str l) (Accessor str r) typ)
266+ toEqTest l r _ = preludeEq l r
93findTypeDecl
268findTypeDecl
94 :: (Functor m, MonadError MultipleErrors m)
269 :: (Functor m, MonadError MultipleErrors m)
@@ -102,123 +277,6 @@ findTypeDecl tyConNm = maybe (throwError . errorMessage $ CannotFindDerivingType
102 isTypeDecl (PositionedDeclaration _ _ d) = isTypeDecl d
277 isTypeDecl (PositionedDeclaration _ _ d) = isTypeDecl d
103 isTypeDecl _ = False
278 isTypeDecl _ = False
105−mkSpineFunction :: forall m. (Functor m, MonadSupply m) => ModuleName -> Declaration -> m Expr
106−mkSpineFunction mn (DataDeclaration _ _ _ args) = lamCase "$x" <$> mapM mkCtorClause args
108− prodConstructor :: Expr -> Expr
109− prodConstructor = App (Constructor (Qualified (Just dataGeneric) (ProperName "SProd")))
111− recordConstructor :: Expr -> Expr
112− recordConstructor = App (Constructor (Qualified (Just dataGeneric) (ProperName "SRecord")))
114− mkCtorClause :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative
115− mkCtorClause (ctorName, tys) = do
116− idents <- replicateM (length tys) freshIdent'
117− return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right (caseResult idents))
120− App (prodConstructor (StringLiteral . showQualified runProperName $ Qualified (Just mn) ctorName))
122− $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys
124− toSpineFun :: Expr -> Type -> Expr
125− toSpineFun i r | Just rec <- objectType r =
126− lamNull . recordConstructor . ArrayLiteral .
127− map (\(str,typ) -> ObjectLiteral [("recLabel", StringLiteral str), ("recValue", toSpineFun (Accessor str i) typ)])
129− toSpineFun i _ = lamNull $ App (mkGenVar C.toSpine) i
130−mkSpineFunction mn (PositionedDeclaration _ _ d) = mkSpineFunction mn d
131−mkSpineFunction _ _ = internalError "mkSpineFunction: expected DataDeclaration"
133−mkSignatureFunction :: ModuleName -> Declaration -> [Type] -> Expr
134−mkSignatureFunction mn (DataDeclaration _ name tyArgs args) classArgs = lamNull . mkSigProd $ map mkProdClause args
136− mkSigProd :: [Expr] -> Expr
137− mkSigProd = App (App (Constructor (Qualified (Just dataGeneric) (ProperName "SigProd")))
138− (StringLiteral (showQualified runProperName (Qualified (Just mn) name)))
141− mkSigRec :: [Expr] -> Expr
142− mkSigRec = App (Constructor (Qualified (Just dataGeneric) (ProperName "SigRecord"))) . ArrayLiteral
144− proxy :: Type -> Type
145− proxy = TypeApp (TypeConstructor (Qualified (Just typesProxy) (ProperName "Proxy")))
147− mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr
148− mkProdClause (ctorName, tys) =
150− [ ("sigConstructor", StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName)))
151− , ("sigValues", ArrayLiteral . map (mkProductSignature . instantiate) $ tys)
154− mkProductSignature :: Type -> Expr
155− mkProductSignature r | Just rec <- objectType r =
156− lamNull . mkSigRec $ [ ObjectLiteral [ ("recLabel", StringLiteral str)
157− , ("recValue", mkProductSignature typ)
159− | (str, typ) <- decomposeRec rec
161− mkProductSignature typ = lamNull $ App (mkGenVar C.toSignature)
162− (TypedValue False (mkGenVar "anyProxy") (proxy typ))
163− instantiate = replaceAllTypeVars (zipWith (\(arg, _) ty -> (arg, ty)) tyArgs classArgs)
164−mkSignatureFunction mn (PositionedDeclaration _ _ d) classArgs = mkSignatureFunction mn d classArgs
165−mkSignatureFunction _ _ _ = internalError "mkSignatureFunction: expected DataDeclaration"
167−mkFromSpineFunction :: forall m. (Functor m, MonadSupply m) => ModuleName -> Declaration -> m Expr
168−mkFromSpineFunction mn (DataDeclaration _ _ _ args) = lamCase "$x" <$> (addCatch <$> mapM mkAlternative args)
170− mkJust :: Expr -> Expr
171− mkJust = App (Constructor (Qualified (Just dataMaybe) (ProperName "Just")))
174− mkNothing = Constructor (Qualified (Just dataMaybe) (ProperName "Nothing"))
176− prodBinder :: [Binder] -> Binder
177− prodBinder = ConstructorBinder (Qualified (Just dataGeneric) (ProperName "SProd"))
179− recordBinder :: [Binder] -> Binder
180− recordBinder = ConstructorBinder (Qualified (Just dataGeneric) (ProperName "SRecord"))
182− mkAlternative :: (ProperName 'ConstructorName, [Type]) -> m CaseAlternative
183− mkAlternative (ctorName, tys) = do
184− idents <- replicateM (length tys) freshIdent'
185− return $ CaseAlternative [ prodBinder [ StringBinder (showQualified runProperName (Qualified (Just mn) ctorName)), ArrayBinder (map VarBinder idents)]]
187− $ liftApplicative (mkJust $ Constructor (Qualified (Just mn) ctorName))
188− (zipWith fromSpineFun (map (Var . Qualified Nothing) idents) tys)
190− addCatch :: [CaseAlternative] -> [CaseAlternative]
191− addCatch = (++ [catchAll])
193− catchAll = CaseAlternative [NullBinder] (Right mkNothing)
196− | Just rec <- objectType r
197− = App (lamCase "r" [ mkRecCase (decomposeRec rec)
198− , CaseAlternative [NullBinder] (Right mkNothing)
200− (App e (mkPrelVar "unit"))
202− fromSpineFun e _ = App (mkGenVar C.fromSpine) (App e (mkPrelVar "unit"))
204− mkRecCase rs = CaseAlternative [ recordBinder [ ArrayBinder (map (VarBinder . Ident . fst) rs)
208− $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar x)) y) rs)
210− mkRecFun :: [(String, Type)] -> Expr
211− mkRecFun xs = mkJust $ foldr lam recLiteral (map fst xs)
212− where recLiteral = ObjectLiteral $ map (\(s,_) -> (s,mkVar s)) xs
213−mkFromSpineFunction mn (PositionedDeclaration _ _ d) = mkFromSpineFunction mn d
214−mkFromSpineFunction _ _ = internalError "mkFromSpineFunction: expected DataDeclaration"
218−objectType :: Type -> Maybe Type
219−objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Object"))) rec) = Just rec
220−objectType _ = Nothing
222lam :: String -> Expr -> Expr
280lam :: String -> Expr -> Expr
223lam s = Abs (Left (Ident s))
281lam s = Abs (Left (Ident s))
@@ -228,8 +286,8 @@ lamNull = lam "$q"
228lamCase :: String -> [CaseAlternative] -> Expr
286lamCase :: String -> [CaseAlternative] -> Expr
229lamCase s = lam s . Case [mkVar s]
287lamCase s = lam s . Case [mkVar s]
231−liftApplicative :: Expr -> [Expr] -> Expr
289+lamCase2 :: String -> String -> [CaseAlternative] -> Expr
232−liftApplicative = foldl' (\x e -> App (App (mkPrelVar "apply") x) e)
290+lamCase2 s t = lam s . lam t . Case [mkVar s, mkVar t]
234mkVarMn :: Maybe ModuleName -> String -> Expr
292mkVarMn :: Maybe ModuleName -> String -> Expr
235mkVarMn mn s = Var (Qualified mn (Ident s))
293mkVarMn mn s = Var (Qualified mn (Ident s))
@@ -237,13 +295,11 @@ mkVarMn mn s = Var (Qualified mn (Ident s))
237mkVar :: String -> Expr
295mkVar :: String -> Expr
238mkVar = mkVarMn Nothing
296mkVar = mkVarMn Nothing
240−mkPrelVar :: String -> Expr
298+objectType :: Type -> Maybe Type
241−mkPrelVar = mkVarMn (Just (ModuleName [ProperName C.prelude]))
299+objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Object"))) rec) = Just rec
242−
300+objectType _ = Nothing
243−mkGenVar :: String -> Expr
244−mkGenVar = mkVarMn (Just (ModuleName [ProperName "Data", ProperName C.generic]))
246decomposeRec :: Type -> [(String, Type)]
302decomposeRec :: Type -> [(String, Type)]
247decomposeRec = sortBy (comparing fst) . go
303decomposeRec = sortBy (comparing fst) . go
248− where go (RCons str typ typs) = (str, typ) : decomposeRec typs
304+ where go (RCons str typ typs) = (str, typ) : decomposeRec typs
249− go _ = []
305+ go _ = []