@@ -59,7 +59,7 @@ import FStringCompat
5959
6060import qualified Data.Set as S
6161
62- -- import Debug.Trace
62+ import Debug.Trace
6363
6464-- | Derive instances for all types with deriving (...) in a package, and
6565-- return the package agumented with the instance definitions.
@@ -96,7 +96,10 @@ doDer flags r packageid xs data_decl@(Cdata {}) =
9696 int_sums = cd_internal_summands data_decl
9797 derivs = cd_derivings data_decl
9898 stockDerivs = addAutoDerivs flags r qual_name ty_vars (getStockDerivs derivs)
99- in Right [data_decl] : map (doDataDer r packageid xs qual_name ty_vars orig_sums int_sums) stockDerivs
99+ viaDerivs = getViaDerivs derivs
100+ in Right [data_decl]
101+ : map (doDataDer r packageid xs qual_name ty_vars orig_sums int_sums) stockDerivs
102+ ++ map (doDataVia r packageid xs qual_name ty_vars orig_sums int_sums) viaDerivs
100103doDer flags r packageid xs struct_decl@ (Cstruct _ s i ty_var_names fields derivs) =
101104 let unqual_name = iKName i
102105 qual_name = qualId packageid unqual_name
@@ -241,6 +244,67 @@ doStructDer _ _ _ i vs cs (CTypeclass di) | isTCId i =
241244doStructDer _ _ _ i vs cs (CTypeclass di) =
242245 Left (getPosition di, ECannotDerive (pfpString di))
243246
247+ -- -------------------------
248+
249+ -- | Derive an instance of a typeclass using Deriving via mechanism
250+ -- for a given data (sum type), and return the instance definitions.
251+ -- I've copied the args from doDataDer, potentially add or remove
252+ -- r = the current symbol table
253+ -- packageid = id name of the package
254+ -- xs = available bindings
255+ -- i = qualified id of the data type
256+ -- vs = argument type variables of the data type
257+ -- ocs = original summands of the data type
258+ -- (an id and a list of types of its arguments)
259+ -- cs = internal summands of the data type
260+ -- (an id and one type -- the list became a struct)
261+ -- di = the class to be derived
262+ -- tgt = data type via which to derive
263+ doDataVia :: SymTab -> Id -> [(Id , CDefn )] -> Id -> [Type ] -> COSummands -> CSummands ->
264+ (CTypeclass , Id ) -> Either EMsg [CDefn ]
265+ doDataVia r packageid xs i vs ocs cs (di, tgt)
266+ | Just (Cclass _ _ ident (dv : args) _ _ fs) <- lookup (typeclassId di) xs
267+ = let
268+ ctx = []
269+ -- TODO: I think there is a type var name clash here. Can I get fresh variable names?
270+ ity = cTApplys (cTCon i) vs
271+ applied = cTApplys (cTCon $ iKName ident) $ ity : map cTVar args
272+ isDataArg :: CType -> Bool
273+ isDataArg (TVar tvar) | tv_name tvar == dv = True
274+ isDataArg t = False
275+ isDataArg' :: CQType -> Bool
276+ isDataArg' (CQType _ t) = isDataArg t
277+ subst' :: CType -> CType
278+ subst' (TVar tvar) | tv_name tvar == dv = ity
279+ subst' t = t
280+ subst :: CType -> (CType , [CType ])
281+ subst ty = let (a, rs) = splitTAp ty
282+ in (subst' a, map subst' rs)
283+ mkCDef :: CField -> CDef
284+ mkCDef f =
285+ let
286+ CQType preds ty = cf_type f
287+ tys = subst ty
288+ (args', ret) = getCQArrows $ cf_type f
289+ vars = zip args' tmpVarXIds
290+ pats = map (CPVar . snd ) vars
291+ cvar :: (CQType , Id ) -> CExpr
292+ cvar (CQType preds (TVar tvar), id ) | tv_name tvar == dv = CCon tgt $ [cVar id ]
293+ cvar (_, id ) = cVar id
294+ args = map cvar vars
295+ fun = unQualId $ cf_name f
296+ fcall = CApply (cVar fun) args
297+ body = if isDataArg' ret
298+ then Ccase (getPosition di) fcall [CCaseArm (CPCon tgt [CPVar id_y]) [] (cVar id_y)]
299+ -- [CLMatch (CPCon tgt [CPVar id_y]) fcall] (cVar id_y)
300+ else fcall
301+ in CDef fun (CQType preds $ uncurry cTApplys tys) [CClause pats [] body]
302+ mkFun :: CField -> CDefl
303+ mkFun f = CLValueSign (mkCDef f) []
304+ in Right $ pure $ Cinstance (CQType ctx applied) (traceShowId $ map mkFun fs)
305+
306+ doDataVia _ _ _ _ _ _ _ (di, tgt) =
307+ Left (getPosition di, ECannotDerive (pfpString di ++ " via " ++ pfpString tgt))
244308
245309-- -------------------------
246310
@@ -876,6 +940,11 @@ genericRepWrapName pos tid isData cid fid = mkId pos $ concatFString $
876940
877941-- -------------------------
878942
943+ doVia :: Position -> Id -> [Type ] -> CFields -> CDefn
944+ doVia dpos ti vs fields = undefined
945+
946+ -- -------------------------
947+
879948eNot :: CExpr -> CExpr
880949eNot e = cVApply idNot [e]
881950eAnd :: CExpr -> CExpr -> CExpr
@@ -999,4 +1068,11 @@ getStockTC _ = []
9991068getStockDerivs :: [CDeriving ] -> [CTypeclass ]
10001069getStockDerivs = concatMap getStockTC
10011070
1071+ getViaTC :: CDeriving -> Maybe (CTypeclass , Id )
1072+ getViaTC (CVia tc id ) = Just (tc, id )
1073+ getViaTC _ = Nothing
1074+
1075+ getViaDerivs :: [CDeriving ] -> [(CTypeclass , Id )]
1076+ getViaDerivs = mapMaybe getViaTC
1077+
10021078-- -------------------------
0 commit comments