]> Git — Sourcephile - haskell/symantic.git/blob - Language/Symantic/Expr/From.hs
init
[haskell/symantic.git] / Language / Symantic / Expr / From.hs
1 {-# LANGUAGE ConstraintKinds #-}
2 {-# LANGUAGE DataKinds #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE FlexibleInstances #-}
5 {-# LANGUAGE GADTs #-}
6 {-# LANGUAGE KindSignatures #-}
7 {-# LANGUAGE MultiParamTypeClasses #-}
8 {-# LANGUAGE Rank2Types #-}
9 {-# LANGUAGE ScopedTypeVariables #-}
10 {-# LANGUAGE TypeFamilies #-}
11 {-# LANGUAGE TypeOperators #-}
12 {-# LANGUAGE UndecidableInstances #-}
13 module Language.Symantic.Expr.From where
14
15 import Data.Maybe (fromMaybe)
16 import Data.Proxy (Proxy(..))
17 import Data.Text (Text)
18 import Data.Type.Equality ((:~:)(Refl))
19 import GHC.Prim (Constraint)
20
21 import Language.Symantic.Type
22 import Language.Symantic.Expr.Root
23 import Language.Symantic.Expr.Alt
24 import Language.Symantic.Expr.Error
25
26 -- * Class 'Expr_from'
27 -- | Parse given @ast@ into
28 -- a 'Type_Root_of_Expr' and
29 -- a 'Forall_Repr_with_Context',
30 -- or return an 'Error_of_Expr'.
31 class Expr_from ast (ex:: *) where
32 expr_from :: Expr_From ast ex hs ret
33 instance -- Expr_from
34 ( Expr_from ast (ex (Expr_Root ex))
35 , Root_of_Expr (ex (Expr_Root ex)) ~ Expr_Root ex
36 ) => Expr_from ast (Expr_Root ex) where
37 expr_from _ex ctx ast k =
38 expr_from (Proxy::Proxy (ex (Expr_Root ex)))
39 ctx ast $ \ty (Forall_Repr_with_Context repr) ->
40 k ty (Forall_Repr_with_Context repr)
41 instance -- Expr_from
42 ( Expr_from ast (curr root)
43 , Expr_from ast (next root)
44 , Root_of_Expr (curr root) ~ root
45 , Root_of_Expr (next root) ~ root
46 , Unlift_Error_Expr (Error_Expr (Error_of_Type ast (Type_Root_of_Expr root))
47 (Type_Root_of_Expr root) ast)
48 (Error_of_Expr ast root)
49 ) => Expr_from ast (Expr_Alt curr next root) where
50 expr_from _ex ctx ast k =
51 case expr_from (Proxy::Proxy (curr root)) ctx ast $
52 \ty (Forall_Repr_with_Context repr) ->
53 Right $ k ty (Forall_Repr_with_Context repr) of
54 Right ret -> ret
55 Left err ->
56 case unlift_error_expr err of
57 Just (Error_Expr_Unsupported_here _
58 :: Error_Expr (Error_of_Type ast (Type_Root_of_Expr root))
59 (Type_Root_of_Expr root) ast) ->
60 expr_from (Proxy::Proxy (next root)) ctx ast $
61 \ty (Forall_Repr_with_Context repr) ->
62 k ty (Forall_Repr_with_Context repr)
63 _ -> Left err
64
65 -- ** Type 'Expr_From'
66 type Expr_From ast ex hs ret
67 = Proxy ex
68 -- ^ Select the 'Expr_from' instance.
69 -> ast
70 -- ^ The input data to parse.
71 -> Context (Lambda_Var (Type_Root_of_Expr ex)) hs
72 -- ^ The bound variables in scope and their types:
73 -- held in the heterogeneous list @hs@,
74 -- from the closest including lambda abstraction to the farest.
75 -> ( forall h
76 . Type_Root_of_Expr ex h
77 -> Forall_Repr_with_Context ex hs h
78 -> Either (Error_of_Expr ast (Root_of_Expr ex)) ret )
79 -- ^ The accumulating continuation.
80 -> Either (Error_of_Expr ast (Root_of_Expr ex)) ret
81
82 -- ** Type 'Context'
83 -- | GADT for a typing context,
84 -- accumulating an @item@ at each lambda;
85 -- used to accumulate object-types (in 'Expr_from')
86 -- or host-terms (in 'Repr_Host')
87 -- associated with the 'Lambda_Var's in scope.
88 data Context :: (* -> *) -> [*] -> * where
89 Context_Empty :: Context item '[]
90 Context_Next :: item h -> Context item hs -> Context item (h ': hs)
91 infixr 5 `Context_Next`
92
93 -- ** Type 'Lambda_Var'
94 -- | Join a name and a type.
95 --
96 -- This data type is used to handle lambda variables by name
97 -- (instead of DeBruijn indices for instance).
98 data Lambda_Var ty h
99 = Lambda_Var Lambda_Var_Name (ty h)
100 type Lambda_Var_Name = Text
101
102 -- ** Type 'Forall_Repr_with_Context'
103 -- | A data type embedding a universal quantification
104 -- over an interpreter @repr@
105 -- and qualified by the symantics of an expression.
106 --
107 -- Moreover the expression is abstracted by a 'Context'
108 -- built at parsing time to build a /Higher-Order Abstract Syntax/ (HOAS)
109 -- for lambda abstractions.
110 --
111 -- This data type is used to keep a parsed expression polymorphic enough
112 -- to stay interpretable by different interpreters.
113 --
114 -- NOTE: 'Sym_of_Expr'@ ex repr@
115 -- is needed to be able to use symantic methods of the parsed expression
116 -- into a 'Forall_Repr_with_Context'@ ex@.
117 --
118 -- NOTE: 'Sym_of_Expr'@ (@'Root_of_Expr'@ ex) repr@
119 -- is needed to be able to use an expression
120 -- out of a 'Forall_Repr_with_Context'@ (@'Root_of_Expr'@ ex)@
121 -- into a 'Forall_Repr_with_Context'@ ex@,
122 -- which happens when a symantic method includes a polymorphic type
123 -- and thus calls: 'expr_from'@ (Proxy::Proxy (@'Root_of_Expr'@ ex))@.
124 data Forall_Repr_with_Context ex hs h
125 = Forall_Repr_with_Context
126 ( forall repr. ( Sym_of_Expr ex repr
127 , Sym_of_Expr (Root_of_Expr ex) repr
128 ) => Context repr hs -> repr h )
129
130 -- ** Type 'Forall_Repr'
131 data Forall_Repr ex h
132 = Forall_Repr
133 { unForall_Repr :: forall repr
134 . ( Sym_of_Expr ex repr
135 , Sym_of_Expr (Root_of_Expr ex) repr )
136 => repr h }
137
138 -- ** Type family 'Sym_of_Expr'
139 -- | The symantic of an expression.
140 type family Sym_of_Expr (ex:: *) (repr:: * -> *) :: Constraint
141 type instance Sym_of_Expr (Expr_Root ex) repr
142 = Sym_of_Expr (ex (Expr_Root ex)) repr
143 type instance Sym_of_Expr (Expr_Alt curr next root) repr
144 = ( Sym_of_Expr (curr root) repr
145 , Sym_of_Expr (next root) repr
146 )
147
148 -- * Checks
149
150 -- | Parsing utility to check that two types are equal,
151 -- or raise 'Error_Expr_Type_mismatch'.
152 check_eq_type
153 :: forall ast ex root ty x y ret.
154 ( root ~ Root_of_Expr ex
155 , ty ~ Type_Root_of_Expr ex
156 , Eq_Type ty
157 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
158 (Error_of_Expr ast root)
159 )
160 => Proxy ex -> ast -> ty x -> ty y
161 -> (x :~: y -> Either (Error_of_Expr ast root) ret)
162 -> Either (Error_of_Expr ast root) ret
163 check_eq_type ex ast x y k =
164 case x `eq_type` y of
165 Just Refl -> k Refl
166 Nothing -> Left $ error_expr ex $
167 Error_Expr_Type_mismatch ast
168 (Exists_Type x)
169 (Exists_Type y)
170 -- | Parsing utility to check that two 'Type_Type1' are equal,
171 -- or raise 'Error_Expr_Type_mismatch'.
172 check_eq_type1
173 :: forall ast ex root ty h1 h2 a1 a2 ret.
174 ( root ~ Root_of_Expr ex
175 , ty ~ Type_Root_of_Expr ex
176 , Eq_Type1 ty
177 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
178 (Error_of_Expr ast root)
179 )
180 => Proxy ex -> ast -> ty (h1 a1) -> ty (h2 a2)
181 -> (h1 :~: h2 -> Either (Error_of_Expr ast root) ret)
182 -> Either (Error_of_Expr ast root) ret
183 check_eq_type1 ex ast h1 h2 k =
184 case h1 `eq_type1` h2 of
185 Just Refl -> k Refl
186 Nothing -> Left $ error_expr ex $
187 Error_Expr_Type_mismatch ast
188 (Exists_Type h1)
189 (Exists_Type h2)
190
191 -- | Parsing utility to check that a type is has instance of a given 'Constraint',
192 -- or raise 'Error_Expr_Constraint_missing'.
193 check_constraint_type
194 :: forall ast ex c root ty h ret.
195 ( root ~ Root_of_Expr ex
196 , ty ~ Type_Root_of_Expr ex
197 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
198 (Error_of_Expr ast root)
199 , Constraint_Type c ty
200 )
201 => Proxy ex -> Proxy c -> ast -> ty h
202 -> (Dict (c h) -> Either (Error_of_Expr ast root) ret)
203 -> Either (Error_of_Expr ast root) ret
204 check_constraint_type ex c ast ty k =
205 case constraint_type c ty of
206 Just Dict -> k Dict
207 Nothing -> Left $ error_expr ex $
208 Error_Expr_Constraint_missing ast
209 {-(Exists_Dict c)-}
210 -- FIXME: not easy to report the constraint
211 -- and still support 'Eq' and 'Show' deriving.
212 (Exists_Type ty)
213
214 -- | Parsing utility to check that a type is has instance of a given 'Constraint'1,
215 -- or raise 'Error_Expr_Constraint_missing'.
216 check_constraint1_type
217 :: forall ast ex c root ty h a ret.
218 ( root ~ Root_of_Expr ex
219 , ty ~ Type_Root_of_Expr ex
220 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
221 (Error_of_Expr ast root)
222 , Constraint_Type1 c ty
223 )
224 => Proxy ex -> Proxy c -> ast -> ty (h a)
225 -> (Dict (c h) -> Either (Error_of_Expr ast root) ret)
226 -> Either (Error_of_Expr ast root) ret
227 check_constraint1_type ex c ast ty k =
228 case constraint_type1 c ty of
229 Just Dict -> k Dict
230 Nothing -> Left $ error_expr ex $
231 Error_Expr_Constraint_missing ast
232 (Exists_Type ty)
233
234 -- | Parsing utility to check that the given type is a 'Type_Type1'
235 -- or raise 'Error_Expr_Type_mismatch'.
236 check_type1
237 :: forall ast ex root ty h ret.
238 ( root ~ Root_of_Expr ex
239 , ty ~ Type_Root_of_Expr ex
240 , Unlift_Type1 (Type_of_Expr root)
241 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
242 (Error_of_Expr ast root)
243 )
244 => Proxy ex -> ast -> ty h
245 -> (forall (t1:: *).
246 ( Type_Type1 t1 ty h
247 , Lift_Type1 t1 (Type_Var0 :|: Type_Var1 :|: Type_of_Expr root)
248 ) -> Either (Error_of_Expr ast root) ret)
249 -> Either (Error_of_Expr ast root) ret
250 check_type1 ex ast ty k =
251 (`fromMaybe` unlift_type1 (unType_Root ty) (Just . k)) $
252 Left $
253 error_expr ex $
254 Error_Expr_Type_mismatch ast
255 (Exists_Type (type_var1 SZero (type_var0 SZero)
256 :: Type_Root_of_Expr ex (Var1 Var0)))
257 (Exists_Type ty)
258
259 -- * Parsers
260
261 -- | Like 'expr_from' but for a root expression.
262 root_expr_from
263 :: forall lam ast root.
264 ( Expr_from ast root
265 , Root_of_Expr root ~ root )
266 => Proxy root -> Proxy lam -> ast
267 -> Either (Error_of_Expr ast root)
268 (Exists_Type_and_Repr (Type_Root_of_Expr root)
269 (Forall_Repr root))
270 root_expr_from _ex _lam ast =
271 expr_from (Proxy::Proxy root) ast
272 Context_Empty $ \ty (Forall_Repr_with_Context repr) ->
273 Right $ Exists_Type_and_Repr ty $
274 Forall_Repr $ repr Context_Empty
275
276 -- | Parse a literal.
277 lit_from
278 :: forall ty lit ex ast hs ret.
279 ( ty ~ Type_Root_of_Expr ex
280 , Read lit
281 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
282 (Error_of_Expr ast (Root_of_Expr ex))
283 ) => (forall repr. Sym_of_Expr ex repr => lit -> repr lit)
284 -> ty lit -> Lambda_Var_Name
285 -> Expr_From ast ex hs ret
286 lit_from lit ty_lit toread ex ast _ctx k =
287 case read_safe toread of
288 Left err -> Left $ error_expr ex $ Error_Expr_Read err ast
289 Right (i::lit) -> k ty_lit $ Forall_Repr_with_Context $ const $ lit i
290
291 -- | Parse a unary operator.
292 op1_from
293 :: forall root ty lit ex ast hs ret.
294 ( ty ~ Type_Root_of_Expr ex
295 , root ~ Root_of_Expr ex
296 , Eq_Type (Type_Root_of_Expr root)
297 , Expr_from ast root
298 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
299 (Error_of_Expr ast root)
300 , Root_of_Expr root ~ root
301 ) => (forall repr. Sym_of_Expr ex repr => repr lit -> repr lit)
302 -> ty lit -> ast
303 -> Expr_From ast ex hs ret
304 op1_from op ty_lit ast_x ex ast ctx k =
305 expr_from (Proxy::Proxy root) ast_x ctx $
306 \ty_x (Forall_Repr_with_Context x) ->
307 check_eq_type ex ast ty_lit ty_x $ \Refl ->
308 k ty_x $ Forall_Repr_with_Context (op . x)
309
310 -- | Parse a binary operator.
311 op2_from
312 :: forall root ty lit ex ast hs ret.
313 ( ty ~ Type_Root_of_Expr ex
314 , root ~ Root_of_Expr ex
315 , Eq_Type (Type_Root_of_Expr root)
316 , Expr_from ast root
317 , Lift_Error_Expr (Error_Expr (Error_of_Type ast ty) ty ast)
318 (Error_of_Expr ast root)
319 , Root_of_Expr root ~ root
320 ) => (forall repr. Sym_of_Expr ex repr => repr lit -> repr lit -> repr lit)
321 -> ty lit -> ast -> ast
322 -> Expr_From ast ex hs ret
323 op2_from op ty_lit ast_x ast_y ex ast ctx k =
324 expr_from (Proxy::Proxy root) ast_x ctx $ \ty_x (Forall_Repr_with_Context x) ->
325 expr_from (Proxy::Proxy root) ast_y ctx $ \ty_y (Forall_Repr_with_Context y) ->
326 check_eq_type ex ast ty_lit ty_x $ \Refl ->
327 check_eq_type ex ast ty_lit ty_y $ \Refl ->
328 k ty_x $ Forall_Repr_with_Context $
329 \c -> x c `op` y c
330