summaryrefslogtreecommitdiff
path: root/prototypes
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-03-24 16:43:54 +0100
committerPéter Diviánszky <divipp@gmail.com>2016-03-24 16:43:54 +0100
commit3d7ffc7cdb6f0c5b78d51900a9dcae29ba6913d6 (patch)
tree0d92909c87462e13d2e207c4a345baf84f8768e4 /prototypes
parent2863e31d34d0131d2dd3cc1f4df6c399c23187c9 (diff)
add reducer prototype with fast de bruijn index shifting (not ready yet)
Diffstat (limited to 'prototypes')
-rw-r--r--prototypes/ShiftReducer.hs696
1 files changed, 696 insertions, 0 deletions
diff --git a/prototypes/ShiftReducer.hs b/prototypes/ShiftReducer.hs
new file mode 100644
index 00000000..ae515b08
--- /dev/null
+++ b/prototypes/ShiftReducer.hs
@@ -0,0 +1,696 @@
1{-# language ScopedTypeVariables #-}
2{-# language LambdaCase #-}
3{-# language TypeOperators #-}
4{-# language TypeFamilies #-}
5{-# language ViewPatterns #-}
6{-# language PatternGuards #-}
7{-# language PatternSynonyms #-}
8{-# language RankNTypes #-}
9{-# language DataKinds #-}
10{-# language KindSignatures #-}
11{-# language GADTs #-}
12{-# language DeriveFunctor #-}
13{-# language DeriveGeneric #-}
14{-# language DefaultSignatures #-}
15{-# language FlexibleInstances #-}
16{-# language FlexibleContexts #-}
17{-# language TemplateHaskell #-} -- for testing
18{-# language NoMonomorphismRestriction #-}
19
20import Data.Monoid
21import Data.Maybe
22import Data.List
23import Data.Map (Map)
24import qualified Data.Map as Map
25import qualified Data.Set as Set
26import Control.Monad
27import Control.Arrow hiding (app)
28import Test.QuickCheck
29import Test.QuickCheck.Function
30import GHC.Generics
31import Debug.Trace
32
33------------------------------------------------------------ utils
34
35iterateN i f x = iterate f x !! i
36
37(<&>) = flip (<$>)
38
39data Void
40
41instance Eq Void where (==) = error "(==) @Void"
42instance Show Void where show = error "show @Void"
43
44{- used later?
45-- supplementary data: data with no semantic relevance
46newtype SData a = SData a
47instance Show (SData a) where show _ = "SData"
48instance Eq (SData a) where _ == _ = True
49instance Ord (SData a) where _ `compare` _ = EQ
50-}
51
52------------------------------------------------------------ streams
53
54-- streams with constant tails
55-- invariant property: Repeat is used when possible (see cons)
56data Stream a
57 = Cons a (Stream a)
58 | Repeat a
59 deriving (Eq, Show, Functor) -- Functor is not proper, may break invariant
60
61-- smart constructor to construct normal form of streams
62cons b (Repeat b') | b == b' = Repeat b'
63cons b x = Cons b x
64
65-- stream head
66sHead (Cons a _) = a
67sHead (Repeat a) = a
68
69-- stream tail
70sTail (Cons _ a) = a
71sTail (Repeat a) = Repeat a
72
73instance Applicative Stream where
74 pure a = Repeat a
75 -- (<*>) is not proper, may break invariant
76 Repeat f <*> Repeat a = Repeat $ f a
77 x <*> y = Cons{-should be cons-} (sHead x $ sHead y) (sTail x <*> sTail y)
78
79foldStream :: (b -> a -> a) -> (b -> a) -> Stream b -> a
80foldStream f g (Cons b u) = f b (foldStream f g u)
81foldStream f g (Repeat b) = g b
82
83-- final value in the stream
84limes :: Stream a -> a
85limes = foldStream const id
86
87-- replace limes by given stream
88sCont :: Eq a => Stream a -> (a -> Stream a) -> Stream a
89sCont as f = foldStream cons f as
90
91-- semantics of Stream
92streamToList :: Stream a -> [a]
93streamToList = foldStream (:) repeat
94
95streamToFun :: Stream a -> Int -> a
96streamToFun u i = streamToList u !! i
97
98sFromList :: Eq a => [a] -> a -> Stream a
99sFromList xs b = foldr cons (Repeat b) xs
100
101instance (Arbitrary a, Eq a) => Arbitrary (Stream a) where
102 arbitrary = sFromList <$> arbitrary <*> arbitrary
103
104-- iterate on stream
105sIterate :: Eq a => (a -> a) -> a -> Stream a
106sIterate f x
107 | y == x = Repeat x
108 | otherwise = Cons x $ sIterate f y
109 where
110 y = f x
111
112sCatMaybes :: Stream (Maybe a) -> [a]
113sCatMaybes = foldStream (\m s -> maybe s (:s) m) (maybe [] repeat)
114
115---------------------------------------------------------- operations involving Boolean streams
116
117mergeStreams :: Eq a => Stream Bool -> Stream a -> Stream a -> Stream a
118mergeStreams (Cons True u) as bs = cons (sHead as) $ mergeStreams u (sTail as) bs
119mergeStreams (Cons False u) as bs = cons (sHead bs) $ mergeStreams u as (sTail bs)
120mergeStreams (Repeat True) as bs = as
121mergeStreams (Repeat False) as bs = bs
122
123sFilter :: Stream Bool -> [a] -> [a]
124sFilter (Cons True u) is = take 1 is ++ sFilter u (drop 1 is)
125sFilter (Cons False u) is = sFilter u (drop 1 is)
126sFilter (Repeat True) is = is
127sFilter (Repeat False) is = []
128
129-- sFilter for streams
130-- the first stream is used when no more element can pass the filter
131filterStream :: Eq a => Stream a -> Stream Bool -> Stream a -> Stream a
132filterStream d (Cons True s) as = cons (sHead as) $ filterStream d s $ sTail as
133filterStream d (Cons False s) as = filterStream d s $ sTail as
134filterStream d (Repeat True) as = as
135filterStream d (Repeat False) as = d
136
137sOr :: Stream Bool -> Stream Bool -> Stream Bool
138sOr (Cons b u) (Cons b' u') = cons (b || b') $ sOr u u'
139sOr (Repeat False) u = u
140sOr (Repeat True) u = Repeat True
141sOr u (Repeat False) = u
142sOr u (Repeat True) = Repeat True
143
144prop_sOr_idemp a = sOr a a == a
145prop_sOr_comm a b = sOr a b == sOr b a
146
147dbAnd a b = not <$> sOr (not <$> a) (not <$> b)
148
149instance Monoid (Stream Bool) where
150 mempty = Repeat False
151 mappend = sOr
152
153prop_StreamBool_monoid_left (a :: Stream Bool) = mempty <> a == a
154prop_StreamBool_monoid_right (a :: Stream Bool) = a <> mempty == a
155prop_StreamBool_monoid_assoc (a :: Stream Bool) b c = (a <> b) <> c == a <> (b <> c)
156
157-- composition of (Stream Bool) values (by sFilter semantics)
158sComp :: Stream Bool -> Stream Bool -> Stream Bool
159sComp bs as = mergeStreams bs as $ Repeat False
160
161prop_sComp a b xs = sFilter (sComp a b) xs == (sFilter b . sFilter a) xs
162prop_sComp_trans a b (getNonNegative -> i) = indexTrans (sComp a b) i == (indexTrans a =<< indexTrans b i)
163
164filterDBUsed :: Stream Bool -> Stream Bool -> Stream Bool
165filterDBUsed = filterStream $ Repeat False
166
167--prop_filterDBUsed bs = mergeStreams bs xs ys sOr b a `sComp` filterDBUsed (sOr b a) a == a
168
169prop_filterDBUsed a b = sOr b a `sComp` filterDBUsed (sOr b a) a == a
170
171compress s = filterDBUsed s s
172
173
174--takeUps :: Int -> Stream Bool -> Stream Bool
175--takeUps i = (`sComp` sFromList (replicate i True) False)
176
177--prop_takeUps (getNonNegative -> n) u = streamToList (takeUps n u) == normSem (take n $ streamToList u)
178
179--takeUps' :: Int -> Stream Bool -> Stream Bool
180--takeUps' i = sComp $ sFromList (replicate i True) False
181
182--prop_takeUps' u (getNonNegative -> n) = streamToList (takeUps' n u) == head (dropWhile ((< n) . length . filter id) (inits $ streamToList u) ++ [streamToList u])
183
184--------------------------------------------------------------- indices
185
186-- index of the first appearance of the limes
187limesIndex :: Stream a -> Int
188limesIndex = foldStream (const (+1)) (const 0)
189
190-- indices at which the stream value is True
191trueIndices :: Stream Bool -> [Int]
192trueIndices s = sFilter s [0..]
193
194prop_trueIndices (getExpDB -> u) = all (streamToFun u) $ trueIndices u
195
196invTrueIndices :: [Int] -> Stream Bool
197invTrueIndices = f 0 where
198 f i [] = Repeat False
199 f i (k: ks) = iterateN (k - i) (cons False) $ cons True $ f (k + 1) ks
200
201prop_invTrueIndices (map getNonNegative . Set.toList -> ks) = trueIndices (invTrueIndices ks) == ks
202prop_invTrueIndices' (getExpDB -> u) = u == invTrueIndices (trueIndices u)
203
204-- a Boolean stream can be seen as an index transformation function for indices 0..n
205indexTrans :: Stream Bool -> Int -> Maybe Int
206indexTrans s i = ((Just <$> sFilter s [0..]) ++ repeat Nothing) !! i
207
208-- inverse of indexTrans
209invIndexTrans :: Stream Bool -> Int -> Maybe Int
210invIndexTrans s i = case dropWhile ((< i) . snd) $ zip [0..] $ sFilter s [0..] of
211 ((x, i'): _) | i' == i -> Just x
212 _ -> Nothing
213
214prop_invIndexTrans u (getNonNegative -> i) = maybe True (==i) (indexTrans u i >>= invIndexTrans u)
215
216diffDBs as = (u, filterDBUsed u <$> as) where u = mconcat as
217
218
219------------------------------------------------------------ used/unused de bruijn indices
220
221-- which de bruijn indicies are used?
222-- semantics of DBUsed is given by trueIndices
223-- True: use index; False: skip index
224type DBUsed = Stream Bool
225
226-- invariant property: limes is False
227-- finite indicies are used; lambda expressions are decorated with this
228newtype ExpDB = ExpDB { getExpDB :: DBUsed }
229 deriving (Eq, Show)
230
231instance Arbitrary ExpDB where
232 arbitrary = ExpDB . flip sFromList False <$> arbitrary
233
234-- invariant property: limes is True
235-- finite indicies are not used; good for index shifting transformations
236newtype ShiftDB = ShiftDB { getShiftDB :: DBUsed }
237 deriving (Eq, Show)
238
239instance Arbitrary ShiftDB where
240 arbitrary = ShiftDB . flip sFromList True <$> arbitrary
241
242------------------------------------------------------------ de bruijn index shifting layer
243
244-- transformation on De-Bruijn indices
245-- Shift s i ~ (fromJust . indexTrans s) <$> i
246data Shift a = Shift DBUsed a
247 deriving (Eq, Functor)
248
249instance Show a => Show (Shift a) where
250 show (Shift s a) = foldStream (:) (:":") ((\b -> if b then 'x' else '_') <$> s) ++ show a
251
252strip (Shift _ x) = x
253
254{-
255instance Applicative Shift where
256 pure = Shift (Repeat False)
257 Shift uf f <*> Shift ua a = Shift (uf <> ua) (f a)
258
259instance Monad Shift where
260 return = pure
261 Shift ux x >>= f = up ux $ f x
262
263--prop_UExpmonadAssoc (x :: Shift ()) (apply -> f) (apply -> g) = ((x >>= f) >>= g) == (x >>= (\x' -> f x' >>= g))
264-}
265
266class GetDBUsed a where
267 getDBUsed :: a -> DBUsed
268
269instance GetDBUsed ExpDB where
270 getDBUsed = getExpDB
271
272instance GetDBUsed (Shift a) where
273 getDBUsed (Shift u _) = u
274
275mkShift :: GetDBUsed a => a -> Shift a
276mkShift e = Shift (getDBUsed e) e
277
278instance (Arbitrary a, GetDBUsed a) => Arbitrary (Shift a) where
279 arbitrary = upToShift <$> arbitrary
280
281----------------
282
283-- for testing
284-- generate a DBUsed with a given number of used indicies
285data Up a = Up DBUsed a
286 deriving (Show)
287
288upToShift :: GetDBUsed a => Up a -> Shift a
289upToShift (Up u x) = Shift (sComp u $ getDBUsed x) x
290
291instance (Arbitrary a, GetDBUsed a) => Arbitrary (Up a) where
292 arbitrary = do
293 f <- arbitrary
294 u <- flip sFromList True . concatMap ((++ [True]) . (`replicate` False) . getNonNegative)
295 <$> replicateM (limesIndex $ getDBUsed f) arbitrary
296 return $ Up u f
297
298class GetDBUsed a => ShiftLike a where
299 setDBUsed :: DBUsed -> a -> a
300
301modDBUsed :: ShiftLike a => (DBUsed -> DBUsed) -> a -> a
302modDBUsed f e = setDBUsed (f $ getDBUsed e) e
303
304up :: ShiftLike a => DBUsed -> a -> a
305up x = modDBUsed (sComp x)
306
307down :: ShiftLike a => DBUsed -> a -> Maybe a
308down a e = case filterDBUsed (not <$> a) (getDBUsed e) of
309 Repeat False -> Just $ modDBUsed (filterDBUsed a) e
310 _ -> Nothing
311
312up_ :: ShiftLike a => Int -> Int -> a -> a
313up_ i j = up (iterateN i (cons True) $ iterateN j (cons False) (Repeat True))
314
315down_ :: ShiftLike a => Int -> a -> Maybe a
316down_ i = down (iterateN i (cons True) $ cons False (Repeat True))
317
318instance ShiftLike (Shift a) where
319 setDBUsed x (Shift _ a) = Shift x a
320
321prop_upDown (Up u ((`Shift` ()) . getExpDB -> e))
322 = down u (up u e) == Just e
323prop_downNothing ((`Shift` ()) . getExpDB -> e) (getNonNegative -> i)
324 = if i `elem` trueIndices (getDBUsed e) then down_ i e == Nothing else isJust (down_ i e)
325
326------------------------------------------------------------ substitutions
327
328type Substs a = Map Int a
329
330substsKeys :: Substs a -> Stream Bool
331substsKeys = invTrueIndices . Map.keys
332
333substsStream :: Eq a => Substs a -> Stream (Maybe a)
334substsStream = elemsUps . Map.toList
335
336elemsUps :: Eq a => [(Int, a)] -> Stream (Maybe a)
337elemsUps = f 0 where
338 f i [] = Repeat Nothing
339 f i ((k, a): ks) = iterateN (k - i) (cons Nothing) $ cons (Just a) $ f (k + 1) ks
340
341streamSubsts :: Stream (Maybe a) -> Substs a
342streamSubsts = Map.fromDistinctAscList . upsElems
343
344upsElems :: Stream (Maybe a) -> [(Int, a)]
345upsElems = f 0 where
346 f _ (Repeat Nothing) = []
347 f i (Cons Nothing u) = f (i+1) u
348 f i (Cons (Just a) u) = (i, a): f (i+1) u
349
350expandSubsts :: (Eq a, ShiftLike a) => Stream Bool -> Substs a -> Substs a
351expandSubsts u m = streamSubsts $ (\x -> mergeStreams u x $ Repeat Nothing) $ substsStream $ up u <$> m
352
353filterSubsts :: (Eq a, ShiftLike a) => Stream Bool -> Substs a -> Substs a
354filterSubsts u m = streamSubsts $ filterStream (Repeat Nothing) u $ substsStream $ modDBUsed (filterDBUsed u) <$> m
355
356------------------------------------------------------------ let expressions (substitutions + expression)
357
358data Let e a = Let (Substs e) a
359 deriving (Eq, Show, Functor)
360
361instance (GetDBUsed e, GetDBUsed a) => GetDBUsed (Let e a) where
362 getDBUsed (Let m e) = getDBUsed $ ShiftLet (getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m)) m e
363
364pattern ShiftLet :: DBUsed -> Substs a -> b -> Shift (Let a b)
365pattern ShiftLet u m e <- (getShiftLet -> (u, m, e)) where ShiftLet u m e = Shift (filterDBUsed (not <$> substsKeys m) u) (Let m e)
366
367getShiftLet (Shift u (Let m e)) = (mergeStreams (substsKeys m) (Repeat True) u, m, e)
368
369-- TODO: remove Eq a
370pattern PShiftLet :: () => (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b)
371pattern PShiftLet m e <- (pushShiftLet -> Let m e) where
372 PShiftLet m e = ShiftLet u (filterSubsts u m) $ modDBUsed (filterDBUsed u) e
373 where
374 u = getDBUsed e <> mconcat (Map.elems $ getDBUsed <$> m)
375
376pushShiftLet (ShiftLet u m e) = Let (expandSubsts u m) (up u e)
377
378mkLet :: (Eq a, ShiftLike a, ShiftLike b) => Substs a -> b -> Shift (Let a b)
379mkLet m e = PShiftLet (Map.filterWithKey (\k _ -> streamToFun c k) m) e
380 where
381 -- determine which let expressions are used (garbage collection)
382 -- TODO: speed this up somehow
383 c = limes $ sIterate f $ getDBUsed e
384 where
385 f x = dbAnd ks $ x <> mconcat (sCatMaybes $ filterStream (Repeat Nothing) x us)
386 ks = substsKeys m
387 us = substsStream $ getDBUsed <$> m
388
389transportIntoLet (Let m _) e = up (not <$> substsKeys m) e
390
391----------------------------------------------------------------- MaybeLet
392
393data MaybeLet a b c
394 = HasLet (Let a (Shift c))
395 | NoLet b
396 deriving (Show, Eq)
397
398type MaybeLet' a b = MaybeLet a b b
399
400maybeLet :: (Eq a, ShiftLike a) => Shift (Let a (Shift b)) -> Shift (MaybeLet' a b)
401maybeLet l@(Shift u (Let m e))
402 | Map.null m = up u $ NoLet <$> e
403 | otherwise = HasLet <$> l
404
405joinLets :: (Eq a, ShiftLike a) => MaybeLet' a (MaybeLet' a b) -> MaybeLet' a b
406joinLets (NoLet e) = e
407joinLets (HasLet (Let m (Shift s' (NoLet e)))) = HasLet $ Let m $ Shift s' e
408joinLets (HasLet (Let m (Shift s' (HasLet (Let m' e)))))
409 = HasLet $ Let (expandSubsts (not <$> substsKeys sm) m <> sm) se
410 where
411 (PShiftLet sm se) = Shift s' (Let m' e)
412
413instance (GetDBUsed a, GetDBUsed b, GetDBUsed c) => GetDBUsed (MaybeLet a b c) where
414 getDBUsed = \case
415 NoLet a -> getDBUsed a
416 HasLet x -> getDBUsed x
417
418-- used in testing
419fromLet (Shift u (NoLet e)) = Shift u e
420
421------------------------------------------------------------ literals
422
423data Lit
424 = LInt Int
425 | LChar Char
426 -- ...
427 deriving (Eq)
428
429instance Show Lit where
430 show = \case
431 LInt i -> show i
432 LChar c -> show c
433
434------------------------------------------------------------ expressions
435
436data Exp_ a b c d e
437 = ELit_ Lit
438 | EVar_ a -- a = () means that the variable de bruijn index is 0 (the only possible index if the exprssion is compact)
439 -- a = Int is the de bruijn index (in cases when the exprssion is not compactified)
440 | ELamD_ b -- lambda with unused argument
441 -- b is usually (Exp_ a b c d e)
442 | ELam_ c -- lambda with used argument
443 -- c usually contains a MaybeLet layer
444 | EApp_ d d -- application
445 -- d usually contains a Shift layer
446 | RHS_ e -- marks the beginning of right hand side (parts right to the equal sign) in fuction definitions
447 -- e is usually (Exp_ a b c d e)
448 -- e = Void means that this constructor cannot be used
449 deriving (Eq, Show) --, Generic)
450
451--------------------------------------------------------
452
453type WithLet a = MaybeLet (Shift LHSExp) a a
454
455-- right-hand-side expression (no RHS constructors inside)
456newtype Exp = Exp (Exp_ () Exp (WithLet Exp) (Shift Exp) Void)
457 deriving (Eq)
458
459pattern ELit l = Exp (ELit_ l)
460pattern EApp a b = Exp (EApp_ a b)
461pattern ELam i = Exp (ELam_ i)
462pattern ELamD i = Exp (ELamD_ i)
463pattern EVar i = Exp (EVar_ i)
464
465pattern EInt i = ELit (LInt i)
466
467-- left-hand-side expression (allows RHS constructor)
468newtype LHSExp = LHSExp (Exp_ () LHSExp (WithLet LHSExp) (Shift LHSExp) Exp)
469 deriving (Eq, Show)
470
471pattern RHS i = LHSExp (RHS_ i)
472
473--------------------------------------------------------
474
475type SExp = Shift Exp
476type LExp = WithLet Exp
477
478-- SLExp is *the* expression type in the user API
479type SLExp = Shift (WithLet Exp)
480
481sFun p s xs c = parens $ \c -> s ++ foldr (\f c -> ' ': f c) c xs
482 where
483 parens x
484 | p < 10 = x c
485 | otherwise = '(': x (')': c)
486
487instance Show Exp where
488 showsPrec p = \case
489 ELit i -> shows i
490 EApp a b -> sFun p "EApp" [showsPrec 10 a, showsPrec 10 b]
491 ELam a -> sFun p "ELam" [showsPrec 10 a]
492 ELamD a -> sFun p "ELamD" [showsPrec 10 a]
493 EVar () -> ("EVar" ++)
494
495instance GetDBUsed Exp where
496 getDBUsed = \case
497 EApp (Shift ua a) (Shift ub b) -> ua <> ub
498 ELit{} -> mempty
499 EVar{} -> cons True mempty
500 ELamD e -> sTail $ getDBUsed e
501 ELam e -> sTail $ getDBUsed e
502
503instance Arbitrary Exp where
504 arbitrary = (\(Shift _ (NoLet e)) -> e) . getSimpleExp <$> arbitrary
505-- shrink = genericShrink
506
507-- SLExp without let and shifting; for testing
508newtype SimpleExp = SimpleExp { getSimpleExp :: SLExp }
509 deriving (Eq, Show)
510
511instance Arbitrary SimpleExp where
512 arbitrary = fmap SimpleExp $ oneof
513 [ var . getNonNegative <$> arbitrary
514 , Int <$> arbitrary
515 , app <$> (getSimpleExp <$> arbitrary) <*> (getSimpleExp <$> arbitrary)
516 , lam <$> (getSimpleExp <$> arbitrary)
517 ]
518
519getLit :: SLExp -> Maybe Lit
520getLit (Shift _ (NoLet (ELit l))) = Just l
521getLit (Shift _ (HasLet (Let _ (Shift _ (ELit l))))) = Just l
522getLit _ = Nothing
523
524pattern Int i <- (getLit -> Just (LInt i)) where Int = Shift mempty . NoLet . EInt
525
526var :: Int -> SLExp
527var i = fmap NoLet $ up_ 0 i $ mkShift $ EVar ()
528
529prop_upVar (getNonNegative -> k) (getNonNegative -> n) (getNonNegative -> i) = up_ k n (var i) == var (if k <= i then n + i else i)
530prop_downVar (getNonNegative -> k) (getNonNegative -> i) = down_ k (var i) == case compare k i of LT -> Just (var $ i-1); EQ -> Nothing; GT -> Just (var i)
531
532lam :: SLExp -> SLExp
533lam (Shift u e) = Shift (sTail u) $ if sHead u then eLam e else eLamD e
534 where
535 eLam (NoLet e) = NoLet $ ELam $ NoLet e
536 -- TODO: improve this by let-floating
537 eLam x = NoLet $ ELam x
538
539 eLamD (NoLet e) = NoLet $ ELamD e
540 -- TODO: review
541 eLamD (HasLet (Let m (Shift u e))) = HasLet $ {-gc?-}Let (filterSubsts ul m) $ Shift (filterDBUsed ul u) $ ELamD e
542 where
543 ul = Cons False $ Repeat True
544
545app :: SLExp -> SLExp -> SLExp
546app (Shift ua (NoLet a)) (Shift ub (NoLet b))
547 = Shift u $ NoLet $ EApp (Shift (filterDBUsed u ua) a) (Shift (filterDBUsed u ub) b)
548 where u = ua <> ub
549app x y = f x y
550 where
551 f :: SLExp -> SLExp -> SLExp
552 f (Shift ula la) (Shift ulb (HasLet lb)) = g app ula la ulb lb
553 f (Shift ulb (HasLet lb)) (Shift ula la) = g (flip app) ula la ulb lb
554
555 g :: (SLExp -> SLExp -> SLExp) -> DBUsed -> LExp -> DBUsed -> Let (Shift LHSExp) (Shift Exp) -> SLExp
556 g app ula la ulb lb
557 = up u $ lets {-Shift u $-}
558 -- app (Shift ula' la) (Shift ulb' lb)
559 -- app (Shift ula' la) (Let mb eb)
560 mb {-HasLet $ Let mb $-} $
561 app xa (fmap NoLet eb)
562 where
563 (u, [ula', ulb']) = diffDBs [ula, ulb]
564 lb'@(Let mb eb) = pushShiftLet $ Shift ulb' lb
565 xa = transportIntoLet lb' $ Shift ula' la
566
567lets :: Substs (Shift LHSExp) -> SLExp -> SLExp
568lets m e = fmap joinLets $ maybeLet $ mkLet m e
569
570-- TODO
571instance Arbitrary LExp where
572 arbitrary = NoLet <$> arbitrary
573
574let1 :: Int -> SLExp -> SLExp -> SLExp
575let1 i (Shift u (NoLet x)) = lets $ Map.singleton i $ Shift u $ RHS x
576let1 i (Shift u (HasLet l)) = lets $ m <> Map.singleton i' (RHS <$> e)
577 where
578 (Let m e) = pushShiftLet $ Shift u l
579 (Just i') = indexTrans (not <$> substsKeys m) i
580
581---------------------------------------------------------
582{-
583newtype ExpS = ExpS (Exp_ Int ExpS (MaybeLet SExp ExpS Exp) SExp)
584 deriving (Eq, Show)
585
586pushShift :: SExp -> ExpS
587pushShift (Shift u e) = ExpS $ case e of
588 EApp a b -> EApp_ (up u a) (up u b)
589 ELit i -> ELit_ i
590 EVar{} -> EVar_ $ fromJust $ indexTrans u 0
591 ELamD e -> ELamD_ $ pushShift $ Shift (cons False u) e
592 ELam (NoLet e) -> ELam_ $ NoLet $ pushShift $ Shift (cons True u) e
593 LHS a b -> LHS_ a (up u <$> b) -- ??? $ SData (pushShift $ Shift u c)
594-- Delta x -> Delta_ $ SData x
595
596prop_var (getNonNegative -> i) = case pushShift (fromLet $ var i) of
597 ExpS (EVar_ i') -> i == i'
598 _ -> False
599
600prop_app (getSimpleExp -> a) (getSimpleExp -> b) = case pushShift $ fromLet $ app a b of
601 ExpS (EApp_ a' b') -> (a', b') == (fromLet a, fromLet b)
602 _ -> False
603
604--prop_lam (getNonNegative -> i) = elimShift undefined undefined undefined (==i) (var i)
605
606--prop_pushShift (Shift u e) =
607
608---------------------------------------------------------
609
610newtype ExpL = ExpL (Exp_ Int SLExp SLExp SLExp)
611 deriving (Eq, Show)
612{-
613pushLet :: LExp -> ExpL
614pushLet (NoLet e) = ExpL $ case e of
615 EInt i -> EInt_ i
616 EApp a b -> EApp_ (NoLet <$> a) (NoLet <$> b)
617 EVar{} -> EVar_ 0
618-- ELam a -> ELam_ $ mkShift a
619 ELamD a -> ELamD_ $ NoLet <$> mkShift a
620pushLet (HasLet (Let m e)) = ExpL $ case pushShift e of
621 ExpS e' -> case e' of
622 EApp_ a b -> EApp_ (fmap HasLet (mkLet m a)) (fmap HasLet (mkLet m b))
623 EInt_ i -> EInt_ i
624 EVar_ i -> EVar_ i
625-}
626pushLet' :: SLExp -> ExpL
627pushLet' (Shift u l) = case l of
628 NoLet e -> {-case pushShift (Shift u e) of
629 ExpS e -> -} ExpL $ case e of
630 ELit i -> ELit_ i
631 EApp a b -> EApp_ (NoLet <$> up u a) (NoLet <$> up u b)
632 EVar () -> EVar_ $ fromJust $ indexTrans u 0
633 ELam a -> ELam_ $ Shift (cons True u) a
634 -- ELamD_ a -> ELamD_ $ NoLet a
635 LHS a b -> LHS_ a ((fmap NoLet . up u) <$> b)
636 HasLet l -> case Shift u l of
637 PShiftLet m e -> case pushShift e of
638 ExpS e' -> case e' of
639 EApp_ a b -> ExpL $ EApp_ (fmap HasLet (mkLet m a)) (fmap HasLet (mkLet m b))
640 ELit_ i -> ExpL $ ELit_ i
641 EVar_ i -> case Map.lookup i m of
642 Nothing -> ExpL $ EVar_ i
643 Just x -> pushLet' $ lets m $ NoLet <$> x
644 LHS_ a b -> error "efun"
645-- Delta_ f -> ExpL $ Delta_ f
646
647---------------------------------------------------------
648
649hnf :: SLExp -> ExpL
650hnf e = case pushLet' e of
651 (ExpL (LHS_ "add" [_, _])) -> error "ok"
652 x@(ExpL (EApp_ a b)) -> case hnf a of
653 ExpL (ELam_ a) -> hnf $ let1 0 b a
654 ExpL (LHS_ n acc) -> hnf $ LHS n (_ b: acc)
655 _ -> x
656 x -> x
657
658-----------------------------------------------------------------------------------
659
660idE :: SLExp
661idE = lam $ var 0
662
663add :: SLExp
664add = NoLet <$> mkShift (LHS "add" []) -- $ ELam $ NoLet $ ELam $ NoLet $ Delta f)
665 where
666 f [Int i, Int j] = Int $ i + j
667
668example1 = app (idE) (Int 10)
669
670example2 = app (app add (Int 10)) (Int 5)
671
672
673-- = fun name args $ \x -> \y -> rhs e
674
675
676----------------------------------------------------------------- run all tests
677-}
678return []
679runTests = $quickCheckAll
680
681{-
682TODO
683
684- primes example running
685- speed up eliminators with caching
686- write performance tests
687- speed up Boolean streams with compression
688- check that all operations is available and efficient
689 - up, down
690 - subst
691 - constructions
692 - lam, pi, app, var, lit, ...
693 - eliminations
694- intergrate into the compiler
695-}
696