| 1 | --bug todo verify full lazy |
|---|
| 2 | --idea: try to take things out of V and use Fun instead |
|---|
| 3 | --how does running size optimizer first help speed if full lazy? makes env list smaller? |
|---|
| 4 | --investigate timeout on '5' |
|---|
| 5 | --expand \a.I = church 0 |
|---|
| 6 | --make errors for apply inc,00 instead of succ,0 |
|---|
| 7 | --does pattern matching rhs of app ruin some lazyness? |
|---|
| 8 | --untitled 619 slow why? |
|---|
| 9 | --cons pred not working |
|---|
| 10 | --remove unused vars from e list in eval |
|---|
| 11 | import System (getArgs) |
|---|
| 12 | import Char |
|---|
| 13 | import IO |
|---|
| 14 | |
|---|
| 15 | chri :: Integer -> Char |
|---|
| 16 | chri i = chr (fromInteger i `mod` 256) |
|---|
| 17 | ordi :: Char -> Integer |
|---|
| 18 | ordi c = toInteger (ord c) |
|---|
| 19 | --monus a b = if a < b then 0 else a - b |
|---|
| 20 | |
|---|
| 21 | data T = Var Int |
|---|
| 22 | | Lam T |
|---|
| 23 | | App T T |
|---|
| 24 | | Num Integer |
|---|
| 25 | | Succa |
|---|
| 26 | | Adda |
|---|
| 27 | | Composea |
|---|
| 28 | | Preda |
|---|
| 29 | deriving (Show) |
|---|
| 30 | data V = Fun (V -> V) |
|---|
| 31 | | Church Integer |
|---|
| 32 | | Succ |
|---|
| 33 | | Pred |
|---|
| 34 | | List [Integer] |
|---|
| 35 | | Add Integer |
|---|
| 36 | | Compose |
|---|
| 37 | | Mult Integer |
|---|
| 38 | | Add1 |
|---|
| 39 | |
|---|
| 40 | app :: V -> V -> V |
|---|
| 41 | app (Fun f) v = f v |
|---|
| 42 | app (List []) _ = Church 1 |
|---|
| 43 | app (List (x:xs)) f = f `app` Church x `app` List xs |
|---|
| 44 | app (Church 0) _ = Church 1 |
|---|
| 45 | app (Church 1) f = f |
|---|
| 46 | app (Church i) (Church j) = Church(j^i) |
|---|
| 47 | app (Church i) Succ = Add i |
|---|
| 48 | app (Church i) (Add j) = Add (i*j) --todo verify |
|---|
| 49 | app (Church i) f = Fun (\x -> f `app` (Church (i-1) `app` f `app` x)) |
|---|
| 50 | app Succ (Church i) = Church (i+1) -- this check is not be lazy |
|---|
| 51 | app Succ a = Fun (\f-> Fun (\x->f `app` (a `app` f `app` x))) |
|---|
| 52 | app (Add i) (Church j) = Church(i+j) |
|---|
| 53 | app (Add n) m = Fun (\f -> Fun (\x -> (Church n) `app` f `app` (m `app` f `app` x))) |
|---|
| 54 | app Add1 (Church i) = Add i |
|---|
| 55 | app Add1 a = Fun (\b-> Fun (\f-> Fun (\x-> a `app` f `app` (b `app` f `app` x)))) |
|---|
| 56 | |
|---|
| 57 | --add cases for 0,1 so check for 2nd arg is lazy?? |
|---|
| 58 | app Compose (Church i) = Mult i |
|---|
| 59 | app Compose n = Fun (\m -> Fun (\f -> n `app` (m `app` f))) |
|---|
| 60 | app (Mult i) (Church j) = Church (i*j) |
|---|
| 61 | app (Mult i) m = Fun (\f -> Church i `app` (m `app` f)) |
|---|
| 62 | |
|---|
| 63 | app Pred i = Fun (\n -> case n of |
|---|
| 64 | -- (Church j) -> if j > 0 then i `app` Church (j-1) else Church 0 |
|---|
| 65 | _ -> Fun (\f -> Fun (\x -> n `app` Fun (\g -> Fun (\h -> h `app` (g `app` f))) `app` Fun (\u -> x) `app` i))) |
|---|
| 66 | |
|---|
| 67 | eval :: T -> [V] -> V |
|---|
| 68 | eval (Num i) _ = Church i |
|---|
| 69 | eval Succa _ = Succ |
|---|
| 70 | eval Composea _ = Compose |
|---|
| 71 | eval Adda _ = Add1 |
|---|
| 72 | eval Preda _ = Pred |
|---|
| 73 | eval (Var x) e = e !! x |
|---|
| 74 | eval (Lam t) e = Fun (\v -> eval t (v:e)) |
|---|
| 75 | eval (App a b) e = eval a e `app` eval b e |
|---|
| 76 | |
|---|
| 77 | clean :: T -> T |
|---|
| 78 | clean (Var x) = Var x |
|---|
| 79 | clean (Lam t) = clean' (Lam (clean t)) |
|---|
| 80 | clean (App a b) = App (clean a) (clean b) |
|---|
| 81 | clean a = a |
|---|
| 82 | |
|---|
| 83 | clean' (Lam (f `App` Var 0)) | free f 0 = unabs f |
|---|
| 84 | clean' a = a |
|---|
| 85 | |
|---|
| 86 | numberize :: T -> T |
|---|
| 87 | numberize (Lam (Lam (App (App (App n (Lam (Lam (App (Var 0) (App (Var 1) (Var 3)))))) (Lam (Var 1))) i))) | free n 0 && free n 1 && free i 0 && free i 1 = |
|---|
| 88 | Preda `App` numberize (clean (unabs (unabs i))) `App` numberize (clean (unabs (unabs n))) |
|---|
| 89 | |
|---|
| 90 | numberize (Lam (n `App` (m `App` Var 0))) | free n 0 && free m 0 = |
|---|
| 91 | Composea `App` numberize (unabs n) `App` numberize (unabs m) |
|---|
| 92 | |
|---|
| 93 | numberize (Lam (Lam (Var 0))) = Num 0 |
|---|
| 94 | numberize (Lam (Var 0)) = Num 1 |
|---|
| 95 | |
|---|
| 96 | numberize (Lam (Lam (Var 1 `App` f))) = |
|---|
| 97 | Succa `App` numberize (clean (Lam (Lam f))) |
|---|
| 98 | |
|---|
| 99 | numberize (Lam (Lam (n `App` Var 1 `App` f))) | free n 0 && free n 1 = |
|---|
| 100 | Adda `App` numberize (unabs (unabs n)) `App` numberize (clean (Lam (Lam f))) |
|---|
| 101 | |
|---|
| 102 | numberize (Var x) = Var x |
|---|
| 103 | numberize (Lam t) = Lam (numberize t) |
|---|
| 104 | numberize (App a b) = App (numberize a) (numberize b) |
|---|
| 105 | |
|---|
| 106 | free :: T -> Int -> Bool |
|---|
| 107 | free (Var x) i = x /= i |
|---|
| 108 | free (Lam t) i = free t (i+1) |
|---|
| 109 | free (App a b) i = free a i && free b i |
|---|
| 110 | free _ _ = True |
|---|
| 111 | |
|---|
| 112 | unabs :: T -> T |
|---|
| 113 | unabs = unabs' 0 where |
|---|
| 114 | unabs' i (Var x) | x >= i = Var (x-1) |
|---|
| 115 | | otherwise = Var x |
|---|
| 116 | unabs' i (Lam t) = Lam (unabs' (i+1) t) |
|---|
| 117 | unabs' i (App a b) = App (unabs' i a) (unabs' i b) |
|---|
| 118 | unabs' _ a = a |
|---|
| 119 | |
|---|
| 120 | iToList :: V -> V |
|---|
| 121 | iToList i = Fun (\rhs -> tolist (show (unchurch i) ++ unlist rhs)) |
|---|
| 122 | |
|---|
| 123 | listToI :: V -> V |
|---|
| 124 | --listToI s = error (show (map (chri) (snd (digits (unlist' s))))) where |
|---|
| 125 | listToI s = List (read ('0':map chri a):b) where |
|---|
| 126 | (a,b) = span digits (snd (break digits (unlist' s))) |
|---|
| 127 | digits = isDigit . chri |
|---|
| 128 | |
|---|
| 129 | unchurch :: V -> Integer |
|---|
| 130 | unchurch (Church i) = i |
|---|
| 131 | unchurch f = i where (Church i) = f `app` Succ `app` Church 0 |
|---|
| 132 | tolist :: String -> V |
|---|
| 133 | tolist = List . map ordi |
|---|
| 134 | unlist :: V -> String |
|---|
| 135 | unlist = map chri . unlist' |
|---|
| 136 | unlist' (List i) = i |
|---|
| 137 | unlist' s = shedlist $ s `app` Fun (\a -> Fun (\b -> Fun (\i -> |
|---|
| 138 | List (unchurch a : unlist' b)))) `app` List [] where |
|---|
| 139 | shedlist (List i) = i |
|---|
| 140 | |
|---|
| 141 | type BitStream = ([Int], String) |
|---|
| 142 | stepBit :: BitStream -> (Int, BitStream) |
|---|
| 143 | stepBit (x:xs, ys) = (x, (xs, ys)) |
|---|
| 144 | stepBit ([], y:ys) = ((ord y) `div` 128, (map (\p->(ord y) `div` 2^p `mod` 2) [6,5..0], ys)) |
|---|
| 145 | |
|---|
| 146 | parse :: BitStream -> (T, BitStream) |
|---|
| 147 | parse s = |
|---|
| 148 | if a == 1 then getVar s2 0 |
|---|
| 149 | else |
|---|
| 150 | if b == 0 then (Lam e1, r1) |
|---|
| 151 | else (App e1 e2, r2) |
|---|
| 152 | where |
|---|
| 153 | (a,s2) = stepBit s |
|---|
| 154 | (b,s3) = stepBit s2 |
|---|
| 155 | (e1,r1) = parse(s3) |
|---|
| 156 | (e2,r2) = parse(r1) |
|---|
| 157 | getVar s i = |
|---|
| 158 | if a==1 then getVar s2 (i+1) |
|---|
| 159 | else (Var i, s2) |
|---|
| 160 | where (a,s2) = stepBit s |
|---|
| 161 | |
|---|
| 162 | main = do |
|---|
| 163 | sources <- mapM readFile =<< getArgs |
|---|
| 164 | hSetBuffering stdout NoBuffering -- because haskell does not flush on error |
|---|
| 165 | interact (\input -> |
|---|
| 166 | let stream = ([], concat sources ++ input) |
|---|
| 167 | (tree, (_, rest)) = parse stream |
|---|
| 168 | tree2 = clean (numberize tree) |
|---|
| 169 | builtin = [Fun iToList, Fun listToI] |
|---|
| 170 | output = unlist $ eval tree2 builtin `app` tolist rest |
|---|
| 171 | in (show tree2) ++ "\n" ++ output) |
|---|