0 | module Language.Reflection.Unify.WithCompiler
2 | import Control.Monad.Either
3 | import Control.Monad.Writer
4 | import Control.Monad.Identity
8 | import Data.Vect.Quantifiers
10 | import Data.SortedMap
11 | import Decidable.Equality
12 | import Language.Reflection
13 | import Language.Reflection.Expr
14 | import Language.Reflection.Logging
15 | import Language.Reflection.Syntax
16 | import Language.Reflection.Unify.Interface
17 | import Language.Reflection.VarSubst
24 | Vect freeVars FVData ->
25 | SortedMap Name $
Fin freeVars
27 | foldl (\acc, (i, fv) => insert fv.name i acc) empty (zip (allFins freeVars) fvs)
32 | Vect freeVars FVData ->
33 | SortedMap String $
Fin freeVars
35 | foldl (\acc, (i, fv) => insert fv.holeName i acc) empty (zip (allFins freeVars) fvs)
38 | {0 freeVars : Nat} ->
39 | MonadWriter (FinSet freeVars) m =>
40 | SortedMap String (Fin freeVars) ->
46 | let Just id = lookup s h2Id
48 | writer (h, insert id empty)
52 | {0 freeVars : Nat} ->
53 | SortedMap String (Fin freeVars) ->
56 | allMatchingHoles h2Id t = execWriter $
mapMTTImp (aMHImpl h2Id) t
58 | fromPiInfo : Lazy t -> PiInfo t -> t
59 | fromPiInfo _ (DefImplicit x) = x
65 | Vect freeVars FVData ->
66 | SortedMap String (Fin freeVars) ->
67 | Vect freeVars $
FVDeps freeVars
72 | (allMatchingHoles h2Id fv.type)
73 | (fromMaybe empty $
allMatchingHoles h2Id <$> fv.value)
74 | (fromPiInfo empty $
allMatchingHoles h2Id <$> fv.piInfo)
81 | Vect freeVars FVData ->
83 | genEmpties fvs = foldl genEmpties' empty $
zip (allFins freeVars) fvs
85 | genEmpties' : FinSet fv -> (Fin fv, FVData) -> FinSet fv
86 | genEmpties' set (i, fv) =
87 | if isNothing fv.value
94 | Vect freeVars FVData ->
97 | let h2Id = genHoleToId fvs
98 | MkDG freeVars fvs (genDeps fvs h2Id) (genEmpties fvs) (genNameToId fvs) h2Id
102 | (dg : DependencyGraph) ->
105 | flip difference dg.empties $
108 | if (flip difference dg.empties (mergeDeps deps)) == empty
112 | $
zip (allFins dg.freeVars) dg.fvDeps
114 | subMatchingHolesImpl :
115 | (dg : DependencyGraph) ->
116 | FinSet dg.freeVars ->
119 | subMatchingHolesImpl dg fbs ih@(IHole _ h) =
120 | case lookup h dg.holeToId of
124 | let fv = index id dg.fvData
125 | in fromMaybe ih fv.value
128 | subMatchingHolesImpl _ _ t = t
132 | (dg : DependencyGraph) ->
133 | FinSet dg.freeVars ->
136 | subMatchingHoles dg fbs = mapTTImp $
subMatchingHolesImpl dg fbs
140 | (dg: DependencyGraph) ->
141 | FinSet dg.freeVars ->
144 | fvSubMatching dg canSub =
145 | { type $= subMatchingHoles dg canSub
146 | , value $= map $
subMatchingHoles dg canSub
147 | , piInfo $= map $
subMatchingHoles dg canSub
150 | valDepsOfVar : (dg : DependencyGraph) -> Fin dg.freeVars -> FinSet dg.freeVars
151 | valDepsOfVar dg id = valueDeps $
index id dg.fvDeps
153 | valDepsOfVars : (dg : DependencyGraph) -> FinSet dg.freeVars -> FinSet dg.freeVars
154 | valDepsOfVars dg vars = foldl (\a, b => union (valDepsOfVar dg b) a) empty (toList vars)
157 | (dg: DependencyGraph) ->
158 | FinSet dg.freeVars ->
159 | (FVData, FVDeps dg.freeVars) ->
160 | (FVData, FVDeps dg.freeVars)
161 | fvSubMatching' dg canSub (fvData, MkFVDeps tyDeps valDeps piInfoDeps) = do
162 | let canSubTy = intersection tyDeps canSub
163 | let canSubVal = intersection valDeps canSub
164 | let canSubPiInfo = intersection piInfoDeps canSub
165 | let tyAddDeps = valDepsOfVars dg canSubTy
166 | let valAddDeps = valDepsOfVars dg canSubVal
167 | let piInfoAddDeps = valDepsOfVars dg canSubPiInfo
168 | let newTyDeps = union tyAddDeps (difference tyDeps canSubTy)
169 | let newValDeps = union valAddDeps (difference valDeps canSubVal)
170 | let newPiInfoDeps = union piInfoAddDeps (difference piInfoDeps canSubPiInfo)
171 | (fvSubMatching dg canSub fvData, MkFVDeps newTyDeps newValDeps newPiInfoDeps)
176 | (dg : DependencyGraph) ->
177 | FinSet dg.freeVars ->
179 | doSub dg canSub = do
180 | let (newFvData, newFvDeps) = unzip $
fvSubMatching' dg canSub <$> zip dg.fvData dg.fvDeps
181 | ({fvData := newFvData, fvDeps := newFvDeps} dg)
183 | subEmptiesTImpl : (dg : DependencyGraph) -> TTImp -> TTImp
184 | subEmptiesTImpl dg t@(IHole _ h) = do
185 | let Just id = lookup h dg.holeToId
187 | if contains id dg.empties
189 | let fv = index id dg.fvData
190 | in IVar EmptyFC fv.name
192 | subEmptiesTImpl dg t = t
194 | subEmptiesT : DependencyGraph -> TTImp -> TTImp
195 | subEmptiesT dg = mapTTImp $
subEmptiesTImpl dg
198 | (dg: DependencyGraph) ->
202 | { type $= subEmptiesT dg
203 | , value $= map $
subEmptiesT dg
208 | (dg : DependencyGraph) ->
210 | subEmpties dg = {fvData $= map $
subEmptiesFV dg} dg
215 | (dg : DependencyGraph) ->
219 | let False = null cs
221 | ds <- pure $
doSub dg cs
226 | else solveDG $
assert_smaller dg ds
229 | ArgDPair = Subset Arg IsNamedArg
234 | SnocVect l ArgDPair ->
235 | m $
(SortedMap Name String, SnocVect l String)
236 | genHoleNames [<] = pure (empty, [<])
237 | genHoleNames (xs :< (Element fv isNamed)) = do
239 | gs <- genSym $
show n
240 | (others, others') <- genHoleNames xs
241 | pure $
(insert n (show gs) others, others' :< show gs)
244 | buildUpDPair : SnocVect l ArgDPair -> TTImp -> TTImp
245 | buildUpDPair [<] t = t
246 | buildUpDPair (xs :< (Element fv isNamed)) t =
248 | `(Builtin.DPair.DPair
250 | ~(ILam EmptyFC MW ExplicitArg (Just $
argName fv) fv.type t))
253 | buildUpTarget : SnocVect l (String, ArgDPair) -> TTImp -> TTImp
254 | buildUpTarget [<] t = t
255 | buildUpTarget (xs :< (s, _)) t =
256 | buildUpTarget xs `((
~(IHole EmptyFC s) **
~t)
)
260 | MonadError (Maybe UnificationError) m =>
265 | m $
Vect l (Name, TTImp, Maybe TTImp)
266 | extractFVData t v ((Element fv isNamed) :: xs) (hn :: hns) = do
268 | DPair myTy dNext => do
269 | let (
vv ** vRest)
= v
271 | quoteT <- quote myTy
272 | rest <- extractFVData (dNext vv) vRest xs hns
276 | if hh == hn then Nothing else Just quoteV
278 | pure $
(argName fv, quoteT, retVal) :: rest
281 | throwError $
Just $
ExtractionError qT
282 | extractFVData t v [] [] = do
288 | INamedApp _ (INamedApp _ `(Builtin.Refl
) _ _) _ _ => pure ()
289 | _ => throwError $
Nothing
290 | _ => throwError $
Just $
InternalError "DPairs don't correspond to each other. Should never occur."
296 | MonadError (Maybe UnificationError) m =>
298 | m $
DependencyGraph
300 | let 0 allFVsNamed = task.lhsAreNamed ++ task.rhsAreNamed
301 | let allFreeVars = pushIn (task.lhsFreeVars ++ task.rhsFreeVars) allFVsNamed
302 | let snocLFV : SnocVect task.lfv _ =
303 | cast $
pushIn task.lhsFreeVars task.lhsAreNamed
304 | let snocRFV : SnocVect task.rfv _ =
305 | cast $
pushIn task.rhsFreeVars task.rhsAreNamed
306 | (lhsNMap, lhsNames) <- genHoleNames snocLFV
307 | (rhsNMap, rhsNames) <- genHoleNames snocRFV
308 | let hole2N = IHole EmptyFC <$> mergeLeft lhsNMap rhsNMap
309 | let allNames = lhsNames ++ rhsNames
311 | let checkTargetType =
312 | buildUpDPair snocLFV $
313 | buildUpDPair snocRFV `(~(task.lhsExpr) ~=~
~(task.rhsExpr))
316 | buildUpTarget (zip lhsNames snocLFV) $
317 | buildUpTarget (zip rhsNames snocRFV) `(Refl
)
318 | logPoint DetailedDebug "unifyWithCompiler" [] "Target type: \{show checkTargetType}"
319 | logPoint DetailedDebug "unifyWithCompiler" [] "Target value: \{show checkTarget}"
321 | Just checkTargetType' : Maybe Type <-
322 | try (Just <$> check checkTargetType) (pure Nothing)
323 | | _ => throwError $
Just $
TargetTypeError checkTargetType
325 | Just checkTarget' : Maybe checkTargetType' <-
326 | try (Just <$> check checkTarget) (pure Nothing)
327 | | _ => throwError $
Just NoUnificationError
328 | ctQuote <- quote checkTarget'
329 | logPoint DetailedDebug "unifyWithCompiler" [] "Target value after quoting: \{show ctQuote}"
330 | let vectNames = cast allNames
333 | extractFVData checkTargetType' checkTarget' allFreeVars vectNames
334 | logPoint DetailedDebug "unifyWithCompiler" [] "Raw unification results: \{show uniResults}"
336 | let allZipped = zip vectNames $
zip (task.lhsFreeVars ++ task.rhsFreeVars) uniResults
337 | let dg = genDG $
makeFVData <$> allZipped
338 | let dg = {fvData $= map {piInfo $= map $
substituteVariables hole2N}} dg
339 | logPoint DetailedDebug "unifyWithCompiler" [] "Initial DG: \{show dg}"
340 | let dg = subEmpties dg
341 | logPoint DetailedDebug "unifyWithCompiler" [] "DG after subEmpties: \{show dg}"
342 | solved <- solveDG dg
343 | logPoint DetailedDebug "unifyWithCompiler" [] "Solved DG: \{show solved}"
348 | unifyWithCompiler :
350 | MonadError (Maybe UnificationError) m =>
352 | m $
UnificationResult
353 | unifyWithCompiler task = do
354 | let ret = runEitherT {m=Elab} {e=Maybe UnificationError} $
unify' task
355 | let err = pure {f=Elab} $
Left $
Just CatastrophicError
357 | dg <- liftEither rr
358 | ur <- pure $
finalizeDG task dg
359 | logPoint DetailedDebug "unifyWithCompiler" [] "Unification result: \{show ur}"
364 | unifyWithCompiler' :
366 | MonadError (Maybe UnificationError) m =>
368 | m $
UnificationResult
369 | unifyWithCompiler' task = do
371 | pure $
finalizeDG task dg
374 | [UnifyWithCompiler]
375 | Elaboration m => CanUnify m where
376 | unify = map cast . runEitherT {m} {e=Maybe UnificationError} . unifyWithCompiler