@@ -1,72 +1,72 @@
1-- | Check universe constraints.
1-- | Check universe constraints.
2module Idris.Core.Constraints ( ucheck ) where
2module Idris.Core.Constraints ( ucheck ) where
4−import Idris.Core.TT ( TC(..), UExp(..), UConstraint(..), FC(..), Err'(..) )
4+import Idris.Core.TT ( TC(..), UExp(..), UConstraint(..), FC(..),
5+ ConstraintFC(..), Err'(..) )
6import Control.Applicative
7import Control.Applicative
7import Control.Monad.State.Strict
8import Control.Monad.State.Strict
8−import Data.Function ( on )
9−import Data.List ( partition, nubBy )
9+import Data.List ( partition )
10import qualified Data.Map.Strict as M
10import qualified Data.Map.Strict as M
11import qualified Data.Set as S
11import qualified Data.Set as S
14-- | Check that a list of universe constraints can be satisfied.
14-- | Check that a list of universe constraints can be satisfied.
15−ucheck :: [(UConstraint, FC)] -> TC ()
15+ucheck :: S.Set ConstraintFC -> TC ()
16−ucheck = void . solve 10 . nubBy ((==) `on` fst) . filter (not . ignore)
16+ucheck = void . solve 10 . S.filter (not . ignore)
18 -- TODO: remove the first ignore clause once Idris.Core.Binary:598 is dealt with
18 -- TODO: remove the first ignore clause once Idris.Core.Binary:598 is dealt with
19− ignore (c,_) | any (== Var (-1)) (varsIn c) = True
19+ ignore (ConstraintFC c _) | any (== Var (-1)) (varsIn c) = True
20− ignore (ULE a b, _) = a == b
20+ ignore (ConstraintFC (ULE a b) _) = a == b
21 ignore _ = False
21 ignore _ = False
23newtype Var = Var Int
23newtype Var = Var Int
24 deriving (Eq, Ord, Show)
24 deriving (Eq, Ord, Show)
26−data Domain = Domain {-# UNPACK #-} !Int
26+data Domain = Domain Int Int
28 deriving (Eq, Ord, Show)
27 deriving (Eq, Ord, Show)
30data SolverState =
29data SolverState =
31 SolverState
30 SolverState
32 { queue :: Queue
31 { queue :: Queue
33 , domainStore :: M.Map Var ( Domain
32 , domainStore :: M.Map Var ( Domain
34− , S.Set (UConstraint, FC) -- constraints that effected this variable
33+ , S.Set ConstraintFC -- constraints that effected this variable
38−data Queue = Queue [(UConstraint, FC)] (S.Set UConstraint)
37+data Queue = Queue [ConstraintFC] (S.Set UConstraint)
41−solve :: Int -> [(UConstraint, FC)] -> TC (M.Map Var Int)
40+solve :: Int -> S.Set ConstraintFC -> TC (M.Map Var Int)
42−solve maxUniverseLevel inpConstraints =
41+solve maxUniverseLevel ucs =
43 evalStateT (propagate >> extractSolution) initSolverState
42 evalStateT (propagate >> extractSolution) initSolverState
45+ inpConstraints = S.toAscList ucs
47 -- | initial solver state.
47 -- | initial solver state.
48 -- the queue contains all constraints, the domain store contains the initial domains.
48 -- the queue contains all constraints, the domain store contains the initial domains.
49 initSolverState :: SolverState
49 initSolverState :: SolverState
50 initSolverState =
50 initSolverState =
52− (initUnaryQueue, initQueue) = partition (\ (c,_) -> length (varsIn c) == 1) inpConstraints
52+ (initUnaryQueue, initQueue) = partition (\ c -> length (varsIn (uconstraint c)) == 1) inpConstraints
54 SolverState
54 SolverState
55− { queue = Queue (initUnaryQueue ++ initQueue) (S.fromList (map fst (initUnaryQueue ++ initQueue)))
55+ { queue = Queue (initUnaryQueue ++ initQueue) (S.fromList (map uconstraint (initUnaryQueue ++ initQueue)))
56 , domainStore = M.fromList
56 , domainStore = M.fromList
57 [ (v, (Domain 0 maxUniverseLevel, S.empty))
57 [ (v, (Domain 0 maxUniverseLevel, S.empty))
58 | v <- ordNub [ v
58 | v <- ordNub [ v
59− | (c, _) <- inpConstraints
59+ | ConstraintFC c _ <- inpConstraints
60 , v <- varsIn c
60 , v <- varsIn c
65 -- | a map from variables to the list of constraints the variable occurs in.
65 -- | 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)
67 constraints = M.fromListWith S.union
67 constraints = M.fromListWith S.union
68− [ (v, S.singleton (c,fc))
68+ [ (v, S.singleton (ConstraintFC c fc))
69− | (c, fc) <- inpConstraints
69+ | ConstraintFC c fc <- inpConstraints
70 , let vars = varsIn c
70 , let vars = varsIn c
71 , length vars > 1 -- do not register unary constraints
71 , length vars > 1 -- do not register unary constraints
72 , v <- vars
72 , v <- vars
@@ -82,20 +82,20 @@ solve maxUniverseLevel inpConstraints =
82 mcons <- nextConstraint
82 mcons <- nextConstraint
83 case mcons of
83 case mcons of
84 Nothing -> return ()
84 Nothing -> return ()
85− Just (cons, fc) -> do
85+ Just (ConstraintFC cons fc) -> do
86 case cons of
86 case cons of
87 ULE a b -> do
87 ULE a b -> do
88 Domain lowerA upperA <- domainOf a
88 Domain lowerA upperA <- domainOf a
89 Domain lowerB upperB <- domainOf b
89 Domain lowerB upperB <- domainOf b
90− when (upperB < upperA) $ updateDomainOf (cons, fc) a (Domain lowerA upperB)
90+ when (upperB < upperA) $ updateDomainOf (ConstraintFC cons fc) a (Domain lowerA upperB)
91− when (lowerA > lowerB) $ updateDomainOf (cons, fc) b (Domain lowerA upperB)
91+ when (lowerA > lowerB) $ updateDomainOf (ConstraintFC cons fc) b (Domain lowerA upperB)
92 ULT a b -> do
92 ULT a b -> do
93 Domain lowerA upperA <- domainOf a
93 Domain lowerA upperA <- domainOf a
94 Domain lowerB upperB <- domainOf b
94 Domain lowerB upperB <- domainOf b
95 let upperB_pred = pred upperB
95 let upperB_pred = pred upperB
96 let lowerA_succ = succ lowerA
96 let lowerA_succ = succ lowerA
97− when (upperB_pred < upperA) $ updateDomainOf (cons, fc) a (Domain lowerA upperB_pred)
97+ when (upperB_pred < upperA) $ updateDomainOf (ConstraintFC cons fc) a (Domain lowerA upperB_pred)
98− when (lowerA_succ > lowerB) $ updateDomainOf (cons, fc) b (Domain lowerA_succ upperB)
98+ when (lowerA_succ > lowerB) $ updateDomainOf (ConstraintFC cons fc) b (Domain lowerA_succ upperB)
101 -- | extract a solution from the state.
101 -- | extract a solution from the state.
@@ -106,13 +106,13 @@ solve maxUniverseLevel inpConstraints =
106 extractValue (Domain x _) = x
106 extractValue (Domain x _) = x
108 -- | dequeue the first constraint.
108 -- | dequeue the first constraint.
109− nextConstraint :: MonadState SolverState m => m (Maybe (UConstraint, FC))
109+ nextConstraint :: MonadState SolverState m => m (Maybe ConstraintFC)
110 nextConstraint = do
110 nextConstraint = do
111 Queue list set <- gets queue
111 Queue list set <- gets queue
112 case list of
112 case list of
113 [] -> return Nothing
113 [] -> return Nothing
114 (q:qs) -> do
114 (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) }
116 return (Just q)
116 return (Just q)
118 -- | look up the domain of a variable from the state.
118 -- | look up the domain of a variable from the state.
@@ -123,11 +123,11 @@ solve maxUniverseLevel inpConstraints =
124 -- | updates the domain of a variable.
124 -- | updates the domain of a variable.
125 -- this function is also where we fail, inc ase of a domain wipe-out.
125 -- 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 ()
127 updateDomainOf suspect (UVar var) newDom = do
127 updateDomainOf suspect (UVar var) newDom = do
128 doms <- gets domainStore
128 doms <- gets domainStore
129 let (oldDom, suspects) = doms M.! Var var
129 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
131 $ "Universe inconsistency."
131 $ "Universe inconsistency."
132 : ("Working on: " ++ show (UVar var))
132 : ("Working on: " ++ show (UVar var))
133 : ("Old domain: " ++ show oldDom)
133 : ("Old domain: " ++ show oldDom)
@@ -145,11 +145,14 @@ solve maxUniverseLevel inpConstraints =
145 Nothing -> return ()
145 Nothing -> return ()
146 Just cs -> do
146 Just cs -> do
147 Queue list set <- gets queue
147 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 ]
149 if null newCons
149 if null newCons
150 then return ()
150 then return ()
151 else modify $ \ st -> st { queue = Queue (list ++ newCons)
151 else modify $ \ st -> st { queue = Queue (list ++ newCons)
152− (S.union set (S.fromList (map fst newCons))) }
152+ (insertAll (map uconstraint newCons) set) }
155+ insertAll (x : xs) s = insertAll xs (S.insert x s)
154 -- | check if a domain is wiped out.
157 -- | check if a domain is wiped out.
155 wipeOut :: Domain -> Bool
158 wipeOut :: Domain -> Bool