@@ -1,72 +1,72 @@
11-- | Check universe constraints.
22module Idris.Core.Constraints ( ucheck ) where
33
4−import Idris.Core.TT ( TC(..), UExp(..), UConstraint(..), FC(..), Err'(..) )
4+import Idris.Core.TT ( TC(..), UExp(..), UConstraint(..), FC(..),
5+ ConstraintFC(..), Err'(..) )
56
67import Control.Applicative
78import Control.Monad.State.Strict
8−import Data.Function ( on )
9−import Data.List ( partition, nubBy )
9+import Data.List ( partition )
1010import qualified Data.Map.Strict as M
1111import qualified Data.Set as S
1212
1313
1414-- | Check that a list of universe constraints can be satisfied.
15−ucheck :: [(UConstraint, FC)] -> TC ()
16−ucheck = void . solve 10 . nubBy ((==) `on` fst) . filter (not . ignore)
15+ucheck :: S.Set ConstraintFC -> TC ()
16+ucheck = void . solve 10 . S.filter (not . ignore)
1717 where
1818 -- TODO: remove the first ignore clause once Idris.Core.Binary:598 is dealt with
19− ignore (c,_) | any (== Var (-1)) (varsIn c) = True
20− ignore (ULE a b, _) = a == b
19+ ignore (ConstraintFC c _) | any (== Var (-1)) (varsIn c) = True
20+ ignore (ConstraintFC (ULE a b) _) = a == b
2121 ignore _ = False
2222
2323newtype Var = Var Int
2424 deriving (Eq, Ord, Show)
2525
26−data Domain = Domain {-# UNPACK #-} !Int
27− {-# UNPACK #-} !Int
26+data Domain = Domain Int Int
2827 deriving (Eq, Ord, Show)
2928
3029data SolverState =
3130 SolverState
3231 { queue :: Queue
3332 , domainStore :: M.Map Var ( Domain
34− , S.Set (UConstraint, FC) -- constraints that effected this variable
33+ , S.Set ConstraintFC -- constraints that effected this variable
3534 )
3635 }
3736
38−data Queue = Queue [(UConstraint, FC)] (S.Set UConstraint)
37+data Queue = Queue [ConstraintFC] (S.Set UConstraint)
3938
4039
41−solve :: Int -> [(UConstraint, FC)] -> TC (M.Map Var Int)
42−solve maxUniverseLevel inpConstraints =
40+solve :: Int -> S.Set ConstraintFC -> TC (M.Map Var Int)
41+solve maxUniverseLevel ucs =
4342 evalStateT (propagate >> extractSolution) initSolverState
4443
4544 where
45+ inpConstraints = S.toAscList ucs
4646
4747 -- | initial solver state.
4848 -- the queue contains all constraints, the domain store contains the initial domains.
4949 initSolverState :: SolverState
5050 initSolverState =
5151 let
52− (initUnaryQueue, initQueue) = partition (\ (c,_) -> length (varsIn c) == 1) inpConstraints
52+ (initUnaryQueue, initQueue) = partition (\ c -> length (varsIn (uconstraint c)) == 1) inpConstraints
5353 in
5454 SolverState
55− { queue = Queue (initUnaryQueue ++ initQueue) (S.fromList (map fst (initUnaryQueue ++ initQueue)))
55+ { queue = Queue (initUnaryQueue ++ initQueue) (S.fromList (map uconstraint (initUnaryQueue ++ initQueue)))
5656 , domainStore = M.fromList
5757 [ (v, (Domain 0 maxUniverseLevel, S.empty))
5858 | v <- ordNub [ v
59− | (c, _) <- inpConstraints
59+ | ConstraintFC c _ <- inpConstraints
6060 , v <- varsIn c
6161 ]
6262 ]
6363 }
6464
6565 -- | a map from variables to the list of constraints the variable occurs in.
66− constraints :: M.Map Var (S.Set (UConstraint, FC))
66+ constraints :: M.Map Var (S.Set ConstraintFC)
6767 constraints = M.fromListWith S.union
68− [ (v, S.singleton (c,fc))
69− | (c, fc) <- inpConstraints
68+ [ (v, S.singleton (ConstraintFC c fc))
69+ | ConstraintFC c fc <- inpConstraints
7070 , let vars = varsIn c
7171 , length vars > 1 -- do not register unary constraints
7272 , v <- vars
@@ -82,20 +82,20 @@ solve maxUniverseLevel inpConstraints =
8282 mcons <- nextConstraint
8383 case mcons of
8484 Nothing -> return ()
85− Just (cons, fc) -> do
85+ Just (ConstraintFC cons fc) -> do
8686 case cons of
8787 ULE a b -> do
8888 Domain lowerA upperA <- domainOf a
8989 Domain lowerB upperB <- domainOf b
90− when (upperB < upperA) $ updateDomainOf (cons, fc) a (Domain lowerA upperB)
91− when (lowerA > lowerB) $ updateDomainOf (cons, fc) b (Domain lowerA upperB)
90+ when (upperB < upperA) $ updateDomainOf (ConstraintFC cons fc) a (Domain lowerA upperB)
91+ when (lowerA > lowerB) $ updateDomainOf (ConstraintFC cons fc) b (Domain lowerA upperB)
9292 ULT a b -> do
9393 Domain lowerA upperA <- domainOf a
9494 Domain lowerB upperB <- domainOf b
9595 let upperB_pred = pred upperB
9696 let lowerA_succ = succ lowerA
97− when (upperB_pred < upperA) $ updateDomainOf (cons, fc) a (Domain lowerA upperB_pred)
98− when (lowerA_succ > lowerB) $ updateDomainOf (cons, fc) b (Domain lowerA_succ upperB)
97+ when (upperB_pred < upperA) $ updateDomainOf (ConstraintFC cons fc) a (Domain lowerA upperB_pred)
98+ when (lowerA_succ > lowerB) $ updateDomainOf (ConstraintFC cons fc) b (Domain lowerA_succ upperB)
9999 propagate
100100
101101 -- | extract a solution from the state.
@@ -106,13 +106,13 @@ solve maxUniverseLevel inpConstraints =
106106 extractValue (Domain x _) = x
107107
108108 -- | dequeue the first constraint.
109− nextConstraint :: MonadState SolverState m => m (Maybe (UConstraint, FC))
109+ nextConstraint :: MonadState SolverState m => m (Maybe ConstraintFC)
110110 nextConstraint = do
111111 Queue list set <- gets queue
112112 case list of
113113 [] -> return Nothing
114114 (q:qs) -> do
115− modify $ \ st -> st { queue = Queue qs (S.delete (fst q) set) }
115+ modify $ \ st -> st { queue = Queue qs (S.delete (uconstraint q) set) }
116116 return (Just q)
117117
118118 -- | look up the domain of a variable from the state.
@@ -123,11 +123,11 @@ solve maxUniverseLevel inpConstraints =
123123
124124 -- | updates the domain of a variable.
125125 -- this function is also where we fail, inc ase of a domain wipe-out.
126− updateDomainOf :: (UConstraint, FC) -> UExp -> Domain -> StateT SolverState TC ()
126+ updateDomainOf :: ConstraintFC -> UExp -> Domain -> StateT SolverState TC ()
127127 updateDomainOf suspect (UVar var) newDom = do
128128 doms <- gets domainStore
129129 let (oldDom, suspects) = doms M.! Var var
130− when (wipeOut newDom) $ lift $ Error $ At (snd suspect) $ Msg $ unlines
130+ when (wipeOut newDom) $ lift $ Error $ At (ufc suspect) $ Msg $ unlines
131131 $ "Universe inconsistency."
132132 : ("Working on: " ++ show (UVar var))
133133 : ("Old domain: " ++ show oldDom)
@@ -145,11 +145,14 @@ solve maxUniverseLevel inpConstraints =
145145 Nothing -> return ()
146146 Just cs -> do
147147 Queue list set <- gets queue
148− let newCons = [ c | c <- S.toList cs, fst c `S.notMember` set ]
148+ let newCons = [ c | c <- S.toList cs, uconstraint c `S.notMember` set ]
149149 if null newCons
150150 then return ()
151151 else modify $ \ st -> st { queue = Queue (list ++ newCons)
152− (S.union set (S.fromList (map fst newCons))) }
152+ (insertAll (map uconstraint newCons) set) }
153+
154+ insertAll [] s = s
155+ insertAll (x : xs) s = insertAll xs (S.insert x s)
153156
154157 -- | check if a domain is wiped out.
155158 wipeOut :: Domain -> Bool