@@ -13,7 +13,7 @@ import Control.Monad (replicateM)
13import Control.Monad.Error.Class (MonadError(..))
13import Control.Monad.Error.Class (MonadError(..))
14import Control.Monad.Supply.Class (MonadSupply)
14import Control.Monad.Supply.Class (MonadSupply)
16−import Data.List (foldl', find, sortBy)
16+import Data.List (foldl', find, sortBy, unzip5)
17import Data.Maybe (fromMaybe)
17import Data.Maybe (fromMaybe)
18import Data.Ord (comparing)
18import Data.Ord (comparing)
@@ -58,9 +58,14 @@ deriveInstance mn ds (TypeInstanceDeclaration nm deps className [wrappedTy, unwr
58 | className == Qualified (Just dataNewtype) (ProperName "Newtype")
58 | className == Qualified (Just dataNewtype) (ProperName "Newtype")
59 , Just (Qualified mn' tyCon, args) <- unwrapTypeConstructor wrappedTy
59 , Just (Qualified mn' tyCon, args) <- unwrapTypeConstructor wrappedTy
60 , mn == fromMaybe mn mn'
60 , mn == fromMaybe mn mn'
62− (inst, actualUnwrappedTy) <- deriveNewtype mn ds tyCon args unwrappedTy
61+ = do (inst, actualUnwrappedTy) <- deriveNewtype mn ds tyCon args unwrappedTy
63− return $ TypeInstanceDeclaration nm deps className [wrappedTy, actualUnwrappedTy] (ExplicitInstance inst)
62+ return $ TypeInstanceDeclaration nm deps className [wrappedTy, actualUnwrappedTy] (ExplicitInstance inst)
63+deriveInstance mn ds (TypeInstanceDeclaration nm deps className [actualTy, repTy] DerivedInstance)
64+ | className == Qualified (Just dataGenericRep) (ProperName C.generic)
65+ , Just (Qualified mn' tyCon, args) <- unwrapTypeConstructor actualTy
66+ , mn == fromMaybe mn mn'
67+ = do (inst, inferredRepTy) <- deriveGenericRep mn ds tyCon args repTy
68+ return $ TypeInstanceDeclaration nm deps className [actualTy, inferredRepTy] (ExplicitInstance inst)
64deriveInstance _ _ (TypeInstanceDeclaration _ _ className tys DerivedInstance)
69deriveInstance _ _ (TypeInstanceDeclaration _ _ className tys DerivedInstance)
65 = throwError . errorMessage $ CannotDerive className tys
70 = throwError . errorMessage $ CannotDerive className tys
66deriveInstance mn ds (TypeInstanceDeclaration nm deps className tys@(_ : _) NewtypeInstance)
71deriveInstance mn ds (TypeInstanceDeclaration nm deps className tys@(_ : _) NewtypeInstance)
@@ -122,6 +127,9 @@ deriveNewtypeInstance className ds tys tyConNm dargs = do
122dataGeneric :: ModuleName
127dataGeneric :: ModuleName
123dataGeneric = ModuleName [ ProperName "Data", ProperName "Generic" ]
128dataGeneric = ModuleName [ ProperName "Data", ProperName "Generic" ]
130+dataGenericRep :: ModuleName
131+dataGenericRep = ModuleName [ ProperName "Data", ProperName "Generic", ProperName "Rep" ]
125dataMaybe :: ModuleName
133dataMaybe :: ModuleName
126dataMaybe = ModuleName [ ProperName "Data", ProperName "Maybe" ]
134dataMaybe = ModuleName [ ProperName "Data", ProperName "Maybe" ]
@@ -304,6 +312,187 @@ deriveGeneric mn ds tyConNm dargs = do
304 mkGenVar :: Ident -> Expr
312 mkGenVar :: Ident -> Expr
305 mkGenVar = mkVarMn (Just (ModuleName [ProperName "Data", ProperName C.generic]))
313 mkGenVar = mkVarMn (Just (ModuleName [ProperName "Data", ProperName C.generic]))
317+ . (MonadError MultipleErrors m, MonadSupply m)
320+ -> ProperName 'TypeName
323+ -> m ([Declaration], Type)
324+deriveGenericRep mn ds tyConNm tyConArgs repTy = do
325+ checkIsWildcard tyConNm repTy
326+ go =<< findTypeDecl tyConNm ds
328+ go :: Declaration -> m ([Declaration], Type)
329+ go (DataDeclaration _ _ args dctors) = do
331+ (reps, to, from) <- unzip3 <$> traverse makeInst dctors
332+ let rep = toRepTy reps
334+ -- If there are no cases, spin
335+ [ ValueDeclaration (Ident "to") Public [] $ Right $
336+ lamCase x [ CaseAlternative [NullBinder]
337+ (Right (App toName (Var (Qualified Nothing x))))
339+ , ValueDeclaration (Ident "from") Public [] $ Right $
340+ lamCase x [ CaseAlternative [NullBinder]
341+ (Right (App fromName (Var (Qualified Nothing x))))
345+ [ ValueDeclaration (Ident "to") Public [] $ Right $
346+ lamCase x (zipWith ($) (map underBinder (sumBinders (length dctors))) to)
347+ , ValueDeclaration (Ident "from") Public [] $ Right $
348+ lamCase x (zipWith ($) (map underExpr (sumExprs (length dctors))) from)
351+ subst = zipWith ((,) . fst) args tyConArgs
352+ return (inst, replaceAllTypeVars subst rep)
353+ go (PositionedDeclaration _ _ d) = go d
354+ go _ = internalError "deriveGenericRep go: expected DataDeclaration"
356+ select :: (a -> a) -> (a -> a) -> Int -> [a -> a]
359+ select l r n = take (n - 1) (iterate (r .) l) ++ [compN (n - 1) r]
361+ sumBinders :: Int -> [Binder -> Binder]
362+ sumBinders = select (ConstructorBinder inl . pure) (ConstructorBinder inr . pure)
364+ sumExprs :: Int -> [Expr -> Expr]
365+ sumExprs = select (App (Constructor inl)) (App (Constructor inr))
367+ compN :: Int -> (a -> a) -> a -> a
369+ compN n f = f . compN (n - 1) f
372+ :: (ProperName 'ConstructorName, [Type])
373+ -> m (Type, CaseAlternative, CaseAlternative)
374+ makeInst (ctorName, args) = do
375+ (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args
376+ return ( TypeApp (TypeApp (TypeConstructor constructor)
377+ (TypeLevelString (runProperName ctorName)))
379+ , CaseAlternative [ ConstructorBinder constructor [matchProduct] ]
380+ (Right (foldl App (Constructor (Qualified (Just mn) ctorName)) ctorArgs))
381+ , CaseAlternative [ ConstructorBinder (Qualified (Just mn) ctorName) matchCtor ]
382+ (Right (constructor' mkProduct))
387+ -> m (Type, Binder, [Expr], [Binder], Expr)
389+ pure (noArgs, NullBinder, [], [], noArgs')
390+ makeProduct args = do
391+ (tys, bs1, es1, bs2, es2) <- unzip5 <$> traverse makeArg args
392+ pure ( foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f)) tys
393+ , foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2]) bs1
396+ , foldr1 (\e1 -> App (App (Constructor productName) e1)) es2
399+ makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr)
400+ makeArg arg | Just rec <- objectType arg = do
401+ let fields = decomposeRec rec
402+ fieldNames <- traverse freshIdent (map fst fields)
403+ pure ( TypeApp (TypeConstructor record)
404+ (foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f))
405+ (map (\(name, ty) ->
406+ TypeApp (TypeApp (TypeConstructor field) (TypeLevelString name)) ty) fields))
407+ , ConstructorBinder record
408+ [ foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2])
409+ (map (\ident -> ConstructorBinder field [VarBinder ident]) fieldNames)
411+ , Literal . ObjectLiteral $
412+ zipWith (\(name, _) ident -> (name, Var (Qualified Nothing ident))) fields fieldNames
413+ , LiteralBinder . ObjectLiteral $
414+ zipWith (\(name, _) ident -> (name, VarBinder ident)) fields fieldNames
416+ foldr1 (\e1 -> App (App (Constructor productName) e1))
417+ (map (field' . Var . Qualified Nothing) fieldNames)
420+ argName <- freshIdent "arg"
421+ pure ( TypeApp (TypeConstructor argument) arg
422+ , ConstructorBinder argument [ VarBinder argName ]
423+ , Var (Qualified Nothing argName)
425+ , argument' (Var (Qualified Nothing argName))
428+ underBinder :: (Binder -> Binder) -> CaseAlternative -> CaseAlternative
429+ underBinder f (CaseAlternative bs e) = CaseAlternative (map f bs) e
431+ underExpr :: (Expr -> Expr) -> CaseAlternative -> CaseAlternative
432+ underExpr f (CaseAlternative b (Right e)) = CaseAlternative b (Right (f e))
433+ underExpr _ _ = internalError "underExpr: expected Right"
435+ toRepTy :: [Type] -> Type
436+ toRepTy [] = noCtors
437+ toRepTy [only] = only
438+ toRepTy ctors = foldr1 (\f -> TypeApp (TypeApp sumCtor f)) ctors
441+ toName = Var (Qualified (Just dataGenericRep) (Ident "to"))
444+ fromName = Var (Qualified (Just dataGenericRep) (Ident "from"))
447+ noCtors = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoConstructors"))
450+ noArgs = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "NoArguments"))
453+ noArgs' = Constructor (Qualified (Just dataGenericRep) (ProperName "NoArguments"))
456+ sumCtor = TypeConstructor (Qualified (Just dataGenericRep) (ProperName "Sum"))
458+ inl :: Qualified (ProperName 'ConstructorName)
459+ inl = Qualified (Just dataGenericRep) (ProperName "Inl")
461+ inr :: Qualified (ProperName 'ConstructorName)
462+ inr = Qualified (Just dataGenericRep) (ProperName "Inr")
464+ productName :: Qualified (ProperName ty)
465+ productName = Qualified (Just dataGenericRep) (ProperName "Product")
467+ constructor :: Qualified (ProperName ty)
468+ constructor = Qualified (Just dataGenericRep) (ProperName "Constructor")
470+ constructor' :: Expr -> Expr
471+ constructor' = App (Constructor constructor)
473+ argument :: Qualified (ProperName ty)
474+ argument = Qualified (Just dataGenericRep) (ProperName "Argument")
476+ argument' :: Expr -> Expr
477+ argument' = App (Constructor argument)
479+ record :: Qualified (ProperName ty)
480+ record = Qualified (Just dataGenericRep) (ProperName "Rec")
482+ record' :: Expr -> Expr
483+ record' = App (Constructor record)
485+ field :: Qualified (ProperName ty)
486+ field = Qualified (Just dataGenericRep) (ProperName "Field")
488+ field' :: Expr -> Expr
489+ field' = App (Constructor field)
491+checkIsWildcard :: MonadError MultipleErrors m => ProperName 'TypeName -> Type -> m ()
492+checkIsWildcard _ (TypeWildcard _) = return ()
493+checkIsWildcard tyConNm _ =
494+ throwError . errorMessage $ ExpectedWildcard tyConNm
307deriveEq ::
496deriveEq ::
308 forall m. (MonadError MultipleErrors m, MonadSupply m)
497 forall m. (MonadError MultipleErrors m, MonadSupply m)
309 => ModuleName
498 => ModuleName
@@ -451,7 +640,7 @@ deriveNewtype
452 -> m ([Declaration], Type)
641 -> m ([Declaration], Type)
453deriveNewtype mn ds tyConNm tyConArgs unwrappedTy = do
642deriveNewtype mn ds tyConNm tyConArgs unwrappedTy = do
454− checkIsWildcard unwrappedTy
643+ checkIsWildcard tyConNm unwrappedTy
455 go =<< findTypeDecl tyConNm ds
644 go =<< findTypeDecl tyConNm ds
457 go :: Declaration -> m ([Declaration], Type)
646 go :: Declaration -> m ([Declaration], Type)
@@ -477,12 +666,6 @@ deriveNewtype mn ds tyConNm tyConArgs unwrappedTy = do
477 go (PositionedDeclaration _ _ d) = go d
666 go (PositionedDeclaration _ _ d) = go d
478 go _ = internalError "deriveNewtype go: expected DataDeclaration"
667 go _ = internalError "deriveNewtype go: expected DataDeclaration"
480− checkIsWildcard :: Type -> m ()
481− checkIsWildcard (TypeWildcard _) =
484− throwError . errorMessage $ NonWildcardNewtypeInstance tyConNm
486findTypeDecl
669findTypeDecl
487 :: (MonadError MultipleErrors m)
670 :: (MonadError MultipleErrors m)
488 => ProperName 'TypeName
671 => ProperName 'TypeName