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
26 import Symantic.Derive
28 type Production = Product
32 {-# INLINE prodValue #-}
33 prodValue :: Production a -> SomeData Identity a
34 prodValue (Pair v _) = v
35 {-# INLINE prodCode #-}
36 prodCode :: Production a -> SomeData TH.CodeQ a
37 prodCode (Pair _ c) = c
39 {-# INLINE production #-}
40 production :: a -> TH.CodeQ a -> Production a
42 (SomeData (Var (Identity v)))
46 prod :: TH.Lift a => a -> Production a
47 prod x = production x [||x||]
49 {-# INLINE runValue #-}
50 runValue :: Production a -> a
51 runValue (Pair v _c) = runIdentity (derive v)
52 {-# INLINE runCode #-}
53 runCode :: Production a -> TH.CodeQ a
54 runCode (Pair _v c) = derive c
56 -- Missing instances in 'Language.Haskell.TH',
57 -- needed for 'prodCon'.
58 deriving instance TH.Lift TH.OccName
59 deriving instance TH.Lift TH.NameFlavour
60 deriving instance TH.Lift TH.ModName
61 deriving instance TH.Lift TH.PkgName
62 deriving instance TH.Lift TH.NameSpace
63 deriving instance TH.Lift TH.Name
65 -- | @$(prodCon 'SomeConstructor)@ generates the 'Production' for @SomeConstructor@.
66 prodCon :: TH.Name -> TH.Q TH.Exp
70 TH.DataConI n _ty _pn ->
71 [| production $(return (TH.ConE n))
72 (TH.unsafeCodeCoerce (return (TH.ConE $(TH.lift n)))) |]
74 instance Show (SomeData TH.CodeQ a) where
75 -- The 'Derivable' constraint contained in 'SomeData'
76 -- is 'TH.CodeQ', hence 'Symantic.View' cannot be used here.
77 -- Fortunately 'TH.showCode' can be implemented.
78 showsPrec p = showString Fun.. TH.showCode p Fun.. derive
80 instance (Abstractable f, Abstractable g) => Abstractable (Product f g) where
81 -- Those 'undefined' are not unreachables by 'f'
82 -- but this is the cost to pay for defining this instance.
83 -- In particular, 'f' must not define the 'TH.CodeQ' part
84 -- using the 'Identity' part.
86 (lam (\x -> let Pair fx _ = f (Pair x undefined) in fx))
87 (lam (\y -> let Pair _ fy = f (Pair undefined y) in fy))
89 (lam1 (\x -> let Pair fx _ = f (Pair x undefined) in fx))
90 (lam1 (\y -> let Pair _ fy = f (Pair undefined y) in fy))
91 const = Pair const const
95 Pair f1 f2 .@ Pair x1 x2 = Pair (f1 .@x1) (f2 .@x2)
98 instance (Num (f a), Num (g a)) => Num (Product f g a) where
99 Pair x1 x2 + Pair y1 y2 = Pair (x1 + y1) (x2 + y2)
100 Pair x1 x2 * Pair y1 y2 = Pair (x1 * y1) (x2 * y2)
101 Pair x1 x2 - Pair y1 y2 = Pair (x1 - y1) (x2 - y2)
102 abs (Pair x1 x2) = Pair (abs x1) (abs x2)
103 fromInteger i = Pair (fromInteger i) (fromInteger i)
104 negate (Pair x1 x2) = Pair (negate x1) (negate x2)
105 signum (Pair x1 x2) = Pair (signum x1) (signum x2)
106 instance (Eitherable f, Eitherable g) => Eitherable (Product f g) where
107 left = Pair left left
108 right = Pair right right
109 instance (TH.Lift c, Typeable c) => Constantable c Production where
110 constant c = Pair (constant c) (constant c)
111 instance Maybeable Production where
112 nothing = Pair nothing nothing
113 just = Pair just just
114 instance Listable Production where
116 cons = Pair cons cons
117 instance Equalable Production where
118 equal = Pair equal equal
121 instance Anythingable Identity
122 instance Abstractable Identity where
123 f .@ x = Identity (runIdentity f (runIdentity x))
124 lam f = Identity (runIdentity Fun.. f Fun.. Identity)
127 const = Identity Fun.const
128 flip = Identity Fun.flip
130 ($) = Identity (Fun.$)
131 (.) = Identity (Fun..)
132 instance Constantable c Identity where
134 instance Eitherable Identity where
135 left = Identity Either.Left
136 right = Identity Either.Right
137 instance Equalable Identity where
138 equal = Identity (Eq.==)
139 instance IfThenElseable Identity where
140 ifThenElse test ok ko = Identity
144 instance Listable Identity where
147 instance Maybeable Identity where
148 nothing = Identity Maybe.Nothing
149 just = Identity Maybe.Just
152 instance Anythingable TH.CodeQ
153 instance Abstractable TH.CodeQ where
154 (.@) f x = [|| $$f $$x ||]
155 lam f = [|| \x -> $$(f [||x||]) ||]
159 const = [|| Fun.const ||]
160 flip = [|| \f x y -> f y x ||]
161 ($) = [|| (Fun.$) ||]
162 (.) = [|| (Fun..) ||]
163 instance TH.Lift c => Constantable c TH.CodeQ where
164 constant c = [|| c ||]
165 instance Eitherable TH.CodeQ where
166 left = [|| Either.Left ||]
167 right = [|| Either.Right ||]
168 instance Equalable TH.CodeQ where
169 equal = [|| (Eq.==) ||]
170 instance IfThenElseable TH.CodeQ where
171 ifThenElse test ok ko = [|| if $$test then $$ok else $$ko ||]
172 instance Listable TH.CodeQ where
175 instance Maybeable TH.CodeQ where
176 nothing = [|| Maybe.Nothing ||]
177 just = [|| Maybe.Just ||]
178 instance Num a => Num (TH.CodeQ a) where
179 x + y = [|| $$x + $$y||]
180 x * y = [|| $$x * $$y||]
181 x - y = [|| $$x - $$y||]
182 abs x = [|| abs $$x ||]
183 fromInteger i = [|| fromInteger $$(TH.liftTyped i) ||]
184 negate x = [|| negate $$x ||]
185 signum x = [|| signum $$x ||]