summaryrefslogtreecommitdiff
path: root/prototypes
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-06-24 13:25:50 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-06-24 13:25:50 +0200
commit637ca925d493cb0d37d039a64cddac63268d314c (patch)
tree3eb2fad6779a46aede41927f6c60e6f453ece835 /prototypes
parent7873bdba0bdee3050659f845cedf19bfa837ef50 (diff)
Lam-machine v2
Diffstat (limited to 'prototypes')
-rw-r--r--prototypes/IndexList.hs63
-rw-r--r--prototypes/LamMachineV2.hs770
2 files changed, 833 insertions, 0 deletions
diff --git a/prototypes/IndexList.hs b/prototypes/IndexList.hs
new file mode 100644
index 00000000..af5b8653
--- /dev/null
+++ b/prototypes/IndexList.hs
@@ -0,0 +1,63 @@
1{-# LANGUAGE NoMonomorphismRestriction #-}
2{-# LANGUAGE PatternSynonyms #-}
3{-# LANGUAGE PatternGuards #-}
4{-# LANGUAGE ViewPatterns #-}
5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE ScopedTypeVariables #-}
7module IndexList where
8
9import Prelude hiding (length, (!!))
10import Control.Arrow
11
12data List a
13 = Nil
14 | Z !(List (a, a))
15 | S a !(List (a, a))
16 deriving Show
17
18z Nil = Nil
19z v = Z v
20
21length :: List a -> Int
22length Nil = 0
23length (Z v) = 2 * length v
24length (S _ v) = 1 + 2 * length v
25
26(!!) :: List a -> Int -> a
27S x v !! 0 = x
28S x v !! i = Z v !! (i-1)
29Z v !! i
30 | even i = fst $ v !! (i `div` 2)
31 | otherwise = snd $ v !! (i `div` 2)
32Nil !! i = error $ "index out of bounds: " ++ show i
33
34update :: List a -> Int -> (a -> a) -> List a
35update (S x v) 0 f = S (f x) v
36update (S x v) i f
37 | even (i-1) = S x $ update v ((i-1) `div` 2) (first f)
38 | otherwise = S x $ update v ((i-1) `div` 2) (second f)
39update (Z v) i f
40 | even i = Z $ update v (i `div` 2) (first f)
41 | otherwise = Z $ update v (i `div` 2) (second f)
42update Nil i _ = error $ "update index out of bounds: " ++ show i
43
44pattern Cons :: a -> List a -> List a
45pattern Cons a v <- (getCons -> Just (a, v))
46 where Cons x Nil = S x Nil
47 Cons x (Z v) = S x v
48 Cons x (S y v) = Z (Cons (x, y) v)
49
50getCons :: List a -> Maybe (a, List a)
51getCons Nil = Nothing
52getCons (S x v) = Just (x, z v)
53getCons (Z v) = (\((x, y), v) -> (x, S y v)) <$> getCons v
54
55pattern List :: [a] -> List a
56pattern List a <- (fromList -> a)
57 where List = foldr Cons Nil
58
59fromList :: List a -> [a]
60fromList (Cons x xs) = x: fromList xs
61fromList Nil = []
62
63
diff --git a/prototypes/LamMachineV2.hs b/prototypes/LamMachineV2.hs
new file mode 100644
index 00000000..b0e9c9db
--- /dev/null
+++ b/prototypes/LamMachineV2.hs
@@ -0,0 +1,770 @@
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE PatternSynonyms #-}
3{-# LANGUAGE PatternGuards #-}
4{-# LANGUAGE ViewPatterns #-}
5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE ScopedTypeVariables #-}
7{-# LANGUAGE TypeSynonymInstances #-}
8{-# LANGUAGE FlexibleInstances #-}
9{-# LANGUAGE GeneralizedNewtypeDeriving #-}
10{-# LANGUAGE MultiParamTypeClasses #-}
11{-# LANGUAGE FlexibleContexts #-}
12{-# LANGUAGE NoMonomorphismRestriction #-}
13{-# LANGUAGE TypeFamilies #-}
14{-# LANGUAGE DeriveFunctor #-}
15{-# LANGUAGE BangPatterns #-}
16
17--module LamMachineV2 where
18
19import Data.List
20import Data.Word
21import Data.Int
22import Data.Monoid
23import Data.Maybe
24import Data.Bits
25import Data.String
26import qualified Vector as PV
27import qualified Data.Vector as PV'
28import qualified Data.Vector.Mutable as V
29import qualified Data.Vector.Unboxed.Mutable as UV
30import qualified Data.Vector.Unboxed as PUV
31import Control.Arrow hiding ((<+>))
32import Control.Category hiding ((.), id)
33import Control.Monad
34import Control.Monad.Writer
35import Control.Monad.ST
36import Debug.Trace
37import qualified Text.Show.Pretty as P
38import System.Environment
39
40import LambdaCube.Compiler.Pretty
41
42-----------------------------------------
43
44class HasLen v where
45 len :: v -> Int
46
47class (HasLen v, Monad m) => VecLike v m where
48 type VElem v
49 new :: Int -> m v
50 append :: v -> (Int, [VElem v]) -> m v
51 read_ :: v -> Int -> m (VElem v)
52 freezedRead :: v -> m (Int -> VElem v)
53 write :: v -> Int -> VElem v -> m v
54 modify :: v -> Int -> (VElem v -> VElem v) -> m v
55 vToList :: v -> m [VElem v]
56
57-----------------
58
59data Vec s a = Vec !Int !(V.STVector s a)
60
61instance HasLen (Vec s a) where
62 len (Vec n _) = n
63
64instance VecLike (Vec s a) (ST s) where
65 type VElem (Vec s a) = a
66
67 new n | n < 0 = error $ "new: " ++ show n
68 new n = Vec 0 <$> V.new n
69
70 append (Vec n v) (k, xs) = do
71 v' <- myGrow_ v (n + k)
72 sequence_ $ zipWith (V.write v') [n..] xs
73 return $ Vec (n + k) v'
74 where
75 myGrow_ v@(V.length -> m) n
76 | m >= n = return v
77 | otherwise = V.grow v (2 * n - m)
78
79 read_ (Vec _ v) i = V.read v i
80
81 freezedRead (Vec _ v) = PV'.unsafeFreeze v <&> PV'.unsafeIndex
82
83 write x@(Vec _ v) i a = V.write v i a >> return x
84
85 modify x@(Vec _ v) i a = V.modify v a i >> return x
86
87 vToList (Vec n v) = mapM (V.read v) [0..n-1]
88
89-----------------
90
91data PVec a = PVec !Int !(PV.V a)
92
93instance HasLen (PVec a) where
94 len (PVec n _) = n
95
96instance Monad m => VecLike (PVec a) m where
97 type VElem (PVec a) = a
98
99 new n = return $ PVec 0 PV.Nil
100
101 append (PVec n v) (k, xs) = return $ PVec (n + k) $ foldl (flip PV.Cons) v $ take k $ xs ++ repeat (error "yzv")
102
103 read_ (PVec n v) i = return $ PV.index v (n - i - 1)
104
105 freezedRead (PVec n v) = return $ \i -> PV.index v (n - i - 1)
106
107 write v i x = modify v i $ const x
108
109 modify (PVec n v) i f = return $ PVec n $ PV.update v (n - i - 1) f
110
111 vToList (PVec _ a) = return $ reverse $ PV.toList a
112
113--------------------------------------------------------------------------- data structures
114
115data Lit
116 = LInt !Int
117 | LChar !Char
118 | LFloat !Double
119 deriving Eq
120
121data Exp
122 = Var_ !DB
123-- | Free !Int
124 | Lam VarInfo Exp
125 | App Exp Exp
126 | Con ConIndex [Exp]
127 | Case CaseInf Exp [Exp]
128 | Lit !Lit
129 | Delta !Op [Exp]
130 deriving (Show)
131
132pattern Var i = Var_ (Pos i)
133pattern Free i = Var_ (Neg i)
134
135type DB = Int
136type ConIndex = (ConInfo, Int)
137type CaseInf = (CaseInfo, [Int])
138
139data Op
140 = Round | ISqrt
141 | Add | Sub | Mod | LessEq | EqInt
142 | YOp | SeqOp
143 deriving (Eq, Show)
144
145pattern Op1 op x = Delta op [x]
146pattern Op2 op x y = Delta op [x, y]
147
148pattern Y s a = Op1 YOp (Lam s a)
149pattern Seq a b = Op2 SeqOp a b
150pattern Int i = Lit (LInt i)
151
152infixl 4 `App`
153
154data EnvPiece e
155 = EApp e
156 | ECase CaseInf [e]
157 | EDelta !Op [Lit] [e]
158 | Update_ !DB
159 deriving (Eq, Show, Functor)
160
161data HNF e
162 = HLam VarInfo e
163 | HCon ConIndex [DB]
164 | HLit !Lit
165 | HVar_ !DB
166 deriving (Eq, Show, Functor)
167
168pattern Update i = Update_ (Pos i)
169
170pattern HVar i = HVar_ (Pos i)
171pattern HFree i = HVar_ (Neg i)
172
173pattern Neg i <- (getNeg -> Just i)
174 where Neg i = negate i - 1
175
176getNeg i | i < 0 = Just $ negate i - 1
177getNeg _ = Nothing
178
179pattern Pos :: Int -> Int
180pattern Pos i <- (getPos -> Just i)
181 where Pos i = i
182
183getPos i | i >= 0 = Just i
184getPos _ = Nothing
185
186
187data EExp
188 = ExpC !Int [EExp] [EnvPiece EExp] (HNF EExp)
189 | ErrExp
190 deriving (Eq, Show)
191
192pattern PExp ps e <- ExpC 0 _ ps e
193 where PExp = ExpC 0 []
194
195pattern SExp e = PExp [] e
196
197pattern ERef r = SExp (HVar_ r)
198
199pattern LExp n ls v = ExpC n ls [] (HVar_ v)
200
201-------------------------------------- max db index
202
203newtype MDB = MDB {getMDB :: Int}
204 deriving (Eq, Show)
205
206instance Monoid MDB where
207 mempty = MDB 0
208 MDB n `mappend` MDB m = MDB $ n `max` m
209
210------------------------------------- rearrange De Bruijn indices
211
212class Rearrange a where
213 rearrange :: (Int -> Int) -> Int -> a -> a
214
215instance Rearrange a => Rearrange [a] where
216 rearrange f i = map (rearrange f i)
217
218instance Rearrange EExp
219 where
220 rearrange _ _ ErrExp = ErrExp
221 rearrange f l_ (ExpC n ls ps e) = ExpC n (rearrange f l ls) (rearrange f l ps) $ rearrange f l e
222 where
223 l = l_ + n
224
225instance Rearrange e => Rearrange (EnvPiece e)
226 where
227 rearrange f l = \case
228 EApp e -> EApp $ rearrange f l e
229 ECase is@(_, i) es -> ECase is $ zipWith (rearrange f . (l +)) i es
230 EDelta o ls es -> EDelta o ls $ rearrange f l es
231 Update_ i -> Update_ $ atL f l i
232
233instance Rearrange e => Rearrange (HNF e)
234 where
235 rearrange f l = \case
236 HLam i e -> HLam i $ rearrange f (l+1) e
237 HCon i ns -> HCon i $ atL f l <$> ns
238 HVar_ i -> HVar_ $ atL f l i
239 x -> x
240
241instance Rearrange Exp
242 where
243 rearrange f l = \case
244 Var_ i -> Var_ $ atL f l i
245 Lam i e -> Lam i $ rearrange f (l+1) e
246 App e e' -> App (rearrange f l e) (rearrange f l e')
247 Con i es -> Con i $ rearrange f l es
248 Case is@(_, i) e es -> Case is (rearrange f l e) $ zipWith (rearrange f . (l +)) i es
249 Delta d es -> Delta d $ rearrange f l es
250 x -> x
251
252{-
253instance (Rearrange a, Rearrange b) => Rearrange (a, b) where
254 rearrange f i (a, b) = (rearrange f i a, rearrange f i b)
255
256instance Rearrange (Info a) where
257 rearrange _ _ = id
258-}
259
260----------
261
262rearrange' f = rearrange f 0
263
264up _ 0 = id
265up l n = rearrange (+n) l
266
267up' = up 0
268
269-----------------------------------------
270
271(<&>) = flip (<$>)
272
273addI f l i | i < l = return
274addI f l i = f (i-l)
275
276atL f l i | i < l = i
277atL f l i = aadd l $ f (i-l)
278
279aadd l (Pos i) = l + i
280aadd l i = i
281
282class FVs a where
283 fv :: Monad m => (Int -> b -> m b) -> Int -> a -> b -> m b
284 sfv :: (Int -> Int) -> Int -> a -> a
285 open :: Int -> Int -> a -> a
286
287instance FVs a => FVs [a] where
288 fv l f [] = return
289 fv l f (x: xs) = fv l f x >=> fv l f xs
290
291 sfv f = map . sfv f
292
293 open f = map . open f
294
295instance (FVs a, FVs b) => FVs (a, b) where
296 fv l f (a, b) = fv l f a >=> fv l f b
297
298 sfv f l (a, b) = (sfv f l a, sfv f l b)
299
300 open f i (a, b) = (open f i a, open f i b)
301
302instance FVs EExp where
303 fv f l ErrExp = return
304 fv f l (ExpC n ls ps e) = fv f l' ls >=> fv f l' ps >=> fv f l' e
305 where l' = l + n
306
307 sfv f l ErrExp = ErrExp
308 sfv f l (ExpC n ls ps e) = ExpC n (sfv f l' ls) (sfv f l' ps) (sfv f l' e)
309 where l' = l + n
310
311 open f l ErrExp = ErrExp
312 open f l (ExpC n ls ps e) = ExpC n (open f l' ls) (open f l' ps) (open f l' e)
313 where l' = l + n
314
315instance FVs e => FVs (EnvPiece e) where
316
317 fv f l = \case
318 EApp e -> fv f l e
319 ECase (_, i) es -> foldr (>=>) return $ zipWith (fv f . (l +)) i es
320 EDelta o ls es -> fv f l es
321 Update_ i -> addI f l i
322
323 sfv f l = \case
324 EApp e -> EApp $ sfv f l e
325 ECase is@(_, i) es -> ECase is $ zipWith (sfv f . (l +)) i es
326 EDelta o ls es -> EDelta o ls $ sfv f l es
327 Update_ i -> Update_ $ atL f l i
328
329 open f l = \case
330 EApp e -> EApp $ open f l e
331 ECase is@(_, i) es -> ECase is $ zipWith (open f . (l +)) i es
332 EDelta o ls es -> EDelta o ls $ open f l es
333 Update_ i -> Update_ $ openL f l i
334
335instance FVs e => FVs (HNF e) where
336
337 fv f l = \case
338 HLam i e -> fv f (l+1) e
339 HCon i ns -> foldr (>=>) return $ map (addI f l) ns
340 HVar_ i -> addI f l i
341 HLit{} -> return
342
343 sfv f l = \case
344 HLam i e -> HLam i $ sfv f (l+1) e
345 HCon i ns -> HCon i $ atL f l <$> ns
346 HVar_ i -> HVar_ $ atL f l i
347 x@HLit{} -> x
348
349 open f l = \case
350 HLam i e -> HLam i $ open f (l+1) e
351 HCon i ns -> HCon i $ openL f l <$> ns
352 HVar_ i -> HVar_ $ openL f l i
353 x@HLit{} -> x
354
355openL f l (Neg i) | i >= f = i - f + l
356openL f l i = i
357
358-----------------------------------------
359
360type GCConfig = (Int, Int, Int, Int)
361
362defaultConfig = (20000, 10000, max 0 $ 10000 - 20, 20)
363
364hnf = hnf_ defaultConfig
365
366hnf_ gcconfig e_
367 = open ii 0 $ steps gcconfig -- $ join (trace . ("\n------------\n" ++) . ppShow)
368 $ preprocess e
369 where
370 (e, MDB ii) = runWriter $ closeExp ii 0 e_
371
372 closeExp f l = \case
373 Free i -> tell (MDB $ i + 1) >> return (Free i)
374 Var i -> return $ if i >= l then Free $ i - l + f else Var i
375 Lam i e -> Lam i <$> closeExp f (l+1) e
376 App e e' -> App <$> closeExp f l e <*> closeExp f l e'
377 Con i es -> Con i <$> traverse (closeExp f l) es
378 Case is@(_, i) e es -> Case is <$> closeExp f l e <*> zipWithM (\ns -> closeExp f (l + ns)) i es
379 Delta d es -> Delta d <$> traverse (closeExp f l) es
380 x -> return x
381
382preprocess :: Exp -> EExp
383preprocess = \case
384 Lit l -> SExp $ HLit l
385 Var_ i -> SExp $ HVar_ i
386 Lam i e -> SExp $ HLam i $ hnf e
387 Y s e -> ExpC (n+1) (ls ++ [({-s,-} PExp ps f)]) mempty (HVar n)
388 where ExpC n ls ps f = hnf e
389 Delta d (e: es) -> add' (EDelta d [] $ preprocess <$> es) $ preprocess e
390 App e f -> add' (EApp $ letify "u" $ preprocess f) $ preprocess e
391 Case is@(_, i) e es -> add' (ECase is $ zipWith (\ns -> if ns == 0 then preprocess else hnf) i es) $ preprocess e
392 Con i es -> foldl (app2 f) (SExp $ HCon i []) $ letify "r" . preprocess <$> es
393 where
394 f [] (HCon i vs) [] (HVar_ v) = ([], HCon i $ vs ++ [v])
395 where
396 add' p (ExpC n ls ps e) = ExpC n ls (ps ++ [up' n p]) e
397
398 app2 g e@(ExpC n ls ps f) e'@(ExpC n' ls' ps' f') = ExpC (n+n') (up n n' ls <> up 0 n ls') ps'' f''
399 where
400 (ps'', f'') = g (up n n' ps) (up n n' f) (up 0 n ps') (up 0 n f')
401
402 letify :: Info String -> EExp -> EExp
403 letify s e@LExp{} = e
404 letify s (ExpC n ls ps e) = LExp (n+1) (up n 1 $ ls <> [({-s,-} PExp ps e)]) n
405
406-------------------------------------------------
407
408nogc_mark = -1
409
410type Vecs s = (Vec s EExp, Vec s EExp)
411
412steps :: GCConfig -> EExp -> EExp
413steps (gc1, gc2, gc3, gc4) e = runST (init e)
414 where
415 init :: forall s . EExp -> ST s EExp
416 init (ExpC n ls ps e) = do
417 v1 <- new n
418 v2 <- new gc4
419 v1' <- append v1 (n, ls)
420 trace "-----" $ vsteps (n, 0, []) (v1', v2) [ps] e
421 where
422 vsteps :: (Int, Int, [Int]) -> Vecs s -> [[EnvPiece EExp]] -> HNF EExp -> ST s EExp
423 vsteps sn ls@(v1@(len -> n), v2@(len -> n')) ps e@(HVar_ i)
424 | i < 0 || i >= n + n' = final sn ls ps e
425 | i < n = do
426 (adjust (n + n') -> e) <- read_ v1 i
427 if isHNF e
428 then addLets sn ls ps e
429 else write v1 i ErrExp >>= \v1 -> addLets sn (v1, v2) ([Update i]: ps) e
430 | i < n + n' = do
431 (adjust (n + n') -> e) <- read_ v2 (i-n)
432 if isHNF e
433 then addLets sn ls ps e
434 else write v2 (i-n) ErrExp >>= \v2 -> addLets sn (v1, v2) ([Update i]: ps) e
435 vsteps sn@(gc1, gc2, argh) ls@(v1@(len -> n), v2@(len -> n')) (getC -> Just (p, ps)) e
436 | Update i <- p = if i < n
437 then do
438 v1' <- write v1 i $ SExp e
439 vsteps (gc1, gc2, i: argh) (v1', v2) ps e
440 else do
441 v2' <- write v2 (i - n) $ SExp e
442 vsteps sn (v1, v2') ps e
443 | Just x <- dx (n + n') p e = addLets sn ls ps x
444 vsteps sn ls ps e = final sn ls ps e
445
446 final sn v ps e = majorGC sn v ps e $ \sn' (v1@(len -> n), _) ps' e' -> do
447 ls' <- vToList v1
448 return $ ExpC n ls' (concat ps') e'
449
450 dx len (EApp (LExp n ls z)) (HLam i (ExpC n' ls' ps' e))
451 = Just $ ExpC (n + n') (rearrange' upFun ls <> rearrange' fu ls') (rearrange' fu ps') $ rearrange' fu e
452 where
453 z' = if z < 0 then z else if z < n then z + len else z - n
454 fu i | i < n' = i + n + len
455 | i == n' = z'
456 | otherwise = i - (1 + n')
457
458 upFun i = if i < n then i + len else i - n
459
460 dx len (ECase _ cs) (HCon (_, i) vs@(length -> n))
461 | n' == 0 && n == 0 = Just e
462 | otherwise = Just $ adjust' (\i -> if i < n' then i + len else if i - n' < n then vs !! (n - (i - n') - 1) else i - n - n') e
463 where
464 e@(ExpC n' _ _ _) = cs !! i
465 dx len (EDelta SeqOp [] [f]) x
466 | isHNF' x = Just $ adjust len f
467 | otherwise = Nothing
468 dx len (EDelta o lits (ExpC n ls ps f: fs)) (HLit l)
469 = Just $ adjust len $ ExpC n ls (ps ++ [EDelta o (l: lits) fs]) f
470 dx len (EDelta o lits []) (HLit l)
471 = Just $ SExp $ delta o $ l: lits
472 dx _ _ _ = Nothing
473
474 addLets sn ls ps (PExp ps' e) = vsteps sn ls (ps': ps) e
475 addLets sn ls@(v1, v2) ps (ExpC n' xs ps' e) = do
476 v2' <- append v2 (n', xs)
477 mkGC sn (v1, v2') (ps': ps) e
478
479 mkGC sn@(mg, sn_, xx) v@(len -> n, len -> n') ps e
480 | n' < gc2 = vsteps (mg, sn_ + 1, xx) v ps e
481 | n + n' - mg < gc1 = minorGC sn v ps e
482 | otherwise = majorGC sn v ps e vsteps
483
484 adjust _ e@PExp{} = e
485 adjust n e@(ExpC n' _ _ _) = adjust' (\i -> if i < n' then i + n else i - n') e
486
487 adjust' fu (ExpC n' xs ps' e) = ExpC n' (rearrange' fu xs) (rearrange' fu ps') (rearrange' fu e)
488
489 minorGC :: (Int, Int, [Int]) -> Vecs s -> [[EnvPiece EExp]] -> HNF EExp -> ST s EExp
490 minorGC (mg, sn, argh) (v1@(len -> n), v2@(len -> n')) (concat -> ps) e = do
491 fv2 <- freezedRead v2
492 genericGC_ fv2 n n' $ \mark co -> do
493 let cc (xx, acc) i = do
494 e <- read_ v1 i
495 (same, xx') <- fv (\i (same, b) -> (,) False <$> mark i b) n e (True, xx)
496 return (xx', if same then acc else i: acc)
497
498 let !la = length argh
499 (xx', argh') <- foldM cc (0, []) argh
500 let !la' = length argh'
501 s <- fv mark n (ps, e) xx'
502 append v1 (s, []) >>= \vv -> co vv $ \fvi v1'@(len -> n'') ->
503 trace ("minor gc: " ++ show (n - la) ++ " + " ++ show (la - la') ++ " + " ++ show la' ++ " + " ++ show xx' ++ " + " ++ show (n' - xx') ++ " - " ++ show (n + n' - n'')) $ do
504 v1'' <- foldM (\v i -> modify v i $ sfv fvi n) v1' argh'
505 v2' <- new gc3
506 vsteps (mg, sn + 1, []) (v1'', v2') [sfv fvi n ps] (sfv fvi n e)
507
508 majorGC :: (Int, Int, [Int]) -> Vecs s -> [[EnvPiece EExp]] -> HNF EExp
509 -> ((Int, Int, [Int]) -> Vecs s -> [[EnvPiece EExp]] -> HNF EExp -> ST s e)
510 -> ST s e
511 majorGC (_, sn, argh) v@(v1@(len -> n), v2@(len -> n')) (concat -> ps) e cont = do
512 fv1 <- freezedRead v1
513 fv2 <- freezedRead v2
514 let read2 i = if i < n then fv1 i else fv2 (i - n)
515 genericGC_ read2 0 (n + n') $ \mark co -> do
516 s <- fv mark 0 (ps, e) 0
517 new s >>= \v -> append v (s, []) >>= \vv -> co vv $
518 \fvi v1'@(len -> n'') ->
519 trace ("major gc: " ++ show n ++ " + " ++ show n' ++ " - " ++ show (n + n' - n'')) $ do
520 v2' <- new gc3
521 cont (n'', sn + 1, []) (v1', v2') [sfv fvi 0 ps] (sfv fvi 0 e)
522
523 genericGC_ read_ n len cont = do
524 vi <- UV.replicate len nogc_mark
525 cont (mark vi read_ n []) $ \vv cont -> do
526 (PUV.unsafeIndex -> fvi) <- PUV.unsafeFreeze vi
527 let sweep i v | i == len = return v
528 sweep i v = do
529 let !ma = fvi i
530 if ma == nogc_mark then sweep (i+1) v else
531 case read_ i of
532 ERef r | r >= n -> sweep (i+1) v
533 e -> sweep (i+1) =<< write v (ma + n) (sfv fvi n e)
534 cont fvi =<< sweep 0 vv
535 where
536 mark vi read_ n acc i t = do
537 ma <- UV.read vi i
538 if ma /= nogc_mark then writes ma >> return t else
539 case read_ i of
540 ERef r | r >= n -> mark vi read_ n (i: acc) (r - n) t
541 e -> do
542 writes t
543 UV.write vi i t
544 fv (mark vi read_ n []) n e $ t+1
545 where
546 writes t = forM_ acc $ \i -> UV.write vi i t
547
548delta ISqrt [LInt i] = HLit $ LInt $ round $ sqrt $ fromIntegral i
549delta LessEq [LInt j, LInt i] = mkBool $ i <= j
550delta EqInt [LInt j, LInt i] = mkBool $ i == j
551delta Add [LInt j, LInt i] = HLit $ LInt $ i + j
552delta Sub [LInt j, LInt i] = HLit $ LInt $ i - j
553delta Mod [LInt j, LInt i] = HLit $ LInt $ i `mod` j
554delta o ls = error $ "delta: " ++ show o ++ "\n" ++ show ls
555
556mkBool b = HCon (if b then ("True", 1) else ("False", 0)) []
557
558isHNF ERef{} = False
559isHNF SExp{} = True
560isHNF _ = False
561
562isHNF' HVar_{} = False
563isHNF' _ = True
564
565getC ((x: xs): xss) = Just (x, xs: xss)
566getC ([]: xss) = getC xss
567getC _ = Nothing
568
569--------------------------------------------------------------- pretty print
570
571newtype Info a = Info {getInfo :: a}
572
573instance Eq (Info a) where _ == _ = True
574instance Show a => Show (Info a) where show (Info s) = show s
575instance IsString a => IsString (Info a) where fromString = Info . fromString
576
577type VarInfo = Info String
578type ConInfo = String
579type CaseInfo = [(String, [String])]
580
581instance PShow Lit where
582 pShow (LInt i) = pShow i
583 pShow (LChar i) = pShow i
584 pShow (LFloat i) = pShow i
585
586instance Show Lit where show = ppShow
587
588shLet [] x = x
589shLet ls x = foldl (flip DFreshName) (DLet' (foldr1 DSemi $ zipWith (\i (_, e) -> DOp "=" (Infix (-1)) (dVar i) e) [0..] ls) x) (Just . getInfo . fst <$> ls)
590
591shCase cn e xs = DPreOp (-20) (ComplexAtom "case" (-10) e (SimpleAtom "of"))
592 $ foldr1 DSemi
593 [ foldr DFreshName
594 (DArr_ "->" (foldl DApp (text a) $ dVar <$> reverse [0..length n - 1])
595 b
596 )
597 $ Just <$> n
598 | ((a, n), b) <- zip cn xs]
599
600shLam n b = DFreshName (Just n) $ showLam (DVar 0) b
601
602showLam x (DFreshName u d) = DFreshName u $ showLam (DUp 0 x) d
603showLam x (DLam xs y) = DLam (DSep (InfixR 11) x xs) y
604showLam x y = DLam x y
605
606instance PShow e => PShow (HNF e) where
607 pShow = \case
608 HLam n e -> shLam (getInfo n) $ pShow e
609 HCon (s, _) is -> foldl DApp (text s) $ dVar <$> is
610 HLit l -> pShow l
611 HVar_ i -> dVar i
612
613dVar (Pos i) = DVar i
614dVar (Neg i) = text $ "v" ++ show i
615
616instance PShow EExp where
617 pShow ErrExp = text "_|_"
618 pShow (ExpC n ls ps e) = shLet ((,) "x" . pShow <$> ls) $ foldl h (pShow e) ps
619 where
620 h e = \case
621 EApp x -> e `DApp` pShow x
622 ECase (cns, _) xs -> shCase cns e $ pShow <$> xs
623 Update_ i -> DOp "@" (InfixR 14) (dVar i) e
624 EDelta o ls es -> shDelta o $ (pShow <$> ls) ++ e: (pShow <$> es)
625{-
626instance PShow Exp where
627 pShow = \case
628 Var i -> DVar i
629 Free i -> text $ "v" ++ show i
630 Lam n e -> shLam (getInfo n) $ pShow e
631 App a b -> pShow a `DApp` pShow b
632 Con (s, _) is -> foldl DApp (text s) $ pShow <$> is
633 Case (cns, _) e xs -> shCase cns (pShow e) $ pShow <$> xs
634 Lit l -> pShow l
635 Delta o es -> shDelta o $ pShow <$> es
636-}
637--shDelta ISqrt [x] =
638shDelta SeqOp [a, b] = DOp "`seq`" (Infix 1) a b
639shDelta EqInt [x, y] = DOp "==" (Infix 4) x y
640shDelta Add [x, y] = DOp "+" (InfixL 6) x y
641shDelta Sub [x, y] = DOp "-" (InfixL 6) x y
642shDelta Mod [x, y] = DOp "`mod`" (InfixL 7) x y
643shDelta o xs = foldl DApp (text $ show o) xs
644
645---------------------------------------------------------------------------------------- examples
646
647--pPrint = putStrLn . ppShow
648
649pattern F = Con ("False", 0) []
650pattern T = Con ("True", 1) []
651pattern ENil = Con ("[]", 0) []
652pattern ECons a b = Con ("ECons", 1) [a, b]
653
654mkCase a b c = Case (a, map (length . snd) a) b c
655
656caseBool x f t = mkCase [("False", []), ("True", [])] x [f, t]
657caseList x n c = mkCase [("[]", []), ("ECons", ["c", "cs"])] x [n, c]
658
659id_ = Lam "x" (Var 0)
660
661if_ b t f = caseBool b f t
662
663not_ x = if_ x F T
664
665test = id_ `App` id_ `App` id_ `App` id_ `App` Int 13
666
667test' = id_ `App` (id_ `App` Int 14)
668
669foldr_ f e = Y "g" $ Lam "as" $ caseList (Var 0) (up' 2 e) (up' 4 f `App` Var 1 `App` (Var 3 `App` Var 0))
670
671filter_ p = foldr_ (Lam "y" $ Lam "ys" $ if_ (up' 2 p `App` Var 1) (ECons (Var 1) (Var 0)) (Var 0)) ENil
672
673and2 a b = if_ a b F
674
675and_ = foldr_ (Lam "a" $ Lam "b" $ and2 (Var 1) (Var 0)) T
676
677map_ f = foldr_ (Lam "z" $ Lam "zs" $ ECons (up' 2 f `App` Var 1) (Var 0)) ENil
678
679neq a b = not_ $ Op2 EqInt a b
680
681from_ = Y "from" $ Lam "n" $ ECons (Var 0) $ Var 1 `App` Op2 Add (Var 0) (Int 1)
682
683undefined_ = Y "undefined" $ Var 0
684
685idx = Y "idx" $ Lam "xs" $ Lam "n" $ caseList (Var 1) undefined_ $ if_ (Op2 EqInt (Var 2) $ Int 0) (Var 1) $ Var 4 `App` Var 0 `App` (Op2 Sub (Var 2) $ Int 1)
686
687t = idx `App` (from_ `App` Int 3) `App` Int 5
688
689takeWhile_ = Y "takeWhile" $ Lam "p" $ Lam "xs" $ caseList (Var 0) ENil $ if_ (Var 3 `App` Var 1) (ECons (Var 1) $ Var 4 `App` Var 3 `App` Var 0) ENil
690
691sum_ = foldr_ (Lam "a" $ Lam "b" $ Op2 Add (Var 1) (Var 0)) (Int 0)
692
693sum' = Y "sum" $ Lam "xs" $ caseList (Var 0) (Int 0) $ Op2 Add (Var 1) $ Var 3 `App` Var 0
694
695infixl 4 `sApp`
696
697sApp a b = Lam "s" (Seq (Var 0) (up' 1 a `App` Var 0)) `App` b
698
699{-
700accsum acc [] = acc
701accsum acc (x: xs) = let z = acc + x `seq` accsum z xs
702-}
703accsum = Y "accsum" $ Lam "acc" $ Lam "xs" $ caseList (Var 0) (Var 1) $ Var 4 `sApp` Op2 Add (Var 3) (Var 1) `App` Var 0
704
705fromTo = Y "fromTo" $ Lam "begin" $ Lam "end" $ ECons (Var 1) $ if_ (Op2 EqInt (Var 0) (Var 1)) ENil $ Var 2 `App` Op2 Add (Var 1) (Int 1) `App` Var 0
706
707from = Y "from" $ Lam "begin" $ ECons (Var 0) $ Var 1 `App` Op2 Add (Var 0) (Int 1)
708
709t' n = sum' `App` (fromTo `App` Int 0 `App` Int n)
710
711t'' n = accsum `App` Int 0 `App` (fromTo `App` Int 0 `App` Int n)
712
713t_opt n = Y "optsum" (Lam "i" $ if_ (Op2 EqInt (Int n) (Var 0)) (Var 0) (Op2 Add (Var 0) $ Var 1 `App` Op2 Add (Int 1) (Var 0))) `App` Int 0
714
715t_seqopt n = Y "seqoptsum" (Lam "i" $ Lam "j" $ if_ (Op2 EqInt (Int n) (Var 0)) (Op2 Add (Int n) (Var 1)) (Var 2 `sApp` Op2 Add (Var 0) (Var 1) `sApp` Op2 Add (Int 1) (Var 0))) `App` Int 0 `App` Int 0
716
717mod_ = Op2 Mod
718
719isqrt = Op1 ISqrt
720
721le = Op2 LessEq
722
723primes = Y "primes"
724 $ ECons (Int 2) $ ECons (Int 3)
725 $ filter_ (Lam "n" $ and_ `App` (map_ (Lam "p" $ neq (Int 0) $ mod_ (Var 1) (Var 0)) `App` (takeWhile_ `App` (Lam "x" $ le (Var 0) $ isqrt $ Var 1) `App` Var 1))) `App` (from `App` Int 5)
726-- primes = 2:3: filter (\n -> and $ map (\p -> n `mod` p /= 0) (takeWhile (\x -> x <= iSqrt n) primes)) (from 5)
727
728
729nthPrime n = idx `App` primes `App` (Int $ n-1)
730
731
732twice = Lam "f" $ Lam "x" $ Var 1 `App` (Var 1 `App` Var 0)
733twice2 = Lam "f" $ Lam "x" $ Var 1 `sApp` (Var 1 `App` Var 0)
734
735inc = Lam "n" $ Op2 Add (Int 1) (Var 0)
736
737test'' = Lam "f" (Int 4) `App` Int 3
738
739twiceTest n = (Lam "twice" $ (iterate (`App` Var 0) (Var 0) !! n) `App` inc `App` Int 0) `App` twice
740twiceTest2 n = (Lam "twice" $ (iterate (`App` Var 0) (Var 0) !! n) `App` inc `App` Int 0) `App` twice2
741
742tests =
743 [ t test (Int 13)
744 , t test' (Int 14)
745 , t test'' (Int 4)
746 , t (t' 10) (Int 55)
747 , t (t'' 10) (Int 55)
748 , t (nthPrime 6) (Int 13)
749 ]
750 where t = (,)
751
752evalTests = case [(a, b) | (hnf -> a, hnf -> b) <- tests, a /= b] of
753 [] -> True
754 (a, b): _ -> error $ "tests:\n" ++ ppShow a ++ "\n------ /= -------\n" ++ ppShow b
755
756
757main | evalTests = do
758 [s, read -> m, read -> m', read -> g3, n] <- getArgs
759 putStrLn . (++"\n---------------") . ppShow $
760 hnf_ (m, m', max 0 $ m' - g3, g3) $ prog s $ read n
761
762prog = \case
763 "prime" -> nthPrime
764 "seq" -> t''
765 "sum" -> t'
766 "opt" -> t_opt
767 "seqopt" -> t_seqopt
768 "twice" -> twiceTest
769 "twice2" -> twiceTest2
770