@@ -7,7 +7,8 @@ import Control.Arrow (first, second, (&&&))
77import Control.Monad (forM_, guard)
88
99import Data.Function (on)
10−import Data.List (find, sortBy, (\\))
10+import Data.List (find, minimumBy, sortBy, (\\))
11+import Data.Map (Map)
1112import qualified Data.Map as M
1213import Data.Maybe (catMaybes, fromMaybe, isJust)
1314import Data.Monoid (Monoid (mempty, mappend))
@@ -16,39 +17,43 @@ import qualified Data.Set as S
1617
1718import Idris.AbsSyntax (addUsingConstraints, addImpl, getContext, getIState, putIState, implicit)
1819import Idris.AbsSyntaxTree (class_instances, defaultSyntax, Idris,
19− IState (idris_classes, tt_ctxt),
20− implicitAllowed, prettyIst, PTerm, toplevel)
20+ IState (idris_classes, idris_docstrings, tt_ctxt),
21+ implicitAllowed, prettyDocumentedIst, prettyIst, PTerm, toplevel)
2122import Idris.Core.Evaluate (Context (definitions), Def (Function, TyDecl, CaseOp), normaliseC)
2223import Idris.Core.TT
2324import Idris.Core.Unify (match_unify)
2425import Idris.Delaborate (delab, delabTy)
25−import Idris.Docstrings (noDocs)
26+import Idris.Docstrings (noDocs, overview)
2627import Idris.ElabDecls (elabType')
2728import Idris.Output (ihRenderResult, ihPrintResult, ihPrintFunTypes)
2829
2930import System.IO (Handle)
3031
32+import Util.Pretty (text, vsep, char, (<>), Doc)
3133
32−searchByType :: (Ord a, Show a) => Handle -> (IState -> Type -> Type -> Maybe a) -> a -> PTerm -> Idris ()
33−searchByType h pred scoreLimit pterm = do
34+searchByType :: Handle -> PTerm -> Idris ()
35+searchByType h pterm = do
3436 pterm' <- addUsingConstraints syn emptyFC pterm
3537 pterm'' <- implicit toplevel syn n pterm'
3638 i <- getIState
3739 let pterm''' = addImpl i pterm''
3840 ty <- elabType' False toplevel syn (fst noDocs) (snd noDocs) emptyFC [] n pterm'
3941 putIState i -- don't actually make any changes
40− ihRenderResult h (prettyIst i pterm)
41− let names = searchUsing pred i ty
42− let names' = take numLimit . takeWhile ((< scoreLimit) . snd . snd) $
43− sortBy (compare `on` (snd . snd)) names
44− forM_ names' $ \(name, (typ, val)) -> do
45− ihPrintFunTypes h [] name [(name, delabTy i name)]
46− ihPrintResult h ("\tScore: " ++ show val ++ "\n")
42+ let names = searchUsing searchPred i ty
43+ let names' = take numLimit . takeWhile ((< scoreLimit) . getScore) $
44+ sortBy (compare `on` getScore) names
45+ let docs =
46+ [ let docInfo = (n, delabTy i n, fmap (overview . fst) (lookupCtxtExact n (idris_docstrings i))) in
47+ displayScore score <> char ' ' <> prettyDocumentedIst i docInfo
48+ | (n, (_,score)) <- names']
49+ ihRenderResult h $ vsep docs
4750 where
51+ getScore = defaultScoreFunction . snd . snd
4852 numLimit = 50
53+ scoreLimit = 100
4954 syn = defaultSyntax { implicitAllowed = True } -- syntax
5055 n = sMN 0 "searchType" -- name
51−
56+
5257
5358searchUsing :: (IState -> Type -> Type -> Maybe a) -> IState -> Type -> [(Name, (Type, a))]
5459searchUsing pred istate ty =
@@ -82,10 +87,10 @@ tcToMaybe (Error _) = Nothing
8287
8388
8489
85−searchPred :: (Score -> Int) -> IState -> Type -> Type -> Maybe Int
86−searchPred scoref istate ty1 = \ty2 -> case matcher ty2 of
90+searchPred :: IState -> Type -> Type -> Maybe Score
91+searchPred istate ty1 = \ty2 -> case matcher ty2 of
8792 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)
8994 where
9095 matcher = unifyWithHoles True istate ty1
9196
@@ -102,7 +107,7 @@ reverseDag xs = map f xs where
102107computeDagP :: Ord n => TT n -> ([((n, TT n), Set n)], TT n)
103108computeDagP t = (reverse (map f args), retTy) where
104109
105− f (n, t) = ((n, t), usedVars t)
110+ f (n, t) = ((n, t), M.keysSet (usedVars t))
106111
107112 (numArgs, args, retTy) = go 0 [] t
108113
@@ -110,17 +115,17 @@ computeDagP t = (reverse (map f args), retTy) where
110115 go k args (Bind n (Pi t) sc) = go (succ k) ( (n, t) : args ) sc
111116 go k args retTy = (k, args, retTy)
112117
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
123118
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
128+usedVars _ = M.empty
124129
125130deleteFromDag :: Ord n => n -> [((n, TT n), (a, Set n))] -> [((n, TT n), (a, Set n))]
126131deleteFromDag name [] = []
@@ -136,6 +141,15 @@ data Score = Score
136141 , leftTypeClass :: Int
137142 , rightTypeClass :: Int } deriving (Eq, Show)
138143
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
152+
139153
140154scoreCriterion :: Score -> Bool
141155scoreCriterion (Score a b c d e) = True {- not
@@ -205,18 +219,17 @@ unifyWithHoles debugParam istate type1 = \type2 -> let
205219 mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
206220
207221 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) }) <$>
209− updateDags xs (holes', updatef args1, args2)
210− (Nothing, Just _) -> thrd (\score -> score { rightApplied = succ (rightApplied score) }) <$>
211− updateDags xs (holes', args1, updatef args2)
212− _ -> error "Shouldn't happen. Watch the alpha conversion!"
222+ (Just (_,ix), Nothing) -> thrd (\score -> score { leftApplied = succ (leftApplied score) }) <$> nextStep
223+ (Nothing, Just (_, ix)) -> thrd (\score -> score { rightApplied = succ (rightApplied score) }) <$> nextStep
224+ (Nothing, Nothing) -> nextStep
225+ _ -> error ("Shouldn't happen. Watch the alpha conversion!\n" ++ show args1 ++ "\n\n" ++ show args2)
213226 where
227+ varsInTy = map fst $ M.toList (usedVars term)
228+ deleteMany = foldr (.) id $ map deleteFromDag (name : varsInTy)
214229 thrd f (a,b,c) = (a,b,f c)
215− holes' = holes \\ [name]
216− updatef = map (first . second $ subst name term) . deleteFromDag name
217− args1' = deleteFromDag name args1
218− args1'' = map (first . second $ subst name term) args1'
219− mgetType name xs = fmap (snd . fst) . find ((name ==) . fst . fst) $ xs
230+ nextStep = updateDags xs (holes \\ [name], updatef args1, updatef args2 )
231+ updatef = map (first . second $ subst name term) . deleteMany
232+ mgetType name xs = fmap ((snd . fst) &&& (fst . snd)) . find ((name ==) . fst . fst) $ xs
220233
221234
222235 go :: State -> [(Type, Type)] -> Maybe State