1 {-# LANGUAGE DefaultSignatures #-}
2 {-# LANGUAGE StandaloneDeriving #-} -- For prodCon
3 {-# LANGUAGE TemplateHaskell #-}
4 {-# LANGUAGE StandaloneDeriving #-}
5 {-# LANGUAGE DeriveLift #-}
6 {-# LANGUAGE UndecidableInstances #-}
7 {-# OPTIONS_GHC -fno-warn-orphans #-}
8 module Symantic.Parser.Grammar.Production where
10 import Control.Monad (Monad(..))
11 import Data.Functor.Identity (Identity(..))
12 import Data.Functor.Product (Product(..))
13 import Prelude (Num(..), undefined)
14 import Text.Show (Show(..), showString)
15 import Type.Reflection (Typeable)
16 import qualified Data.Either as Either
17 import qualified Data.Eq as Eq
18 import qualified Data.Function as Fun
19 import qualified Data.Maybe as Maybe
20 import qualified Language.Haskell.TH as TH
21 import qualified Language.Haskell.TH.Syntax as TH
22 import qualified Language.Haskell.TH.Show as TH
24 import Symantic.Typed.Data
25 import Symantic.Typed.Lang
26 import Symantic.Typed.Optim
27 import Symantic.Typed.Trans
29 type Production = Product
33 {-# INLINE prodValue #-}
34 prodValue :: Production a -> SomeData Identity a
35 prodValue (Pair v _) = v
36 {-# INLINE prodCode #-}
37 prodCode :: Production a -> SomeData TH.CodeQ a
38 prodCode (Pair _ c) = c
40 {-# INLINE production #-}
41 production :: a -> TH.CodeQ a -> Production a
43 (SomeData (Var (Identity v)))
47 prod :: TH.Lift a => a -> Production a
48 prod x = production x [||x||]
50 {-# INLINE runValue #-}
51 runValue :: Production a -> a
52 runValue x = runIdentity (trans x)
53 {-# INLINE runCode #-}
54 runCode :: Production a -> TH.CodeQ a
57 -- Missing instances in 'Language.Haskell.TH',
58 -- needed for 'prodCon'.
59 deriving instance TH.Lift TH.OccName
60 deriving instance TH.Lift TH.NameFlavour
61 deriving instance TH.Lift TH.ModName
62 deriving instance TH.Lift TH.PkgName
63 deriving instance TH.Lift TH.NameSpace
64 deriving instance TH.Lift TH.Name
66 -- | @$(prodCon 'SomeConstructor)@ generates the 'Production' for @SomeConstructor@.
67 prodCon :: TH.Name -> TH.Q TH.Exp
71 TH.DataConI n _ty _pn ->
72 [| production $(return (TH.ConE n))
73 (TH.unsafeCodeCoerce (return (TH.ConE $(TH.lift n)))) |]
75 instance Trans Production Identity where
76 trans (Pair (SomeData v) _c) = trans v
77 instance Trans Production TH.CodeQ where
78 trans (Pair _v (SomeData c)) = trans c
80 instance Show (SomeData TH.CodeQ a) where
81 -- The 'Trans' constraint contained in 'SomeData'
82 -- is 'TH.CodeQ', hence 'Symantic.Typed.View' cannot be used here.
83 -- Fortunately 'TH.showCode' can be implemented.
84 showsPrec p = showString Fun.. TH.showCode p Fun.. trans
86 instance (Abstractable f, Abstractable g) => Abstractable (Product f g) where
87 -- Those 'undefined' are not unreachables by 'f'
88 -- but this is the cost to pay for defining this instance.
89 -- In particular, 'f' must not define the 'TH.CodeQ' part
90 -- using the 'Identity' part.
92 (lam (\x -> let Pair fx _ = f (Pair x undefined) in fx))
93 (lam (\y -> let Pair _ fy = f (Pair undefined y) in fy))
95 (lam1 (\x -> let Pair fx _ = f (Pair x undefined) in fx))
96 (lam1 (\y -> let Pair _ fy = f (Pair undefined y) in fy))
97 const = Pair const const
100 flip = Pair flip flip
101 Pair f1 f2 .@ Pair x1 x2 = Pair (f1 .@x1) (f2 .@x2)
104 instance (Num (f a), Num (g a)) => Num (Product f g a) where
105 Pair x1 x2 + Pair y1 y2 = Pair (x1 + y1) (x2 + y2)
106 Pair x1 x2 * Pair y1 y2 = Pair (x1 * y1) (x2 * y2)
107 Pair x1 x2 - Pair y1 y2 = Pair (x1 - y1) (x2 - y2)
108 abs (Pair x1 x2) = Pair (abs x1) (abs x2)
109 fromInteger i = Pair (fromInteger i) (fromInteger i)
110 negate (Pair x1 x2) = Pair (negate x1) (negate x2)
111 signum (Pair x1 x2) = Pair (signum x1) (signum x2)
112 instance (Eitherable f, Eitherable g) => Eitherable (Product f g) where
113 left = Pair left left
114 right = Pair right right
115 instance (TH.Lift c, Typeable c) => Constantable c Production where
116 constant c = Pair (constant c) (constant c)
117 instance Maybeable Production where
118 nothing = Pair nothing nothing
119 just = Pair just just
120 instance Listable Production where
122 cons = Pair cons cons
123 instance Equalable Production where
124 equal = Pair equal equal
126 optimizeProduction :: Production a -> Production a
127 optimizeProduction (Pair v c) = Pair (normalOrderReduction v) (normalOrderReduction c)
130 instance Anythingable Identity
131 instance Abstractable Identity where
132 f .@ x = Identity (runIdentity f (runIdentity x))
133 lam f = Identity (runIdentity Fun.. f Fun.. Identity)
136 const = Identity Fun.const
137 flip = Identity Fun.flip
139 ($) = Identity (Fun.$)
140 (.) = Identity (Fun..)
141 instance Constantable c Identity where
143 instance Eitherable Identity where
144 left = Identity Either.Left
145 right = Identity Either.Right
146 instance Equalable Identity where
147 equal = Identity (Eq.==)
148 instance IfThenElseable Identity where
149 ifThenElse test ok ko = Identity
153 instance Listable Identity where
156 instance Maybeable Identity where
157 nothing = Identity Maybe.Nothing
158 just = Identity Maybe.Just
161 instance Anythingable TH.CodeQ
162 instance Abstractable TH.CodeQ where
163 (.@) f x = [|| $$f $$x ||]
164 lam f = [|| \x -> $$(f [||x||]) ||]
168 const = [|| Fun.const ||]
169 flip = [|| \f x y -> f y x ||]
170 ($) = [|| (Fun.$) ||]
171 (.) = [|| (Fun..) ||]
172 instance TH.Lift c => Constantable c TH.CodeQ where
173 constant c = [|| c ||]
174 instance Eitherable TH.CodeQ where
175 left = [|| Either.Left ||]
176 right = [|| Either.Right ||]
177 instance Equalable TH.CodeQ where
178 equal = [|| (Eq.==) ||]
179 instance IfThenElseable TH.CodeQ where
180 ifThenElse test ok ko = [|| if $$test then $$ok else $$ko ||]
181 instance Listable TH.CodeQ where
184 instance Maybeable TH.CodeQ where
185 nothing = [|| Maybe.Nothing ||]
186 just = [|| Maybe.Just ||]
187 instance Num a => Num (TH.CodeQ a) where
188 x + y = [|| $$x + $$y||]
189 x * y = [|| $$x * $$y||]
190 x - y = [|| $$x - $$y||]
191 abs x = [|| abs $$x ||]
192 fromInteger i = [|| fromInteger $$(TH.liftTyped i) ||]
193 negate x = [|| negate $$x ||]
194 signum x = [|| signum $$x ||]