summaryrefslogtreecommitdiff
path: root/prototypes
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-05-19 18:48:06 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-05-19 18:48:06 +0200
commit158fca8352725e5db5d1bdc88e21b802091fbfc0 (patch)
tree551640ef4939fd547a7ca66f21e66176ef4fa369 /prototypes
parentf0180a74480031783dddbae6f000c87be43edda2 (diff)
inspector application
Diffstat (limited to 'prototypes')
-rw-r--r--prototypes/Inspector.hs118
-rw-r--r--prototypes/LamMachine.hs486
2 files changed, 323 insertions, 281 deletions
diff --git a/prototypes/Inspector.hs b/prototypes/Inspector.hs
new file mode 100644
index 00000000..60389b97
--- /dev/null
+++ b/prototypes/Inspector.hs
@@ -0,0 +1,118 @@
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
11import Data.List
12import Data.Maybe
13import Control.Arrow
14import Control.Category hiding ((.), id)
15import Control.Monad.Writer
16import Control.Monad.State
17import Control.Monad.Identity
18import Debug.Trace
19import System.Environment
20import System.IO
21
22import LambdaCube.Compiler.Pretty
23
24import LamMachine
25
26--------------------------------------------------------------------------------
27
28data StepTree a b
29 = NoStep
30-- | Ready a
31 | Step a b (StepTree a b)
32 | Steps a (StepTree a b) (StepTree a b)
33 deriving Show
34
35stepTree :: MSt -> StepTree StepTag MSt
36stepTree = fst . steps (runState $ return NoStep)
37 (\t c -> runState $ Step t <$> get <*> state c)
38 (\t c2 c1 -> runState $ Steps t <$> state c1 <*> state c2)
39
40stepList (initSt -> st) = ("Start", st): f (stepTree st)
41 where
42 f = \case
43 NoStep -> []
44 Step t x st -> (t, x): f st
45 Steps _ a b -> f a ++ f b
46
47
48data Command = UpArrow | DownArrow | LeftArrow | RightArrow
49 | IntArg Int | ProgramChange
50 deriving (Eq, Show)
51
52getCommand pr msg = do
53 putStr $ (if pr then "\n" else "\CR") ++ "-------------- " ++ msg ++ " --------> "
54 getChar >>= \case
55 '\ESC' -> getChar >>= \case
56 '[' -> getChar >>= \case
57 'A' -> c 4 >> ret UpArrow
58 'B' -> c 4 >> ret DownArrow
59 'C' -> c 4 >> ret LeftArrow
60 'D' -> c 4 >> ret RightArrow
61 c -> clear c
62 c -> clear c
63 d | '0' <= d && d <= '9' -> readI [d]
64 'n' -> ret ProgramChange
65 c -> clear c
66 where
67 ret a = {-putStr (" -- " ++ show a) >> -} return a
68 readI ds = getChar >>= \case
69 d | '0' <= d && d <= '9' -> readI $ d: ds
70 '\n' -> c 1 >> ret (IntArg $ read $ reverse ds)
71 c -> clear c
72 clear _ = getCommand True msg
73 c n = replicateM n $ putChar '\b'
74
75
76main = do
77 hSetBuffering stdin NoBuffering
78 hSetBuffering stdout NoBuffering
79 getArgs >>= \case
80 [b, n] ->
81 putStrLn $ ppShow $ hnf $ case b of
82 "lazy" -> t' $ read n
83 "seq" -> t'' $ read n
84 _ -> cycle True mempty
85 where
86 cycle (pr :: Bool) st = do
87 n <- getCommand pr $ message st
88 case (n, st) of
89 (DownArrow, st@(_, _:_:_)) -> cycle' $ goLeft st
90 (UpArrow, st@(_:_, _)) -> cycle' $ goRight st
91 (LeftArrow, st@(_, _:_:_)) -> cycle' $ iterate goLeft st !! 100
92 (RightArrow, st@(_:_, _)) -> cycle' $ iterate goRight st !! 100
93 (IntArg n, _) -> cycle' ([], stepList $ t' n)
94 (ProgramChange, _) -> cycle' ([], stepList $ t'' 1000)
95 _ -> cycle False st
96
97 cycle' st@(h, (_, x): _) = do
98 putStr $ "\n" ++ ppShow x
99 cycle True st
100 cycle' st = cycle True st
101
102 goLeft (xs, y: ys) = (y: xs, ys)
103 goLeft xs = xs
104 goRight (x: xs, ys) = (xs, x: ys)
105 goRight xs = xs
106
107 message ([], []) = ""
108 message (h, x) = show (length h) ++ " " ++ f x
109 where
110 f ((msg,_):_) = msg
111 f _ = ""
112
113mread :: Read a => String -> Maybe a
114mread s = case reads s of
115 [(a, "")] -> Just a
116 _ -> Nothing
117
118
diff --git a/prototypes/LamMachine.hs b/prototypes/LamMachine.hs
index f2f48b11..13fded03 100644
--- a/prototypes/LamMachine.hs
+++ b/prototypes/LamMachine.hs
@@ -3,56 +3,50 @@
3{-# LANGUAGE PatternGuards #-} 3{-# LANGUAGE PatternGuards #-}
4{-# LANGUAGE ViewPatterns #-} 4{-# LANGUAGE ViewPatterns #-}
5{-# LANGUAGE LambdaCase #-} 5{-# LANGUAGE LambdaCase #-}
6{-# LANGUAGE ScopedTypeVariables #-}
6{-# LANGUAGE TypeSynonymInstances #-} 7{-# LANGUAGE TypeSynonymInstances #-}
7{-# LANGUAGE FlexibleInstances #-} 8{-# LANGUAGE FlexibleInstances #-}
8{-# LANGUAGE GeneralizedNewtypeDeriving #-} 9{-# LANGUAGE GeneralizedNewtypeDeriving #-}
9 10
11module LamMachine where
12
10import Data.List 13import Data.List
11import Data.Maybe 14import Data.Maybe
12import Control.Arrow 15import Control.Arrow
13import Control.Category hiding ((.)) 16import Control.Category hiding ((.), id)
14import Control.Monad.Writer 17--import Debug.Trace
15import Control.Monad.Identity
16import Debug.Trace
17import System.Environment
18 18
19import LambdaCube.Compiler.Pretty 19import LambdaCube.Compiler.Pretty
20import LambdaCube.Compiler.DeBruijn hiding (up)
21 20
22----------------- 21--------------------------------------------------------------------- data structures
23 22
24-- expression
25data Exp_ 23data Exp_
26 = Var_ Int 24 = Var_
27 | Y_ Exp 25 | Int_ !Int -- ~ constructor with 0 args
28 | Int_ Int
29 | Lam_ Exp 26 | Lam_ Exp
30
31 | App_ Exp Exp
32 | Seq_ Exp Exp
33 | Con_ String Int [Exp] 27 | Con_ String Int [Exp]
34 | Case_ Exp [(String, Exp)] 28 | Case_ [String]{-for pretty print-} Exp [Exp] -- --> simplify
35 | Op1_ Op1 Exp 29 | Op1_ !Op1 Exp
36 | Op2_ Op2 Exp Exp 30 | Op2_ !Op2 Exp Exp
37 31
38data Op1 = Round 32data Op1 = YOp | Round
39 deriving (Eq, Show) 33 deriving (Eq, Show)
40 34
41data Op2 = Add | Sub | Mod | LessEq | EqInt 35data Op2 = AppOp | SeqOp | Add | Sub | Mod | LessEq | EqInt
42 deriving (Eq, Show) 36 deriving (Eq, Show)
43 37
44-- cached free variables set 38-- cached and compressed free variables set
45data Exp = Exp {dbUps :: [Up], _maxFreeVars :: Int, expexp :: Exp_ } 39type FV = [Int]
40
41data Exp = Exp !FV Exp_
46 42
47-- state of the machine 43-- state of the machine
48data MSt = MSt Exp 44data MSt = MSt Exp Exp [Exp]
49 Exp
50 [Exp]
51 45
52--------------------------------------------------------------------- toolbox: pretty print 46--------------------------------------------------------------------- toolbox: pretty print
53 47
54instance PShow Exp where 48instance PShow Exp where
55 pShow e@(Exp u t x) = case e of -- shUps' u t $ case Exp [] t x of 49 pShow e@(Exp _ x) = case e of -- shUps' u t $ case Exp [] t x of
56 Var i -> DVar i 50 Var i -> DVar i
57 Let a b -> shLet (pShow a) $ pShow b 51 Let a b -> shLet (pShow a) $ pShow b
58 App a b -> DApp (pShow a) (pShow b) 52 App a b -> DApp (pShow a) (pShow b)
@@ -65,8 +59,8 @@ instance PShow Exp where
65 Op2 Add x y -> DOp "+" (InfixL 6) (pShow x) (pShow y) 59 Op2 Add x y -> DOp "+" (InfixL 6) (pShow x) (pShow y)
66 Op2 o x y -> text (show o) `DApp` pShow x `DApp` pShow y 60 Op2 o x y -> text (show o) `DApp` pShow x `DApp` pShow y
67 Y e -> "Y" `DApp` pShow e 61 Y e -> "Y" `DApp` pShow e
68 Case e xs -> DPreOp (-20) (ComplexAtom "case" (-10) (pShow e) (SimpleAtom "of")) 62 Case cn e xs -> DPreOp (-20) (ComplexAtom "case" (-10) (pShow e) (SimpleAtom "of"))
69 $ foldr1 DSemi [DArr_ "->" (text a) (pShow b) | (a, b) <- xs] 63 $ foldr1 DSemi [DArr_ "->" (text a) (pShow b) | (a, b) <- zip cn xs]
70 64
71instance PShow MSt where 65instance PShow MSt where
72 pShow (MSt as b bs) = case foldl (flip (:)) (DBrace (pShow b): [pShow x | x <- bs]) $ [pShow as] of 66 pShow (MSt as b bs) = case foldl (flip (:)) (DBrace (pShow b): [pShow x | x <- bs]) $ [pShow as] of
@@ -88,282 +82,208 @@ showLet x (DLet' xs y) = DLet' (DSemi x xs) y
88showLet x y = DLet' x y 82showLet x y = DLet' x y
89 83
90 84
91--------------------------------------------------------------------- toolbox: free variables 85--------------------------------------------------------------------- pattern synonyms
86
87pattern Int i <- Exp _ (Int_ i)
88 where Int i = Exp [0] $ Int_ i
89pattern Op2 op a b <- Exp u (Op2_ op (upp u -> a) (upp u -> b))
90 where Op2 op a b = Exp s $ Op2_ op az bz where (s, az, bz) = delta2 a b
91pattern Op1 op a <- Exp u (Op1_ op (upp u -> a))
92 where Op1 op a = dup1 (Op1_ op) a
93pattern Var i <- Exp (varIndex -> i) Var_
94 where Var 0 = Exp [1] Var_
95 Var i = Exp [0, i, i+1] Var_
96pattern Lam i <- Exp u (Lam_ (upp ((+1) <$> u) -> i))
97 where Lam i = dupLam i
98pattern Con a b i <- Exp u (Con_ a b (map (upp u) -> i))
99 where Con a b [] = Exp [0] $ Con_ a b []
100 Con a b [x] = dup1 (Con_ a b . (:[])) x
101 Con a b [x, y] = Exp s $ Con_ a b [xz, yz] where (s, xz, yz) = delta2 x y
102 Con a b x = Exp s $ Con_ a b bz where (s, bz) = deltas x
103pattern Case a b c <- Exp u (Case_ a (upp u -> b) (map (upp u) -> c))
104 where Case cn a b = Exp s $ Case_ cn az bz where (s, az: bz) = deltas $ a: b
105
106pattern Let i x = App (Lam x) i
107pattern Y a = Op1 YOp a
108pattern App a b = Op2 AppOp a b
109pattern Seq a b = Op2 SeqOp a b
92 110
93maxFreeVars (Exp xs s _) = foldl' f s xs 111infixl 4 `App`
94 where 112
95 f m (Up l n) = n + m 113varIndex (_: i: _) = i
114varIndex _ = 0
96 115
97upVarIndex xs s = foldr f s xs 116dupLam (Exp vs ax) = Exp (f vs) $ Lam_ $ Exp (g vs) ax
98 where 117 where
99 f (Up l n) i 118 f (0: nus) = 0 .: map (+(-1)) nus
100 | l > i = i 119 f us = map (+(-1)) us
101 | otherwise = n + i
102 120
103upp u x = foldr up x u 121 g xs@(0: _) = [0, 1, altersum xs + 1]
122 g xs = [altersum xs]
104 123
105up' l n = up $ Up l n 124dup1 f (Exp ab x) = Exp ab $ f $ Exp [altersum ab] x
106 125
107up :: Up -> Exp -> Exp 126altersum [x] = x
108up (Up i 0) e = e 127altersum (a: b: cs) = a - b + altersum cs
109up u@(Up i num) e@(Exp us s x) = Exp (insertUp_ s u us) s x
110 128
111insertUp_ s u@(Up i _) [] 129initSt :: Exp -> MSt
112 | i >= s = [] 130initSt e = MSt (Var 0) e []
113 | otherwise = [u]
114insertUp_ s u@(Up l n) us_@(u'@(Up l' n'): us)
115 | l < l' = u: us_
116 | l >= l' && l <= l' + n' = Up l' (n' + n): us
117 | otherwise = u': insertUp_ s (Up (l-n') n) us
118 131
119-- TODO: remove if possible 132-- for statistics
120fvs (Exp us fv _) = gen 0 $ foldr f [fv] us where 133size :: MSt -> Int
121 f (Up l n) xs = l: l+n: map (+n) xs 134size (MSt xs _ ys) = length (getLets xs) + length ys
122 gen i (a: xs) = [i..a-1] ++ gen' xs 135 where
123 gen' [] = [] 136 getLets (Let x y) = x: getLets y
124 gen' (a: xs) = gen a xs 137 getLets x = [x]
125 138
126usedVar' i (Exp us fv _) = f i us where 139--------------------------------------------------------------------- toolbox: de bruijn index shifting
127 f i [] = i < fv
128 f i (Up l n: us)
129 | l > i = f i us
130 | i < l + n = False
131 | otherwise = f (n + i) us
132 140
133down i0 e0@(Exp us fv e) = f i0 us where 141upp [k] ys = ys
134 f i [] 142upp (x: y: xs) ys = upp xs (up x (y - x) ys)
135 | i < fv = Nothing
136 | otherwise = Just $ Exp [] fv e
137 f i (u@(Up j n): us)
138 | i < j = up' (j-1) n <$> f i us
139 | i >= j + n = up u <$> f (i-n) us
140 | otherwise = Just $ up' j (n-1) $ Exp us fv e
141 143
142upss u (Exp _ i e) = Exp u i e 144up i 0 e = e
145up i num (Exp us x) = Exp (f i (i + num) us) x
146 where
147 f l n [s]
148 | l >= s = [s]
149 | otherwise = [l, n, s+n-l]
150 f l n us_@(l': n': us)
151 | l < l' = l : n: map (+(n-l)) us_
152 | l <= n' = l': n' + n - l: map (+(n-l)) us
153 | otherwise = l': n': f l n us
154
155-- free variables set
156fvs (Exp us _) = gen 0 us where
157 gen i (a: xs) = [i..a-1] ++ gen' xs
158 gen' [] = []
159 gen' (a: xs) = gen a xs
143 160
144dup2 f ax bx = Exp s (maxFreeVars az `max` maxFreeVars bz) $ f az bz where 161(.:) :: Int -> [Int] -> [Int]
145 (s, [a', b']) = deltaUps [ax, bx] 162a .: (x: y: xs) | a == x = y: xs
146 az = upss a' ax 163a .: xs = a: xs
147 bz = upss b' bx
148 164
149dup1 :: (Exp -> Exp_) -> Exp -> Exp 165usedVar i (Exp us _) = f us where
150dup1 f (Exp a b x) = Exp a b $ f $ Exp [] b x 166 f [fv] = i < fv
167 f (l: n: us) = i < l || i >= n && f us
151 168
152dupCon f [] = Exp [] 0 $ f [] 169down i (Exp us e) = Exp <$> f us <*> pure e where
153dupCon f bx = Exp s (maximum $ maxFreeVars <$> bz) $ f bz where 170 f [fv]
154 (s, b') = deltaUps bx 171 | i < fv = Nothing
155 bz = zipWith upss b' bx 172 | otherwise = Just [fv]
173 f vs@(j: vs'@(n: us))
174 | i < j = Nothing
175 | i < n = Just $ j .: map (+(-1)) vs'
176 | otherwise = (j:) . (n .:) <$> f us
156 177
157dupCase f ax (unzip -> (ss, bx)) 178delta2 (Exp (add0 -> ua) a) (Exp (add0 -> ub) b) = (add0 s, Exp (dLadders 0 ua s) a, Exp (dLadders 0 ub s) b)
158 = Exp s (maxFreeVars az `max` maximum (maxFreeVars <$> bz)) $ f az $ zip ss bz
159 where 179 where
160 (s, a': b') = deltaUps $ ax: bx 180 s = iLadders ua ub
161 az = upss a' ax
162 bz = zipWith upss b' bx
163 181
164dupLam f e@(Exp a fv ax) = Exp (ff a) fv' $ f $ Exp (gg a) fv ax 182deltas [] = ([0], [])
183deltas es = (add0 s, [Exp (dLadders 0 u s) e | (u, Exp _ e) <- zip xs es])
165 where 184 where
166 fv' = max 0 $ fv - 1 185 xs = [add0 ue | Exp ue _ <- es]
167
168 gg (Up 0 n: _) = [Up 0 1]
169 gg _ = []
170
171 ff (Up 0 n: us) = insertUp_ fv' (Up 0 $ n - 1) $ incUp (-1) <$> us
172 ff us = incUp (-1) <$> us
173
174pattern Int i <- Exp _ _ (Int_ i)
175 where Int i = Exp [] 0 $ Int_ i
176pattern App a b <- Exp u _ (App_ (upp u -> a) (upp u -> b))
177 where App a b = dup2 App_ a b
178pattern Seq a b <- Exp u _ (Seq_ (upp u -> a) (upp u -> b))
179 where Seq a b = dup2 Seq_ a b
180pattern Op2 op a b <- Exp u _ (Op2_ op (upp u -> a) (upp u -> b))
181 where Op2 op a b = dup2 (Op2_ op) a b
182pattern Op1 op a <- Exp u _ (Op1_ op (upp u -> a))
183 where Op1 op a = dup1 (Op1_ op) a
184pattern Var i <- Exp u _ (Var_ (upVarIndex u -> i))
185 where Var 0 = Exp [] 1 $ Var_ 0
186 Var i = Exp [Up 0 i] 1 $ Var_ 0
187pattern Lam i <- Exp u _ (Lam_ (upp (incUp 1 <$> u) -> i))
188 where Lam i = dupLam Lam_ i
189pattern Y i <- Exp u _ (Y_ (upp u -> i))
190 where Y i = dup1 Y_ i
191pattern Con a b i <- Exp u _ (Con_ a b (map (upp u) -> i))
192 where Con a b i = dupCon (Con_ a b) i
193pattern Case a b <- Exp u _ (Case_ (upp u -> a) (map (second $ upp u) -> b))
194 where Case a b = dupCase Case_ a b
195
196pattern Let i x = App (Lam x) i
197 186
198infixl 4 `App` 187 s = foldr1 iLadders xs
199 188
200--------------------------------------------------------------------- toolbox: de bruijn index shifting 189iLadders :: [Int] -> [Int] -> [Int]
201 190iLadders x [] = x
202data Up = Up !Int{-level-} !Int{-num-} 191iLadders [] x = x
203 deriving (Eq, Show) 192iLadders x@(a: b: us) x'@(a': b': us')
204 193 | b <= a' = addL a b $ iLadders us x'
205incUp t (Up l n) = Up (l+t) n 194 | b' <= a = addL a' b' $ iLadders x us'
206 195 | otherwise = addL (min a a') c $ iLadders (addL c b us) (addL c b' us')
207showUps us n = foldr f (replicate n True) us where
208 f (Up l n) is = take l is ++ replicate n False ++ drop l is
209
210deltaUps = deltaUps_ . map crk
211 where 196 where
212 crk (Exp u e _) = (u, e) 197 c = min b b'
213 198
214 deltaUps_ (map toLadder -> xs) = (fromLadder $ negL s, [fromLadder $ dLadders 0 (negL u) (negL s) | u <- xs]) 199addL a b cs | a == b = cs
215 where 200addL a b (c: cs) | b == c = a: cs
216 s = foldr1 iLadders xs 201addL a b cs = a: b: cs
217
218 toLadder (us, k) = add1 0 $ f 0 us where
219 f s (Up l n: us) = (l+s): (l+s+n): f (s+n) us
220 f s [] = k+s: []
221
222 iLadders :: [Int] -> [Int] -> [Int]
223 iLadders x [] = x
224 iLadders [] x = x
225 iLadders x@(a: b: us) x'@(a': b': us')
226 | b <= a' = addL a b $ iLadders us x'
227 | b' <= a = addL a' b' $ iLadders x us'
228 | otherwise = addL (min a a') c $ iLadders (addL c b us) (addL c b' us')
229 where
230 c = min b b'
231
232 addL a b cs | a == b = cs
233 addL a b [] = a: b: []
234 addL a b (c: cs) | b == c = a: cs
235 | otherwise = a: b: c: cs
236
237 fromLadder :: [Int] -> [Up]
238 fromLadder = f 0 where
239 f s (a: b: cs) = Up (a-s) (b-a): f (s+b-a) cs
240 f s [] = []
241
242 add1 a (b: cs) | a == b = cs
243 | otherwise = a: b: cs
244
245 dLadders :: Int -> [Int] -> [Int] -> [Int]
246 dLadders s x [] = map (+(-s)) x
247 dLadders s [] x = [] -- impossible?
248 dLadders s x@(a: b: us) x'@(a': b': us')
249 | a' >= b = addL (a - s) (b - s) $ dLadders s us x'
250 | a' < a || b' < a' || b < a = error "dLadders"
251 | otherwise = addL (a - s) (a' - s) $ dLadders (s + sd) (addL c b us) (addL c b' us')
252 where
253 c = min b b'
254 sd = c - a'
255 202
256 negL [] = [] 203add0 [] = [0]
257 negL xs = init $ add1 0 xs 204add0 (0: cs) = cs
205add0 cs = 0: cs
258 206
259 207dLadders :: Int -> [Int] -> [Int] -> [Int]
260getLets (Let x y) = x: getLets y 208dLadders s [] x = [s]
261getLets x = [x] 209dLadders s x@(a: b: us) x'@(a': b': us')
210 | b' <= a = addL s (s + b' - a') $ dLadders (s + b' - a') x us'
211 | a' < a = addL s (s + a - a') $ dLadders (s + a - a') x (addL a b' us')
212 | a' == a = dLadders (s + b - a) us (addL b b' us')
262 213
263--------------------------- 214---------------------------
264 215
265tryRemoves xs = tryRemoves_ (Var <$> xs) 216tryRemoves xs = tryRemoves_ (Var <$> xs)
266tryRemoves_ [] dt = dt
267tryRemoves_ (Var i: vs) dt
268 | Just dt' <- tryRemove_ i dt
269 = tryRemoves_ (catMaybes $ down i <$> vs) dt'
270 | otherwise = tryRemoves_ vs dt
271 217
272tryRemove i x = fromMaybe x $ tryRemove_ i x 218tryRemoves_ [] dt = dt
219tryRemoves_ (Var i: vs) dt = maybe (tryRemoves_ vs dt) (tryRemoves_ $ catMaybes $ down i <$> vs) $ tryRemove_ i dt
273 220
274tryRemove_ i dt@(MSt xs e es) 221tryRemove_ i (MSt xs e es) = MSt <$> down (i+1) xs <*> down i e <*> downDown i es
275 | Just e' <- down i e
276 , Just xs' <- down (i+1) xs
277 , Just es' <- downDown i es
278 = Just $ MSt xs' e' es'
279 | otherwise
280 = Nothing
281 222
282downDown i [] = Just [] 223downDown i [] = Just []
283downDown 0 (_: xs) = Just xs 224downDown 0 (_: xs) = Just xs
284downDown i (x: xs) 225downDown i (x: xs) = (:) <$> down (i-1) x <*> downDown (i-1) xs
285 | Just x' <- down (i-1) x
286 , Just xs' <- downDown (i-1) xs
287 = Just $ x': xs'
288 | otherwise = Nothing
289 226
290--------------------------------------------------------------------- toolbox: machine monad 227----------------------------------------------------------- machine code begins here
291
292class Monad m => MachineMonad m where
293 traceStep :: String -> m ()
294 collectSizeStat :: Int -> m ()
295
296instance MachineMonad Identity where
297 traceStep _ = return ()
298 collectSizeStat _ = return ()
299
300instance MachineMonad IO where
301 traceStep s = return ()
302-- traceStep = putStrLn
303 collectSizeStat s = return ()
304
305instance MachineMonad (Writer [Int]) where
306 traceStep s = return ()
307 collectSizeStat s = tell [s]
308 228
309runMachineStat e = putStr $ unlines $ ppShow t: "--------": show (length w, w):[] 229justResult :: MSt -> MSt
310 where 230justResult = steps id (const ($)) (const (.))
311 (t, w) = runWriter (hnf e :: Writer [Int] MSt)
312 231
313runMachineIO e = do 232hnf = justResult . initSt
314 t <- hnf e :: IO MSt
315 putStr $ unlines $ ppShow t: []
316 233
317runMachinePure e = putStr $ unlines $ ppShow t: [] 234----------------
318 where
319 t = runIdentity $ hnf e
320 235
321----------------------------------------------------------- machine code begins here 236type GenSteps e
237 = (MSt -> e)
238 -- -> (StepTag -> e)
239 -> (StepTag -> (MSt -> e) -> MSt -> e)
240 -> (StepTag -> (MSt -> e) -> (MSt -> e) -> MSt -> e)
241 -> MSt -> e
322 242
323-- big step 243type StepTag = String
324step :: MachineMonad m => MSt -> m MSt
325step dt@(MSt t e vs) = case e of
326 244
327 Int{} -> return dt 245steps :: forall e . GenSteps e
246steps nostep {-ready-} bind cont dt@(MSt t e vs) = case e of
328 247
329 Lam{} -> return dt 248 Int{} -> nostep dt --ready "hnf int"
249 Lam{} -> nostep dt --ready "hnf lam"
330 250
331 Con cn i xs 251 Con cn i xs
332 | lz /= 0 -> return $ MSt (up' 1 lz t) (Con cn i xs') $ zs ++ vs -- share complex constructor arguments 252 | lz /= 0 -> step "copy con" $ MSt (up 1 lz t) (Con cn i xs') $ zs ++ vs -- share complex constructor arguments
333 | otherwise -> return dt 253 | otherwise -> nostep dt --ready "hnf con"
334 where 254 where
335 lz = length zs 255 lz = length zs
336 (xs', concat -> zs) = unzip $ f 0 xs 256 (xs', concat -> zs) = unzip $ f 0 xs
337 f i [] = [] 257 f i [] = []
338 f i (x: xs) | simple x = (up' 0 lz x, []): f i xs 258 f i (x: xs) | simple x = (up 0 lz x, []): f i xs
339 | otherwise = (Var i, [up' 0 (lz - i - 1) x]): f (i+1) xs 259 | otherwise = (Var i, [up 0 (lz - i - 1) x]): f (i+1) xs
340 260
341 Var i -> lookupHNF "var" (\e _ -> e) i dt 261 Var i -> lookupHNF_ rec "var" const i dt
342 262
343 Seq a b -> case a of 263 Seq a b -> case a of
344 Int{} -> stepMsg "seq" $ MSt t b vs 264 Int{} -> step "seq" $ MSt t b vs
345 Lam{} -> stepMsg "seq" $ tryRemoves (fvs a) $ MSt t b vs 265 Lam{} -> step "seq" $ tryRemoves (fvs a) $ MSt t b vs
346 Con{} -> stepMsg "seq" $ tryRemoves (fvs a) $ MSt t b vs 266 Con{} -> step "seq" $ tryRemoves (fvs a) $ MSt t b vs
347 Var i -> lookupHNF' "seqvar" (\e (Seq _ b) -> b) i dt 267 Var i -> lookupHNF' "seqvar" (\e (Seq _ b) -> b) i dt
348 _ -> stepMsg "seqexp" $ MSt (up' 1 1 t) (Seq (Var 0) $ up' 0 1 b) $ a: vs 268 _ -> step "seqexp" $ MSt (up 1 1 t) (Seq (Var 0) $ up 0 1 b) $ a: vs
349 269
350 -- TODO: handle recursive constants 270 -- TODO: handle recursive constants
351 Y (Lam x) -> stepMsg "Y" $ MSt (up' 1 1 t) x $ e: vs 271 Y (Lam x) -> step "Y" $ MSt (up 1 1 t) x $ e: vs
352 272
353 App a b -> case a of 273 App a b -> case a of
354 Lam x | usedVar' 0 x 274 Lam x | usedVar 0 x
355 -> stepMsg "app" $ MSt (up' 1 1 t) x $ b: vs 275 -> step "app" $ MSt (up 1 1 t) x $ b: vs
356 Lam x -> stepMsg "appdel" $ tryRemoves (fvs b) $ MSt t x vs 276 Lam x -> step "appdel" $ tryRemoves (fvs b) $ MSt t x vs
357 Var i -> lookupHNF' "appvar" (\e (App _ y) -> App e y) i dt 277 Var i -> lookupHNF' "appvar" (\e (App _ y) -> App e y) i dt
358 _ -> stepMsg "appexp" $ MSt (up' 1 1 t) (App (Var 0) $ up' 0 1 b) $ a: vs 278 _ -> step "appexp" $ MSt (up 1 1 t) (App (Var 0) $ up 0 1 b) $ a: vs
359 279
360 Case a cs -> case a of 280 Case cn a cs -> case a of
361 Con cn i es -> stepMsg "case" $ tryRemoves (nub $ foldMap (fvs . snd) $ delElem i cs) $ (MSt t (foldl App (snd $ cs !! i) es) vs) 281 Con cn i es -> step "case" $ tryRemoves (nub $ foldMap fvs $ delElem i cs) $ (MSt t (foldl App (cs !! i) es) vs)
362 Var i -> lookupHNF' "casevar" (\e (Case _ cs) -> Case e cs) i dt 282 Var i -> lookupHNF' "casevar" (\e (Case cn _ cs) -> Case cn e cs) i dt
363 _ -> stepMsg "caseexp" $ MSt (up' 1 1 t) (Case (Var 0) $ second (up' 0 1) <$> cs) $ a: vs 283 _ -> step "caseexp" $ MSt (up 1 1 t) (Case cn (Var 0) $ up 0 1 <$> cs) $ a: vs
364 284
365 Op2 op x y -> case (x, y) of 285 Op2 op x y -> case (x, y) of
366 (Int e, Int f) -> return $ MSt t (int op e f) vs 286 (Int e, Int f) -> step "op-done" $ MSt t (int op e f) vs
367 where 287 where
368 int Add a b = Int $ a + b 288 int Add a b = Int $ a + b
369 int Sub a b = Int $ a - b 289 int Sub a b = Int $ a - b
@@ -372,50 +292,56 @@ step dt@(MSt t e vs) = case e of
372 int EqInt a b = if a == b then T else F 292 int EqInt a b = if a == b then T else F
373 (Var i, _) -> lookupHNF' "op2-1var" (\e (Op2 op _ y) -> Op2 op e y) i dt 293 (Var i, _) -> lookupHNF' "op2-1var" (\e (Op2 op _ y) -> Op2 op e y) i dt
374 (_, Var i) -> lookupHNF' "op2-2var" (\e (Op2 op x _) -> Op2 op x e) i dt 294 (_, Var i) -> lookupHNF' "op2-2var" (\e (Op2 op x _) -> Op2 op x e) i dt
375 (Int{}, _) -> stepMsg "op2" $ MSt (up' 1 1 t) (Op2 op x (Var 0)) $ y: vs 295 (Int{}, _) -> step "op2" $ MSt (up 1 1 t) (Op2 op x (Var 0)) $ y: vs
376 (_, Int{}) -> stepMsg "op2" $ MSt (up' 1 1 t) (Op2 op (Var 0) y) $ x: vs 296 (_, Int{}) -> step "op2" $ MSt (up 1 1 t) (Op2 op (Var 0) y) $ x: vs
377 _ -> stepMsg "op2" $ MSt (up' 1 2 t) (Op2 op (Var 0) (Var 1)) $ x: y: vs 297 _ -> step "op2" $ MSt (up 1 2 t) (Op2 op (Var 0) (Var 1)) $ x: y: vs
298 where
299 rec = steps nostep bind cont
378 300
379stepMsg :: MachineMonad m => String -> MSt -> m MSt 301 step :: StepTag -> MSt -> e
380stepMsg msg dt = do 302 step t = bind t rec
381 traceStep $ ((msg ++ "\n") ++) $ show $ pShow dt
382 collectSizeStat $ size dt
383 step dt
384 303
385hnf e = stepMsg "hnf" $ MSt (Var 0) e [] 304 hnf :: (MSt -> e) -> MSt -> e
305 hnf f = cont "hnf" f rec
386 306
387size (MSt xs _ ys) = length (getLets xs) + length ys 307 -- lookup var in head normal form
308 lookupHNF_ :: (MSt -> e) -> StepTag -> (Exp -> Exp -> Exp) -> Int -> MSt -> e
309 lookupHNF_ end msg f i dt = bind "shiftL" (hnf shiftLookup) $ iterate shiftL dt !! (i+1)
310 where
311 shiftLookup dt@(MSt _ e _)
312 = case iterate shiftR dt !! (i+1) of
313 MSt xs z es -> bind "shiftR" (tryRemove i) $ MSt xs (f (up 0 (i+1) e) z) es
388 314
389shiftL (MSt xs x (e: es)) = MSt (Let x xs) e es 315 shiftL (MSt xs x (e: es)) = MSt (Let x xs) e es
390shiftR (MSt (Let x xs) e es) = MSt xs x $ e: es
391 316
392shiftLookup f n dt@(MSt _ e _) = repl $ iterate shiftR dt !! (n+1) where 317 shiftR (MSt (Let x xs) e es) = MSt xs x $ e: es
393 repl (MSt xs z es) = MSt xs (f (up' 0 (n+1) e) z) es
394 318
395-- lookup var in head normal form 319 tryRemove i st = maybe (end st) (bind "remove" end) $ tryRemove_ i st
396lookupHNF msg f i dt = tryRemove i . shiftLookup f i <$> stepMsg msg (iterate shiftL dt !! (i+1))
397 320
398-- lookup & step 321 -- lookup & step
399lookupHNF' msg f i dt = stepMsg ("C " ++ msg) =<< lookupHNF msg f i dt 322 lookupHNF' :: StepTag -> (Exp -> Exp -> Exp) -> Int -> MSt -> e
323 lookupHNF' msg f i dt = lookupHNF_ rec msg f i dt
400 324
401simple = \case 325 simple = \case
402 Var{} -> True 326 Var{} -> True
403 Int{} -> True 327 Int{} -> True
404 _ -> False 328 _ -> False
405 329
406delElem i xs = take i xs ++ drop (i+1) xs 330 delElem i xs = take i xs ++ drop (i+1) xs
407 331
408---------------------------------------------------------------------------------------- examples 332---------------------------------------------------------------------------------------- examples
409 333
410id_ = Lam (Var 0) 334runMachinePure = putStrLn . ppShow . hnf
411 335
412pattern F = Con "False" 0 [] 336pattern F = Con "False" 0 []
413pattern T = Con "True" 1 [] 337pattern T = Con "True" 1 []
414pattern Nil = Con "[]" 0 [] 338pattern Nil = Con "[]" 0 []
415pattern Cons a b = Con "Cons" 1 [a, b] 339pattern Cons a b = Con "Cons" 1 [a, b]
416 340
417caseBool x f t = Case x [("False", f), ("True", t)] 341caseBool x f t = Case ["False", "True"] x [f, t]
418caseList x n c = Case x [("[]", n), ("Cons", c)] 342caseList x n c = Case ["[]", "Cons"] x [n, c]
343
344id_ = Lam (Var 0)
419 345
420if_ b t f = caseBool b f t 346if_ b t f = caseBool b f t
421 347
@@ -425,7 +351,7 @@ test = runMachinePure (id_ `App` id_ `App` id_ `App` id_ `App` Con "()" 0 [])
425 351
426test' = runMachinePure (id_ `App` (id_ `App` Con "()" 0 [])) 352test' = runMachinePure (id_ `App` (id_ `App` Con "()" 0 []))
427 353
428foldr_ f e = Y $ Lam $ Lam $ caseList (Var 0) (up' 0 2 e) (Lam $ Lam $ up' 0 4 f `App` Var 1 `App` (Var 3 `App` Var 0)) 354foldr_ f e = Y $ Lam $ Lam $ caseList (Var 0) (up 0 2 e) (Lam $ Lam $ up 0 4 f `App` Var 1 `App` (Var 3 `App` Var 0))
429 355
430filter_ p = foldr_ (Lam $ Lam $ if_ (p `App` Var 1) (Cons (Var 1) (Var 0)) (Var 0)) Nil 356filter_ p = foldr_ (Lam $ Lam $ if_ (p `App` Var 1) (Cons (Var 1) (Var 0)) (Var 0)) Nil
431 357
@@ -465,12 +391,6 @@ t' n = sum' `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 Les
465 391
466t'' n = accsum `App` Int 0 `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 LessEq x $ Int 3) (from_ `App` Int 0) 392t'' n = accsum `App` Int 0 `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 LessEq x $ Int 3) (from_ `App` Int 0)
467 393
468main = do
469 [b, n] <- getArgs
470 runMachineIO $ case b of
471 "lazy" -> t' $ read n
472 "seq" -> t'' $ read n
473
474{- TODO 394{- TODO
475 395
476primes :: [Int] 396primes :: [Int]
@@ -505,6 +425,9 @@ mkUps = f 0
505 f i [] = [] 425 f i [] = []
506 f i (x: xs) = insertUp (Up (x-i) 1) $ f (i+1) xs 426 f i (x: xs) = insertUp (Up (x-i) 1) $ f (i+1) xs
507 427
428showUps us n = foldr f (replicate n True) us where
429 f (Up l n) is = take l is ++ replicate n False ++ drop l is
430
508deltaUps_ (map $ uncurry showUps -> us) = (mkUps $ back s, [mkUps $ u `diffUps` s | u <- us]) 431deltaUps_ (map $ uncurry showUps -> us) = (mkUps $ back s, [mkUps $ u `diffUps` s | u <- us])
509 where 432 where
510 s = foldr1 sect $ us 433 s = foldr1 sect $ us
@@ -520,8 +443,10 @@ diffUpsTest xs
520 443
521diffUpsTest' = diffUpsTest [x,y] --diffUpsTest x y 444diffUpsTest' = diffUpsTest [x,y] --diffUpsTest x y
522 445
523x = ([Up 1 2, Up 3 4, Up 8 2], 20) 446--x = ([Up 8 2], 200)
524y = ([Up 2 2, Up 5 1, Up 6 2, Up 7 2], 18) 447--y = ([], 28)
448x = ([Up 1 2, Up 3 4, Up 8 2], 200)
449y = ([Up 2 2, Up 5 1, Up 6 2, Up 7 2], 28)
525 450
526-- TODO: remove 451-- TODO: remove
527insertUp (Up l 0) us = us 452insertUp (Up l 0) us = us
@@ -530,6 +455,5 @@ insertUp u@(Up l n) us_@(u'@(Up l' n'): us)
530 | l < l' = u: us_ 455 | l < l' = u: us_
531 | l >= l' && l <= l' + n' = Up l' (n' + n): us 456 | l >= l' && l <= l' + n' = Up l' (n' + n): us
532 | otherwise = u': insertUp (Up (l-n') n) us 457 | otherwise = u': insertUp (Up (l-n') n) us
533
534-} 458-}
535 459