0 | module Deriving.DepTyCheck.Util.Specialisation
2 | import public Control.Monad.Either
4 | import public Data.DPair
5 | import public Data.List.Ex
6 | import public Data.List.Map
7 | import public Data.SortedMap
8 | import public Data.SortedMap.Extra
9 | import public Data.SortedSet
11 | import public Deriving.DepTyCheck.Gen.ForOneType.Interface
13 | import public Deriving.SpecialiseData
14 | import public Language.Reflection.Unify
16 | import public Data.Hashable
17 | import public Data.Hashable.Base
21 | allQImpl : Monad m => NamesInfoInTypes => TTImp -> TTImp -> m TTImp
22 | allQImpl (IPi {}) r = pure r
23 | allQImpl (IApp {}) (IApp _ (Implicit {}) _) = pure `(?
)
24 | allQImpl (IApp {}) r@(IApp {}) = pure r
25 | allQImpl (IApp {}) _ = pure `(?
)
26 | allQImpl v@(IVar _ n) _ =
27 | case lookupType n of
29 | Nothing => pure `(?
)
30 | allQImpl _ _ = pure `(?
)
35 | allQuestions : NamesInfoInTypes => TTImp -> TTImp
36 | allQuestions t = runIdentity $
mapMTTImp' allQImpl t
42 | constructor MkGenArg
46 | LogPosition GenArg where
47 | logPosition (MkGenArg a Nothing) = "\{fromMaybe "<unnamed arg>" a.name}"
48 | logPosition (MkGenArg a $
Just t) = "(\{fromMaybe "<unnamed arg>" a.name} := \{show t})"
50 | unGA : List GenArg -> (List Arg, List (Maybe TTImp))
52 | unGA (x :: xs) = let (ys, zs) = unGA xs in (x.arg :: ys, x.given :: zs)
54 | (.isGenerated) : GenArg -> Bool
55 | (.isGenerated) = isNothing . given
57 | (.isGiven) : GenArg -> Bool
58 | (.isGiven) = isJust . given
61 | (.isPassthrough) : Elaboration m => GenArg -> m Bool
62 | (.isPassthrough) (MkGenArg a Nothing) = pure True
63 | (.isPassthrough) (MkGenArg a $
Just g) = do
64 | let True = snd (unPi a.type) == `(Type)
79 | (sig : GenSignature) ->
80 | List (Fin sig.targetType.args.length, Arg) ->
81 | List (Fin sig.targetType.args.length, TTImp) ->
83 | mkArgs sig [] _ = []
84 | mkArgs sig ((_, x) :: xs) [] = MkGenArg x Nothing :: mkArgs sig xs []
85 | mkArgs sig ((i1, x) :: xs) g@((i2, y) :: ys) =
87 | then MkGenArg x (Just y) :: mkArgs sig xs ys
88 | else MkGenArg x Nothing :: mkArgs sig xs g
90 | singleArg : NamesInfoInTypes => Nat -> GenArg -> (TTImp, List GenArg)
91 | singleArg n (MkGenArg a v) = do
92 | let n : Name = fromString "lam^\{show n}"
93 | (IVar EmptyFC n, [MkGenArg (MkArg a.count a.piInfo (Just n) $
allQuestions a.type) v])
95 | processArg : MonadLog m => NamesInfoInTypes => GenSignature -> Nat -> GenArg -> m (TTImp, List GenArg)
97 | processArgs' : MonadLog m => NamesInfoInTypes => GenSignature -> Nat -> List GenArg -> m (List AnyApp, List GenArg)
98 | processArgs' sig k [] = pure ([], [])
99 | processArgs' sig k (x :: xs) = do
100 | (aT, l) <- assert_total $
processArg sig k x
101 | (recAA, l') <- processArgs' sig (k + length l) xs
102 | pure (appArg x.arg aT :: recAA, l ++ l')
104 | processArg sig argIdx ga with (ga.given)
105 | processArg sig argIdx ga | Nothing =
106 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
107 | "No given value, passing through"
108 | $
singleArg argIdx ga
109 | processArg sig argIdx ga | Just x = do
110 | let (appLhs, appTerms) = unAppAny x
111 | let IVar _ tyName = appLhs
112 | | IPrimVal _ (PrT _) =>
113 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
114 | "Given a primitive type invocation, specialising"
117 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
118 | "Given value head is not a variable, passing through"
119 | $
singleArg argIdx ga
120 | case lookupType tyName of
122 | let (_ :: _) = appTerms
124 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
125 | "Given a type invocation w/o arguments, specialising"
127 | let givens = map (uncurry MkGenArg) $
zip tyInfo.args $
popArgVals tyInfo.args (mkAllApps appTerms)
128 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
129 | "Given a type invocation, traversing arguments: \{show $ map (fromMaybe "" . name . arg) givens}"
130 | map (mapFst $
reAppAny appLhs) $
processArgs' sig argIdx $
takeWhile (.isGiven) givens
132 | if (snd (unPi ga.arg.type) == `(Type))
134 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
135 | "Given a non-global type expr, passing through"
136 | $
singleArg argIdx ga
138 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig, ga]
139 | "Given a non-type expr, passing through"
140 | $
singleArg argIdx ga
144 | NamesInfoInTypes =>
145 | (sig : GenSignature) ->
147 | m (TTImp, List Arg, List $
Maybe TTImp)
148 | processArgs sig ga = bimap (reAppAny $
IVar EmptyFC sig.targetType.name) unGA <$> processArgs' sig 0 ga
155 | formGivenVals : (s : SortedSet _) -> List TTImp -> Vect s.size TTImp
156 | formGivenVals a b = fgvImpl (Vect.fromList $
Prelude.toList a) b
158 | fgvImpl : Vect l _ -> List TTImp -> Vect l TTImp
160 | fgvImpl (_ :: xs) [] = `(_) :: fgvImpl xs []
161 | fgvImpl (x :: xs) (y :: ys) = y :: fgvImpl xs ys
163 | genGivens : List (TTImp, Fin x, Arg) -> (s : SortedSet (Fin x) ** Vect s.size TTImp)
165 | let (l1, l2, l3) = unzip3 l
166 | let s = SortedSet.fromList l2
167 | let gv = formGivenVals s l1
171 | specTaskToName : Monad m => TTImp -> m Name
172 | specTaskToName t = do
173 | let (_, lamBody) = unLambda t
174 | let (callee, _) = unAppAny lamBody
177 | (IVar _ n) => show $
snd $
unNS n
179 | hash <- pure $
show $
hash t
180 | pure $
fromString "\{vname}^\{hash}.\{vname}^\{hash}"
182 | nameUnambigAndVis : Elaboration m => Name -> m Bool
183 | nameUnambigAndVis n = do
185 | _ : Unit <- check `(let x = ~(var n) in ()
)
186 | pure True) (pure False)
188 | allConstructorsVisible : Elaboration m => TypeInfo -> m Bool
189 | allConstructorsVisible ti = do
190 | all id <$> traverse (nameUnambigAndVis . name) ti.cons
192 | mkDPairOfUnknowns : Nat -> (Name -> TTImp) -> TTImp -> TTImp
193 | mkDPairOfUnknowns 0 _ t = t
194 | mkDPairOfUnknowns (S n) helper t = do
195 | let nn = fromString $
"dph^\{show n}"
196 | `(MkDPair
~(helper nn) ~(mkDPairOfUnknowns n helper t))
198 | dPairOfUnknowns : Nat -> TTImp
199 | dPairOfUnknowns 0 = `(?
)
200 | dPairOfUnknowns (S n) = `(DPair ? $
\_ => ~(dPairOfUnknowns n))
202 | inSameNS : (nsSource: Name) -> Name -> Name
203 | inSameNS (NS ns _) n = NS ns n
207 | specialiseIfNeeded :
209 | NamesInfoInTypes =>
211 | DerivationClosure m =>
212 | (sig : GenSignature) ->
214 | Vect sig.givenParams.size TTImp ->
216 | specialiseIfNeeded sig fuel givenParamValues = do
217 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "Checking specialisation need for \{show givenParamValues}..."
219 | let True = any (\a => snd (unPi a.type) == `(Type)) $
index' sig.targetType.args <$> Prelude.toList sig.givenParams
221 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig]
222 | "Not found any given type args, specialisation not needed."
225 | True <- allConstructorsVisible sig.targetType
227 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig]
228 | "\{sig.targetType.name} has invisible constructors, specialisation impossible."
231 | let givenIdxVals = Prelude.toList sig.givenParams `zipV` givenParamValues
232 | let genArgs = mkArgs sig (withIndex sig.targetType.args) givenIdxVals
236 | False <- all id <$> traverse (.isPassthrough) genArgs
238 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig]
239 | "Not found any type arguments that can be specialised upon, specialisation impossible."
242 | (lambdaRet, fvArgs, givenSubst) <- processArgs sig genArgs
243 | let preNorm = foldr lam lambdaRet fvArgs
244 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "Task before normalisation: \{show preNorm}"
246 | (lambdaTy, lambdaBody) <- normaliseTask fvArgs lambdaRet
247 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "NormaliseTask returned: lambdaTy = \{show lambdaTy};"
248 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] " lambdaBody = \{show lambdaBody};"
250 | specName <- specTaskToName lambdaBody
251 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "Specialised type name: \{show specName}"
253 | (specTy, specDecls) : (TypeInfo, List Decl) <- case lookupType specName of
256 | info <- try (Just <$> getInfo' specName) (pure Nothing)
260 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "Specialised type not found, deriving..."
262 | NS nsn _ <- inCurrentNS ""
263 | | _ => fail "Internal error: inCurrentNS did not return NS"
265 | Right (specTy, specDecls) <- runEitherT {m} {e=SpecialisationError} $
266 | specialiseDataRaw {nsProvider = inNS thisNS} specName lambdaTy lambdaBody
267 | | Left err => fail "INTERNAL ERROR: Specialisation \{show lambdaBody} failed with error \{show err}."
268 | logPoint DetailedDebug "deptycheck.derive.specialisation" [sig] "Derived \{show specTy.name}"
271 | specTy <- getInfo' specName
272 | logValue Trace "deptycheck.derive.specialisation" [sig]
273 | "Declared specialised type \{show specTy.name}: \{show lambdaRet}"
276 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig]
277 | "Found \{show specTy.name}"
280 | logValue DetailedDebug "deptycheck.derive.specialisation" [sig]
281 | "Found \{show specTy.name}"
284 | let Yes stNamed = areAllTyArgsNamed specTy
285 | | No _ => fail "INTERNAL ERROR: Specialised type \{show specTy.name} does not have fully named arguments and constructors."
287 | let (
newGP ** newGVals)
= genGivens $
mapMaybe (\(a,b) => map (,b) a) $
zip givenSubst $
withIndex specTy.args
289 | (inv, cg_rhs) <- callGen (MkGenSignature specTy newGP) fuel newGVals
290 | let inv : TTImp = case cg_rhs of
292 | Just (
n ** perm)
=> reorderGend False perm inv
294 | let generateds = sig.targetType.args.length `minus` sig.givenParams.size
297 | then `(map
(cast
@{~(var $
inSameNS specTy.name "mToP")}) $
~inv)
299 | `(the
(Gen MaybeEmpty
~(dPairOfUnknowns generateds)) $ map
(\invv =>
301 | ~(mkDPairOfUnknowns generateds bindVar (bindVar "inv")) =>
302 | ~(mkDPairOfUnknowns generateds var `(cast
@{~(var $
inSameNS specTy.name "mToP")} inv
))) ~inv)