Skip to content

Commit 1421449

Browse files
committed
Initial deriving
This actually generates some plausibly passing code
1 parent ac16af8 commit 1421449

1 file changed

Lines changed: 78 additions & 2 deletions

File tree

src/comp/Deriving.hs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import FStringCompat
5959

6060
import 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
100103
doDer 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 =
241244
doStructDer _ _ _ 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+
879948
eNot :: CExpr -> CExpr
880949
eNot e = cVApply idNot [e]
881950
eAnd :: CExpr -> CExpr -> CExpr
@@ -999,4 +1068,11 @@ getStockTC _ = []
9991068
getStockDerivs :: [CDeriving] -> [CTypeclass]
10001069
getStockDerivs = 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

Comments
 (0)