@@ -1,6 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22
3−module Core.Unify(unify, Fails) where
3+module Core.Unify(match_unify, unify, Fails) where
44
55import Core.TT
66import Core.Evaluate
@@ -27,6 +27,66 @@ data UResult a = UOK a
2727 | UPartOK a
2828 | UFail Err
2929
30+-- Solve metavariables by matching terms against each other
31+-- Not really unification, of course!
32+
33+match_unify :: Context -> Env -> TT Name -> TT Name -> [Name] -> [Name] ->
34+ TC [(Name, TT Name)]
35+match_unify ctxt env topx topy dont holes =
36+-- trace ("Matching " ++ show (topx, topy)) $
37+ case runStateT (un [] topx topy) (UI 0 []) of
38+ OK (v, UI _ fails) -> return (filter notTrivial v)
39+ Error e -> tfail e
40+ where
41+ un names (P _ x _) tm
42+ | holeIn env x || x `elem` holes
43+ = do sc 1; checkCycle (x, tm)
44+ un names tm (P _ y _)
45+ | holeIn env y || y `elem` holes
46+ = do sc 1; checkCycle (y, tm)
47+ un names x y
48+ | OK True <- convEq' ctxt x y = do sc 1; return []
49+ un bnames (V i) (P _ x _)
50+ | fst (bnames!!i) == x || snd (bnames!!i) == x = do sc 1; return []
51+ un bnames (P _ x _) (V i)
52+ | fst (bnames!!i) == x || snd (bnames!!i) == x = do sc 1; return []
53+ un names (App fx ax) (App fy ay)
54+ = do hf <- un names fx fy
55+ ha <- un names ax ay
56+ combine names hf ha
57+
58+
59+ -- TODO: there's an annoying amount of repetition between this and the
60+ -- main unification function. Consider lifting it out.
61+
62+ sc i = do UI s f <- get
63+ put (UI (s+i) f)
64+
65+ unifyFail x y = do UI s f <- get
66+ let r = recoverable x y
67+ let err = CantUnify r
68+ topx topy (CantUnify r x y (Msg "") [] s) (errEnv env) s
69+ put (UI s ((x, y, env, err) : f))
70+ lift $ tfail err
71+ combine bnames as [] = return as
72+ combine bnames as ((n, t) : bs)
73+ = case lookup n as of
74+ Nothing -> combine bnames (as ++ [(n,t)]) bs
75+ Just t' -> do ns <- un bnames t t'
76+ -- make sure there's n mapping from n in ns
77+ let ns' = filter (\ (x, _) -> x/=n) ns
78+ sc 1
79+ combine bnames as (ns' ++ bs)
80+
81+ checkCycle p@(x, P _ _ _) = return [p]
82+ checkCycle (x, tm)
83+ | not (x `elem` freeNames tm) = return [(x, tm)]
84+ | otherwise = lift $ tfail (InfiniteUnify x tm (errEnv env))
85+
86+notTrivial (x, P _ x' _) = x /= x'
87+notTrivial _ = True
88+
89+
3090unify :: Context -> Env -> TT Name -> TT Name -> [Name] -> [Name] ->
3191 TC ([(Name, TT Name)], Fails)
3292unify ctxt env topx topy dont holes =
@@ -45,9 +105,6 @@ unify ctxt env topx topy dont holes =
45105-- Error e@(CantUnify False _ _ _ _ _) -> tfail e
46106 Error e -> tfail e
47107 where
48− notTrivial (x, P _ x' _) = x /= x'
49− notTrivial _ = True
50−
51108 headDiff (P (DCon _ _) x _) (P (DCon _ _) y _) = x /= y
52109 headDiff (P (TCon _ _) x _) (P (TCon _ _) y _) = x /= y
53110 headDiff _ _ = False
@@ -311,6 +368,7 @@ unify ctxt env topx topy dont holes =
311368 | not (x `elem` freeNames tm) = return [(x, tm)]
312369 | otherwise = lift $ tfail (InfiniteUnify x tm (errEnv env))
313370
371+
314372 combineArgs bnames args = ca [] args where
315373 ca acc [] = return acc
316374 ca acc (x : xs) = do x' <- combine bnames acc x
@@ -326,30 +384,30 @@ unify ctxt env topx topy dont holes =
326384 sc 1
327385 combine bnames as (ns' ++ bs)
328386
329− -- If there are any clashes of constructors, deem it unrecoverable, otherwise some
330− -- more work may help.
331− -- FIXME: Depending on how overloading gets used, this may cause problems. Better
332− -- rethink overloading properly...
333−
334− recoverable (P (DCon _ _) x _) (P (DCon _ _) y _)
335− | x == y = True
336− | otherwise = False
337− recoverable (P (TCon _ _) x _) (P (TCon _ _) y _)
338− | x == y = True
339− | otherwise = False
340− recoverable (Constant _) (P (DCon _ _) y _) = False
341− recoverable (P (DCon _ _) x _) (Constant _) = False
342− recoverable (Constant _) (P (TCon _ _) y _) = False
343− recoverable (P (TCon _ _) x _) (Constant _) = False
344− recoverable (P (DCon _ _) x _) (P (TCon _ _) y _) = False
345− recoverable (P (TCon _ _) x _) (P (DCon _ _) y _) = False
346− recoverable p@(Constant _) (App f a) = recoverable p f
347− recoverable (App f a) p@(Constant _) = recoverable f p
348− recoverable p@(P _ n _) (App f a) = recoverable p f
387+-- If there are any clashes of constructors, deem it unrecoverable, otherwise some
388+-- more work may help.
389+-- FIXME: Depending on how overloading gets used, this may cause problems. Better
390+-- rethink overloading properly...
391+
392+recoverable (P (DCon _ _) x _) (P (DCon _ _) y _)
393+ | x == y = True
394+ | otherwise = False
395+recoverable (P (TCon _ _) x _) (P (TCon _ _) y _)
396+ | x == y = True
397+ | otherwise = False
398+recoverable (Constant _) (P (DCon _ _) y _) = False
399+recoverable (P (DCon _ _) x _) (Constant _) = False
400+recoverable (Constant _) (P (TCon _ _) y _) = False
401+recoverable (P (TCon _ _) x _) (Constant _) = False
402+recoverable (P (DCon _ _) x _) (P (TCon _ _) y _) = False
403+recoverable (P (TCon _ _) x _) (P (DCon _ _) y _) = False
404+recoverable p@(Constant _) (App f a) = recoverable p f
405+recoverable (App f a) p@(Constant _) = recoverable f p
406+recoverable p@(P _ n _) (App f a) = recoverable p f
349407-- recoverable (App f a) p@(P _ _ _) = recoverable f p
350− recoverable (App f a) (App f' a')
351− = recoverable f f' -- && recoverable a a'
352− recoverable _ _ = True
408+recoverable (App f a) (App f' a')
409+ = recoverable f f' -- && recoverable a a'
410+recoverable _ _ = True
353411
354412errEnv = map (\(x, b) -> (x, binderTy b))
355413