on master help sign in
Added universe constraint checker and --typeintype command line option
commit3b5e50c1f948d88de26a2404f00c0821d9ebba28 authorEdwin Brady <eb@cs.st-andrews.ac.uk> dateThu 1 Dec 2011, 15:13 (15 years ago) parentb2f6cc3
7 files changed+69−97
idris.cabal+1−1 lib/prelude/list.idr+6−5 samples/interp.idr+2−2 src/Core/Constraints.hs+24−85 src/Idris/AbsSyntax.hs+13−2 src/Idris/REPL.hs+17−2 src/Main.hs+6
idris.cabal+1−1
@@ -27,7 +27,7 @@ Executable idris
2727 Other-modules: Core.TT, Core.Evaluate, Core.Typecheck,
2828 Core.ProofShell, Core.ProofState, Core.CoreParser,
2929 Core.ShellParser, Core.Unify, Core.Elaborate,
30− Core.CaseTree,
30+ Core.CaseTree, Core.Constraints,
3131
3232 Idris.AbsSyntax, Idris.Parser, Idris.REPL,
3333 Idris.REPLParser, Idris.ElabDecls, Idris.Error,
lib/prelude/list.idr+6−5
@@ -38,11 +38,6 @@ filter pred (x :: xs) with (pred x, filter pred xs) {
3838 filter pred (x :: xs) | (False, fxs) = fxs;
3939}
4040
41−merge : Ord a => List a -> List a -> List a;
42−merge xs [] = xs;
43−merge [] ys = ys;
44−merge (x :: xs) (y :: ys) = if (x < y) then (x :: merge xs (y :: ys))
45− else (y :: merge (x :: xs) ys);
4641
4742sort : Ord a => List a -> List a;
4843sort [] = [];
@@ -55,5 +50,11 @@ sort xs = let s = split xs in
5550
5651 split : List a -> (List a, List a);
5752 split xs = splitrec xs xs id;
53+
54+ merge : Ord a => List a -> List a -> List a;
55+ merge xs [] = xs;
56+ merge [] ys = ys;
57+ merge (x :: xs) (y :: ys) = if (x < y) then (x :: merge xs (y :: ys))
58+ else (y :: merge (x :: xs) ys);
5859}
5960
samples/interp.idr+2−2
@@ -24,8 +24,8 @@ using (G : Vect Ty n) {
2424 | App : Expr G (TyFun a t) -> Expr G a -> Expr G t
2525 | Op : (Int -> Int -> interpTy c) ->
2626 Expr G TyInt -> Expr G TyInt -> Expr G c
27− | Op' : (interpTy a -> interpTy b -> interpTy c) ->
28− Expr G a -> Expr G b -> Expr G c
27+ | Op' : (interpTy a -> interpTy b -> interpTy c) -> Expr G a -> Expr G b ->
28+ Expr G c
2929 | If : Expr G TyBool -> Expr G a -> Expr G a -> Expr G a
3030 | Bind : Expr G a -> (interpTy a -> Expr G b) -> Expr G b;
3131
src/Core/Constraints.hs+24−85
@@ -1,5 +1,3 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−
31module Core.Constraints(ucheck) where
42
53import Core.TT
@@ -14,13 +12,11 @@ import Data.Maybe
1412import qualified Data.Map as M
1513
1614
17−ucheck :: Int -> [(UConstraint, FC)] -> TC ()
18−ucheck num cs = case solve (mkNode num cs) of
19− Left _ -> tfail UniverseError
20− Right _ -> return ()
21−
22−mkNode :: Int -> [(UConstraint, FC)] -> Node
23−mkNode num cs = relNode num (M.toList (mkRels cs M.empty))
15+ucheck :: [(UConstraint, FC)] -> TC ()
16+ucheck cs = acyclic rels (map fst (M.toList rels))
17+ where lhs (ULT l _) = l
18+ lhs (ULE l _) = l
19+ rels = mkRels cs M.empty
2420
2521type Relations = M.Map UExp [(UConstraint, FC)]
2622
@@ -33,80 +29,23 @@ mkRels ((c, f) : cs) acc
3329 where lhs (ULT l _) = l
3430 lhs (ULE l _) = l
3531
36−relNode :: Int -> [(UExp, [(UConstraint, FC)])] -> Node
37−relNode num [] = CI 0 $ map Le (map (expNode . UVar) [0..num])
38−relNode num ((c, cons) : cs) = relNode num cs
39−
40−data Child = Lt Node | Le Node
41− deriving Show
42−
43−data Node = CI Int [Child]
44− | CV String [Child]
45− deriving Show
46−
47−expNode :: UExp -> Node
48−expNode (UVar i) = CV (show (UVar i)) []
49−expNode (UVal i) = CI i []
50−
51−test :: Node
52−test = CI 0 $ [Lt x, Lt y, Le z] ++ map Le ints
53− where
54− x = CV "x" []
55− y = CV "y" [Lt z]
56− z = CV "z" [Lt x]
57− ints = [ -- CI 3 [Lt y]
58− ]
59−
60−add :: Node -> Node -> Node
61−add i node = undefined
62−
63−test2 :: Node
64−test2 = CI 0 $ [ Le v84, Le q25 ] ++ map Le [g,e85,v29,f90,j45,g86,n45,v84,q25,y48,q45,h45,g90]
65− where
66− g = CV "g" [Le y48]
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]
72− n45 = CV "n45" []
73− v84 = CV "v84" []
74− q25 = CV "q25" []
75− y48 = CV "y48" []
76− q45 = CV "q45" []
77− h45 = CV "h45" []
78− g90 = CV "g90" []
79−
80−cyclic :: Node
81−cyclic = CI 0 $ map Le [a,b,c]
82− where
83− a = CV "a" [Lt b]
84− b = CV "b" [Lt c]
85− c = CV "c" [Lt a]
86−
87−-- onChild :: Int -> Child -> m ()
88−onChild i (Lt n) = solveFrom (i+1) n
89−onChild i (Le n) = solveFrom i n
90−
91−solveFrom ::
92− ( Applicative m
93− , MonadState (M.Map String Int, [String]) m
94− , MonadError String m
95− ) => Int -> Node -> m ()
96−solveFrom num (CI i chs ) = do
97− let numi = max num i
98− mapM_ (onChild numi) chs
99−solveFrom num (CV nm chs) = do
100− nms <- snd <$> get
101− if nm `elem` nms
102− then throwError $ "cycle: " ++ intercalate ", " nms
103− else do
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
32+acyclic :: Relations -> [UExp] -> TC ()
33+acyclic r cvs = checkCycle (FC "root" 0) r [] 0 cvs
34+ where
35+ checkCycle :: FC -> Relations -> [UExp] -> Int -> [UExp] -> TC ()
36+ checkCycle fc r path inc [] = return ()
37+ checkCycle fc r path inc (c : cs)
38+ = do check fc path inc c
39+ -- Remove c from r since we know there's no cycles now
40+ let r' = M.insert c [] r
41+ checkCycle fc r' path inc cs
42+
43+ check fc path inc cv
44+ | inc > 0 && cv `elem` path = Error $ At fc UniverseError
45+ | otherwise = case M.lookup cv r of
46+ Nothing -> return ()
47+ Just cs -> mapM_ (next (cv:path) inc) cs
48+
49+ next path inc (ULT l r, fc) = check fc path (inc + 1) r
50+ next path inc (ULE l r, fc) = check fc path inc r
11051
111−solve :: Node -> Either String (M.Map String Int)
112−solve n = fst <$> execStateT (solveFrom 0 n) (M.empty, [])
src/Idris/AbsSyntax.hs+13−2
@@ -17,11 +17,12 @@ import qualified Epic.Epic as E
1717
1818data IOption = IOption { opt_logLevel :: Int,
1919 opt_typecase :: Bool,
20+ opt_typeintype :: Bool,
2021 opt_showimp :: Bool
2122 }
2223 deriving (Show, Eq)
2324
24−defaultOpts = IOption 0 False False
25+defaultOpts = IOption 0 False False False
2526
2627-- TODO: Add 'module data' to IState, which can be saved out and reloaded quickly (i.e
2728-- without typechecking).
@@ -154,6 +155,16 @@ logLevel :: Idris Int
154155logLevel = do i <- get
155156 return (opt_logLevel (idris_options i))
156157
158+typeInType :: Idris Bool
159+typeInType = do i <- get
160+ return (opt_typeintype (idris_options i))
161+
162+setTypeInType :: Bool -> Idris ()
163+setTypeInType t = do i <- get
164+ let opts = idris_options i
165+ let opt' = opts { opt_typeintype = t }
166+ put (i { idris_options = opt' })
167+
157168impShow :: Idris Bool
158169impShow = do i <- get
159170 return (opt_showimp (idris_options i))
@@ -835,7 +846,7 @@ implicitise syn ist tm
835846addImpl :: IState -> PTerm -> PTerm
836847addImpl ist ptm = ai [] ptm
837848 where
838− ai env (PRef fc f) = aiFn ist fc f []
849+ ai env (PRef fc f) = aiFn ist fc f []
839850 ai env (PEq fc l r) = let l' = ai env l
840851 r' = ai env r in
841852 PEq fc l' r'
src/Idris/REPL.hs+17−2
@@ -17,6 +17,7 @@ import Paths_idris
1717import Core.Evaluate
1818import Core.ProofShell
1919import Core.TT
20+import Core.Constraints
2021
2122import System.Console.Readline
2223import System.FilePath
@@ -42,6 +43,15 @@ repl orig mods
4243 Just mods -> repl orig mods
4344 Nothing -> return ()
4445
46+iucheck :: Idris ()
47+iucheck = do tit <- typeInType
48+ when (not tit) $
49+ do ist <- get
50+ idrisCatch (tclift $ ucheck (idris_constraints ist))
51+ (\e -> do let msg = report e
52+ setErrLine (getErrLine msg)
53+ iputStrLn msg)
54+
4555mkPrompt [] = "Idris"
4656mkPrompt [x] = "*" ++ dropExtension x
4757mkPrompt (x:xs) = "*" ++ dropExtension x ++ " " ++ mkPrompt xs
@@ -84,6 +94,7 @@ edit f orig
8494 clearErr
8595 put (orig { idris_options = idris_options i })
8696 loadModule f
97+ iucheck
8798 return ()
8899 where getEditor env | Just ed <- lookup "EDITOR" env = ed
89100 | Just ed <- lookup "VISUAL" env = ed
@@ -137,10 +148,14 @@ process (Check t) = do (tm, ty) <- elabVal toplevel False t
137148 iputStrLn (showImp imp (delab ist tm) ++ " : " ++
138149 showImp imp (delab ist ty))
139150process Universes = do i <- get
140− let cs = nub $ idris_constraints i
151+ let cs = idris_constraints i
141152-- iputStrLn $ showSep "\n" (map show cs)
142153 lift $ print (map fst cs)
143− iputStrLn $ "(" ++ show (length cs) ++ " constraints)"
154+ let n = length cs
155+ iputStrLn $ "(" ++ show n ++ " constraints)"
156+ case ucheck cs of
157+ Error e -> iputStrLn $ pshow i e
158+ OK _ -> iputStrLn "Universes OK"
144159process (Defn n) = do ctxt <- getContext
145160 lift $ print (lookupDef Nothing n ctxt)
146161process (Spec t) = do (tm, ty) <- elabVal toplevel False t
src/Main.hs+6
@@ -15,6 +15,7 @@ import Core.TT
1515import Core.Typecheck
1616import Core.ProofShell
1717import Core.Evaluate
18+import Core.Constraints
1819
1920import Idris.AbsSyntax
2021import Idris.Parser
@@ -22,6 +23,7 @@ import Idris.REPL
2223import Idris.ElabDecls
2324import Idris.Primitives
2425import Idris.Imports
26+import Idris.Error
2527import Paths_idris
2628
2729-- Main program reads command line options, parses the main program, and gets
@@ -34,6 +36,7 @@ data Opt = Filename String
3436 | OLogging Int
3537 | Output String
3638 | TypeCase
39+ | TypeInType
3740 deriving Eq
3841
3942main = do xs <- getArgs
@@ -52,6 +55,7 @@ runIdris opts =
5255 when runrepl $ iputStrLn banner
5356 ist <- get
5457 mods <- mapM loadModule inputs
58+ iucheck
5559 ok <- noErrors
5660 when ok $ case output of
5761 [] -> return ()
@@ -60,6 +64,7 @@ runIdris opts =
6064 where
6165 makeOption (OLogging i) = setLogLevel i
6266 makeOption TypeCase = setTypeCase True
67+ makeOption TypeInType = setTypeInType True
6368 makeOption _ = return ()
6469
6570getFile :: Opt -> Maybe String
@@ -83,6 +88,7 @@ parseArgs ("--noprelude":ns) = liftM (NoPrelude : ) (parseArgs ns)
8388parseArgs ("--check":ns) = liftM (NoREPL : ) (parseArgs ns)
8489parseArgs ("-o":n:ns) = liftM (\x -> NoREPL : Output n : x) (parseArgs ns)
8590parseArgs ("--typecase":ns) = liftM (TypeCase : ) (parseArgs ns)
91+parseArgs ("--typeintype":ns) = liftM (TypeInType : ) (parseArgs ns)
8692parseArgs (n:ns) = liftM (Filename n : ) (parseArgs ns)
8793
8894{-