@@ -1,6 +1,6 @@
1{-# LANGUAGE PatternGuards #-}
1{-# LANGUAGE PatternGuards #-}
3−module Idris.CaseSplit(split) where
3+module Idris.CaseSplit(split, splitOnLine) where
5-- splitting a variable in a pattern clause
5-- splitting a variable in a pattern clause
@@ -8,14 +8,22 @@ import Idris.AbsSyntax
8import Idris.ElabDecls
8import Idris.ElabDecls
9import Idris.ElabTerm
9import Idris.ElabTerm
10import Idris.Delaborate
10import Idris.Delaborate
11import Idris.Error
12import Idris.Error
13import Core.TT
14import Core.TT
14import Core.Evaluate
16import Core.Evaluate
16import Data.Maybe
18import Data.Maybe
17import Control.Monad
19import Control.Monad
18−import Control.Monad.State
20+import Control.Monad.State.Strict
22+import Text.Parser.Combinators
23+import Text.Parser.Char(anyChar)
24+import Text.Trifecta(Result(..), parseString)
25+import Text.Trifecta.Delta
26+import qualified Data.ByteString.UTF8 as UTF8
@@ -31,9 +39,12 @@ Always take the "more specific" argument when there is a discrepancy, i.e.
31names over '_', patterns over names, etc.
39names over '_', patterns over names, etc.
42+-- Given a variable to split, and a term application, return a list of
34−split :: Name -> PTerm -> Idris [PTerm]
44+split :: Name -> PTerm -> Idris [[(Name, PTerm)]]
35split n t'
45split n t'
36 = do (tm, ty, pats) <- elabValBind toplevel True t'
46 = do (tm, ty, pats) <- elabValBind toplevel True t'
47+ logLvl 4 ("Elaborated:\n" ++ show tm ++ " : " ++ show ty ++ "\n" ++ show pats)
37 ist <- getIState
48 ist <- getIState
38-- iputStrLn (show (delab ist tm) ++ " : " ++ show (delab ist ty))
49-- iputStrLn (show (delab ist tm) ++ " : " ++ show (delab ist ty))
39-- iputStrLn (show pats)
50-- iputStrLn (show pats)
@@ -43,25 +54,48 @@ split n t'
43 Nothing -> fail $ show n ++ " is not a pattern variable"
54 Nothing -> fail $ show n ++ " is not a pattern variable"
44 Just ty ->
55 Just ty ->
45 do let splits = findPats ist ty
56 do let splits = findPats ist ty
57+ iLOG ("New patterns " ++ show splits)
46 let newPats_in = zipWith (replaceVar ctxt n) splits (repeat t)
58 let newPats_in = zipWith (replaceVar ctxt n) splits (repeat t)
59+ logLvl 4 ("Trying " ++ showSep "\n" (map show newPats_in))
47 newPats <- mapM elabNewPat newPats_in
60 newPats <- mapM elabNewPat newPats_in
61+ logLvl 3 ("Original:\n" ++ show t)
62+ logLvl 3 ("Split:\n" ++
48− logLvl 5 (showSep "\n" (map show (t : mapMaybe id newPats)))
63+ (showSep "\n" (map show (mapMaybe id newPats))))
49− logLvl 5 "----"
64+ logLvl 3 "----"
50− let newPats' = evalState (mapM (mergePat ctxt t)
65+ let newPats' = mergeAllPats ctxt t (mapMaybe id newPats)
51− (mapMaybe id newPats))
66+ iLOG ("Name updates " ++ showSep "\n"
52− []
67+ (map (\ (p, u) -> show u ++ " " ++ show p) newPats'))
53− return newPats'
68+ return (map snd newPats')
70+data MergeState = MS { namemap :: [(Name, Name)],
71+ updates :: [(Name, PTerm)] }
73+addUpdate n tm = do ms <- get
74+ put (ms { updates = ((n, tm) : updates ms) } )
76+mergeAllPats :: Context -> PTerm -> [PTerm] -> [(PTerm, [(Name, PTerm)])]
77+mergeAllPats ctxt t [] = []
78+mergeAllPats ctxt t (p : ps)
79+ = let (p', MS _ u) = runState (mergePat ctxt t p) (MS [] [])
80+ ps' = mergeAllPats ctxt t ps in
55−mergePat :: Context -> PTerm -> PTerm -> State [(Name, Name)] PTerm
83+mergePat :: Context -> PTerm -> PTerm -> State MergeState PTerm
56-- If any names are unified, make sure they stay unified. Always prefer
84-- If any names are unified, make sure they stay unified. Always prefer
57-- user provided name (first pattern)
85-- user provided name (first pattern)
86+mergePat ctxt (PPatvar fc n) new
87+ = mergePat ctxt (PRef fc n) new
88+mergePat ctxt old (PPatvar fc n)
89+ = mergePat ctxt old (PRef fc n)
58mergePat ctxt orig@(PRef fc n) new@(PRef _ n')
90mergePat ctxt orig@(PRef fc n) new@(PRef _ n')
91+ | isConName n' ctxt = do addUpdate n new;
59− | isConName n' ctxt = return new
92+ return new
60 | otherwise
93 | otherwise
61− = do nmap <- get
94+ = do ms <- get
62− case lookup n' nmap of
95+ case lookup n' (namemap ms) of
96+ Just x -> do addUpdate n (PRef fc x)
63− Just x -> return (PRef fc x)
97+ return (PRef fc x)
64− Nothing -> do put ((n', n) : nmap)
98+ Nothing -> do put (ms { namemap = ((n', n) : namemap ms) })
65 return (PRef fc n)
99 return (PRef fc n)
66mergePat ctxt (PApp _ _ args) (PApp fc f args')
100mergePat ctxt (PApp _ _ args) (PApp fc f args')
67 = do newArgs <- zipWithM mergeArg args args'
101 = do newArgs <- zipWithM mergeArg args args'
@@ -72,15 +106,17 @@ mergePat ctxt (PApp _ _ args) (PApp fc f args')
72 return (y { machine_inf = machine_inf x,
106 return (y { machine_inf = machine_inf x,
73 getTm = tm' })
107 getTm = tm' })
74 _ -> return (y { getTm = tm' })
108 _ -> return (y { getTm = tm' })
75−mergePat ctxt (PRef fc n) t = tidy t
109+mergePat ctxt (PRef fc n) t = do tm <- tidy t
76mergePat ctxt x y = return y
112mergePat ctxt x y = return y
78mergeUserImpl :: PTerm -> PTerm -> PTerm
114mergeUserImpl :: PTerm -> PTerm -> PTerm
79mergeUserImpl x y = x
115mergeUserImpl x y = x
81tidy orig@(PRef fc n)
117tidy orig@(PRef fc n)
82− = do nmap <- get
118+ = do ms <- get
83− case lookup n nmap of
119+ case lookup n (namemap ms) of
84 Just x -> return (PRef fc x)
120 Just x -> return (PRef fc x)
85 Nothing -> case n of
121 Nothing -> case n of
86 (UN _) -> return orig
122 (UN _) -> return orig
@@ -118,6 +154,8 @@ findPats ist t = [Placeholder]
118replaceVar :: Context -> Name -> PTerm -> PTerm -> PTerm
154replaceVar :: Context -> Name -> PTerm -> PTerm -> PTerm
119replaceVar ctxt n t (PApp fc f pats) = PApp fc f (map substArg pats)
155replaceVar ctxt n t (PApp fc f pats) = PApp fc f (map substArg pats)
120 where subst :: PTerm -> PTerm
156 where subst :: PTerm -> PTerm
157+ subst orig@(PPatvar _ v) | v == n = t
158+ | otherwise = Placeholder
121 subst orig@(PRef _ v) | v == n = t
159 subst orig@(PRef _ v) | v == n = t
122 | isConName v ctxt = orig
160 | isConName v ctxt = orig
123 subst (PRef _ _) = Placeholder
161 subst (PRef _ _) = Placeholder
@@ -128,5 +166,21 @@ replaceVar ctxt n t (PApp fc f pats) = PApp fc f (map substArg pats)
129replaceVar ctxt n t pat = pat
167replaceVar ctxt n t pat = pat
131−
169+splitOnLine :: Int -- ^ line number
132−
170+ -> Name -- ^ variable
171+ -> FilePath -- ^ name of file
172+ -> String -- ^ file contents
173+ -> Idris [[(Name, PTerm)]]
174+splitOnLine l n fn inp = do
175+-- let (before, later) = splitAt (l-1) (lines inp)
177+ cl <- getInternalApp fn l
178+ logLvl 3 ("Working with " ++ showImp Nothing True False cl)
180+-- iputStrLn (showSep "\n" (map show tms))
181+ return tms -- "" -- not yet done...
183+getFnName (PClause _ n _ _ _ _) = n
184+getFnName (PWith _ n _ _ _ _) = n