@@ -7,7 +7,8 @@ import Control.Arrow (first, second, (&&&))
7import Control.Monad (forM_, guard)
7import Control.Monad (forM_, guard)
9import Data.Function (on)
9import Data.Function (on)
10−import Data.List (find, sortBy, (\\))
10+import Data.List (find, minimumBy, sortBy, (\\))
11import qualified Data.Map as M
12import qualified Data.Map as M
12import Data.Maybe (catMaybes, fromMaybe, isJust)
13import Data.Maybe (catMaybes, fromMaybe, isJust)
13import Data.Monoid (Monoid (mempty, mappend))
14import Data.Monoid (Monoid (mempty, mappend))
@@ -16,39 +17,43 @@ import qualified Data.Set as S
17import Idris.AbsSyntax (addUsingConstraints, addImpl, getContext, getIState, putIState, implicit)
18import Idris.AbsSyntax (addUsingConstraints, addImpl, getContext, getIState, putIState, implicit)
18import Idris.AbsSyntaxTree (class_instances, defaultSyntax, Idris,
19import Idris.AbsSyntaxTree (class_instances, defaultSyntax, Idris,
19− IState (idris_classes, tt_ctxt),
20+ IState (idris_classes, idris_docstrings, tt_ctxt),
20− implicitAllowed, prettyIst, PTerm, toplevel)
21+ implicitAllowed, prettyDocumentedIst, prettyIst, PTerm, toplevel)
21import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
22import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
22import Idris.Core.TT
23import Idris.Core.TT
23import Idris.Core.Unify (match_unify)
24import Idris.Core.Unify (match_unify)
24import Idris.Delaborate (delab, delabTy)
25import Idris.Delaborate (delab, delabTy)
25−import Idris.Docstrings (noDocs)
26+import Idris.Docstrings (noDocs, overview)
26import Idris.ElabDecls (elabType')
27import Idris.ElabDecls (elabType')
27import Idris.Output (ihRenderResult, ihPrintResult, ihPrintFunTypes)
28import Idris.Output (ihRenderResult, ihPrintResult, ihPrintFunTypes)
29import System.IO (Handle)
30import System.IO (Handle)
32+import Util.Pretty (text, vsep, char, (<>), Doc)
32−searchByType :: (Ord a, Show a) => Handle -> (IState -> Type -> Type -> Maybe a) -> a -> PTerm -> Idris ()
34+searchByType :: Handle -> PTerm -> Idris ()
33−searchByType h pred scoreLimit pterm = do
35+searchByType h pterm = do
34 pterm' <- addUsingConstraints syn emptyFC pterm
36 pterm' <- addUsingConstraints syn emptyFC pterm
35 pterm'' <- implicit toplevel syn n pterm'
37 pterm'' <- implicit toplevel syn n pterm'
36 i <- getIState
38 i <- getIState
37 let pterm''' = addImpl i pterm''
39 let pterm''' = addImpl i pterm''
38 ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
40 ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
39 putIState i -- don't actually make any changes
41 putIState i -- don't actually make any changes
40− ihRenderResult h (prettyIst i pterm)
41− let names = searchUsing pred i ty
42+ let names = searchUsing searchPred i ty
42− let names' = take numLimit . takeWhile ((< scoreLimit) . snd . snd) $
43+ let names' = take numLimit . takeWhile ((< scoreLimit) . getScore) $
43− sortBy (compare `on` (snd . snd)) names
44+ sortBy (compare `on` getScore) names
44− forM_ names' $ \(name, (typ, val)) -> do
45+ let docs =
45− ihPrintFunTypes h [] name [(name, delabTy i name)]
46+ [ let docInfo = (n, delabTy i n, fmap (overview . fst) (lookupCtxtExact n (idris_docstrings i))) in
46− ihPrintResult h ("\tScore: " ++ show val ++ "\n")
47+ displayScore score <> char ' ' <> prettyDocumentedIst i docInfo
48+ | (n, (_,score)) <- names']
49+ ihRenderResult h $ vsep docs
51+ getScore = defaultScoreFunction . snd . snd
48 numLimit = 50
52 numLimit = 50
49 syn = defaultSyntax { implicitAllowed = True } -- syntax
54 syn = defaultSyntax { implicitAllowed = True } -- syntax
50 n = sMN 0 "searchType" -- name
55 n = sMN 0 "searchType" -- name
53searchUsing :: (IState -> Type -> Type -> Maybe a) -> IState -> Type -> [(Name, (Type, a))]
58searchUsing :: (IState -> Type -> Type -> Maybe a) -> IState -> Type -> [(Name, (Type, a))]
54searchUsing pred istate ty =
59searchUsing pred istate ty =
@@ -82,10 +87,10 @@ tcToMaybe (Error _) = Nothing
85−searchPred :: (Score -> Int) -> IState -> Type -> Type -> Maybe Int
90+searchPred :: IState -> Type -> Type -> Maybe Score
86−searchPred scoref istate ty1 = \ty2 -> case matcher ty2 of
91+searchPred istate ty1 = \ty2 -> case matcher ty2 of
87 Nothing -> Nothing
92 Nothing -> Nothing
88− Just xs -> guard (not (null xs)) >> return (minimum (map scoref xs))
93+ Just xs -> guard (not (null xs)) >> return (minimumBy (compare `on` defaultScoreFunction) xs)
90 matcher = unifyWithHoles True istate ty1
95 matcher = unifyWithHoles True istate ty1
@@ -102,7 +107,7 @@ reverseDag xs = map f xs where
102computeDagP :: Ord n => TT n -> ([((n, TT n), Set n)], TT n)
107computeDagP :: Ord n => TT n -> ([((n, TT n), Set n)], TT n)
103computeDagP t = (reverse (map f args), retTy) where
108computeDagP t = (reverse (map f args), retTy) where
105− f (n, t) = ((n, t), usedVars t)
110+ f (n, t) = ((n, t), M.keysSet (usedVars t))
107 (numArgs, args, retTy) = go 0 [] t
112 (numArgs, args, retTy) = go 0 [] t
@@ -110,17 +115,17 @@ computeDagP t = (reverse (map f args), retTy) where
110 go k args (Bind n (Pi t) sc) = go (succ k) ( (n, t) : args ) sc
115 go k args (Bind n (Pi t) sc) = go (succ k) ( (n, t) : args ) sc
111 go k args retTy = (k, args, retTy)
116 go k args retTy = (k, args, retTy)
113− usedVars :: Ord n => TT n -> Set n
114− usedVars (V j) = error "unexpected! run vToP first"
115− usedVars (P Bound n t) = S.singleton n `S.union` usedVars t
116− usedVars (Bind n binder t2) = (S.delete n (usedVars t2) `S.union`) $ case binder of
117− Let t v -> usedVars t `S.union` usedVars v
118− Guess t v -> usedVars t `S.union` usedVars v
119− b -> usedVars (binderTy b)
120− usedVars (App t1 t2) = usedVars t1 `S.union` usedVars t2
121− usedVars (Proj t _) = usedVars t
122− usedVars _ = S.empty
119+usedVars :: Ord n => TT n -> Map n (TT n)
120+usedVars (V j) = error "unexpected! run vToP first"
121+usedVars (P Bound n t) = M.singleton n t `M.union` usedVars t
122+usedVars (Bind n binder t2) = (M.delete n (usedVars t2) `M.union`) $ case binder of
123+ Let t v -> usedVars t `M.union` usedVars v
124+ Guess t v -> usedVars t `M.union` usedVars v
125+ b -> usedVars (binderTy b)
126+usedVars (App t1 t2) = usedVars t1 `M.union` usedVars t2
127+usedVars (Proj t _) = usedVars t
125deleteFromDag :: Ord n => n -> [((n, TT n), (a, Set n))] -> [((n, TT n), (a, Set n))]
130deleteFromDag :: Ord n => n -> [((n, TT n), (a, Set n))] -> [((n, TT n), (a, Set n))]
126deleteFromDag name [] = []
131deleteFromDag name [] = []
@@ -136,6 +141,15 @@ data Score = Score
136 , leftTypeClass :: Int
141 , leftTypeClass :: Int
137 , rightTypeClass :: Int } deriving (Eq, Show)
142 , rightTypeClass :: Int } deriving (Eq, Show)
144+displayScore :: Score -> Doc a
145+displayScore (Score trans lapp rapp lclass rclass) = text $ case (lt, gt) of
146+ (True , True ) -> "="
147+ (True , False) -> "<"
148+ (False, True ) -> ">"
149+ (False, False) -> " "
150+ where lt = lapp + lclass == 0
151+ gt = rapp + rclass == 0
140scoreCriterion :: Score -> Bool
154scoreCriterion :: Score -> Bool
141scoreCriterion (Score a b c d e) = True {- not
155scoreCriterion (Score a b c d e) = True {- not
@@ -205,18 +219,17 @@ unifyWithHoles debugParam istate type1 = \type2 -> let
205 mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
219 mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
207 updateDags ((name, term) : xs) (holes, args1, args2) = case (mgetType name args1, mgetType name args2) of
221 updateDags ((name, term) : xs) (holes, args1, args2) = case (mgetType name args1, mgetType name args2) of
208− (Just _, Nothing) -> thrd (\score -> score { leftApplied = succ (leftApplied score) }) <$>
222+ (Just (_,ix), Nothing) -> thrd (\score -> score { leftApplied = succ (leftApplied score) }) <$> nextStep
209− updateDags xs (holes', updatef args1, args2)
210− (Nothing, Just _) -> thrd (\score -> score { rightApplied = succ (rightApplied score) }) <$>
223+ (Nothing, Just (_, ix)) -> thrd (\score -> score { rightApplied = succ (rightApplied score) }) <$> nextStep
211− updateDags xs (holes', args1, updatef args2)
224+ (Nothing, Nothing) -> nextStep
212− _ -> error "Shouldn't happen. Watch the alpha conversion!"
225+ _ -> error ("Shouldn't happen. Watch the alpha conversion!\n" ++ show args1 ++ "\n\n" ++ show args2)
227+ varsInTy = map fst $ M.toList (usedVars term)
228+ deleteMany = foldr (.) id $ map deleteFromDag (name : varsInTy)
214 thrd f (a,b,c) = (a,b,f c)
229 thrd f (a,b,c) = (a,b,f c)
215− holes' = holes \\ [name]
230+ nextStep = updateDags xs (holes \\ [name], updatef args1, updatef args2 )
216− updatef = map (first . second $ subst name term) . deleteFromDag name
217− args1' = deleteFromDag name args1
218− args1'' = map (first . second $ subst name term) args1'
231+ updatef = map (first . second $ subst name term) . deleteMany
219− mgetType name xs = fmap (snd . fst) . find ((name ==) . fst . fst) $ xs
232+ mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
222 go :: State -> [(Type, Type)] -> Maybe State
235 go :: State -> [(Type, Type)] -> Maybe State