1 {-# LANGUAGE PatternSynonyms #-}
2 {-# LANGUAGE TemplateHaskell #-}
3 module Symantic.Parser.Staging where
5 import Data.Bool (Bool(..))
6 import Data.Either (Either(..))
8 import Data.Maybe (Maybe(..))
9 import Data.Ord (Ord(..))
10 import Data.Kind (Type)
11 import Text.Show (Show(..), showParen, showString)
12 import qualified Data.Eq as Eq
13 import qualified Data.Function as Function
14 import qualified Language.Haskell.TH as TH
15 import qualified Language.Haskell.TH.Syntax as TH
17 import Symantic.Univariant.Trans
20 -- | Compile-time 'value' and corresponding 'code'
21 -- (that can produce that value at runtime).
22 data ValueCode a = ValueCode
26 getValue :: ValueCode a -> a
27 getValue = unValue Function.. value
28 getCode :: ValueCode a -> TH.CodeQ a
32 newtype Value a = Value { unValue :: a }
34 -- * Class 'Haskellable'
35 -- | Final encoding of some Haskell functions
36 -- useful for some optimizations in 'optimizeComb'.
37 class Haskellable (repr :: Type -> Type) where
38 (.) :: repr ((b->c) -> (a->b) -> a -> c)
39 ($) :: repr ((a->b) -> a -> b)
40 (.@) :: repr (a->b) -> repr a -> repr b
41 bool :: Bool -> repr Bool
42 char :: TH.Lift tok => tok -> repr tok
43 cons :: repr (a -> [a] -> [a])
44 const :: repr (a -> b -> a)
45 eq :: Eq a => repr a -> repr (a -> Bool)
46 flip :: repr ((a -> b -> c) -> b -> a -> c)
50 left :: repr (l -> Either l r)
51 right :: repr (r -> Either l r)
52 nothing :: repr (Maybe a)
53 just :: repr (a -> Maybe a)
55 -- ** Type 'Haskellable'
56 -- | Initial encoding of 'Haskellable'.
58 Haskell :: ValueCode a -> Haskell a
59 (:.) :: Haskell ((b->c) -> (a->b) -> a -> c)
60 (:$) :: Haskell ((a->b) -> a -> b)
61 (:@) :: Haskell (a->b) -> Haskell a -> Haskell b
62 Cons :: Haskell (a -> [a] -> [a])
63 Const :: Haskell (a -> b -> a)
64 Eq :: Eq a => Haskell a -> Haskell (a -> Bool)
65 Flip :: Haskell ((a -> b -> c) -> b -> a -> c)
74 -- Dummy constraint to get the following constraint
75 -- in scope when pattern-matching.
77 ((x -> y -> z) ~ ((b -> c) -> (a -> b) -> a -> c)) =>
78 Haskell x -> Haskell y -> Haskell z
79 pattern (:.@) f g = (:.) :@ f :@ g
82 ((x -> y) ~ ((a -> b -> c) -> b -> a -> c)) =>
83 Haskell x -> Haskell y
84 pattern FlipApp f = Flip :@ f
87 (x ~ (a -> b -> b)) =>
89 pattern FlipConst = FlipApp Const
92 instance Show (Haskell a) where
94 Haskell{} -> showString "Haskell"
95 (:$) -> showString "($)"
98 Function.$ showsPrec 9 f
99 Function.. showString " . "
100 Function.. showsPrec 9 g
101 (:.) -> showString "(.)"
104 Function.$ showsPrec 10 x
105 Function.. showString " : "
106 Function.. showsPrec 10 xs
107 Cons -> showString "cons"
108 Const -> showString "const"
111 Function.$ showString "== "
112 Function.. showsPrec 0 x
113 Flip -> showString "flip"
114 Id -> showString "id"
115 Unit -> showString "()"
118 Function.$ showsPrec 10 f
119 Function.. showString " "
120 Function.. showsPrec 10 x
121 instance Trans Haskell Value where
122 trans = value Function.. trans
123 instance Trans Haskell TH.CodeQ where
124 trans = code Function.. trans
125 instance Trans Haskell ValueCode where
130 (:@) f x -> (.@) (trans f) (trans x)
137 instance Trans ValueCode Haskell where
139 type instance Output Haskell = ValueCode
141 instance Haskellable Haskell where
144 -- Small optimizations, mainly to reduce dump sizes.
146 (Const :@ x) .@ _y = x
147 ((Flip :@ Const) :@ _x) .@ y = y
156 bool b = Haskell (bool b)
157 char c = Haskell (char c)
160 right = Haskell right
161 nothing = Haskell nothing
163 instance Haskellable ValueCode where
164 (.) = ValueCode (.) (.)
165 ($) = ValueCode ($) ($)
166 (.@) f x = ValueCode ((.@) (value f) (value x)) ((.@) (code f) (code x))
167 bool b = ValueCode (bool b) (bool b)
168 char c = ValueCode (char c) (char c)
169 cons = ValueCode cons cons
170 const = ValueCode const const
171 eq x = ValueCode (eq (value x)) (eq (code x))
172 flip = ValueCode flip flip
174 nil = ValueCode nil nil
175 unit = ValueCode unit unit
176 left = ValueCode left left
177 right = ValueCode right right
178 nothing = ValueCode nothing nothing
179 just = ValueCode just just
180 instance Haskellable Value where
181 (.) = Value (Function..)
182 ($) = Value (Function.$)
183 (.@) f x = Value (unValue f (unValue x))
187 const = Value Function.const
188 eq x = Value (unValue x Eq.==)
189 flip = Value Function.flip
190 id = Value Function.id
195 nothing = Value Nothing
197 instance Haskellable TH.CodeQ where
198 (.) = [|| (Function..) ||]
199 ($) = [|| (Function.$) ||]
200 (.@) f x = [|| $$f $$x ||]
204 const = [|| Function.const ||]
205 eq x = [|| ($$x Eq.==) ||]
206 flip = [|| \f x y -> f y x ||]
211 right = [|| Right ||]
212 nothing = [|| Nothing ||]