Last active
August 29, 2015 14:03
-
-
Save lnicola/86b1a0ff412c3bd918fc to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| rem ghc -O2 -auto-all -prof --make slowsilver && slowsilver +RTS -p -hc && hp2ps slowsilver | |
| ghc -O2 -auto-all -prof --make slowsilver && slowsilver +RTS -p |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {-# LANGUAGE BangPatterns #-} | |
| module Main (main) where | |
| import Data.List.Stream hiding (insert, lookup) | |
| import Prelude hiding (lookup, length, foldl, foldl1) | |
| --import Prelude hiding (lookup) | |
| import Control.Monad.State.Strict | |
| import Data.Array.IO | |
| import Data.Map hiding (map) | |
| import Data.IORef | |
| data Expression = EInteger Int | EBoolean Bool | ESymbol String | EDefine String Expression | EPrimitive ([Value] -> RuntimeResult) | EIf Expression Expression Expression | ELambda [String] Expression | EBlock [Expression] | EApplication Expression [Expression] | |
| data Value = VInteger {-# UNPACK #-} !Int | VBoolean {-# UNPACK #-} !Bool | VSymbol {-# UNPACK #-} !(Int, Int) | VFunction {-# UNPACK #-} !([Value] -> RuntimeResult) | |
| type CompileContext = (Map String (Int, Int), Map String Int, Int, IOArray Int Int) | |
| type CompileResult = StateT CompileContext IO RuntimeResult | |
| type RuntimeContext = IOArray Int (IOArray Int Value) | |
| type RuntimeResult = IO Value | |
| instance Show Value where | |
| show (VInteger x) = show x | |
| show (VBoolean x) = show x | |
| show (VSymbol x) = show x | |
| show (VFunction _) = "<function>" | |
| primitive_lt [VInteger x, VInteger y] = return $! if x < y then VBoolean True else VBoolean False | |
| primitive_add [VInteger x, VInteger y] = return $! VInteger $ x + y | |
| primitive_sub [VInteger x, VInteger y] = return $! VInteger $ x - y | |
| runtimeLookup !context (frame, position) = do | |
| f <- readArray context frame | |
| r <- readArray f position | |
| return $! r | |
| runtimeSet context (frame, position) val = do | |
| f <- readArray context frame | |
| writeArray f position val | |
| return $ VBoolean False | |
| runtimeDefine env r pos = r >>= runtimeSet env (0, pos) | |
| runtimeIf !cond expr1 expr2 = do | |
| r <- cond | |
| case r of | |
| VBoolean True -> expr1 | |
| _ -> expr2 | |
| runtimeLambda depth !la env r = return $! VFunction $ \ar -> do | |
| f <- readArray env depth | |
| u <- newListArray (0, la) ar | |
| writeArray env depth u | |
| x <- r | |
| writeArray env depth f | |
| return x | |
| runtimeApplication f args = do | |
| (VFunction g) <- f | |
| sequence args >>= g | |
| compileLookup sym = do | |
| (locals, globals, _, _) <- get | |
| return $! case lookup sym locals of | |
| Just value -> value | |
| Nothing -> case lookup sym globals of | |
| Just value -> (0, value) | |
| compile :: Expression -> RuntimeContext -> CompileResult | |
| compile (EInteger x) _ = return $ return $! VInteger x | |
| compile (EBoolean x) _ = return $ return $! VBoolean x | |
| compile (ESymbol sym) env = liftM (runtimeLookup env) $ compileLookup sym | |
| compile (EDefine sym val) env = do | |
| (locals, globals, depth, lengths) <- get | |
| globalLength <- liftIO $ readArray lengths 0 | |
| liftIO $ writeArray lengths 0 $ globalLength + 1 | |
| put (locals, insert sym globalLength globals, depth, lengths) | |
| r <- compile val env | |
| return $ runtimeDefine env r globalLength | |
| compile (EPrimitive f) _ = return $ return $! VFunction f | |
| compile (EIf cond expr1 expr2) env = do | |
| ccond <- compile cond env | |
| cexpr1 <- compile expr1 env | |
| cexpr2 <- compile expr2 env | |
| return $ runtimeIf ccond cexpr1 cexpr2 | |
| compile (ELambda args value) env = do | |
| (locals, globals, depth, lengths) <- get | |
| let (newLocals, _) = foldl (\(l, c) s -> (insert s (depth + 1, c) l, c + 1)) (locals, 0) args | |
| liftIO $ writeArray lengths (depth + 1) (length args) | |
| put (newLocals, globals, depth + 1, lengths) | |
| r <- compile value env | |
| put (locals, globals, depth, lengths) | |
| return $ runtimeLambda (depth + 1) (length args) env r | |
| compile (EBlock exprs) env = liftM (foldl1 (>>)) $ mapM (\e -> compile e env) exprs | |
| compile (EApplication f args) env = liftM2 runtimeApplication (compile f env) (mapM (\e -> compile e env) args) | |
| main = do | |
| context <- newArray_ (0, 40) | |
| lengths <- newArray (0, 40) 0 | |
| mapM_ (aux context) [0..40] | |
| ctx <- newIORef context | |
| env <- readIORef ctx | |
| c <- evalStateT (compile test env) (empty, empty, 0, lengths) | |
| c >>= print | |
| test = EBlock | |
| [ | |
| EDefine "+" (EPrimitive primitive_add), | |
| EDefine "-" (EPrimitive primitive_sub), | |
| EDefine "<" (EPrimitive primitive_lt), | |
| EDefine "fib" $ ELambda ["n"] $ EIf | |
| (EApplication (ESymbol "<") [EInteger 1, ESymbol "n"]) | |
| (EApplication (ESymbol "+") | |
| [ | |
| EApplication (ESymbol "fib") [EApplication (ESymbol "-") [ESymbol "n", EInteger 1]], | |
| EApplication (ESymbol "fib") [EApplication (ESymbol "-") [ESymbol "n", EInteger 2]] | |
| ]) | |
| (ESymbol "n"), | |
| EApplication (ESymbol "fib") [EInteger 25] | |
| ] | |
| aux context k = newArray (0, 35) (VBoolean False) >>= writeArray context k |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment