1module Generate.Cases (caseToMatch, Match (..), Clause (..), matchSubst) where
3import Control.Arrow (first)
4import Control.Monad (liftM,foldM)
5import Data.List (groupBy,sortBy,lookup)
6import Data.Maybe (fromMaybe)
9import SourceSyntax.Location
10import SourceSyntax.Literal
11import SourceSyntax.Pattern
12import SourceSyntax.Expression
13import Transform.Substitute
15caseToMatch patterns = do
17 match [v] (map (first (:[])) patterns) Fail
20 return $ "case" ++ show n
23 = Match String [Clause t v] (Match t v)
31 Clause (Either String Literal) [String] (Match t v)
34matchSubst :: [(String,String)] -> Match t v -> Match t v
35matchSubst _ Break = Break
36matchSubst _ Fail = Fail
37matchSubst pairs (Seq ms) = Seq (map (matchSubst pairs) ms)
38matchSubst pairs (Other (L t s e)) =
39 Other . L t s $ foldr ($) e $ map (\(x,y) -> subst x (Var y)) pairs
40matchSubst pairs (Match n cs m) =
41 Match (varSubst n) (map clauseSubst cs) (matchSubst pairs m)
42 where varSubst v = fromMaybe v (lookup v pairs)
43 clauseSubst (Clause c vs m) =
44 Clause c (map varSubst vs) (matchSubst pairs m)
52isVar p = not (isCon p)
54match :: [String] -> [([Pattern],LExpr t v)] -> Match t v -> Unique (Match t v)
55match [] [] def = return def
56match [] [([],e)] Fail = return $ Other e
57match [] [([],e)] Break = return $ Other e
58match [] cs def = return $ Seq (map (Other . snd) cs ++ [def])
60 | all isVar cs' = matchVar vs cs' def
61 | all isCon cs' = matchCon vs cs' def
62 | otherwise = matchMix vs cs' def
64 cs' = map (dealias v) cs
66dealias v c@(p:ps, L t s e) =
68 PAlias x pattern -> (pattern:ps, L t s $ subst x (Var v) e)
71matchVar :: [String] -> [([Pattern],LExpr t v)] -> Match t v
73matchVar (v:vs) cs def = match vs (map subVar cs) def
75 subVar (p:ps, ce@(L t s e)) = (ps, L t s $ subOnePattern p e)
78 subOnePattern pattern e =
80 PVar x -> subst x (Var v) e
83 foldr (\x -> subst x (Access (loc (Var v)) x)) e fs
85matchCon :: [String] -> [([Pattern],LExpr t v)] -> Match t v
87matchCon (v:vs) cs def = (flip (Match v) def) `liftM` mapM toClause css
89 css = groupBy eq (sortBy cmp cs)
91 cmp (p1:_,_) (p2:_,_) =
93 (PData n1 _, PData n2 _) -> compare n1 n2
96 eq (p1:_,_) (p2:_,_) =
98 (PData n1 _, PData n2 _) -> n1 == n2
103 (PData name _ : _, _) -> matchClause (Left name) (v:vs) cs Break
104 (PLiteral lit : _, _) -> matchClause (Right lit) (v:vs) cs Break
106matchClause :: Either String Literal
108 -> [([Pattern],LExpr t v)]
110 -> Unique (Clause t v)
111matchClause c (v:vs) cs def =
113 Clause c vs' `liftM` match (vs' ++ vs) (map flatten cs) def
118 PData _ ps' -> (ps' ++ ps, e)
119 PLiteral _ -> (ps, e)
123 (PData _ ps : _, _) -> mapM (\_ -> newVar) ps
124 (PLiteral _ : _, _) -> return []
126matchMix :: [String] -> [([Pattern],LExpr t v)] -> Match t v
127 -> Unique (Match t v)
128matchMix vs cs def = foldM (flip $ match vs) def (reverse css)
129 where css = groupBy (\p1 p2 -> isCon p1 == isCon p2) cs
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list