summaryrefslogtreecommitdiff
path: root/src/LambdaCube/Compiler/DesugaredSource.hs
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-04-26 19:25:07 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-04-26 19:25:07 +0200
commitb3c4fc5fcf623c389666192e905c0e3cb8d1d1d1 (patch)
treef9376e2b6dc257c9c09fcab238583d9631c8584d /src/LambdaCube/Compiler/DesugaredSource.hs
parent2f994583a60245cb3638f21e091d71284e67f883 (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.hs494
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 #-}
10module LambdaCube.Compiler.DesugaredSource where
11
12import Data.Monoid
13import Data.Maybe
14import Data.List
15import Data.Char
16import Data.String
17import Data.Function
18import qualified Data.Map as Map
19import qualified Data.Set as Set
20import qualified Data.IntMap as IM
21import Control.Monad.Except
22import Control.Monad.Reader
23import Control.Monad.Writer
24import Control.Monad.State
25import Control.Arrow hiding ((<+>))
26import Control.Applicative
27import Control.DeepSeq
28import Debug.Trace
29
30import LambdaCube.Compiler.Utils
31
32import qualified LambdaCube.Compiler.Pretty as Parser
33import LambdaCube.Compiler.Pretty hiding (Doc, braces, parens)
34import LambdaCube.Compiler.Lexer
35
36-------------------------------------------------------------------------------- expression representation
37
38data 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
48type SExp = SExp' Void
49
50data Binder
51 = BPi Visibility
52 | BLam Visibility
53 | BMeta -- a metavariable is like a floating hidden lambda
54 deriving (Eq, Show)
55
56data Visibility = Hidden | Visible
57 deriving (Eq, Show)
58
59dummyName s = SIName (debugSI s) ("v_" ++ s)
60dummyName' = SData . dummyName
61sVar = SVar . dummyName
62
63pattern 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
65pattern SPi h a b <- SBind (BPi h) _ a b
66 where SPi h a b = SBind (BPi h) (dummyName' "SPi") a b
67pattern SLam h a b <- SBind (BLam h) _ a b
68 where SLam h a b = SBind (BLam h) (dummyName' "SLam") a b
69pattern Wildcard t <- SBind BMeta _ t (SVar _ 0)
70 where Wildcard t = SBind BMeta (dummyName' "Wildcard") t (sVar "Wildcard2" 0)
71pattern SLet n a b <- SLet_ _ (SData n) a b
72 where SLet n a b = SLet_ (sourceInfo a <> sourceInfo b) (SData n) a b
73pattern SLamV a = SLam Visible (Wildcard SType) a
74pattern SVar a b = SVar_ (SData a) b
75
76pattern SApp h a b <- SApp_ _ h a b
77 where SApp h a b = SApp_ (sourceInfo a <> sourceInfo b) h a b
78pattern SAppH a b = SApp Hidden a b
79pattern SAppV a b = SApp Visible a b
80pattern SAppV2 f a b = f `SAppV` a `SAppV` b
81
82infixl 2 `SAppV`, `SAppH`
83
84pattern SBuiltin s <- SGlobal (SIName _ s)
85 where SBuiltin s = SGlobal (SIName (debugSI $ "builtin " ++ s) s)
86
87pattern SRHS a = SBuiltin "^rhs" `SAppV` a
88pattern Section e = SBuiltin "^section" `SAppV` e
89pattern SType = SBuiltin "'Type"
90pattern Parens e = SBuiltin "parens" `SAppV` e
91pattern SAnn a t = SBuiltin "typeAnn" `SAppH` t `SAppV` a
92pattern TyType a = SAnn a SType
93
94-- builtin heterogenous list
95pattern HList a = SBuiltin "'HList" `SAppV` a
96pattern HCons a b = SBuiltin "HCons" `SAppV` a `SAppV` b
97pattern HNil = SBuiltin "HNil"
98
99-- builtin list
100pattern BList a = SBuiltin "'List" `SAppV` a
101pattern BCons a b = SBuiltin "Cons" `SAppV` a `SAppV` b
102pattern BNil = SBuiltin "Nil"
103
104getTTuple (HList (getList -> Just xs)) = xs
105getTTuple x = [x]
106
107getList BNil = Just []
108getList (BCons x (getList -> Just y)) = Just (x:y)
109getList _ = Nothing
110
111sLit = SLit mempty
112
113isPi (BPi _) = True
114isPi _ = False
115
116pattern UncurryS :: [(Visibility, SExp' a)] -> SExp' a -> SExp' a
117pattern UncurryS ps t <- (getParamsS -> (ps, t))
118 where UncurryS ps t = foldr (uncurry SPi) t ps
119
120getParamsS (SPi h t x) = first ((h, t):) $ getParamsS x
121getParamsS x = ([], x)
122
123pattern AppsS :: SExp' a -> [(Visibility, SExp' a)] -> SExp' a
124pattern AppsS f args <- (getApps -> (f, args))
125 where AppsS = foldl $ \a (v, b) -> SApp v a b
126
127getApps = second reverse . run where
128 run (SApp h a b) = second ((h, b):) $ run a
129 run x = (x, [])
130
131-- todo: remove
132downToS err n m = [sVar (err ++ "_" ++ show i) (n + i) | i <- [m-1, m-2..0]]
133
134instance 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
144instance 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
156class 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
170instance (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
176instance Up a => Up [a] where
177 up_ i k = map (up_ i k)
178
179up n = up_ n 0
180up1 = up1_ 0
181
182foldS
183 :: Monoid m
184 => (Int -> t -> m)
185 -> (SIName -> Int -> m)
186 -> (SIName -> Int -> Int -> m)
187 -> Int
188 -> SExp' t
189 -> m
190foldS 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
201foldName f = foldS (\_ -> elimVoid) (\sn _ -> f sn) mempty 0
202
203usedS :: SIName -> SExp -> Bool
204usedS n = getAny . foldName (Any . (== n))
205
206mapS
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
213mapS 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
223instance Up Void where
224 up_ _ _ = elimVoid
225 foldVar _ _ = elimVoid
226
227instance 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)
233class Rearrange a where
234 rearrange :: Int -> (Int -> Int) -> a -> a
235
236rSubst :: Rearrange a => Int -> Int -> a -> a
237rSubst i j = rearrange 0 $ \k -> if k == i then j else if k > i then k - 1 else k
238
239rUp :: Rearrange a => Int -> Int -> a -> a
240rUp n l = rearrange l $ \k -> if k >= 0 then k + n else k
241
242instance Rearrange a => Rearrange [a] where
243 rearrange l f = map $ rearrange l f
244
245instance (Rearrange a, Rearrange b) => Rearrange (Either a b) where
246 rearrange l f = rearrange l f +++ rearrange l f
247
248instance (Rearrange a, Rearrange b) => Rearrange (a, b) where
249 rearrange l f = rearrange l f *** rearrange l f
250
251instance 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
255class DeBruijnify a where
256 deBruijnify_ :: Int -> [SIName] -> a -> a
257
258deBruijnify = deBruijnify_ 0
259
260instance (DeBruijnify a, DeBruijnify b) => DeBruijnify (a, b) where
261 deBruijnify_ k ns = deBruijnify_ k ns *** deBruijnify_ k ns
262
263instance (DeBruijnify a, DeBruijnify b) => DeBruijnify (Either a b) where
264 deBruijnify_ k ns = deBruijnify_ k ns +++ deBruijnify_ k ns
265
266instance (DeBruijnify a) => DeBruijnify [a] where
267 deBruijnify_ k ns = fmap (deBruijnify_ k ns)
268
269instance 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
276trSExp :: (a -> b) -> SExp' a -> SExp' b
277trSExp 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
287trSExp' :: SExp -> SExp' a
288trSExp' = trSExp elimVoid
289
290-------------------------------------------------------------------------------- statements
291
292data 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
298pattern Primitive n t <- Let n (Just t) (SBuiltin "undefined") where Primitive n t = Let n (Just t) $ SBuiltin "undefined"
299
300instance 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
306instance 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
313data StmtNode = StmtNode
314 { snId :: !Int
315 , snValue :: Stmt
316 , snChildren :: [StmtNode]
317 , snRevChildren :: [StmtNode]
318 }
319
320sortDefs :: [Stmt] -> [Stmt]
321sortDefs 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
344desugarMutual [x] = [x]
345desugarMutual xs = xs
346
347-------------------------------------------------------------------------------- modules
348
349data Module_ a = Module
350 { extensions :: Extensions
351 , moduleImports :: [(SIName, ImportItems)]
352 , moduleExports :: Maybe [Export]
353 , definitions :: a
354 }
355
356data Export = ExportModule SIName | ExportId SIName
357
358data ImportItems
359 = ImportAllBut [SIName]
360 | ImportJust [SIName]
361
362type Extensions = [Extension]
363
364data Extension
365 = NoImplicitPrelude
366 | TraceTypeCheck
367 deriving (Enum, Eq, Ord, Show)
368
369extensionMap :: Map.Map String Extension
370extensionMap = Map.fromList $ map (show &&& id) [toEnum 0 .. ]
371
372-------------------------------------------------------------------------------- builtin precedences
373
374data 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
389instance Up a => PShow (SExp' a) where
390 pShowPrec _ = showDoc_ . sExpDoc
391
392type Doc = NameDB PrecString
393
394-- name De Bruijn indices
395type NameDB a = StateT [String] (Reader [String]) a
396
397showDoc :: Doc -> String
398showDoc = str . flip runReader [] . flip evalStateT (flip (:) <$> iterate ('\'':) "" <*> ['a'..'z'])
399
400showDoc_ :: Doc -> Parser.Doc
401showDoc_ = text . str . flip runReader [] . flip evalStateT (flip (:) <$> iterate ('\'':) "" <*> ['a'..'z'])
402
403sExpDoc :: Up a => SExp' a -> Doc
404sExpDoc = \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
416shVar i = asks lookupVarName where
417 lookupVarName xs | i < length xs && i >= 0 = xs !! i
418 lookupVarName _ = "V" ++ show i
419
420newName = gets head <* modify tail
421
422shLet i a b = shAtom <$> shVar i >>= \i' -> local (dropNth i) $ shLam' <$> (cpar . shLet' (fmap inBlue i') <$> a) <*> b
423shLet_ a b = newName >>= \i -> shLam' <$> (cpar . shLet' (shAtom i) <$> a) <*> local (i:) b
424shLam 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
440data PS a = PS Prec a deriving (Functor)
441type PrecString = PS String
442
443getPrec (PS p _) = p
444prec i s = PS i (s i)
445str (PS _ s) = s
446
447lpar, rpar :: PrecString -> Prec -> String
448lpar (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
453rpar (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
460par True s = "(" ++ s ++ ")"
461par False s = s
462
463isAtom = (==PrecAtom) . getPrec
464isAtom' = (<=PrecAtom') . getPrec
465
466shAtom = PS PrecAtom
467shAtom' = PS PrecAtom'
468shTuple xs = prec PrecAtom $ \_ -> case xs of
469 [x] -> "((" ++ str x ++ "))"
470 xs -> "(" ++ intercalate ", " (map str xs) ++ ")"
471shAnn _ True x y | str y `elem` ["Type", inGreen "Type"] = x
472shAnn s simp x y | isAtom x && isAtom y = shAtom' $ str x <> s <> str y
473shAnn s simp x y = prec PrecAnn $ lpar x <> " " <> const s <> " " <> rpar y
474shApp Hidden x y = prec PrecApp $ lpar x <> " " <> const (str $ brace y)
475shApp h x y = prec PrecApp $ lpar x <> " " <> rpar y
476shArr x y | isAtom x && isAtom y = shAtom' $ str x <> "->" <> str y
477shArr x y = prec PrecArr $ lpar x <> " -> " <> rpar y
478shCstr x y | isAtom x && isAtom y = shAtom' $ str x <> "~" <> str y
479shCstr x y = prec PrecEq $ lpar x <> " ~ " <> rpar y
480shLet' x y | isAtom x && isAtom y = shAtom' $ str x <> ":=" <> str y
481shLet' x y = prec PrecLet $ lpar x <> " := " <> rpar y
482shLam' 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
486shLam' x y | isAtom x && isAtom y = shAtom' $ "\\" <> str x <> "->" <> str y
487shLam' x y = prec PrecLam $ "\\" <> lpar x <> " -> " <> rpar y
488brace s = shAtom $ "{" <> str s <> "}"
489cpar s | isAtom' s = s -- TODO: replace with lpar, rpar
490cpar s = shAtom $ par True $ str s
491epar = fmap underlined
492
493instance IsString (Prec -> String) where fromString = const
494