@@ -1,6 +1,6 @@
11{-# LANGUAGE PatternGuards #-}
22
3−module Idris.CaseSplit(split) where
3+module Idris.CaseSplit(split, splitOnLine) where
44
55-- splitting a variable in a pattern clause
66
@@ -8,14 +8,22 @@ import Idris.AbsSyntax
88import Idris.ElabDecls
99import Idris.ElabTerm
1010import Idris.Delaborate
11+import Idris.Parser
1112import Idris.Error
1213
1314import Core.TT
15+import Core.Typecheck
1416import Core.Evaluate
1517
1618import Data.Maybe
1719import Control.Monad
18−import Control.Monad.State
20+import Control.Monad.State.Strict
21+
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
1927
2028{-
2129
@@ -31,9 +39,12 @@ Always take the "more specific" argument when there is a discrepancy, i.e.
3139names over '_', patterns over names, etc.
3240-}
3341
34−split :: Name -> PTerm -> Idris [PTerm]
42+-- Given a variable to split, and a term application, return a list of
43+-- variable updates
44+split :: Name -> PTerm -> Idris [[(Name, PTerm)]]
3545split n t'
3646 = do (tm, ty, pats) <- elabValBind toplevel True t'
47+ logLvl 4 ("Elaborated:\n" ++ show tm ++ " : " ++ show ty ++ "\n" ++ show pats)
3748 ist <- getIState
3849-- iputStrLn (show (delab ist tm) ++ " : " ++ show (delab ist ty))
3950-- iputStrLn (show pats)
@@ -43,25 +54,48 @@ split n t'
4354 Nothing -> fail $ show n ++ " is not a pattern variable"
4455 Just ty ->
4556 do let splits = findPats ist ty
57+ iLOG ("New patterns " ++ show splits)
4658 let newPats_in = zipWith (replaceVar ctxt n) splits (repeat t)
59+ logLvl 4 ("Trying " ++ showSep "\n" (map show newPats_in))
4760 newPats <- mapM elabNewPat newPats_in
48− logLvl 5 (showSep "\n" (map show (t : mapMaybe id newPats)))
49− logLvl 5 "----"
50− let newPats' = evalState (mapM (mergePat ctxt t)
51− (mapMaybe id newPats))
52− []
53− return newPats'
54−
55−mergePat :: Context -> PTerm -> PTerm -> State [(Name, Name)] PTerm
61+ logLvl 3 ("Original:\n" ++ show t)
62+ logLvl 3 ("Split:\n" ++
63+ (showSep "\n" (map show (mapMaybe id newPats))))
64+ logLvl 3 "----"
65+ let newPats' = mergeAllPats ctxt t (mapMaybe id newPats)
66+ iLOG ("Name updates " ++ showSep "\n"
67+ (map (\ (p, u) -> show u ++ " " ++ show p) newPats'))
68+ return (map snd newPats')
69+
70+data MergeState = MS { namemap :: [(Name, Name)],
71+ updates :: [(Name, PTerm)] }
72+
73+addUpdate n tm = do ms <- get
74+ put (ms { updates = ((n, tm) : updates ms) } )
75+
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
81+ ((p, u) : ps')
82+
83+mergePat :: Context -> PTerm -> PTerm -> State MergeState PTerm
5684-- If any names are unified, make sure they stay unified. Always prefer
5785-- 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)
5890mergePat ctxt orig@(PRef fc n) new@(PRef _ n')
59− | isConName n' ctxt = return new
91+ | isConName n' ctxt = do addUpdate n new;
92+ return new
6093 | otherwise
61− = do nmap <- get
62− case lookup n' nmap of
63− Just x -> return (PRef fc x)
64− Nothing -> do put ((n', n) : nmap)
94+ = do ms <- get
95+ case lookup n' (namemap ms) of
96+ Just x -> do addUpdate n (PRef fc x)
97+ return (PRef fc x)
98+ Nothing -> do put (ms { namemap = ((n', n) : namemap ms) })
6599 return (PRef fc n)
66100mergePat ctxt (PApp _ _ args) (PApp fc f args')
67101 = do newArgs <- zipWithM mergeArg args args'
@@ -72,15 +106,17 @@ mergePat ctxt (PApp _ _ args) (PApp fc f args')
72106 return (y { machine_inf = machine_inf x,
73107 getTm = tm' })
74108 _ -> return (y { getTm = tm' })
75−mergePat ctxt (PRef fc n) t = tidy t
109+mergePat ctxt (PRef fc n) t = do tm <- tidy t
110+ addUpdate n tm
111+ return tm
76112mergePat ctxt x y = return y
77113
78114mergeUserImpl :: PTerm -> PTerm -> PTerm
79115mergeUserImpl x y = x
80116
81117tidy orig@(PRef fc n)
82− = do nmap <- get
83− case lookup n nmap of
118+ = do ms <- get
119+ case lookup n (namemap ms) of
84120 Just x -> return (PRef fc x)
85121 Nothing -> case n of
86122 (UN _) -> return orig
@@ -118,6 +154,8 @@ findPats ist t = [Placeholder]
118154replaceVar :: Context -> Name -> PTerm -> PTerm -> PTerm
119155replaceVar ctxt n t (PApp fc f pats) = PApp fc f (map substArg pats)
120156 where subst :: PTerm -> PTerm
157+ subst orig@(PPatvar _ v) | v == n = t
158+ | otherwise = Placeholder
121159 subst orig@(PRef _ v) | v == n = t
122160 | isConName v ctxt = orig
123161 subst (PRef _ _) = Placeholder
@@ -128,5 +166,21 @@ replaceVar ctxt n t (PApp fc f pats) = PApp fc f (map substArg pats)
128166
129167replaceVar ctxt n t pat = pat
130168
131−
132−
169+splitOnLine :: Int -- ^ line number
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)
176+-- i <- getIState
177+ cl <- getInternalApp fn l
178+ logLvl 3 ("Working with " ++ showImp Nothing True False cl)
179+ tms <- split n cl
180+-- iputStrLn (showSep "\n" (map show tms))
181+ return tms -- "" -- not yet done...
182+
183+getFnName (PClause _ n _ _ _ _) = n
184+getFnName (PWith _ n _ _ _ _) = n
185+
186+