0 | module Language.Reflection.Unify.Interface
2 | import Control.Monad.Either
5 | import Data.SortedMap
7 | import Decidable.Equality
8 | import Derive.Prelude
9 | import Language.Reflection
10 | import Language.Reflection.Expr
11 | import Language.Reflection.TTImp
12 | import Language.Reflection.TT
13 | import Language.Reflection.Syntax
15 | %language ElabReflection
21 | record UnificationTask where
22 | constructor MkUniTask
26 | lhsFreeVars : Vect lfv Arg
27 | {auto 0 lhsAreNamed : All IsNamedArg lhsFreeVars}
33 | rhsFreeVars : Vect rfv Arg
34 | {auto 0 rhsAreNamed : All IsNamedArg rhsFreeVars}
38 | %name UnificationTask
task
40 | %runElab derive "Count" [Show]
41 | %runElab derive "PiInfo" [Show]
42 | %runElab derive "Syntax.Arg" [Show]
45 | Show UnificationTask where
47 | showCon p "MkUniTask" $
50 | , showArg t.lhsFreeVars
53 | , showArg t.rhsFreeVars
60 | constructor MkFVData
68 | piInfo : PiInfo TTImp
74 | %name FVData
fv, fvData
76 | %runElab derive "FVData" [Show, Eq]
79 | Interpolation FVData where
80 | interpolate (MkFVData n h r p t v) = joinBy "" [ showPiInfo p $
showCount r "\{n} \{h} : \{show t}", " = \{show v}" ]
84 | makeFVData : (String, Arg, Name, TTImp, Maybe TTImp) -> FVData
85 | makeFVData (h, fv, n, t, v) = MkFVData n h fv.count fv.piInfo t v
88 | record FVDeps (freeVars : Nat) where
89 | constructor MkFVDeps
90 | typeDeps : FinSet freeVars
91 | valueDeps : FinSet freeVars
92 | piInfoDeps : FinSet freeVars
96 | {freeVars : Nat} -> Show (FVDeps freeVars) where
98 | showCon p "MkFVDeps" $
100 | [ showArg t.typeDeps
101 | , showArg t.valueDeps
102 | , showArg t.piInfoDeps
105 | {freeVars : Nat} -> Eq (FVDeps freeVars) where
106 | (==) a b = a.typeDeps == b.typeDeps && a.valueDeps == b.valueDeps && a.piInfoDeps == b.piInfoDeps
109 | mergeDeps : FVDeps fv -> FinSet fv
110 | mergeDeps (MkFVDeps typeDeps valueDeps piInfoDeps) = union typeDeps $
union valueDeps piInfoDeps
113 | removeDeps : FinSet fv -> FVDeps fv -> FVDeps fv
115 | { typeDeps $= flip difference d
116 | , valueDeps $= flip difference d
117 | , piInfoDeps $= flip difference d
122 | record DependencyGraph where
127 | fvData : Vect freeVars FVData
129 | fvDeps : Vect freeVars $
FVDeps freeVars
131 | empties : FinSet freeVars
133 | nameToId : SortedMap Name $
Fin freeVars
135 | holeToId : SortedMap String $
Fin freeVars
137 | %name DependencyGraph
dg, depGraph
139 | %runElab derive "DependencyGraph" [Show]
142 | Eq DependencyGraph where
143 | (==) (MkDG a b c d e f) (MkDG a' b' c' d' e' f') with (decEq a a')
144 | (==) (MkDG a b c d e f) (MkDG a b' c' d' e' f') | Yes Refl =
145 | b == b' && c == c' && d == d' && e == e' && f == f'
150 | record UnificationResult where
153 | task : UnificationTask
155 | uniDg : DependencyGraph
157 | lhsResult : SortedMap Name TTImp
159 | rhsResult : SortedMap Name TTImp
161 | fullResult : SortedMap Name TTImp
164 | order : List $
Fin uniDg.freeVars
166 | %runElab derive "UnificationResult" [Show]
169 | data UnificationError : Type where
170 | CatastrophicError : UnificationError
171 | InternalError : String -> UnificationError
172 | TargetTypeError : TTImp -> UnificationError
173 | ExtractionError : TTImp -> UnificationError
174 | NoUnificationError : UnificationError
176 | %runElab derive "UnificationError" [Show, Eq]
179 | data UnificationVerdict : Type where
180 | Success : UnificationResult -> UnificationVerdict
181 | Undecided : UnificationVerdict
182 | Fail : UnificationError -> UnificationVerdict
184 | %runElab derive "UnificationVerdict" [Show]
187 | isSuccess : UnificationVerdict -> Bool
188 | isSuccess (Success _) = True
189 | isSuccess _ = False
192 | isUndecided : UnificationVerdict -> Bool
193 | isUndecided Undecided = True
194 | isUndecided _ = False
197 | isFail : UnificationVerdict -> Bool
198 | isFail (Fail _) = True
202 | Cast (Either (Maybe UnificationError) UnificationResult) UnificationVerdict where
203 | cast (Right s) = Success s
204 | cast (Left Nothing) = Undecided
205 | cast (Left $
Just e) = Fail e
208 | interface CanUnify (0 m : Type -> Type) where
209 | constructor MkCanUnify
210 | unify : UnificationTask -> m UnificationVerdict
213 | Monad m => MonadTrans t => CanUnify m => CanUnify (t m) where
214 | unify = lift . unify
217 | leaves : (dg : DependencyGraph) -> FinSet dg.freeVars
220 | (\acc,(id, deps) => if null deps then insert id acc else acc)
222 | zip (allFins dg.freeVars) (map mergeDeps dg.fvDeps)
225 | emptyLeaves : (dg : DependencyGraph) -> FinSet dg.freeVars
226 | emptyLeaves dg = intersection dg.empties $
leaves dg
229 | flattenEmpties : (dg : DependencyGraph) -> SnocList $
Fin dg.freeVars
230 | flattenEmpties dg = flattenEmpties' dg [<]
232 | flattenEmpties' : (dg : DependencyGraph) -> SnocList (Fin dg.freeVars) -> SnocList $
Fin dg.freeVars
233 | flattenEmpties' dg@(MkDG {freeVars, fvData, fvDeps, empties, nameToId, holeToId}) ctx = do
234 | let els = emptyLeaves dg
235 | let False = null els
240 | (assert_smaller dg $
MkDG
243 | (removeDeps els <$> fvDeps)
244 | (assert_smaller empties $
flip difference els empties)
247 | (ctx <>< toList els)
250 | filterEmpty : Vect _ FVData -> List (Name, TTImp)
251 | filterEmpty = foldl myfun []
253 | myfun : List (Name, TTImp) -> FVData -> List (Name, TTImp)
256 | Just val => (x.name, val) :: xs
261 | finalizeDG : (task : UnificationTask) -> (dg : DependencyGraph) -> UnificationResult
262 | finalizeDG task dg = do
263 | let fvOrder = flattenEmpties dg
264 | let urList = filterEmpty dg.fvData
265 | let (lhsRL, rhsRL) = List.splitAt task.lfv urList
269 | , lhsResult = fromList lhsRL
270 | , rhsResult = fromList rhsRL
271 | , fullResult = fromList urList
272 | , order = toList fvOrder