1 {-# LANGUAGE PatternSynonyms #-}
2 {-# LANGUAGE TemplateHaskell #-}
3 {-# LANGUAGE ViewPatterns #-}
4 {-# LANGUAGE UndecidableInstances #-}
5 module Symantic.Parser.Grammar.Optimizations where
7 import Data.Bool (Bool)
8 import Data.Char (Char)
9 import Data.Either (Either(..), either)
10 import Data.Eq (Eq(..))
11 import qualified Prelude as Pre
12 import Data.String (String)
15 import Symantic.Base.Univariant
16 import Symantic.Parser.Grammar.Combinators
17 import Symantic.Parser.Grammar.Observations
18 import Symantic.Parser.Staging hiding (Haskell(..))
19 import qualified Symantic.Parser.Staging as Hask
20 -- import qualified Language.Haskell.TH.Syntax as TH
24 Pure :: Hask.Haskell a -> Comb a
25 Satisfy :: Hask.Haskell (Char -> Bool) -> Comb Char
27 Try :: Comb a -> Comb a
28 Look :: Comb a -> Comb a
29 NegLook :: Comb a -> Comb ()
30 (:<*>) :: Comb (a -> b) -> Comb a -> Comb b
31 (:<|>) :: Comb a -> Comb a -> Comb a
33 Branch :: Comb (Either a b) -> Comb (a -> c) -> Comb (b -> c) -> Comb c
34 Match :: Eq a => [Hask.Haskell (a -> Bool)] -> [Comb b] -> Comb a -> Comb b -> Comb b
35 ChainPre :: Comb (a -> a) -> Comb a -> Comb a
36 ChainPost :: Comb a -> Comb (a -> a) -> Comb a
37 Def :: String -> Comb a -> Comb a
38 Ref :: Bool -> String -> Comb a
40 pattern (:<$>) :: Hask.Haskell (a -> b) -> Comb a -> Comb b
41 pattern (:$>) :: Comb a -> Hask.Haskell b -> Comb b
42 pattern (:<$) :: Hask.Haskell a -> Comb b -> Comb a
43 pattern (:*>) :: Comb a -> Comb b -> Comb b
44 pattern (:<*) :: Comb a -> Comb b -> Comb a
45 pattern x :<$> p = Pure x :<*> p
46 pattern p :$> x = p :*> Pure x
47 pattern x :<$ p = Pure x :<* p
48 pattern x :<* p = Hask.Const :<$> x :<*> p
49 pattern p :*> x = Hask.Id :<$ p :<*> x
52 infixl 4 :<*>, :<*, :*>
53 infixl 4 :<$>, :<$, :$>
55 instance Applicable Comb where
58 instance Alternable Comb where
62 instance Selectable Comb where
64 instance Matchable Comb where
66 instance Foldable Comb where
69 instance Charable Comb where
71 instance Lookable Comb where
74 instance Sharable Comb where
87 Symantic Comb repr where
90 Satisfy p -> satisfy p
93 Look x -> look (sym x)
94 NegLook x -> negLook (sym x)
95 x :<*> y -> sym x <*> sym y
96 x :<|> y -> sym x <|> sym y
98 Branch lr l r -> branch (sym lr) (sym l) (sym r)
99 Match cs bs a b -> conditional cs (sym Pre.<$> bs) (sym a) (sym b)
100 ChainPre x y -> chainPre (sym x) (sym y)
101 ChainPost x y -> chainPost (sym x) (sym y)
102 Def n x -> def n (sym x)
105 type instance Unlift Comb = repr
115 ) => Unliftable Comb where
118 Satisfy p -> satisfy p
120 Try x -> try (unlift x)
121 Look x -> look (unlift x)
122 NegLook x -> negLook (unlift x)
123 x :<*> y -> unlift x <*> unlift y
124 x :<|> y -> unlift x <|> unlift y
126 Branch lr l r -> branch (unlift lr) (unlift l) (unlift r)
127 Match cs bs a b -> conditional cs (unlift Pre.<$> bs) (unlift a) (unlift b)
128 ChainPre x y -> chainPre (unlift x) (unlift y)
129 ChainPost x y -> chainPost (unlift x) (unlift y)
130 Ref{..} -> let_ let_rec let_name
141 ) => Comb repr a -> repr a
145 optComb :: Comb a -> Comb a
147 Def n x -> Def n (optComb x)
148 -- Applicable Right Absorption Law
149 Empty :<*> _ -> Empty
152 -- Applicable Failure Weakening Law
153 u :<*> Empty -> optComb (u :*> Empty)
154 u :<* Empty -> optComb (u :*> Empty)
155 -- Branch Absorption Law
156 Branch Empty _ _ -> empty
157 -- Branch Weakening Law
158 Branch b Empty Empty -> optComb (b :*> Empty)
160 -- Applicable Identity Law
162 -- Flip const optimisation
163 Hask.Flip Hask.:@ Hask.Const :<$> u -> optComb (u :*> Pure Hask.Id)
165 f :<$> Pure x -> Pure (f Hask.:@ x)
166 -- Functor Composition Law
167 -- (a shortcut that could also have been be caught
168 -- by the Composition Law and Homomorphism law)
169 f :<$> (g :<$> p) -> optComb ((Hask.:.) Hask.:@ f Hask.:@ g :<$> p)
171 u :<*> (v :<*> w) -> optComb (optComb (optComb ((Hask.:.) :<$> u) :<*> v) :<*> w)
173 Hask.Flip Hask.:@ Hask.Const :<$> p :<*> q -> p :*> q
175 Hask.Const :<$> p :<*> q -> p :<* q
176 -- Reassociation Law 1
177 (u :*> v) :<*> w -> optComb (u :*> optComb (v :<*> w))
179 u :<*> Pure x -> optComb (Hask.Flip Hask.:@ (Hask.:$) Hask.:@ x :<$> u)
180 -- Right Absorption Law
181 (_ :<$> p) :*> q -> p :*> q
182 -- Left Absorption Law
183 p :<* (_ :<$> q) -> p :<* q
184 -- Reassociation Law 2
185 u :<*> (v :<* w) -> optComb (optComb (u :<*> v) :<* w)
186 -- Reassociation Law 3
187 u :<*> (v :$> x) -> optComb (optComb (u :<*> Pure x) :<* v)
196 (u :<|> v) :<|> w -> u :<|> optComb (v :<|> w)
201 (u :$> _) :*> v -> u :*> v
203 u :*> (v :*> w) -> optComb (optComb (u :*> v) :*> w)
207 u :<* (v :$> _) -> optComb (u :<* v)
209 x :<$ u -> optComb (u :$> x)
211 (u :<* v) :<* w -> optComb (u :<* optComb (v :<* w))
217 -- Pure negative-lookahead
218 NegLook Pure{} -> Empty
220 -- Dead negative-lookahead
221 NegLook Empty -> Pure Hask.unit
222 -- Double Negation Law
223 NegLook (NegLook p) -> optComb (Look (Try p) :*> Pure Hask.unit)
224 -- Zero Consumption Law
225 NegLook (Try p) -> optComb (NegLook p)
227 Look (Look p) -> Look p
228 -- Right Identity Law
229 NegLook (Look p) -> optComb (NegLook p)
232 Look (NegLook p) -> NegLook p
234 NegLook (Try p :<|> q) -> optComb (optComb (NegLook p) :*> optComb (NegLook q))
235 -- Distributivity Law
236 Look p :<|> Look q -> optComb (Look (optComb (Try p :<|> q)))
238 Look (p :$> x) -> optComb (optComb (Look p) :$> x)
240 Look (f :<$> p) -> optComb (f :<$> optComb (Look p))
242 p :<*> NegLook q -> optComb (optComb (p :<*> Pure Hask.unit) :<* NegLook q)
244 NegLook (p :$> _) -> optComb (NegLook p)
246 NegLook (_ :<$> p) -> optComb (NegLook p)
248 Try (p :$> x) -> optComb (optComb (Try p) :$> x)
250 Try (f :<$> p) -> optComb (f :<$> optComb (Try p))
252 -- pure Left/Right laws
253 Branch (Pure (unlift -> lr)) l r ->
255 Left v -> optComb (l :<*> Pure (Hask.Haskell (ValueCode (Value v) c)))
256 where c = Code [|| case $$(getCode lr) of Left x -> x ||]
257 Right v -> optComb (r :<*> Pure (Hask.Haskell (ValueCode (Value v) c)))
258 where c = Code [|| case $$(getCode lr) of Right x -> x ||]
259 -- Generalised Identity law
260 Branch b (Pure (unlift -> l)) (Pure (unlift -> r)) ->
261 optComb (Hask.Haskell (ValueCode v c) :<$> b)
263 v = Value (either (getValue l) (getValue r))
264 c = Code [|| either $$(getCode l) $$(getCode r) ||]
266 Branch (x :*> y) p q ->
267 optComb (x :*> optComb (Branch y p q))
268 -- Negated Branch law
270 Branch (Pure (Hask.Haskell (ValueCode v c)) :<*> b) Empty l
272 v = Value (either Right Left)
273 c = Code [||either Right Left||]
275 Branch (Branch b Empty (Pure (unlift -> lr))) Empty br ->
276 optComb (Branch (optComb (Pure (Hask.Haskell (ValueCode (Value v) c)) :<*> b)) Empty br)
279 v (Right r) = case getValue lr r of
282 c = Code [|| \case Left{} -> Left ()
283 Right r -> case $$(getCode lr) r of
285 Right rr -> Right rr ||]
286 -- Distributivity Law
287 f :<$> Branch b l r -> optComb (Branch b (optComb ((Hask..@) (Hask..) f :<$> l))
288 (optComb ((Hask..@) (Hask..) f :<$> r)))
293 type instance Unlift (Ref repr) = repr
294 instance Liftable (Ref repr) where
295 lift x = let n = x in LetNode (makeParserName n) n
296 lift1 f x = let n = f (let_sub x) in LetNode (makeParserName n) n
297 lift2 f x y = let n = f (let_sub x) (let_sub y) in LetNode (makeParserName n) n
298 lift3 f x y z = let n = f (let_sub x) (let_sub y) (let_sub z) in LetNode (makeParserName n) n
299 instance Applicable repr => Applicable (Ref repr)
301 data Ref repr a where
302 LetNode :: { let_id :: IO ParserName, let_sub :: repr a } -> Ref repr a
303 --LetLeaf :: repr a -> Ref repr a
305 instance Liftable (Ref (Comb repr)) where
308 lift1 f x = case x of
309 LetLeaf l -> LetLeaf (f l)
310 LetNode l -> LetLeaf (f l)
311 instance Applicable (Ref (Comb repr)) where
312 pure a = LetLeaf (pure a)
313 x <*> y = LetNode (mkParserName x) (<*>
314 instance Applicable (Comb (Ref repr)) where
316 x <*> y = LetNode (mkParserName x) (:<*>