C  A Haskell Interpreter using Plugins

Here is a full length example of a Haskell interpreter/compiler in the style of Malcolm Wallace's hi. Rather than compiling the user's code to an executable, we use hs-plugins to instead load an object file and execute that instead, using the eval interface. This cuts out the linking phase from the process, making turnaround at the prompt around twice as fast as hi.

Source of Plugs

import System.Eval.Haskell
import System.Plugins

import System.Exit              ( ExitCode(..), exitWith )
import System.IO
import System.Console.Readline  ( readline, addHistory )

symbol = "resource"

main = do
        putStrLn banner 
        putStr "Loading package base" >> hFlush stdout
        loadPackage "base" 
        putStr " ... linking ... " >> hFlush stdout
        resolveObjs
        putStrLn "done"

        shell []

shell :: [String] -> IO ()
shell imps = do 
        s <- readline "plugs> "
        cmd <- case s of 
                Nothing          -> exitWith ExitSuccess
                Just (':':'q':_) -> exitWith ExitSuccess
                Just s           -> addHistory s >> return s
        imps' <- run cmd imps
        shell imps'

run :: String -> [String] -> IO [String]
run ""   is = return is
run ":?" is = putStrLn help >> return is

run ":l" _             = return []
run (':':'l':' ':m) is = return (m:is)

run (':':'t':' ':s) is = do 
        ty <- typeOf s is
        when (not $ null ty) (putStrLn $ s ++ " :: " ++ ty)
        return is

run (':':_) is = putStrLn help >> return is

run s is = do 
        s <- unsafeEval ("show $ "++s) is
        when (isJust s) (putStrLn (fromJust s))
        return is

banner = "\ 
\           __                          \n\
\    ____  / /_  ______ ______          \n\
\   / __ \\/ / / / / __ `/ ___/     PLugin User's GHCi System, for Haskell 98\n\
\  / /_/ / / /_/ / /_/ (__  )      http://www.cse.unsw.edu.au/~dons/hs-plugins\n\
\ / .___/_/\\__,_/\\__, /____/       Type :? for help     \n\
\/_/            /____/                  \n"

help = "\
\Commands :\n\ 
\  <expr>               evaluate expression\n\ 
\  :t <expr>            show type of expression (monomorphic only)\n\ 
\  :l module            bring module in to scope\n\ 
\  :l                   clear module list\n\ 
\  :quit                quit\n\ 
\  :?                   display this list of commands"

A Transcript

And a transcript:

$ ./plugs
           __                          
    ____  / /_  ______ ______          
   / __ \/ / / / / __ `/ ___/     PLugin User's GHCi System, for Haskell 98
  / /_/ / / /_/ / /_/ (__  )      http://www.cse.unsw.edu.au/~dons/hs-plugins
 / .___/_/\__,_/\__, /____/       Type :? for help     
/_/            /____/                  

Loading package base ... linking ... done
plugs> 1
1
plugs> let x = 1 + 2 in x
3
plugs> :l Data.List
plugs> case [1,3,2] of x -> sort x
[1,2,3]
plugs> reverse [1,3,2]
[2,3,1]
plugs> map (\x-> (x,2^x)) [1,2,3,4,5,6,7,8,9,10]
[(1,2),(2,4),(3,8),(4,16),(5,32),(6,64),(7,128),(8,256),(9,512),(10,1024)]
plugs> :t "haskell"
"haskell" :: [Char]
plugs> :quit