0 | module Language.Reflection.Unify.Interface
2 | import Control.Monad.Either
5 | import Data.SortedMap
7 | import Data.Vect.Quantifiers
8 | import Decidable.Equality
10 | import Language.Reflection
11 | import Language.Reflection.Compat
12 | import Language.Reflection.Expr
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
41 | sUT : Show UnificationTask
42 | sUT = %runElab derive
47 | constructor MkFVData
55 | piInfo : PiInfo TTImp
61 | %name FVData
fv, fvData
64 | sFVData : Show FVData
65 | sFVData = %runElab derive
69 | (MkFVData name holeName rig piInfo type value) == (MkFVData name' holeName' rig' piInfo' type' value') =
70 | name == name' && holeName == holeName' && rig == rig' && piInfo == piInfo' && type == type' && value == value'
73 | Interpolation FVData where
74 | interpolate (MkFVData n h r p t v) = concat {t=List} [ showPiInfo p $
showCount r "\{n} \{h} : \{show t}", " = \{show v}" ]
78 | makeFVData : (String, Arg, Name, TTImp, Maybe TTImp) -> FVData
79 | makeFVData (h, fv, n, t, v) = MkFVData n h fv.count fv.piInfo t v
82 | record FVDeps (freeVars : Nat) where
83 | constructor MkFVDeps
84 | typeDeps : FinSet freeVars
85 | valueDeps : FinSet freeVars
86 | piInfoDeps : FinSet freeVars
90 | {freeVars : Nat} -> Show (FVDeps freeVars) where
92 | showCon p "MkFVDeps" $
94 | [ showArg t.typeDeps
95 | , showArg t.valueDeps
96 | , showArg t.piInfoDeps
99 | {freeVars : Nat} -> Eq (FVDeps freeVars) where
100 | (==) a b = a.typeDeps == b.typeDeps && a.valueDeps == b.valueDeps && a.piInfoDeps == b.piInfoDeps
103 | mergeDeps : FVDeps fv -> FinSet fv
104 | mergeDeps (MkFVDeps typeDeps valueDeps piInfoDeps) = union typeDeps $
union valueDeps piInfoDeps
107 | removeDeps : FinSet fv -> FVDeps fv -> FVDeps fv
109 | { typeDeps $= flip difference d
110 | , valueDeps $= flip difference d
111 | , piInfoDeps $= flip difference d
116 | record DependencyGraph where
121 | fvData : Vect freeVars FVData
123 | fvDeps : Vect freeVars $
FVDeps freeVars
125 | empties : FinSet freeVars
127 | nameToId : SortedMap Name $
Fin freeVars
129 | holeToId : SortedMap String $
Fin freeVars
131 | %name DependencyGraph
dg, depGraph
135 | Show DependencyGraph where
139 | [ showArg t.freeVars
142 | , showArg t.empties
143 | , showArg t.nameToId
144 | , showArg t.holeToId
148 | Eq DependencyGraph where
149 | (==) (MkDG a b c d e f) (MkDG a' b' c' d' e' f') with (decEq a a')
150 | (==) (MkDG a b c d e f) (MkDG a b' c' d' e' f') | Yes Refl =
151 | b == b' && c == c' && d == d' && e == e' && f == f'
156 | record UnificationResult where
159 | task : UnificationTask
161 | uniDg : DependencyGraph
163 | lhsResult : SortedMap Name TTImp
165 | rhsResult : SortedMap Name TTImp
167 | fullResult : SortedMap Name TTImp
170 | order : List $
Fin uniDg.freeVars
174 | Show UnificationResult where
180 | , showArg t.lhsResult
181 | , showArg t.rhsResult
182 | , showArg t.fullResult
187 | data UnificationError : Type where
188 | CatastrophicError : UnificationError
189 | InternalError : String -> UnificationError
190 | TargetTypeError : TTImp -> UnificationError
191 | ExtractionError : TTImp -> UnificationError
192 | NoUnificationError : UnificationError
195 | sUE : Show UnificationError
196 | sUE = %runElab derive
199 | Eq UnificationError where
200 | CatastrophicError == CatastrophicError = True
201 | InternalError s == InternalError s' = s == s'
202 | TargetTypeError t == TargetTypeError t' = t == t'
203 | ExtractionError t == ExtractionError t' = t == t'
204 | NoUnificationError == NoUnificationError = True
208 | data UnificationVerdict : Type where
209 | Success : UnificationResult -> UnificationVerdict
210 | Undecided : UnificationVerdict
211 | Fail : UnificationError -> UnificationVerdict
214 | sUV : Show UnificationVerdict
215 | sUV = %runElab derive
218 | isSuccess : UnificationVerdict -> Bool
219 | isSuccess (Success _) = True
220 | isSuccess _ = False
223 | isUndecided : UnificationVerdict -> Bool
224 | isUndecided Undecided = True
225 | isUndecided _ = False
228 | isFail : UnificationVerdict -> Bool
229 | isFail (Fail _) = True
233 | Cast (Either (Maybe UnificationError) UnificationResult) UnificationVerdict where
234 | cast (Right s) = Success s
235 | cast (Left Nothing) = Undecided
236 | cast (Left $
Just e) = Fail e
239 | interface CanUnify (0 m : Type -> Type) where
240 | constructor MkCanUnify
241 | unify : UnificationTask -> m UnificationVerdict
244 | Monad m => MonadTrans t => CanUnify m => CanUnify (t m) where
245 | unify = lift . unify
248 | leaves : (dg : DependencyGraph) -> FinSet dg.freeVars
251 | (\acc,(id, deps) => if null deps then insert id acc else acc)
253 | zip (allFins dg.freeVars) (map mergeDeps dg.fvDeps)
256 | emptyLeaves : (dg : DependencyGraph) -> FinSet dg.freeVars
257 | emptyLeaves dg = intersection dg.empties $
leaves dg
262 | flattenEmpties : Monad m => (dg : DependencyGraph) -> m $
SnocList $
Fin dg.freeVars
263 | flattenEmpties dg = flattenEmpties' dg [<]
265 | flattenEmpties' : (dg : DependencyGraph) -> SnocList (Fin dg.freeVars) -> m $
SnocList $
Fin dg.freeVars
266 | flattenEmpties' dg@(MkDG {freeVars, fvData, fvDeps, empties, nameToId, holeToId}) ctx = do
267 | els <- pure $
id $
emptyLeaves dg
268 | let False = null els
273 | (assert_smaller dg $
MkDG
276 | (removeDeps els <$> fvDeps)
277 | (assert_smaller empties $
flip difference els empties)
280 | (ctx <>< toList els)
283 | filterEmpty : Vect _ FVData -> List (Name, TTImp)
284 | filterEmpty = foldl myfun []
286 | myfun : List (Name, TTImp) -> FVData -> List (Name, TTImp)
289 | Just val => (x.name, val) :: xs
296 | finalizeDG : Monad m => (task : UnificationTask) -> (dg : DependencyGraph) -> m UnificationResult
297 | finalizeDG task dg = do
298 | fvOrder <- flattenEmpties dg
299 | urList <- pure $
id $
filterEmpty dg.fvData
300 | (lhsRL, rhsRL) <- pure $
id $
List.splitAt task.lfv urList
304 | , lhsResult = fromList lhsRL
305 | , rhsResult = fromList rhsRL
306 | , fullResult = fromList urList
307 | , order = toList fvOrder