diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-05-19 18:48:06 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-05-19 18:48:06 +0200 |
commit | 158fca8352725e5db5d1bdc88e21b802091fbfc0 (patch) | |
tree | 551640ef4939fd547a7ca66f21e66176ef4fa369 /prototypes | |
parent | f0180a74480031783dddbae6f000c87be43edda2 (diff) |
inspector application
Diffstat (limited to 'prototypes')
-rw-r--r-- | prototypes/Inspector.hs | 118 | ||||
-rw-r--r-- | prototypes/LamMachine.hs | 486 |
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 | |||
11 | import Data.List | ||
12 | import Data.Maybe | ||
13 | import Control.Arrow | ||
14 | import Control.Category hiding ((.), id) | ||
15 | import Control.Monad.Writer | ||
16 | import Control.Monad.State | ||
17 | import Control.Monad.Identity | ||
18 | import Debug.Trace | ||
19 | import System.Environment | ||
20 | import System.IO | ||
21 | |||
22 | import LambdaCube.Compiler.Pretty | ||
23 | |||
24 | import LamMachine | ||
25 | |||
26 | -------------------------------------------------------------------------------- | ||
27 | |||
28 | data 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 | |||
35 | stepTree :: MSt -> StepTree StepTag MSt | ||
36 | stepTree = 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 | |||
40 | stepList (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 | |||
48 | data Command = UpArrow | DownArrow | LeftArrow | RightArrow | ||
49 | | IntArg Int | ProgramChange | ||
50 | deriving (Eq, Show) | ||
51 | |||
52 | getCommand 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 | |||
76 | main = 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 | |||
113 | mread :: Read a => String -> Maybe a | ||
114 | mread 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 | ||
11 | module LamMachine where | ||
12 | |||
10 | import Data.List | 13 | import Data.List |
11 | import Data.Maybe | 14 | import Data.Maybe |
12 | import Control.Arrow | 15 | import Control.Arrow |
13 | import Control.Category hiding ((.)) | 16 | import Control.Category hiding ((.), id) |
14 | import Control.Monad.Writer | 17 | --import Debug.Trace |
15 | import Control.Monad.Identity | ||
16 | import Debug.Trace | ||
17 | import System.Environment | ||
18 | 18 | ||
19 | import LambdaCube.Compiler.Pretty | 19 | import LambdaCube.Compiler.Pretty |
20 | import LambdaCube.Compiler.DeBruijn hiding (up) | ||
21 | 20 | ||
22 | ----------------- | 21 | --------------------------------------------------------------------- data structures |
23 | 22 | ||
24 | -- expression | ||
25 | data Exp_ | 23 | data 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 | ||
38 | data Op1 = Round | 32 | data Op1 = YOp | Round |
39 | deriving (Eq, Show) | 33 | deriving (Eq, Show) |
40 | 34 | ||
41 | data Op2 = Add | Sub | Mod | LessEq | EqInt | 35 | data 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 |
45 | data Exp = Exp {dbUps :: [Up], _maxFreeVars :: Int, expexp :: Exp_ } | 39 | type FV = [Int] |
40 | |||
41 | data Exp = Exp !FV Exp_ | ||
46 | 42 | ||
47 | -- state of the machine | 43 | -- state of the machine |
48 | data MSt = MSt Exp | 44 | data MSt = MSt Exp Exp [Exp] |
49 | Exp | ||
50 | [Exp] | ||
51 | 45 | ||
52 | --------------------------------------------------------------------- toolbox: pretty print | 46 | --------------------------------------------------------------------- toolbox: pretty print |
53 | 47 | ||
54 | instance PShow Exp where | 48 | instance 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 | ||
71 | instance PShow MSt where | 65 | instance 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 | |||
88 | showLet x y = DLet' x y | 82 | showLet x y = DLet' x y |
89 | 83 | ||
90 | 84 | ||
91 | --------------------------------------------------------------------- toolbox: free variables | 85 | --------------------------------------------------------------------- pattern synonyms |
86 | |||
87 | pattern Int i <- Exp _ (Int_ i) | ||
88 | where Int i = Exp [0] $ Int_ i | ||
89 | pattern 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 | ||
91 | pattern Op1 op a <- Exp u (Op1_ op (upp u -> a)) | ||
92 | where Op1 op a = dup1 (Op1_ op) a | ||
93 | pattern Var i <- Exp (varIndex -> i) Var_ | ||
94 | where Var 0 = Exp [1] Var_ | ||
95 | Var i = Exp [0, i, i+1] Var_ | ||
96 | pattern Lam i <- Exp u (Lam_ (upp ((+1) <$> u) -> i)) | ||
97 | where Lam i = dupLam i | ||
98 | pattern 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 | ||
103 | pattern 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 | |||
106 | pattern Let i x = App (Lam x) i | ||
107 | pattern Y a = Op1 YOp a | ||
108 | pattern App a b = Op2 AppOp a b | ||
109 | pattern Seq a b = Op2 SeqOp a b | ||
92 | 110 | ||
93 | maxFreeVars (Exp xs s _) = foldl' f s xs | 111 | infixl 4 `App` |
94 | where | 112 | |
95 | f m (Up l n) = n + m | 113 | varIndex (_: i: _) = i |
114 | varIndex _ = 0 | ||
96 | 115 | ||
97 | upVarIndex xs s = foldr f s xs | 116 | dupLam (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 | ||
103 | upp u x = foldr up x u | 121 | g xs@(0: _) = [0, 1, altersum xs + 1] |
122 | g xs = [altersum xs] | ||
104 | 123 | ||
105 | up' l n = up $ Up l n | 124 | dup1 f (Exp ab x) = Exp ab $ f $ Exp [altersum ab] x |
106 | 125 | ||
107 | up :: Up -> Exp -> Exp | 126 | altersum [x] = x |
108 | up (Up i 0) e = e | 127 | altersum (a: b: cs) = a - b + altersum cs |
109 | up u@(Up i num) e@(Exp us s x) = Exp (insertUp_ s u us) s x | ||
110 | 128 | ||
111 | insertUp_ s u@(Up i _) [] | 129 | initSt :: Exp -> MSt |
112 | | i >= s = [] | 130 | initSt e = MSt (Var 0) e [] |
113 | | otherwise = [u] | ||
114 | insertUp_ 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 |
120 | fvs (Exp us fv _) = gen 0 $ foldr f [fv] us where | 133 | size :: MSt -> Int |
121 | f (Up l n) xs = l: l+n: map (+n) xs | 134 | size (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 | ||
126 | usedVar' 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 | ||
133 | down i0 e0@(Exp us fv e) = f i0 us where | 141 | upp [k] ys = ys |
134 | f i [] | 142 | upp (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 | ||
142 | upss u (Exp _ i e) = Exp u i e | 144 | up i 0 e = e |
145 | up 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 | ||
156 | fvs (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 | ||
144 | dup2 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] | 162 | a .: (x: y: xs) | a == x = y: xs |
146 | az = upss a' ax | 163 | a .: xs = a: xs |
147 | bz = upss b' bx | ||
148 | 164 | ||
149 | dup1 :: (Exp -> Exp_) -> Exp -> Exp | 165 | usedVar i (Exp us _) = f us where |
150 | dup1 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 | ||
152 | dupCon f [] = Exp [] 0 $ f [] | 169 | down i (Exp us e) = Exp <$> f us <*> pure e where |
153 | dupCon 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 | ||
157 | dupCase f ax (unzip -> (ss, bx)) | 178 | delta2 (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 | ||
164 | dupLam f e@(Exp a fv ax) = Exp (ff a) fv' $ f $ Exp (gg a) fv ax | 182 | deltas [] = ([0], []) |
183 | deltas 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 | |||
174 | pattern Int i <- Exp _ _ (Int_ i) | ||
175 | where Int i = Exp [] 0 $ Int_ i | ||
176 | pattern App a b <- Exp u _ (App_ (upp u -> a) (upp u -> b)) | ||
177 | where App a b = dup2 App_ a b | ||
178 | pattern Seq a b <- Exp u _ (Seq_ (upp u -> a) (upp u -> b)) | ||
179 | where Seq a b = dup2 Seq_ a b | ||
180 | pattern 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 | ||
182 | pattern Op1 op a <- Exp u _ (Op1_ op (upp u -> a)) | ||
183 | where Op1 op a = dup1 (Op1_ op) a | ||
184 | pattern 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 | ||
187 | pattern Lam i <- Exp u _ (Lam_ (upp (incUp 1 <$> u) -> i)) | ||
188 | where Lam i = dupLam Lam_ i | ||
189 | pattern Y i <- Exp u _ (Y_ (upp u -> i)) | ||
190 | where Y i = dup1 Y_ i | ||
191 | pattern Con a b i <- Exp u _ (Con_ a b (map (upp u) -> i)) | ||
192 | where Con a b i = dupCon (Con_ a b) i | ||
193 | pattern Case a b <- Exp u _ (Case_ (upp u -> a) (map (second $ upp u) -> b)) | ||
194 | where Case a b = dupCase Case_ a b | ||
195 | |||
196 | pattern Let i x = App (Lam x) i | ||
197 | 186 | ||
198 | infixl 4 `App` | 187 | s = foldr1 iLadders xs |
199 | 188 | ||
200 | --------------------------------------------------------------------- toolbox: de bruijn index shifting | 189 | iLadders :: [Int] -> [Int] -> [Int] |
201 | 190 | iLadders x [] = x | |
202 | data Up = Up !Int{-level-} !Int{-num-} | 191 | iLadders [] x = x |
203 | deriving (Eq, Show) | 192 | iLadders x@(a: b: us) x'@(a': b': us') |
204 | 193 | | b <= a' = addL a b $ iLadders us x' | |
205 | incUp 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') | |
207 | showUps 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 | |||
210 | deltaUps = 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]) | 199 | addL a b cs | a == b = cs |
215 | where | 200 | addL a b (c: cs) | b == c = a: cs |
216 | s = foldr1 iLadders xs | 201 | addL 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 [] = [] | 203 | add0 [] = [0] |
257 | negL xs = init $ add1 0 xs | 204 | add0 (0: cs) = cs |
205 | add0 cs = 0: cs | ||
258 | 206 | ||
259 | 207 | dLadders :: Int -> [Int] -> [Int] -> [Int] | |
260 | getLets (Let x y) = x: getLets y | 208 | dLadders s [] x = [s] |
261 | getLets x = [x] | 209 | dLadders 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 | ||
265 | tryRemoves xs = tryRemoves_ (Var <$> xs) | 216 | tryRemoves xs = tryRemoves_ (Var <$> xs) |
266 | tryRemoves_ [] dt = dt | ||
267 | tryRemoves_ (Var i: vs) dt | ||
268 | | Just dt' <- tryRemove_ i dt | ||
269 | = tryRemoves_ (catMaybes $ down i <$> vs) dt' | ||
270 | | otherwise = tryRemoves_ vs dt | ||
271 | 217 | ||
272 | tryRemove i x = fromMaybe x $ tryRemove_ i x | 218 | tryRemoves_ [] dt = dt |
219 | tryRemoves_ (Var i: vs) dt = maybe (tryRemoves_ vs dt) (tryRemoves_ $ catMaybes $ down i <$> vs) $ tryRemove_ i dt | ||
273 | 220 | ||
274 | tryRemove_ i dt@(MSt xs e es) | 221 | tryRemove_ 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 | ||
282 | downDown i [] = Just [] | 223 | downDown i [] = Just [] |
283 | downDown 0 (_: xs) = Just xs | 224 | downDown 0 (_: xs) = Just xs |
284 | downDown i (x: xs) | 225 | downDown 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 | |||
292 | class Monad m => MachineMonad m where | ||
293 | traceStep :: String -> m () | ||
294 | collectSizeStat :: Int -> m () | ||
295 | |||
296 | instance MachineMonad Identity where | ||
297 | traceStep _ = return () | ||
298 | collectSizeStat _ = return () | ||
299 | |||
300 | instance MachineMonad IO where | ||
301 | traceStep s = return () | ||
302 | -- traceStep = putStrLn | ||
303 | collectSizeStat s = return () | ||
304 | |||
305 | instance MachineMonad (Writer [Int]) where | ||
306 | traceStep s = return () | ||
307 | collectSizeStat s = tell [s] | ||
308 | 228 | ||
309 | runMachineStat e = putStr $ unlines $ ppShow t: "--------": show (length w, w):[] | 229 | justResult :: MSt -> MSt |
310 | where | 230 | justResult = steps id (const ($)) (const (.)) |
311 | (t, w) = runWriter (hnf e :: Writer [Int] MSt) | ||
312 | 231 | ||
313 | runMachineIO e = do | 232 | hnf = justResult . initSt |
314 | t <- hnf e :: IO MSt | ||
315 | putStr $ unlines $ ppShow t: [] | ||
316 | 233 | ||
317 | runMachinePure e = putStr $ unlines $ ppShow t: [] | 234 | ---------------- |
318 | where | ||
319 | t = runIdentity $ hnf e | ||
320 | 235 | ||
321 | ----------------------------------------------------------- machine code begins here | 236 | type 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 | 243 | type StepTag = String |
324 | step :: MachineMonad m => MSt -> m MSt | ||
325 | step dt@(MSt t e vs) = case e of | ||
326 | 244 | ||
327 | Int{} -> return dt | 245 | steps :: forall e . GenSteps e |
246 | steps 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 | ||
379 | stepMsg :: MachineMonad m => String -> MSt -> m MSt | 301 | step :: StepTag -> MSt -> e |
380 | stepMsg 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 | ||
385 | hnf e = stepMsg "hnf" $ MSt (Var 0) e [] | 304 | hnf :: (MSt -> e) -> MSt -> e |
305 | hnf f = cont "hnf" f rec | ||
386 | 306 | ||
387 | size (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 | ||
389 | shiftL (MSt xs x (e: es)) = MSt (Let x xs) e es | 315 | shiftL (MSt xs x (e: es)) = MSt (Let x xs) e es |
390 | shiftR (MSt (Let x xs) e es) = MSt xs x $ e: es | ||
391 | 316 | ||
392 | shiftLookup 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 |
396 | lookupHNF msg f i dt = tryRemove i . shiftLookup f i <$> stepMsg msg (iterate shiftL dt !! (i+1)) | ||
397 | 320 | ||
398 | -- lookup & step | 321 | -- lookup & step |
399 | lookupHNF' 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 | ||
401 | simple = \case | 325 | simple = \case |
402 | Var{} -> True | 326 | Var{} -> True |
403 | Int{} -> True | 327 | Int{} -> True |
404 | _ -> False | 328 | _ -> False |
405 | 329 | ||
406 | delElem 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 | ||
410 | id_ = Lam (Var 0) | 334 | runMachinePure = putStrLn . ppShow . hnf |
411 | 335 | ||
412 | pattern F = Con "False" 0 [] | 336 | pattern F = Con "False" 0 [] |
413 | pattern T = Con "True" 1 [] | 337 | pattern T = Con "True" 1 [] |
414 | pattern Nil = Con "[]" 0 [] | 338 | pattern Nil = Con "[]" 0 [] |
415 | pattern Cons a b = Con "Cons" 1 [a, b] | 339 | pattern Cons a b = Con "Cons" 1 [a, b] |
416 | 340 | ||
417 | caseBool x f t = Case x [("False", f), ("True", t)] | 341 | caseBool x f t = Case ["False", "True"] x [f, t] |
418 | caseList x n c = Case x [("[]", n), ("Cons", c)] | 342 | caseList x n c = Case ["[]", "Cons"] x [n, c] |
343 | |||
344 | id_ = Lam (Var 0) | ||
419 | 345 | ||
420 | if_ b t f = caseBool b f t | 346 | if_ 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 | ||
426 | test' = runMachinePure (id_ `App` (id_ `App` Con "()" 0 [])) | 352 | test' = runMachinePure (id_ `App` (id_ `App` Con "()" 0 [])) |
427 | 353 | ||
428 | foldr_ 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)) | 354 | foldr_ 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 | ||
430 | filter_ p = foldr_ (Lam $ Lam $ if_ (p `App` Var 1) (Cons (Var 1) (Var 0)) (Var 0)) Nil | 356 | filter_ 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 | ||
466 | t'' n = accsum `App` Int 0 `App` (fromTo `App` Int 0 `App` Int n) -- takeWhile_ (\x -> Op2 LessEq x $ Int 3) (from_ `App` Int 0) | 392 | t'' 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 | ||
468 | main = 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 | ||
476 | primes :: [Int] | 396 | primes :: [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 | ||
428 | showUps 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 | |||
508 | deltaUps_ (map $ uncurry showUps -> us) = (mkUps $ back s, [mkUps $ u `diffUps` s | u <- us]) | 431 | deltaUps_ (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 | ||
521 | diffUpsTest' = diffUpsTest [x,y] --diffUpsTest x y | 444 | diffUpsTest' = diffUpsTest [x,y] --diffUpsTest x y |
522 | 445 | ||
523 | x = ([Up 1 2, Up 3 4, Up 8 2], 20) | 446 | --x = ([Up 8 2], 200) |
524 | y = ([Up 2 2, Up 5 1, Up 6 2, Up 7 2], 18) | 447 | --y = ([], 28) |
448 | x = ([Up 1 2, Up 3 4, Up 8 2], 200) | ||
449 | y = ([Up 2 2, Up 5 1, Up 6 2, Up 7 2], 28) | ||
525 | 450 | ||
526 | -- TODO: remove | 451 | -- TODO: remove |
527 | insertUp (Up l 0) us = us | 452 | insertUp (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 | ||