diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-04-26 19:25:07 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-04-26 19:25:07 +0200 |
commit | b3c4fc5fcf623c389666192e905c0e3cb8d1d1d1 (patch) | |
tree | f9376e2b6dc257c9c09fcab238583d9631c8584d /src/LambdaCube/Compiler/DesugaredSource.hs | |
parent | 2f994583a60245cb3638f21e091d71284e67f883 (diff) |
split desugared source code representation into a separate module
Diffstat (limited to 'src/LambdaCube/Compiler/DesugaredSource.hs')
-rw-r--r-- | src/LambdaCube/Compiler/DesugaredSource.hs | 494 |
1 files changed, 494 insertions, 0 deletions
diff --git a/src/LambdaCube/Compiler/DesugaredSource.hs b/src/LambdaCube/Compiler/DesugaredSource.hs new file mode 100644 index 00000000..96e4ea2d --- /dev/null +++ b/src/LambdaCube/Compiler/DesugaredSource.hs | |||
@@ -0,0 +1,494 @@ | |||
1 | {-# LANGUAGE LambdaCase #-} | ||
2 | {-# LANGUAGE ViewPatterns #-} | ||
3 | {-# LANGUAGE PatternSynonyms #-} | ||
4 | {-# LANGUAGE FlexibleContexts #-} | ||
5 | {-# LANGUAGE FlexibleInstances #-} | ||
6 | {-# LANGUAGE NoMonomorphismRestriction #-} | ||
7 | {-# LANGUAGE OverloadedStrings #-} | ||
8 | {-# LANGUAGE DeriveFunctor #-} | ||
9 | {-# LANGUAGE ScopedTypeVariables #-} | ||
10 | module LambdaCube.Compiler.DesugaredSource where | ||
11 | |||
12 | import Data.Monoid | ||
13 | import Data.Maybe | ||
14 | import Data.List | ||
15 | import Data.Char | ||
16 | import Data.String | ||
17 | import Data.Function | ||
18 | import qualified Data.Map as Map | ||
19 | import qualified Data.Set as Set | ||
20 | import qualified Data.IntMap as IM | ||
21 | import Control.Monad.Except | ||
22 | import Control.Monad.Reader | ||
23 | import Control.Monad.Writer | ||
24 | import Control.Monad.State | ||
25 | import Control.Arrow hiding ((<+>)) | ||
26 | import Control.Applicative | ||
27 | import Control.DeepSeq | ||
28 | import Debug.Trace | ||
29 | |||
30 | import LambdaCube.Compiler.Utils | ||
31 | |||
32 | import qualified LambdaCube.Compiler.Pretty as Parser | ||
33 | import LambdaCube.Compiler.Pretty hiding (Doc, braces, parens) | ||
34 | import LambdaCube.Compiler.Lexer | ||
35 | |||
36 | -------------------------------------------------------------------------------- expression representation | ||
37 | |||
38 | data SExp' a | ||
39 | = SLit SI Lit | ||
40 | | SGlobal SIName | ||
41 | | SApp_ SI Visibility (SExp' a) (SExp' a) | ||
42 | | SBind_ SI Binder (SData SIName){-parameter name-} (SExp' a) (SExp' a) | ||
43 | | SVar_ (SData SIName) !Int | ||
44 | | SLet_ SI (SData SIName) (SExp' a) (SExp' a) -- let x = e in f --> SLet e f{-x is Var 0-} | ||
45 | | STyped a | ||
46 | deriving (Eq, Show) | ||
47 | |||
48 | type SExp = SExp' Void | ||
49 | |||
50 | data Binder | ||
51 | = BPi Visibility | ||
52 | | BLam Visibility | ||
53 | | BMeta -- a metavariable is like a floating hidden lambda | ||
54 | deriving (Eq, Show) | ||
55 | |||
56 | data Visibility = Hidden | Visible | ||
57 | deriving (Eq, Show) | ||
58 | |||
59 | dummyName s = SIName (debugSI s) ("v_" ++ s) | ||
60 | dummyName' = SData . dummyName | ||
61 | sVar = SVar . dummyName | ||
62 | |||
63 | pattern SBind v x a b <- SBind_ _ v x a b | ||
64 | where SBind v x a b = SBind_ (sourceInfo a <> sourceInfo b) v x a b | ||
65 | pattern SPi h a b <- SBind (BPi h) _ a b | ||
66 | where SPi h a b = SBind (BPi h) (dummyName' "SPi") a b | ||
67 | pattern SLam h a b <- SBind (BLam h) _ a b | ||
68 | where SLam h a b = SBind (BLam h) (dummyName' "SLam") a b | ||
69 | pattern Wildcard t <- SBind BMeta _ t (SVar _ 0) | ||
70 | where Wildcard t = SBind BMeta (dummyName' "Wildcard") t (sVar "Wildcard2" 0) | ||
71 | pattern SLet n a b <- SLet_ _ (SData n) a b | ||
72 | where SLet n a b = SLet_ (sourceInfo a <> sourceInfo b) (SData n) a b | ||
73 | pattern SLamV a = SLam Visible (Wildcard SType) a | ||
74 | pattern SVar a b = SVar_ (SData a) b | ||
75 | |||
76 | pattern SApp h a b <- SApp_ _ h a b | ||
77 | where SApp h a b = SApp_ (sourceInfo a <> sourceInfo b) h a b | ||
78 | pattern SAppH a b = SApp Hidden a b | ||
79 | pattern SAppV a b = SApp Visible a b | ||
80 | pattern SAppV2 f a b = f `SAppV` a `SAppV` b | ||
81 | |||
82 | infixl 2 `SAppV`, `SAppH` | ||
83 | |||
84 | pattern SBuiltin s <- SGlobal (SIName _ s) | ||
85 | where SBuiltin s = SGlobal (SIName (debugSI $ "builtin " ++ s) s) | ||
86 | |||
87 | pattern SRHS a = SBuiltin "^rhs" `SAppV` a | ||
88 | pattern Section e = SBuiltin "^section" `SAppV` e | ||
89 | pattern SType = SBuiltin "'Type" | ||
90 | pattern Parens e = SBuiltin "parens" `SAppV` e | ||
91 | pattern SAnn a t = SBuiltin "typeAnn" `SAppH` t `SAppV` a | ||
92 | pattern TyType a = SAnn a SType | ||
93 | |||
94 | -- builtin heterogenous list | ||
95 | pattern HList a = SBuiltin "'HList" `SAppV` a | ||
96 | pattern HCons a b = SBuiltin "HCons" `SAppV` a `SAppV` b | ||
97 | pattern HNil = SBuiltin "HNil" | ||
98 | |||
99 | -- builtin list | ||
100 | pattern BList a = SBuiltin "'List" `SAppV` a | ||
101 | pattern BCons a b = SBuiltin "Cons" `SAppV` a `SAppV` b | ||
102 | pattern BNil = SBuiltin "Nil" | ||
103 | |||
104 | getTTuple (HList (getList -> Just xs)) = xs | ||
105 | getTTuple x = [x] | ||
106 | |||
107 | getList BNil = Just [] | ||
108 | getList (BCons x (getList -> Just y)) = Just (x:y) | ||
109 | getList _ = Nothing | ||
110 | |||
111 | sLit = SLit mempty | ||
112 | |||
113 | isPi (BPi _) = True | ||
114 | isPi _ = False | ||
115 | |||
116 | pattern UncurryS :: [(Visibility, SExp' a)] -> SExp' a -> SExp' a | ||
117 | pattern UncurryS ps t <- (getParamsS -> (ps, t)) | ||
118 | where UncurryS ps t = foldr (uncurry SPi) t ps | ||
119 | |||
120 | getParamsS (SPi h t x) = first ((h, t):) $ getParamsS x | ||
121 | getParamsS x = ([], x) | ||
122 | |||
123 | pattern AppsS :: SExp' a -> [(Visibility, SExp' a)] -> SExp' a | ||
124 | pattern AppsS f args <- (getApps -> (f, args)) | ||
125 | where AppsS = foldl $ \a (v, b) -> SApp v a b | ||
126 | |||
127 | getApps = second reverse . run where | ||
128 | run (SApp h a b) = second ((h, b):) $ run a | ||
129 | run x = (x, []) | ||
130 | |||
131 | -- todo: remove | ||
132 | downToS err n m = [sVar (err ++ "_" ++ show i) (n + i) | i <- [m-1, m-2..0]] | ||
133 | |||
134 | instance SourceInfo (SExp' a) where | ||
135 | sourceInfo = \case | ||
136 | SGlobal sn -> sourceInfo sn | ||
137 | SBind_ si _ _ _ _ -> si | ||
138 | SApp_ si _ _ _ -> si | ||
139 | SLet_ si _ _ _ -> si | ||
140 | SVar sn _ -> sourceInfo sn | ||
141 | SLit si _ -> si | ||
142 | STyped _ -> mempty | ||
143 | |||
144 | instance SetSourceInfo SExp where | ||
145 | setSI si = \case | ||
146 | SBind_ _ a b c d -> SBind_ si a b c d | ||
147 | SApp_ _ a b c -> SApp_ si a b c | ||
148 | SLet_ _ le a b -> SLet_ si le a b | ||
149 | SVar sn i -> SVar (setSI si sn) i | ||
150 | SGlobal sn -> SGlobal (setSI si sn) | ||
151 | SLit _ l -> SLit si l | ||
152 | STyped v -> elimVoid v | ||
153 | |||
154 | -------------------------------------------------------------------------------- low-level toolbox | ||
155 | |||
156 | class Up a where | ||
157 | up_ :: Int -> Int -> a -> a | ||
158 | up_ n i = iterateN n $ up1_ i | ||
159 | up1_ :: Int -> a -> a | ||
160 | up1_ = up_ 1 | ||
161 | |||
162 | foldVar :: Monoid e => (Int{-level-} -> Int{-index-} -> e) -> Int -> a -> e | ||
163 | |||
164 | usedVar :: Int -> a -> Bool | ||
165 | usedVar = (getAny .) . foldVar ((Any .) . (==)) | ||
166 | |||
167 | closedExp :: a -> a | ||
168 | closedExp a = a | ||
169 | |||
170 | instance (Up a, Up b) => Up (a, b) where | ||
171 | up_ n i (a, b) = (up_ n i a, up_ n i b) | ||
172 | usedVar i (a, b) = usedVar i a || usedVar i b | ||
173 | foldVar f i (a, b) = foldVar f i a <> foldVar f i b | ||
174 | closedExp (a, b) = (closedExp a, closedExp b) | ||
175 | |||
176 | instance Up a => Up [a] where | ||
177 | up_ i k = map (up_ i k) | ||
178 | |||
179 | up n = up_ n 0 | ||
180 | up1 = up1_ 0 | ||
181 | |||
182 | foldS | ||
183 | :: Monoid m | ||
184 | => (Int -> t -> m) | ||
185 | -> (SIName -> Int -> m) | ||
186 | -> (SIName -> Int -> Int -> m) | ||
187 | -> Int | ||
188 | -> SExp' t | ||
189 | -> m | ||
190 | foldS h g f = fs | ||
191 | where | ||
192 | fs i = \case | ||
193 | SApp _ a b -> fs i a <> fs i b | ||
194 | SLet _ a b -> fs i a <> fs (i+1) b | ||
195 | SBind_ _ _ _ a b -> fs i a <> fs (i+1) b | ||
196 | SVar sn j -> f sn j i | ||
197 | SGlobal sn -> g sn i | ||
198 | x@SLit{} -> mempty | ||
199 | STyped x -> h i x | ||
200 | |||
201 | foldName f = foldS (\_ -> elimVoid) (\sn _ -> f sn) mempty 0 | ||
202 | |||
203 | usedS :: SIName -> SExp -> Bool | ||
204 | usedS n = getAny . foldName (Any . (== n)) | ||
205 | |||
206 | mapS | ||
207 | :: (Int -> a -> SExp' a) | ||
208 | -> (SIName -> Int -> SExp' a) | ||
209 | -> (SIName -> Int -> Int{-level-} -> SExp' a) | ||
210 | -> Int | ||
211 | -> SExp' a | ||
212 | -> SExp' a | ||
213 | mapS hh gg f2 = g where | ||
214 | g i = \case | ||
215 | SApp_ si v a b -> SApp_ si v (g i a) (g i b) | ||
216 | SLet_ si x a b -> SLet_ si x (g i a) (g (i+1) b) | ||
217 | SBind_ si k si' a b -> SBind_ si k si' (g i a) (g (i+1) b) | ||
218 | SVar sn j -> f2 sn j i | ||
219 | SGlobal sn -> gg sn i | ||
220 | STyped x -> hh i x | ||
221 | x@SLit{} -> x | ||
222 | |||
223 | instance Up Void where | ||
224 | up_ _ _ = elimVoid | ||
225 | foldVar _ _ = elimVoid | ||
226 | |||
227 | instance Up a => Up (SExp' a) where | ||
228 | up_ n = mapS (\i x -> STyped $ up_ n i x) (const . SGlobal) (\sn j i -> SVar sn $ if j < i then j else j+n) | ||
229 | foldVar f = foldS (foldVar f) mempty $ \sn j i -> f j i | ||
230 | |||
231 | -- rearrange free variables | ||
232 | -- up_ n k == rearrange k (+n) | ||
233 | class Rearrange a where | ||
234 | rearrange :: Int -> (Int -> Int) -> a -> a | ||
235 | |||
236 | rSubst :: Rearrange a => Int -> Int -> a -> a | ||
237 | rSubst i j = rearrange 0 $ \k -> if k == i then j else if k > i then k - 1 else k | ||
238 | |||
239 | rUp :: Rearrange a => Int -> Int -> a -> a | ||
240 | rUp n l = rearrange l $ \k -> if k >= 0 then k + n else k | ||
241 | |||
242 | instance Rearrange a => Rearrange [a] where | ||
243 | rearrange l f = map $ rearrange l f | ||
244 | |||
245 | instance (Rearrange a, Rearrange b) => Rearrange (Either a b) where | ||
246 | rearrange l f = rearrange l f +++ rearrange l f | ||
247 | |||
248 | instance (Rearrange a, Rearrange b) => Rearrange (a, b) where | ||
249 | rearrange l f = rearrange l f *** rearrange l f | ||
250 | |||
251 | instance Rearrange SExp where | ||
252 | rearrange i f = mapS (\_ -> elimVoid) (const . SGlobal) (\sn j i -> SVar sn $ if j < i then j else i + f (j - i)) i | ||
253 | |||
254 | -- replace names with de bruijn indices | ||
255 | class DeBruijnify a where | ||
256 | deBruijnify_ :: Int -> [SIName] -> a -> a | ||
257 | |||
258 | deBruijnify = deBruijnify_ 0 | ||
259 | |||
260 | instance (DeBruijnify a, DeBruijnify b) => DeBruijnify (a, b) where | ||
261 | deBruijnify_ k ns = deBruijnify_ k ns *** deBruijnify_ k ns | ||
262 | |||
263 | instance (DeBruijnify a, DeBruijnify b) => DeBruijnify (Either a b) where | ||
264 | deBruijnify_ k ns = deBruijnify_ k ns +++ deBruijnify_ k ns | ||
265 | |||
266 | instance (DeBruijnify a) => DeBruijnify [a] where | ||
267 | deBruijnify_ k ns = fmap (deBruijnify_ k ns) | ||
268 | |||
269 | instance DeBruijnify SExp where | ||
270 | deBruijnify_ j xs | ||
271 | = mapS (\_ -> elimVoid) (\sn x -> maybe (SGlobal sn) (\i -> SVar sn $ i + x) $ elemIndex sn xs) | ||
272 | (\sn j k -> SVar sn $ if j >= k then j + l else j) j | ||
273 | where | ||
274 | l = length xs | ||
275 | |||
276 | trSExp :: (a -> b) -> SExp' a -> SExp' b | ||
277 | trSExp f = g where | ||
278 | g = \case | ||
279 | SApp_ si v a b -> SApp_ si v (g a) (g b) | ||
280 | SLet_ si x a b -> SLet_ si x (g a) (g b) | ||
281 | SBind_ si k si' a b -> SBind_ si k si' (g a) (g b) | ||
282 | SVar sn j -> SVar sn j | ||
283 | SGlobal sn -> SGlobal sn | ||
284 | SLit si l -> SLit si l | ||
285 | STyped a -> STyped $ f a | ||
286 | |||
287 | trSExp' :: SExp -> SExp' a | ||
288 | trSExp' = trSExp elimVoid | ||
289 | |||
290 | -------------------------------------------------------------------------------- statements | ||
291 | |||
292 | data Stmt | ||
293 | = Let SIName (Maybe SExp) SExp | ||
294 | | Data SIName [(Visibility, SExp)]{-parameters-} SExp{-type-} Bool{-True:add foralls-} [(SIName, SExp)]{-constructor names and types-} | ||
295 | | PrecDef SIName Fixity | ||
296 | deriving (Show) | ||
297 | |||
298 | pattern Primitive n t <- Let n (Just t) (SBuiltin "undefined") where Primitive n t = Let n (Just t) $ SBuiltin "undefined" | ||
299 | |||
300 | instance PShow Stmt where | ||
301 | pShowPrec p = \case | ||
302 | Let n ty e -> text (sName n) </> "=" <+> maybe (pShow e) (\ty -> pShow e </> "::" <+> pShow ty) ty | ||
303 | Data n ps ty fa cs -> "data" <+> text (sName n) | ||
304 | PrecDef n i -> "precedence" <+> text (sName n) <+> text (show i) | ||
305 | |||
306 | instance DeBruijnify Stmt where | ||
307 | deBruijnify_ k v = \case | ||
308 | Let sn mt e -> Let sn (deBruijnify_ k v <$> mt) (deBruijnify_ k v e) | ||
309 | x -> error $ "deBruijnify @ " ++ show x | ||
310 | |||
311 | -------------------------------------------------------------------------------- declaration desugaring | ||
312 | |||
313 | data StmtNode = StmtNode | ||
314 | { snId :: !Int | ||
315 | , snValue :: Stmt | ||
316 | , snChildren :: [StmtNode] | ||
317 | , snRevChildren :: [StmtNode] | ||
318 | } | ||
319 | |||
320 | sortDefs :: [Stmt] -> [Stmt] | ||
321 | sortDefs xs = concatMap (desugarMutual . map snValue) $ scc snId snChildren snRevChildren nodes | ||
322 | where | ||
323 | nodes = zipWith mkNode [0..] xs | ||
324 | where | ||
325 | mkNode i s = StmtNode i s (nubBy ((==) `on` snId) $ catMaybes $ (`Map.lookup` defMap) <$> need) | ||
326 | (fromMaybe [] $ IM.lookup i revMap) | ||
327 | where | ||
328 | need = Set.toList $ case s of | ||
329 | PrecDef{} -> mempty | ||
330 | Let _ mt e -> foldMap names mt <> names e | ||
331 | Data _ ps t _ cs -> foldMap (names . snd) ps <> names t <> foldMap (names . snd) cs | ||
332 | |||
333 | names = foldName Set.singleton | ||
334 | |||
335 | revMap = IM.unionsWith (++) [IM.singleton (snId c) [n] | n <- nodes, c <- snChildren n] | ||
336 | |||
337 | defMap = Map.fromList [(s, n) | n <- nodes, s <- def $ snValue n] | ||
338 | where | ||
339 | def = \case | ||
340 | PrecDef{} -> mempty | ||
341 | Let n _ _ -> [n] | ||
342 | Data n _ _ _ cs -> n: map fst cs | ||
343 | |||
344 | desugarMutual [x] = [x] | ||
345 | desugarMutual xs = xs | ||
346 | |||
347 | -------------------------------------------------------------------------------- modules | ||
348 | |||
349 | data Module_ a = Module | ||
350 | { extensions :: Extensions | ||
351 | , moduleImports :: [(SIName, ImportItems)] | ||
352 | , moduleExports :: Maybe [Export] | ||
353 | , definitions :: a | ||
354 | } | ||
355 | |||
356 | data Export = ExportModule SIName | ExportId SIName | ||
357 | |||
358 | data ImportItems | ||
359 | = ImportAllBut [SIName] | ||
360 | | ImportJust [SIName] | ||
361 | |||
362 | type Extensions = [Extension] | ||
363 | |||
364 | data Extension | ||
365 | = NoImplicitPrelude | ||
366 | | TraceTypeCheck | ||
367 | deriving (Enum, Eq, Ord, Show) | ||
368 | |||
369 | extensionMap :: Map.Map String Extension | ||
370 | extensionMap = Map.fromList $ map (show &&& id) [toEnum 0 .. ] | ||
371 | |||
372 | -------------------------------------------------------------------------------- builtin precedences | ||
373 | |||
374 | data Prec | ||
375 | = PrecAtom -- ( _ ) ... | ||
376 | | PrecAtom' | ||
377 | | PrecAt -- _@_ {assoc} -- in patterns | ||
378 | | PrecProj -- _ ._ {left} | ||
379 | | PrecSwiz -- _%_ {left} | ||
380 | | PrecApp -- _ _ {left} | ||
381 | | PrecOp | ||
382 | | PrecArr -- _ -> _ {right} | ||
383 | | PrecEq -- _ ~ _ | ||
384 | | PrecAnn -- _ :: _ {right} | ||
385 | | PrecLet -- _ := _ | ||
386 | | PrecLam -- \ _ -> _ {right} {accum} | ||
387 | deriving (Eq, Ord) | ||
388 | |||
389 | instance Up a => PShow (SExp' a) where | ||
390 | pShowPrec _ = showDoc_ . sExpDoc | ||
391 | |||
392 | type Doc = NameDB PrecString | ||
393 | |||
394 | -- name De Bruijn indices | ||
395 | type NameDB a = StateT [String] (Reader [String]) a | ||
396 | |||
397 | showDoc :: Doc -> String | ||
398 | showDoc = str . flip runReader [] . flip evalStateT (flip (:) <$> iterate ('\'':) "" <*> ['a'..'z']) | ||
399 | |||
400 | showDoc_ :: Doc -> Parser.Doc | ||
401 | showDoc_ = text . str . flip runReader [] . flip evalStateT (flip (:) <$> iterate ('\'':) "" <*> ['a'..'z']) | ||
402 | |||
403 | sExpDoc :: Up a => SExp' a -> Doc | ||
404 | sExpDoc = \case | ||
405 | SGlobal ns -> pure $ shAtom $ sName ns | ||
406 | SAnn a b -> shAnn ":" False <$> sExpDoc a <*> sExpDoc b | ||
407 | TyType a -> shApp Visible (shAtom "tyType") <$> sExpDoc a | ||
408 | SApp h a b -> shApp h <$> sExpDoc a <*> sExpDoc b | ||
409 | Wildcard t -> shAnn ":" True (shAtom "_") <$> sExpDoc t | ||
410 | SBind_ _ h _ a b -> join $ shLam (usedVar 0 b) h <$> sExpDoc a <*> pure (sExpDoc b) | ||
411 | SLet _ a b -> shLet_ (sExpDoc a) (sExpDoc b) | ||
412 | STyped _{-(e,t)-} -> pure $ shAtom "<<>>" -- todo: expDoc e | ||
413 | SVar _ i -> shAtom <$> shVar i | ||
414 | SLit _ l -> pure $ shAtom $ show l | ||
415 | |||
416 | shVar i = asks lookupVarName where | ||
417 | lookupVarName xs | i < length xs && i >= 0 = xs !! i | ||
418 | lookupVarName _ = "V" ++ show i | ||
419 | |||
420 | newName = gets head <* modify tail | ||
421 | |||
422 | shLet i a b = shAtom <$> shVar i >>= \i' -> local (dropNth i) $ shLam' <$> (cpar . shLet' (fmap inBlue i') <$> a) <*> b | ||
423 | shLet_ a b = newName >>= \i -> shLam' <$> (cpar . shLet' (shAtom i) <$> a) <*> local (i:) b | ||
424 | shLam usedVar h a b = newName >>= \i -> | ||
425 | let lam = case h of | ||
426 | BPi _ -> shArr | ||
427 | _ -> shLam' | ||
428 | p = case h of | ||
429 | BMeta -> cpar . shAnn ":" True (shAtom $ inBlue i) | ||
430 | BLam h -> vpar h | ||
431 | BPi h -> vpar h | ||
432 | vpar Hidden = brace . shAnn ":" True (shAtom $ inGreen i) | ||
433 | vpar Visible = ann (shAtom $ inGreen i) | ||
434 | ann | usedVar = shAnn ":" False | ||
435 | | otherwise = const id | ||
436 | in lam (p a) <$> local (i:) b | ||
437 | |||
438 | ----------------------------------------- | ||
439 | |||
440 | data PS a = PS Prec a deriving (Functor) | ||
441 | type PrecString = PS String | ||
442 | |||
443 | getPrec (PS p _) = p | ||
444 | prec i s = PS i (s i) | ||
445 | str (PS _ s) = s | ||
446 | |||
447 | lpar, rpar :: PrecString -> Prec -> String | ||
448 | lpar (PS i s) j = par (i >. j) s where | ||
449 | PrecLam >. i = i > PrecAtom' | ||
450 | i >. PrecLam = i >= PrecArr | ||
451 | PrecApp >. PrecApp = False | ||
452 | i >. j = i >= j | ||
453 | rpar (PS i s) j = par (i >. j) s where | ||
454 | PrecLam >. PrecLam = False | ||
455 | PrecLam >. i = i > PrecAtom' | ||
456 | PrecArr >. PrecArr = False | ||
457 | PrecAnn >. PrecAnn = False | ||
458 | i >. j = i >= j | ||
459 | |||
460 | par True s = "(" ++ s ++ ")" | ||
461 | par False s = s | ||
462 | |||
463 | isAtom = (==PrecAtom) . getPrec | ||
464 | isAtom' = (<=PrecAtom') . getPrec | ||
465 | |||
466 | shAtom = PS PrecAtom | ||
467 | shAtom' = PS PrecAtom' | ||
468 | shTuple xs = prec PrecAtom $ \_ -> case xs of | ||
469 | [x] -> "((" ++ str x ++ "))" | ||
470 | xs -> "(" ++ intercalate ", " (map str xs) ++ ")" | ||
471 | shAnn _ True x y | str y `elem` ["Type", inGreen "Type"] = x | ||
472 | shAnn s simp x y | isAtom x && isAtom y = shAtom' $ str x <> s <> str y | ||
473 | shAnn s simp x y = prec PrecAnn $ lpar x <> " " <> const s <> " " <> rpar y | ||
474 | shApp Hidden x y = prec PrecApp $ lpar x <> " " <> const (str $ brace y) | ||
475 | shApp h x y = prec PrecApp $ lpar x <> " " <> rpar y | ||
476 | shArr x y | isAtom x && isAtom y = shAtom' $ str x <> "->" <> str y | ||
477 | shArr x y = prec PrecArr $ lpar x <> " -> " <> rpar y | ||
478 | shCstr x y | isAtom x && isAtom y = shAtom' $ str x <> "~" <> str y | ||
479 | shCstr x y = prec PrecEq $ lpar x <> " ~ " <> rpar y | ||
480 | shLet' x y | isAtom x && isAtom y = shAtom' $ str x <> ":=" <> str y | ||
481 | shLet' x y = prec PrecLet $ lpar x <> " := " <> rpar y | ||
482 | shLam' x y | PrecLam <- getPrec y = prec PrecLam $ "\\" <> lpar x <> " " <> pure (dropC $ str y) | ||
483 | where | ||
484 | dropC (ESC s (dropC -> x)) = ESC s x | ||
485 | dropC (x: xs) = xs | ||
486 | shLam' x y | isAtom x && isAtom y = shAtom' $ "\\" <> str x <> "->" <> str y | ||
487 | shLam' x y = prec PrecLam $ "\\" <> lpar x <> " -> " <> rpar y | ||
488 | brace s = shAtom $ "{" <> str s <> "}" | ||
489 | cpar s | isAtom' s = s -- TODO: replace with lpar, rpar | ||
490 | cpar s = shAtom $ par True $ str s | ||
491 | epar = fmap underlined | ||
492 | |||
493 | instance IsString (Prec -> String) where fromString = const | ||
494 | |||