summaryrefslogtreecommitdiff
path: root/prototypes/LamMachine.hs
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-05-16 04:33:01 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-05-16 04:33:01 +0200
commit503ff0250240f487d7562ec1c83e4c3251479f0b (patch)
tree947dd8e01b54550cbb7b08b09e930c19af1f719c /prototypes/LamMachine.hs
parent7a8eabd1a066579d4dcb35f5950f87bad5667b37 (diff)
LamMachine
Diffstat (limited to 'prototypes/LamMachine.hs')
-rw-r--r--prototypes/LamMachine.hs402
1 files changed, 402 insertions, 0 deletions
diff --git a/prototypes/LamMachine.hs b/prototypes/LamMachine.hs
new file mode 100644
index 00000000..3bfbe104
--- /dev/null
+++ b/prototypes/LamMachine.hs
@@ -0,0 +1,402 @@
1{-# LANGUAGE OverloadedStrings #-}
2{-# LANGUAGE PatternSynonyms #-}
3{-# LANGUAGE PatternGuards #-}
4{-# LANGUAGE ViewPatterns #-}
5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE TypeSynonymInstances #-}
7{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9
10import Data.List
11import Data.Maybe
12import Control.Arrow
13import Control.Category hiding ((.))
14import Control.Monad.Writer
15import Control.Monad.Identity
16import Debug.Trace
17import System.Environment
18
19import LambdaCube.Compiler.Pretty
20import LambdaCube.Compiler.DeBruijn hiding (up)
21
22-----------------
23
24-- expression
25data Exp_
26 = Lam_ Exp
27 | Var_ Int
28 | App_ Exp Exp
29 | Seq_ Exp Exp
30 | Con_ String Int [Exp]
31 | Case_ Exp [(String, Exp)]
32 | Int_ Int
33 | Op1_ Op1 Exp
34 | Op2_ Op2 Exp Exp
35 | Y_ Exp
36 deriving (Eq)
37
38data Op1 = Round
39 deriving (Eq, Show)
40
41data Op2 = Add | Sub | Mod | LessEq | EqInt
42 deriving (Eq, Show)
43
44-- cached free variables set
45data Exp = Exp FreeVars Exp_
46
47-- state of the machine
48data MSt = MSt [(FreeVars, Exp)] -- TODO: use finger tree instead of list
49 Exp
50 [Exp] -- TODO: use finger tree instead of list
51
52--------------------------------------------------------------------- toolbox: pretty print
53
54instance PShow Exp where
55 pShow = \case
56 Var i -> DVar i
57 App a b -> DApp (pShow a) (pShow b)
58 Seq a b -> DOp "`seq`" (Infix 1) (pShow a) (pShow b)
59 Lam e -> shLam_ True $ pShow e
60 Con s i xs -> foldl DApp (text s) $ pShow <$> xs
61 Int i -> pShow i
62 Op1 o x -> text (show o) `DApp` pShow x
63 Op2 EqInt x y -> DOp "==" (Infix 4) (pShow x) (pShow y)
64 Op2 Add x y -> DOp "+" (InfixL 6) (pShow x) (pShow y)
65 Op2 o x y -> text (show o) `DApp` pShow x `DApp` pShow y
66 Y e -> "Y" `DApp` pShow e
67 Case e xs -> DPreOp (-20) (ComplexAtom "case" (-10) (pShow e) (SimpleAtom "of")) $ foldr1 DSemi [DArr_ "->" (text a) (pShow b) | (a, b) <- xs]
68
69shLam_ usedVar b = DFreshName usedVar $ showLam (DVar 0) b
70
71showLam x (DFreshName u d) = DFreshName u $ showLam (DUp 0 x) d
72showLam x (DLam xs y) = DLam (DSep (InfixR 11) x xs) y
73showLam x y = DLam x y
74
75shLet i a b = DLet' (DLet "=" (blue $ shVar i) $ DUp i a) (DUp i b)
76
77showLet x (DFreshName u d) = DFreshName u $ showLet (DUp 0 x) d
78showLet x (DLet' xs y) = DLet' (DSemi x xs) y
79showLet x y = DLet' x y
80
81shLet_ a b = DFreshName True $ showLet (DLet "=" (shVar 0) $ DUp 0 a) b
82
83instance PShow MSt where
84 pShow (MSt as b bs) = case foldl (flip (:)) (DBrace (pShow b): [pShow x | x <- bs]) [pShow x | EPP x <- as] of
85 x: xs -> foldl (flip shLet_) x xs
86
87
88--------------------------------------------------------------------- toolbox: free variables
89
90instance Eq Exp where Exp _ a == Exp _ b = a == b
91
92instance HasFreeVars Exp where
93 getFreeVars (Exp fv _) = fv
94
95pattern Int i <- Exp _ (Int_ i)
96 where Int i = Exp mempty $ Int_ i
97pattern App a b <- Exp _ (App_ a b)
98 where App a b = Exp (getFreeVars a <> getFreeVars b) $ App_ a b
99pattern Seq a b <- Exp _ (Seq_ a b)
100 where Seq a b = Exp (getFreeVars a <> getFreeVars b) $ Seq_ a b
101pattern Op2 op a b <- Exp _ (Op2_ op a b)
102 where Op2 op a b = Exp (getFreeVars a <> getFreeVars b) $ Op2_ op a b
103pattern Op1 op a <- Exp _ (Op1_ op a)
104 where Op1 op a = Exp (getFreeVars a) $ Op1_ op a
105pattern Var i <- Exp _ (Var_ i)
106 where Var i = Exp (freeVar i) $ Var_ i
107pattern Lam i <- Exp _ (Lam_ i)
108 where Lam i = Exp (shiftFreeVars (-1) $ getFreeVars i) $ Lam_ i
109pattern Y i <- Exp _ (Y_ i)
110 where Y i = Exp (getFreeVars i) $ Y_ i
111pattern Con a b i <- Exp _ (Con_ a b i)
112 where Con a b i = Exp (foldMap getFreeVars i) $ Con_ a b i
113pattern Case a b <- Exp _ (Case_ a b)
114 where Case a b = Exp (getFreeVars a <> foldMap (getFreeVars . snd) b) $ Case_ a b
115
116infixl 4 `App`
117
118--------------------------------------------------------------------- toolbox: de bruijn index shifting
119-- TODO: speedup these with reification
120
121data Up = Up !Int{-level-} !Int{-num-}
122
123up :: Up -> Exp -> Exp
124up (Up i num) e = f i e where
125 f i e@(Exp s x)
126 | dbGE i s = e
127 | otherwise = Exp (rearrangeFreeVars (RFUp num) i s) $ case x of
128 App_ a b -> App_ (f i a) (f i b)
129 Seq_ a b -> Seq_ (f i a) (f i b)
130 Con_ cn s xs -> Con_ cn s (f i <$> xs)
131 Case_ s xs -> Case_ (f i s) (second (f i) <$> xs)
132 Lam_ e -> Lam_ (f (i+1) e)
133 Var_ k | i <= k -> Var_ (k + num)
134 | otherwise -> Var_ k
135 x@Int_{} -> x
136 Y_ a -> Y_ $ f i a
137 Op1_ op a -> Op1_ op (f i a)
138 Op2_ op a b -> Op2_ op (f i a) (f i b)
139
140
141ups' a b = ups $ Up a b
142
143ups :: Up -> [(FreeVars, Exp)] -> [(FreeVars, Exp)]
144ups l [] = []
145ups l@(Up i _) xs@((s, e): es)
146 | dbGE i s = xs
147 | otherwise = eP (up l e) $ ups (incUp 1 l) es
148
149incUp t (Up l n) = Up (l+t) n
150
151eP x [] = [(getFreeVars x, x)]
152eP x xs@((s, _):_) = (getFreeVars x <> lowerFreeVars s, x): xs
153
154pattern EPP x <- (_, x)
155
156---------------------------
157
158down i x | usedVar i x = Nothing
159down i x = Just $ down_ i x
160
161down_ i e@(Exp s x)
162 | dbGE i s = e
163 | otherwise = Exp (delVar i s) $ case x of
164 Var_ j | j > i -> Var_ $ j - 1
165 | otherwise -> Var_ j
166 Lam_ e -> Lam_ $ down_ (i+1) e
167 Y_ e -> Y_ $ down_ i e
168 App_ a b -> App_ (down_ i a) (down_ i b)
169 Seq_ a b -> Seq_ (down_ i a) (down_ i b)
170 Con_ s k es -> Con_ s k $ (down_ i <$> es)
171 Case_ e es -> Case_ (down_ i e) $ map (second $ down_ i) es
172 Int_ i -> Int_ i
173 Op1_ o e -> Op1_ o $ down_ i e
174 Op2_ o e f -> Op2_ o (down_ i e) (down_ i f)
175
176tryRemoves xs = tryRemoves_ (Var <$> freeVars xs)
177tryRemoves_ [] dt = dt
178tryRemoves_ (Var i: vs) dt
179 | Just dt' <- tryRemove_ i dt
180 = tryRemoves_ (catMaybes $ down i <$> vs) dt'
181 | otherwise = tryRemoves_ vs dt
182
183tryRemove i x = fromMaybe x $ tryRemove_ i x
184
185tryRemove_ i dt@(MSt xs e es)
186 | Just e' <- down i e
187 , Just xs' <- downUp i xs
188 , Just es' <- downDown i es
189 = Just $ MSt xs' e' es'
190 | otherwise
191 = Nothing
192
193downEP i ( x) = down i x
194downEP_ i (s, x) = (delVar i s, down_ i x)
195
196downUp i [] = Just []
197downUp i x@((s, _): _)
198 | usedVar (i+1) s = Nothing
199 | otherwise = Just $ downUp_ i x
200
201downUp_ i [] = []
202downUp_ i (x: xs)
203 | x' <- downEP_ (i+1) x
204 , xs' <- downUp_ (i+1) xs
205 = x': xs'
206
207downDown i [] = Just []
208downDown 0 (_: xs) = Just xs
209downDown i (x: xs)
210 | Just x' <- downEP (i-1) x
211 , Just xs' <- downDown (i-1) xs
212 = Just $ x': xs'
213 | otherwise = Nothing
214
215--------------------------------------------------------------------- toolbox: machine monad
216
217class Monad m => MachineMonad m where
218 traceStep :: String -> m ()
219 collectSizeStat :: Int -> m ()
220
221instance MachineMonad Identity where
222 traceStep _ = return ()
223 collectSizeStat _ = return ()
224
225instance MachineMonad IO where
226 traceStep s = return ()
227-- traceStep = putStrLn
228 collectSizeStat s = return ()
229
230instance MachineMonad (Writer [Int]) where
231 traceStep s = return ()
232 collectSizeStat s = tell [s]
233
234runMachineStat e = putStr $ unlines $ ppShow t: "--------": show (length w, w):[]
235 where
236 (t, w) = runWriter (hnf e :: Writer [Int] MSt)
237
238runMachineIO e = do
239 t <- hnf e :: IO MSt
240 putStr $ unlines $ ppShow t: []
241
242runMachinePure e = putStr $ unlines $ ppShow t: []
243 where
244 t = runIdentity $ hnf e
245
246----------------------------------------------------------- machine code begins here
247
248-- big step
249step :: MachineMonad m => MSt -> m MSt
250step dt@(MSt t e vs) = case e of
251
252 Int{} -> return dt
253
254 Lam{} -> return dt
255
256 Con cn i xs
257 | lz /= 0 -> return $ MSt (ups' 1 lz t) (Con cn i xs') $ zs ++ vs -- share complex constructor arguments
258 | otherwise -> return dt
259 where
260 lz = length zs
261 (xs', concat -> zs) = unzip $ f 0 xs
262 f i [] = []
263 f i (x: xs) | simple x = (up (Up 0 lz) x, []): f i xs
264 | otherwise = (Var i, [up (Up 0 (lz - i - 1)) x]): f (i+1) xs
265
266 Var i -> lookupHNF "var" (\e (Var i) -> e) i dt
267
268 Seq Int{} b -> stepMsg "seq" $ MSt t b vs
269 Seq a@Lam{} b -> stepMsg "seq" $ tryRemoves (getFreeVars a) $ MSt t b vs
270 Seq a@Con{} b -> stepMsg "seq" $ tryRemoves (getFreeVars a) $ MSt t b vs
271 Seq (Var i) _ -> lookupHNF' "seqvar" (\e (Seq _ b) -> b) i dt
272 Seq a b -> stepMsg "seqexp" $ MSt (ups' 1 1 t) (Seq (Var 0) $ up (Up 0 1) b) $ a: vs
273
274 -- TODO: handle recursive constants
275 Y (Lam x) -> stepMsg "Y" $ MSt (ups' 1 1 t) x $ e: vs
276
277 App (Lam x) b | usedVar 0 x
278 -> stepMsg "app" $ MSt (ups' 1 1 t) x $ b: vs
279 App (Lam x) b -> stepMsg "appdel" $ tryRemoves (getFreeVars b) $ MSt t x vs
280 App (Var i) _ -> lookupHNF' "appvar" (\e (App _ y) -> App e y) i dt
281 App a b -> stepMsg "appexp" $ MSt (ups' 1 1 t) (App (Var 0) $ up (Up 0 1) b) $ a: vs
282
283 Case (Con cn i es) cs -> stepMsg "case" $ tryRemoves (foldMap (getFreeVars . snd) $ delElem i cs) $ (MSt t (foldl App (snd $ cs !! i) es) vs)
284 Case (Var i) _ -> lookupHNF' "casevar" (\e (Case _ cs) -> Case e cs) i dt
285 Case v cs -> stepMsg "caseexp" $ MSt (ups' 1 1 t) (Case (Var 0) $ second (up (Up 0 1)) <$> cs) $ v: vs
286
287 Op2 op (Int e) (Int f) -> return $ MSt t (int op e f) vs
288 where
289 int Add a b = Int $ a + b
290 int Sub a b = Int $ a - b
291 int Mod a b = Int $ a `mod` b
292 int LessEq a b = if a <= b then T else F
293 int EqInt a b = if a == b then T else F
294 Op2 op (Var i) _ -> lookupHNF' "op2-1var" (\e (Op2 op _ y) -> Op2 op e y) i dt
295 Op2 op _ (Var i) -> lookupHNF' "op2-2var" (\e (Op2 op x _) -> Op2 op x e) i dt
296 Op2 op x@Int{} y -> stepMsg "op2" $ MSt (ups' 1 1 t) (Op2 op x (Var 0)) $ y: vs
297 Op2 op y x@Int{} -> stepMsg "op2" $ MSt (ups' 1 1 t) (Op2 op (Var 0) x) $ y: vs
298 Op2 op x y -> stepMsg "op2" $ MSt (ups' 1 2 t) (Op2 op (Var 0) (Var 1)) $ x: y: vs
299
300stepMsg :: MachineMonad m => String -> MSt -> m MSt
301stepMsg msg dt = do
302 traceStep $ ((msg ++ "\n") ++) $ show $ pShow dt
303 collectSizeStat $ size dt
304 step dt
305
306hnf e = stepMsg "hnf" $ MSt [] e []
307
308size (MSt xs _ ys) = length xs + length ys
309
310shiftL (MSt xs x (e: es)) = MSt (eP x xs) e es
311shiftR (MSt (EPP x: xs) e es) = MSt xs x $ e: es
312
313shiftLookup f n dt@(MSt _ e _) = repl $ iterate shiftR dt !! (n+1) where
314 repl (MSt xs z es) = MSt xs (f (up (Up 0 (n+1)) e) z) es
315
316-- lookup var in head normal form
317lookupHNF msg f i dt = tryRemove i . shiftLookup f i <$> stepMsg msg (iterate shiftL dt !! (i+1))
318
319-- lookup & step
320lookupHNF' msg f i dt = stepMsg ("C " ++ msg) =<< lookupHNF msg f i dt
321
322simple = \case
323 Var{} -> True
324 Int{} -> True
325 _ -> False
326
327delElem i xs = take i xs ++ drop (i+1) xs
328
329---------------------------------------------------------------------------------------- examples
330
331id_ = Lam (Var 0)
332
333pattern F = Con "False" 0 []
334pattern T = Con "True" 1 []
335pattern Nil = Con "[]" 0 []
336pattern Cons a b = Con "Cons" 1 [a, b]
337
338caseBool x f t = Case x [("False", f), ("True", t)]
339caseList x n c = Case x [("[]", n), ("Cons", c)]
340
341if_ b t f = caseBool b f t
342
343not_ x = caseBool x T F
344
345test = runMachinePure (id_ `App` id_ `App` id_ `App` id_ `App` Con "()" 0 [])
346
347test' = runMachinePure (id_ `App` (id_ `App` Con "()" 0 []))
348
349foldr_ f e = Y $ Lam $ Lam $ caseList (Var 0) (up (Up 0 2) e) (Lam $ Lam $ up (Up 0 4) f `App` Var 1 `App` (Var 3 `App` Var 0))
350
351filter_ p = foldr_ (Lam $ Lam $ if_ (p `App` Var 1) (Cons (Var 1) (Var 0)) (Var 0)) Nil
352
353and2 a b = if_ a b F
354
355and_ = foldr_ (Lam $ Lam $ and2 (Var 1) (Var 0)) T
356
357map_ f = foldr_ (Lam $ Lam $ Cons (f (Var 1)) (Var 0)) Nil
358
359neq a b = not_ $ Op2 EqInt a b
360
361from_ = Y $ Lam $ Lam $ Cons (Var 0) $ Var 1 `App` Op2 Add (Var 0) (Int 1)
362
363idx xs n = caseList xs undefined $ Lam $ Lam $ if_ (Op2 EqInt n $ Int 0) (Var 1) $ idx (Var 0) (Op2 Sub n $ Int 1)
364
365t = runMachinePure $ idx (from_ `App` Int 3) (Int 5)
366
367takeWhile_ p xs = caseList xs Nil $ Lam $ Lam $ if_ (p (Var 1)) (Cons (Var 1) $ takeWhile_ p (Var 0)) Nil
368
369sum_ = foldr_ (Lam $ Lam $ Op2 Add (Var 1) (Var 0)) (Int 0)
370
371sum' = Y $ Lam $ Lam $ caseList (Var 0) (Int 0) $ Lam $ Lam $ Op2 Add (Var 1) $ Var 3 `App` Var 0
372
373infixl 4 `sApp`
374
375sApp a b = Seq b (App a b)
376
377{-
378accsum acc [] = acc
379accsum acc (x: xs) = let z = acc + x `seq` accsum z xs
380-}
381accsum = Y $ Lam $ Lam $ Lam $ caseList (Var 0) (Var 1) $ Lam $ Lam $ Var 4 `sApp` Op2 Add (Var 3) (Var 1) `App` Var 0
382
383fromTo = Y $ Lam $ Lam $ Lam $ Cons (Var 1) $ if_ (Op2 EqInt (Var 0) (Var 1)) Nil $ Var 2 `App` Op2 Add (Var 1) (Int 1) `App` Var 0
384
385t' n = sum' `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 LessEq x $ Int 3) (from_ `App` Int 0)
386
387t'' n = accsum `App` Int 0 `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 LessEq x $ Int 3) (from_ `App` Int 0)
388
389main = do
390 [b, n] <- getArgs
391 runMachineIO $ case b of
392 "lazy" -> t' $ read n
393 "seq" -> t'' $ read n
394
395{- TODO
396
397primes :: [Int]
398primes = 2:3: filter (\n -> and $ map (\p -> n `mod` p /= 0) (takeWhile (\x -> x <= iSqrt n) primes)) (from 5)
399
400
401main = primes !! 3000
402-}