1 | module Deriving.DepTyCheck.Gen.ForOneType.Impl
3 | import public Data.Either
5 | import public Deriving.DepTyCheck.Gen.Labels
6 | import public Deriving.DepTyCheck.Gen.ForOneTypeCon.Impl
7 | import public Deriving.DepTyCheck.Gen.ForOneType.Interface
15 | defArgNames : {sig : GenSignature} -> Vect sig.givenParams.size Name
16 | defArgNames = sig.givenParams.asVect <&> argName' . index' sig.targetType.args
19 | canonicDefaultLHS' : (namesFun : Name -> Name) -> GenSignature -> Name -> (fuel : Name) -> TTImp
20 | canonicDefaultLHS' nmf sig n fuel = callCanonic sig n .| bindVar fuel .| bindVar . nmf <$> defArgNames
23 | canonicDefaultRHS' : (namesFun : Name -> Name) -> GenSignature -> Name -> (fuel : TTImp) -> TTImp
24 | canonicDefaultRHS' nmf sig n fuel = callCanonic sig n fuel .| var . nmf <$> defArgNames
27 | canonicDefaultLHS : GenSignature -> Name -> (fuel : Name) -> TTImp
28 | canonicDefaultLHS = canonicDefaultLHS' id
31 | canonicDefaultRHS : GenSignature -> Name -> (fuel : TTImp) -> TTImp
32 | canonicDefaultRHS = canonicDefaultRHS' id
39 | DeriveBodyRhsForCon => DeriveBodyForType where
40 | canonicBody sig n = do
43 | Prelude.when .| null sig.targetType.cons .| fail "No constructors found for the type `\{show sig.targetType.name}`"
46 | Prelude.when .| sig.targetType.name == `{Test.DepTyCheck.Gen.Gen
} .| fail "Target type of a derived `Gen` cannot be a `Gen`"
49 | let consClaims = sig.targetType.cons <&> \con => export' (consGenName con) (canonicSig sig)
52 | consBodies <- for sig.targetType.cons $
\con => logBounds Info "deptycheck.derive.consBody" [sig, con] $
53 | canonicConsBody sig (consGenName con) con <&> def (consGenName con)
56 | let Just consRecs = lookupConsWithWeight sig
57 | | Nothing => fail "INTERNAL ERROR: unknown type for consRecs: \{show sig.targetType.name}"
60 | let typesWithWeightFun = mapMaybe (usedWeightFun . snd) consRecs
63 | let fuelArg = "^fuel_arg^"
66 | let outmostRHS = fuelDecisionExpr fuelArg $
map @{Compose} weightExpr consRecs
69 | pure $
MkPair typesWithWeightFun [ canonicDefaultLHS' interimNamesWrapper sig n fuelArg .= local (consClaims ++ consBodies) outmostRHS ]
73 | consGenName : Con -> Name
74 | consGenName con = UN $
Basic $
"<<\{show con.name}>>"
77 | fuelDecisionExpr : (fuelArg : Name) -> List (Con, Either TTImp (Name -> TTImp)) -> TTImp
78 | fuelDecisionExpr fuelAr consRecs = do
80 | let callConstFreqs : CTLabel -> (fuel : TTImp) -> List (Con, TTImp) -> TTImp
81 | callConstFreqs l fuel cons = if isJust $
find (not . isWeight1 . snd) cons
82 | then callFrequency l $
cons <&> map (callConsGen fuel) . swap
83 | else callOneOf l $
cons <&> callConsGen fuel . fst
86 | let Nothing = for consRecs $
\(con, w) => (con,) <$> getLeft w
88 | | Just consRecs => callConstFreqs "\{logPosition sig} (non-spending)".label (var fuelAr) consRecs
91 | iCase .| var fuelAr .| var `{Data.Fuel.Fuel
} .|
94 | let nonSpendCons = mapMaybe (\(con, w) => (con,) <$> getLeft w) consRecs in
95 | var `{Data.Fuel.Dry
} .= callConstFreqs "\{logPosition sig} (dry fuel)".label (var fuelAr) nonSpendCons
99 | let subFuelArg = UN $
Basic $
"^sub" ++ show fuelAr
100 | let weightAndFuel = either ((var fuelAr,)) (\f => (var subFuelArg, f subFuelArg))
101 | var `{Data.Fuel.More
} .$ bindVar subFuelArg .= callFrequency "\{logPosition sig} (non-dry fuel)".label
102 | (consRecs <&> \(con, rec) => let (f, w) = weightAndFuel rec in (w, callConsGen f con))
107 | callConsGen : (fuel : TTImp) -> Con -> TTImp
108 | callConsGen fuel con = canonicDefaultRHS' interimNamesWrapper sig .| consGenName con .| fuel
111 | MainCoreDerivator : DeriveBodyRhsForCon => DeriveBodyForType
112 | MainCoreDerivator = %search