@@ -16,54 +16,91 @@ mkSubst : {vars : _} -> (args : List (Var vars)) ->
1616mkSubst [] NilMatch = []
1717mkSubst (x :: xs) (ConsMatch m) = x :: mkSubst xs m
1818
19+ data MatchedPattern : Scoped where
20+ ConMatched : Name -> (tag : Int) -> List (Var vars) -> MatchedPattern vars
21+ DelayMatched : (ty, arg : Var vars) -> MatchedPattern vars
22+ ConstMatched : Constant -> MatchedPattern vars
23+
24+ data UnmatchedPattern : Type where
25+ ConUnmatched : List (Name, Int) -> UnmatchedPattern
26+ ConstUnmatched : List Constant -> UnmatchedPattern
27+
1928data MatchResult : Scoped where
20- ConPat : Name -> (tag : Int) -> List (Var vars) -> MatchResult vars
21- DelayPat : (ty, arg : Var vars) -> MatchResult vars
22- ConstPat : Constant -> MatchResult vars
29+ Matched : MatchedPattern vars -> MatchResult vars
30+ Unmatched : UnmatchedPattern -> MatchResult vars
31+
32+ Weaken MatchedPattern where
33+ weakenNs s (ConMatched n tag args) = ConMatched n tag (weakenNs s <$> args)
34+ weakenNs s (DelayMatched ty arg) = DelayMatched (weakenNs s ty) (weakenNs s arg)
35+ weakenNs s (ConstMatched c) = ConstMatched c
2336
2437Weaken MatchResult where
25- weakenNs s (ConPat n tag args) = ConPat n tag (weakenNs s <$> args)
26- weakenNs s (DelayPat ty arg) = DelayPat (weakenNs s ty) (weakenNs s arg)
27- weakenNs s (ConstPat c) = ConstPat c
38+ weakenNs s (Matched p) = Matched (weakenNs s p)
39+ weakenNs _ (Unmatched p) = Unmatched p
40+
41+ destructMatchResult : Maybe (MatchResult vars) ->
42+ Either (MatchedPattern vars) (Maybe UnmatchedPattern)
43+ destructMatchResult (Just (Matched p)) = Left p
44+ destructMatchResult (Just (Unmatched p)) = Right (Just p)
45+ destructMatchResult Nothing = Right Nothing
46+
47+ addUnmatchedCon : (Name, Int) -> Maybe UnmatchedPattern -> Maybe UnmatchedPattern
48+ addUnmatchedCon con Nothing = Just $ ConUnmatched [con]
49+ addUnmatchedCon con (Just (ConUnmatched cs))
50+ = toMaybe (not $ con `elem` cs) $ ConUnmatched (con :: cs)
51+ addUnmatchedCon _ (Just (ConstUnmatched _ )) = Nothing -- shouldn't happen
52+
53+ addUnmatchedConst : Constant -> Maybe UnmatchedPattern -> Maybe UnmatchedPattern
54+ addUnmatchedConst c Nothing = Just $ ConstUnmatched [c]
55+ addUnmatchedConst c (Just (ConstUnmatched cs))
56+ = toMaybe (not $ c `elem` cs) $ ConstUnmatched (c :: cs)
57+ addUnmatchedConst _ (Just (ConUnmatched _ )) = Nothing -- shouldn't happen
2858
2959export
3060optimiseTree : {vars : _} -> List (Var vars, MatchResult vars) -> CaseTree vars -> Maybe (CaseTree vars)
3161
3262optimiseAlts : {vars : _} -> List (Var vars, MatchResult vars) ->
33- Var vars -> List (CaseAlt vars) ->
63+ Var vars -> Maybe UnmatchedPattern -> List (CaseAlt vars) ->
3464 (List (Maybe (CaseAlt vars)), Maybe (CaseTree vars))
35- optimiseAlts ps v [] = ([], Nothing )
36- optimiseAlts ps v (ConCase n tag args sc :: alts)
37- = do let sz = mkSizeOf args
65+ optimiseAlts ps v _ [] = ([], Nothing )
66+ optimiseAlts ps v p (ConCase n tag args sc :: alts)
67+ = do let Just p' = addUnmatchedCon (n, tag) p
68+ | _ => optimiseAlts ps v p alts -- unreachable case
69+ let sz = mkSizeOf args
3870 let v' = weakenNs sz v
39- let ps' = map (bimap (weakenNs sz) (weakenNs sz)) ps
4071 let args' = allVarsPrefix sz
41- let alt = ConCase n tag args <$> optimiseTree ((v', ConPat n tag args') :: ps') sc
42- mapFst (alt :: ) (optimiseAlts ps v alts)
43- optimiseAlts ps v (DelayCase ty arg sc :: alts)
72+ let ps' = map (bimap (weakenNs sz) (weakenNs sz)) ps
73+ let ps'' = (v' , Matched $ ConMatched n tag args') :: ps'
74+ let alt = ConCase n tag args <$> optimiseTree ps'' sc
75+ mapFst (alt ::) (optimiseAlts ps v (Just p' ) alts)
76+ optimiseAlts ps v p (DelayCase ty arg sc :: alts)
4477 = do let sz = mkSizeOf [ty, arg]
4578 let v' = weakenNs sz v
4679 let ps' = map (bimap (weakenNs sz) (weakenNs sz)) ps
47- let alt = DelayCase ty arg <$> optimiseTree ((v', DelayPat first (later first)) :: ps') sc
48- mapFst (alt :: ) (optimiseAlts ps v alts)
49- optimiseAlts ps v (ConstCase c sc :: alts)
50- = do let alt = ConstCase c <$> optimiseTree ((v, ConstPat c) :: ps) sc
51- mapFst (alt :: ) (optimiseAlts ps v alts)
52- optimiseAlts ps _ (DefaultCase sc :: _ )
53- = ([], optimiseTree ps sc)
80+ let ps'' = (v' , Matched $ DelayMatched first (later first)) :: ps'
81+ let alt = DelayCase ty arg <$> optimiseTree ps'' sc
82+ mapFst (alt ::) (optimiseAlts ps v p alts)
83+ optimiseAlts ps v p (ConstCase c sc :: alts)
84+ = do let Just p' = addUnmatchedConst c p
85+ | _ => optimiseAlts ps v p alts -- unreachable case
86+ let ps' = (v, Matched $ ConstMatched c) :: ps
87+ let alt = ConstCase c <$> optimiseTree ps' sc
88+ mapFst (alt :: ) (optimiseAlts ps v (Just p') alts)
89+ optimiseAlts ps v p (DefaultCase sc :: _ )
90+ = ([], optimiseTree (maybe ps (\ p => (v, Unmatched p) :: ps) p) sc)
5491
5592pickAlt : {vars : _} -> List (Var vars, MatchResult vars) ->
56- MatchResult vars -> List (CaseAlt vars) -> Maybe (CaseTree vars)
93+ MatchedPattern vars -> List (CaseAlt vars) -> Maybe (CaseTree vars)
5794pickAlt _ _ [] = Nothing
58- pickAlt ps p@(ConPat n t args) (ConCase n' t' args' sc :: alts)
95+ pickAlt ps p@(ConMatched n t args) (ConCase n' t' args' sc :: alts)
5996 = if t == t' && n == n'
6097 then do match <- checkLengthMatch args args' -- lengths should always match
6198 optimiseTree ps $ substCaseTree zero (mkSizeOf _ ) (mkSubst args match) sc
6299 else pickAlt ps p alts
63- pickAlt ps (DelayPat ty arg) (DelayCase ty' arg' sc :: _ )
100+ pickAlt ps (DelayMatched ty arg) (DelayCase ty' arg' sc :: _ )
64101 = do let subst : Subst Var [ty', arg'] vars = mkSubst [ty, arg] %search
65102 optimiseTree ps $ substCaseTree zero (mkSizeOf _ ) subst sc
66- pickAlt ps p@(ConstPat c) (ConstCase c' sc :: alts)
103+ pickAlt ps p@(ConstMatched c) (ConstCase c' sc :: alts)
67104 = if c == c'
68105 then optimiseTree ps sc
69106 else pickAlt ps p alts
@@ -72,9 +109,9 @@ pickAlt ps p (_ :: alts) = pickAlt ps p alts
72109
73110optimiseTree ps (Case idx el ty alts)
74111 = do let var = MkVar el
75- case lookup var ps of
76- Just p => pickAlt ps p alts
77- Nothing => case mapFst catMaybes $ optimiseAlts ps var alts of
112+ case destructMatchResult $ lookup var ps of
113+ Left p => pickAlt ps p alts
114+ Right p => case mapFst catMaybes $ optimiseAlts ps var p alts of
78115 ([], def) => def
79116 (alts, Nothing ) => Just $ Case idx el ty alts
80117 (alts, Just def) =>
0 commit comments