@@ -1,5 +1,3 @@
1−{-# LANGUAGE FlexibleContexts #-}
3module Core.Constraints(ucheck) where
1module Core.Constraints(ucheck) where
5import Core.TT
3import Core.TT
@@ -14,13 +12,11 @@ import Data.Maybe
14import qualified Data.Map as M
12import qualified Data.Map as M
17−ucheck :: Int -> [(UConstraint, FC)] -> TC ()
15+ucheck :: [(UConstraint, FC)] -> TC ()
18−ucheck num cs = case solve (mkNode num cs) of
16+ucheck cs = acyclic rels (map fst (M.toList rels))
19− Left _ -> tfail UniverseError
17+ where lhs (ULT l _) = l
20− Right _ -> return ()
18+ lhs (ULE l _) = l
22−mkNode :: Int -> [(UConstraint, FC)] -> Node
23−mkNode num cs = relNode num (M.toList (mkRels cs M.empty))
19+ rels = mkRels cs M.empty
25type Relations = M.Map UExp [(UConstraint, FC)]
21type Relations = M.Map UExp [(UConstraint, FC)]
@@ -33,80 +29,23 @@ mkRels ((c, f) : cs) acc
33 where lhs (ULT l _) = l
29 where lhs (ULT l _) = l
34 lhs (ULE l _) = l
30 lhs (ULE l _) = l
36−relNode :: Int -> [(UExp, [(UConstraint, FC)])] -> Node
32+acyclic :: Relations -> [UExp] -> TC ()
37−relNode num [] = CI 0 $ map Le (map (expNode . UVar) [0..num])
33+acyclic r cvs = checkCycle (FC "root" 0) r [] 0 cvs
38−relNode num ((c, cons) : cs) = relNode num cs
34+ where
39−
35+ checkCycle :: FC -> Relations -> [UExp] -> Int -> [UExp] -> TC ()
40−data Child = Lt Node | Le Node
36+ checkCycle fc r path inc [] = return ()
41− deriving Show
37+ checkCycle fc r path inc (c : cs)
42−
38+ = do check fc path inc c
43−data Node = CI Int [Child]
39+ -- Remove c from r since we know there's no cycles now
44− | CV String [Child]
40+ let r' = M.insert c [] r
45− deriving Show
41+ checkCycle fc r' path inc cs
47−expNode :: UExp -> Node
43+ check fc path inc cv
48−expNode (UVar i) = CV (show (UVar i)) []
44+ | inc > 0 && cv `elem` path = Error $ At fc UniverseError
49−expNode (UVal i) = CI i []
45+ | otherwise = case M.lookup cv r of
50−
46+ Nothing -> return ()
51−test :: Node
47+ Just cs -> mapM_ (next (cv:path) inc) cs
52−test = CI 0 $ [Lt x, Lt y, Le z] ++ map Le ints
48+
53− where
49+ next path inc (ULT l r, fc) = check fc path (inc + 1) r
54− x = CV "x" []
50+ next path inc (ULE l r, fc) = check fc path inc r
57− ints = [ -- CI 3 [Lt y]
60−add :: Node -> Node -> Node
61−add i node = undefined
64−test2 = CI 0 $ [ Le v84, Le q25 ] ++ map Le [g,e85,v29,f90,j45,g86,n45,v84,q25,y48,q45,h45,g90]
67− e85 = CV "e85" [Le n45, Le q45, Le h45]
68− v29 = CV "v29" [Lt g90]
69− f90 = CV "f90" [Lt g90]
70− j45 = CV "j45" [Lt f90]
71− g86 = CV "g86" [Lt f90]
81−cyclic = CI 0 $ map Le [a,b,c]
87−-- onChild :: Int -> Child -> m ()
88−onChild i (Lt n) = solveFrom (i+1) n
89−onChild i (Le n) = solveFrom i n
93− , MonadState (M.Map String Int, [String]) m
94− , MonadError String m
95− ) => Int -> Node -> m ()
96−solveFrom num (CI i chs ) = do
98− mapM_ (onChild numi) chs
99−solveFrom num (CV nm chs) = do
102− then throwError $ "cycle: " ++ intercalate ", " nms
104− modify $ second (nm:) -- add this node for cycle detection
105− i <- M.lookup nm . fst <$> get
106− let numi = max num (fromMaybe 0 i)
107− modify $ first (M.insert nm numi)
108− mapM_ (onChild numi) chs
109− modify $ second (drop 1) -- remove the node
111−solve :: Node -> Either String (M.Map String Int)
112−solve n = fst <$> execStateT (solveFrom 0 n) (M.empty, [])