1 {-# LANGUAGE TemplateHaskell #-}
2 module Symantic.Parser.Staging where
4 import Data.Bool (Bool)
5 import Data.Char (Char)
7 import Language.Haskell.TH (TExpQ)
8 import qualified Data.Eq as Eq
9 import qualified Data.Function as Function
11 import Symantic.Base.Univariant
14 data Runtime a = Runtime
16 -- ^ The value of the runtime code,
17 -- kept along to be made available to the optimizer.
19 -- ^ An AST of a runtime value.
21 getEval :: Runtime a -> a
22 getEval = unEval Function.. eval
23 getCode :: Runtime a -> TExpQ a
24 getCode = unCode Function.. code
25 type instance Unlift Runtime = Runtime
26 instance Liftable Runtime where
29 instance Unliftable Runtime where
34 newtype Eval a = Eval { unEval :: a }
35 type instance Unlift Eval = Eval
36 instance Liftable Eval where
39 instance Unliftable Eval where
44 newtype Code a = Code { unCode :: TExpQ a }
45 type instance Unlift Code = Code
46 instance Liftable Code where
49 instance Unliftable Code where
53 -- * Class 'Haskellable'
54 -- | Final encoding of some Haskellable functions
55 -- useful for some optimizations in 'optGram'.
56 class Haskellable (app :: * -> *) where
57 runtime :: Unlift app a -> app a
58 (.) :: app ((b->c) -> (a->b) -> a -> c)
59 ($) :: app ((a->b) -> a -> b)
60 (.@) :: app (a->b) -> app a -> app b
61 bool :: Bool -> app Bool
62 char :: Char -> app Char
63 cons :: app (a -> [a] -> [a])
64 const :: app (a -> b -> a)
65 eq :: Eq a => app a -> app (a -> Bool)
66 flip :: app ((a -> b -> c) -> b -> a -> c)
70 -- instance Haskellable Identity
72 -- ** Type 'Haskellable'
73 -- | Initial encoding of 'Haskellable'
74 data Haskell (app:: * -> *) a where
75 Haskell :: app a -> Haskell app a
76 (:.) :: Haskell app ((b->c) -> (a->b) -> a -> c)
77 (:$) :: Haskell app ((a->b) -> a -> b)
78 (:@) :: Haskell app (a->b) -> Haskell app a -> Haskell app b
79 Const :: Haskell app (a -> b -> a)
80 Flip :: Haskell app ((a -> b -> c) -> b -> a -> c)
81 Id :: Haskell app (a->a)
82 type instance Unlift (Haskell app) = app
83 instance (Liftable app, Unliftable app, Haskellable app) => Liftable (Haskell app) where
85 instance (Unliftable app, Haskellable app) => Unliftable (Haskell app) where
87 Haskell x -> runtime (unlift x)
90 (:@) f x -> (.@) (unlift f) (unlift x)
98 instance Haskellable (Haskell app) where
106 instance Haskellable Runtime where
107 runtime = Function.id
108 (.) = Runtime (.) (.)
109 ($) = Runtime ($) ($)
110 (.@) f x = Runtime ((.@) (eval f) (eval x)) ((.@) (code f) (code x))
111 bool b = Runtime (bool b) (bool b)
112 char c = Runtime (char c) (char c)
113 cons = Runtime cons cons
114 const = Runtime const const
115 eq x = Runtime (eq (eval x)) (eq (code x))
116 flip = Runtime flip flip
118 nil = Runtime nil nil
119 unit = Runtime unit unit
120 instance Haskellable Eval where
122 (.) = Eval (Function..)
123 ($) = Eval (Function.$)
124 (.@) f x = Eval (unEval f (unEval x))
128 const = Eval Function.const
129 eq x = Eval (unEval x Eq.==)
130 flip = Eval Function.flip
131 id = Eval Function.id
134 instance Haskellable Code where
136 (.) = Code [|| \f g x -> f (g x) ||]
137 ($) = Code [|| \f x -> f x ||]
138 (.@) f x = Code [|| $$(unCode f) $$(unCode x) ||]
139 bool b = Code [|| b ||]
140 char c = Code [|| c ||]
141 cons = Code [|| \x xs -> x : xs ||]
142 const = Code [|| \x _ -> x ||]
143 eq x = Code [|| \y -> $$(unCode x) Eq.== y ||]
144 flip = Code [|| \f x y -> f y x ||]
145 id = Code [|| \x -> x ||]
146 nil = Code [|| [] ||]
147 unit = Code [|| () ||]