diff --git a/DDC/Driver/Command/Ast.hs b/DDC/Driver/Command/Ast.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/Ast.hs
@@ -0,0 +1,61 @@
+
+module DDC.Driver.Command.Ast
+        ( cmdAstModule
+        , cmdAstExp)
+where
+import DDC.Driver.Command.Check
+import DDC.Driver.Source
+import DDC.Build.Language
+import Control.Monad.Trans.Error
+import qualified Language.Haskell.Exts.Parser as H
+import qualified Language.Haskell.Exts.Pretty as H
+
+
+-- | Parse, check, and pretty print a module's internal representation.
+cmdAstModule :: Language -> Source -> String -> IO ()
+cmdAstModule language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment bundle
+ = do   mModule <- runErrorT 
+                $ cmdCheckModuleFromString fragment source str
+        goShow mModule
+ where
+        -- Expression had a parse or type error.
+        goShow (Left err)
+         = do   putStrLn err
+                return ()
+
+        -- Expression is well-typed.
+        goShow (Right x)
+         = let p = pretty x in
+           putStrLn p
+         
+        pretty x
+         = case H.parseExp (show x) of
+                H.ParseOk parsed -> H.prettyPrint parsed
+                err -> show err
+
+
+-- | Parse, check, and pretty print an expression's internal representation.
+cmdAstExp :: Language -> Source -> String -> IO ()
+cmdAstExp language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment bundle
+ , modules              <- bundleModules  bundle
+ =   cmdParseCheckExp fragment modules True source str 
+ >>= goShow
+ where
+        -- Expression had a parse or type error.
+        goShow Nothing
+         = return ()
+
+        -- Expression is well-typed.
+        goShow (Just x)
+         = let p = pretty x in
+	   putStrLn p
+	 
+	pretty x
+	 = case H.parseExp (show x) of
+		H.ParseOk parsed -> H.prettyPrint parsed
+		err -> show err
+
diff --git a/DDC/Driver/Command/BaseBuild.hs b/DDC/Driver/Command/BaseBuild.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/BaseBuild.hs
@@ -0,0 +1,80 @@
+
+module DDC.Driver.Command.BaseBuild
+        (cmdBaseBuild)
+where
+import DDC.Driver.Stage
+import DDC.Build.Platform
+import DDC.Build.Builder
+import DDC.Driver.Command.Compile
+import System.FilePath
+import System.Directory
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import Control.Monad
+
+
+baseLiteFiles :: Builder -> [FilePath]
+baseLiteFiles builder
+ = let  _bits    = show $ archPointerWidth $ platformArch $ buildTarget builder
+   in   [ "lite" </> "base" </> "Data" </> "Numeric" </> "Bool.dcl"
+        , "lite" </> "base" </> "Data" </> "Numeric" </> "Int.dcl"
+        , "lite" </> "base" </> "Data" </> "Numeric" </> "Nat.dcl" ]
+
+
+baseSaltFiles :: Builder -> [FilePath]
+baseSaltFiles builder
+ = let  bits    = show $ archPointerWidth $ platformArch $ buildTarget builder
+   in   [ "salt" </> "runtime"   ++ bits </> "Object.dcs" ]
+
+
+baseSeaFiles  :: Builder -> [FilePath]
+baseSeaFiles _builder
+ =      ["sea"  </> "primitive" </> "Primitive.c"]
+
+
+-- Buid the base libraries and runtime system.
+cmdBaseBuild :: Config  -> ErrorT String IO ()
+cmdBaseBuild config
+ = do   let builder     = configBuilder config
+        let target      = buildTarget builder
+
+        -- Ensure the lib dir exists.
+        exists   <- liftIO $ doesDirectoryExist $ buildBaseLibDir builder
+        when (not exists)
+         $ liftIO $ createDirectory $ buildBaseLibDir builder
+
+        -- Build all the .dcl files.
+        let srcLiteFiles = map (buildBaseSrcDir builder </>) (baseLiteFiles builder)
+        let objLiteFiles = map (flip replaceExtension "o")   srcLiteFiles
+        mapM_ (cmdCompile config) srcLiteFiles
+
+        -- Build all the .dcs files.
+        let srcSaltFiles = map (buildBaseSrcDir builder </>) (baseSaltFiles builder)
+        let objSaltFiles = map (flip replaceExtension "o")   srcSaltFiles
+        mapM_ (cmdCompile config) srcSaltFiles
+
+        -- Build all the .c files.
+        let srcSeaFiles  = map (buildBaseSrcDir builder </>) (baseSeaFiles builder)
+        let objSeaFiles  = map (flip replaceExtension "o")   srcSeaFiles
+        liftIO $ zipWithM_ (buildCC builder) srcSeaFiles objSeaFiles
+
+        -- All the .o files
+        let objFiles     = objLiteFiles ++ objSaltFiles ++ objSeaFiles
+
+        -- Link the .o files into a static library.
+        let staticRuntime 
+                = buildBaseLibDir builder
+                </> "libddc-runtime." ++ staticFileExtensionOfPlatform target
+
+        liftIO $ buildLdLibStatic builder objFiles staticRuntime
+
+
+        -- Link the .o files into a shared library.
+        let sharedRuntime 
+                = buildBaseLibDir builder
+                </> "libddc-runtime." ++ sharedFileExtensionOfPlatform target
+
+        liftIO $ buildLdLibShared builder objFiles sharedRuntime
+
+        return ()
+
diff --git a/DDC/Driver/Command/Check.hs b/DDC/Driver/Command/Check.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/Check.hs
@@ -0,0 +1,378 @@
+module DDC.Driver.Command.Check
+        ( cmdUniverse
+        , cmdUniverse1
+        , cmdUniverse2
+        , cmdUniverse3
+        , cmdShowKind
+        , cmdTypeEquiv
+        , cmdShowWType
+        , cmdShowType
+        , cmdExpRecon
+        , ShowTypeMode(..)
+        , cmdCheckModuleFromFile
+        , cmdCheckModuleFromString
+        , cmdParseCheckType
+        , cmdParseCheckExp)
+where
+import DDC.Driver.Source
+import DDC.Driver.Output
+import DDC.Build.Language
+import DDC.Core.Fragment
+import DDC.Core.Load
+import DDC.Core.Parser
+import DDC.Core.Lexer
+import DDC.Core.Module
+import DDC.Core.Exp
+import DDC.Core.Pretty
+import DDC.Core.Compounds
+import DDC.Type.Transform.SpreadT
+import DDC.Type.Universe
+import DDC.Type.Equiv
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import qualified DDC.Base.Parser        as BP
+import qualified DDC.Type.Check         as T
+
+
+-- universe -------------------------------------------------------------------
+-- | Show the universe of some type.
+cmdUniverse :: Language -> Source -> String -> IO ()
+cmdUniverse language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment bundle
+ , profile              <- fragmentProfile fragment
+ = do   result          <- cmdParseCheckType source fragment str
+        case result of
+         Just (t, _)
+          | Just u      <- universeOfType (profilePrimKinds profile) t
+          ->    outDocLn $ ppr u
+
+         _ ->   outDocLn $ text "no universe"
+
+
+-- | Given the type of some thing (up one level)
+--   show the universe of the thing.
+cmdUniverse1 :: Language -> Source -> String -> IO ()
+cmdUniverse1 language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment bundle
+ , profile              <- fragmentProfile fragment
+ = do   result          <- cmdParseCheckType source fragment str
+        case result of
+         Just (t, _)
+          | Just u      <- universeFromType1 (profilePrimKinds profile) t
+          ->    outDocLn $ ppr u
+
+         _ ->   outDocLn $ text "no universe"
+
+
+-- | Given the kind of some thing (up two levels)
+--   show the universe of the thing.
+cmdUniverse2 :: Language -> Source -> String -> IO ()
+cmdUniverse2 language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment bundle
+ = do   result          <- cmdParseCheckType source fragment str
+        case result of
+         Just (t, _)
+          | Just u      <- universeFromType2 t
+          ->    outDocLn $ ppr u
+
+         _ ->   outDocLn $ text "no universe"
+
+
+-- | Given the sort of some thing (up three levels)
+--   show the universe of the thing.
+--   We can't type check naked sorts, so just parse them.
+cmdUniverse3 :: Language -> Source -> String -> IO ()
+cmdUniverse3 language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = let  srcName = nameOfSource source
+        srcLine = lineStartOfSource source
+        kenv    = profilePrimKinds profile
+
+        -- Parse the tokens.
+        goParse toks                
+         = case BP.runTokenParser describeTok srcName pType toks of
+            Left err    -> outDocLn $ ppr err
+            Right t     -> goUniverse3 (spreadT kenv t)
+
+        goUniverse3 tt
+         = case universeFromType3 tt of
+            Just u      -> outDocLn $ ppr u
+            Nothing     -> outDocLn $ text "no universe"
+
+   in   goParse (fragmentLexExp fragment srcName srcLine str)
+
+
+-- kind ------------------------------------------------------------------------
+-- | Show the kind of a type.
+cmdShowKind :: Language -> Source -> String -> IO ()
+cmdShowKind language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = let  srcName = nameOfSource source
+        srcLine = lineStartOfSource source
+        toks    = fragmentLexExp fragment srcName srcLine str
+        eTK     = loadType profile srcName toks
+   in   case eTK of
+         Left err       -> outDocLn $ ppr err
+         Right (t, k)   -> outDocLn $ ppr t <+> text "::" <+> ppr k
+
+
+-- tequiv ---------------------------------------------------------------------
+-- | Check if two types are equivlant.
+cmdTypeEquiv :: Language -> Source -> String -> IO ()
+cmdTypeEquiv language source ss
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = let  srcName = nameOfSource source
+        srcLine = lineStartOfSource source
+        
+        goParse toks
+         = case BP.runTokenParser describeTok (nameOfSource source)
+                        (do t1 <- pTypeAtom
+                            t2 <- pTypeAtom
+                            return (t1, t2))
+                        toks
+            of Left err -> outDocLn $ text "parse error " <> ppr err
+               Right tt -> goEquiv tt
+         
+        goEquiv (t1, t2)
+         = do   b1 <- checkT t1
+                b2 <- checkT t2
+                if b1 && b2 
+                 then outStrLn $ show $ equivT t1 t2    
+                 else return ()
+
+        defs    = profilePrimDataDefs profile
+        kenv    = profilePrimKinds    profile
+
+        checkT t
+         = case T.checkType defs kenv (spreadT kenv t) of
+                Left err 
+                 -> do  outDocLn $ ppr err
+                        return False
+
+                Right{} 
+                 ->     return True
+
+   in goParse (fragmentLexExp fragment srcName srcLine ss)
+
+
+-- wtype ----------------------------------------------------------------------
+-- | Show the type of a witness.
+cmdShowWType :: Language -> Source -> String -> IO ()
+cmdShowWType language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = let  srcName = nameOfSource source
+        srcLine = lineStartOfSource source
+        toks    = fragmentLexExp fragment srcName srcLine str
+        eTK     = loadWitness profile srcName toks
+   in   case eTK of
+         Left err       -> outDocLn $ ppr err
+         Right (t, k)   -> outDocLn $ ppr t <+> text "::" <+> ppr k
+
+
+-- check / type / effect / closure --------------------------------------------
+-- | What components of the checked type to display.
+data ShowTypeMode
+        = ShowTypeAll
+        | ShowTypeValue
+        | ShowTypeEffect
+        | ShowTypeClosure
+        deriving (Eq, Show)
+
+
+-- | Show the type of an expression.
+cmdShowType :: Language -> ShowTypeMode -> Source -> String -> IO ()
+cmdShowType language mode source ss
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , modules              <- bundleModules   bundle
+ = cmdParseCheckExp fragment modules True source ss >>= goResult
+ where
+        goResult Nothing
+         = return ()
+
+        goResult (Just x)
+         = let  -- This will always succeed because a well typed expression
+                -- is never a naked type or witness, and only those don't
+                -- have annotations.
+                Just annot      = takeAnnotOfExp x
+
+                t               = annotType annot
+                eff             = annotEffect annot
+                clo             = annotClosure annot
+           in case mode of
+                ShowTypeAll
+                 -> do  outDocLn $ ppr x
+                        outDocLn $ text ":*:" <+> ppr t
+                        outDocLn $ text ":!:" <+> ppr eff
+                        outDocLn $ text ":$:" <+> ppr clo
+        
+                ShowTypeValue
+                 ->     outDocLn $ ppr x <+> text "::" <+> ppr t
+        
+                ShowTypeEffect
+                 ->     outDocLn $ ppr x <+> text ":!" <+> ppr eff
+
+                ShowTypeClosure
+                 ->     outDocLn $ ppr x <+> text ":$" <+> ppr clo
+
+
+-- Recon ----------------------------------------------------------------------
+-- | Check expression and reconstruct type annotations on binders.
+cmdExpRecon :: Language -> Source -> String -> IO ()
+cmdExpRecon language source ss
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , modules              <- bundleModules   bundle
+ =   cmdParseCheckExp fragment modules True source ss 
+ >>= goResult
+ where
+        goResult Nothing
+         = return ()
+
+        goResult (Just x)
+         = outDocLn $ ppr x
+
+
+-- Check ----------------------------------------------------------------------
+-- | Parse and type-check a core module from a file.
+cmdCheckModuleFromFile
+        :: (Ord n, Show n, Pretty n, Pretty (err (AnTEC () n)))
+        => Fragment n err
+        -> FilePath
+        -> ErrorT String IO (Module (AnTEC () n) n)
+
+cmdCheckModuleFromFile fragment filePath
+ = goLoad 
+ where  lexModule =  fragmentLexModule fragment filePath 1
+
+        -- Load and type-check the module.
+        goLoad 
+         = do   mModule <- liftIO 
+                        $ loadModuleFromFile 
+                                (fragmentProfile fragment) lexModule filePath
+                case mModule of
+                 Left  err      -> throwError (renderIndent $ ppr err)
+                 Right mm       -> goCheckFragment mm
+
+        -- Do fragment specific checks.
+        goCheckFragment mm
+         = case fragmentCheckModule fragment mm of
+                Just err        -> throwError (renderIndent $ ppr err)
+                Nothing         -> return mm
+
+
+-- | Parse and type-check a core module from a string.
+cmdCheckModuleFromString
+        :: (Ord n, Show n, Pretty n, Pretty (err (AnTEC () n)))
+        => Fragment n err
+        -> Source
+        -> String
+        -> ErrorT String IO (Module (AnTEC () n) n)
+
+cmdCheckModuleFromString fragment source str
+ = goLoad
+ where  lexModule = fragmentLexModule fragment 
+                        (nameOfSource source) 
+                        (lineStartOfSource source)
+
+        -- Load and type-check the module.
+        goLoad
+         = let  mModule = loadModuleFromString
+                                (fragmentProfile fragment) lexModule
+                                (nameOfSource source)
+                                str
+
+            in  case mModule of
+                  Left err       -> throwError (renderIndent $ ppr err)
+                  Right mm       -> goCheckFragment mm
+
+        goCheckFragment mm
+         = case fragmentCheckModule fragment mm of
+                Just err        -> throwError  (renderIndent $ ppr err)
+                Nothing         -> return mm
+
+
+-- | Parse a core type, and check its kind.
+cmdParseCheckType 
+        :: (Ord n, Show n, Pretty n)
+        => Source
+        -> Fragment n err
+        -> String 
+        -> IO (Maybe (Type n, Kind n))
+
+cmdParseCheckType source frag str
+ = let  srcName = nameOfSource source
+        srcLine = lineStartOfSource source
+        toks    = fragmentLexExp frag srcName srcLine str
+        eTK     = loadType (fragmentProfile frag) srcName toks
+   in   case eTK of
+         Left err       
+          -> do outDocLn $ ppr err
+                return Nothing
+
+         Right (t, k)
+          ->    return $ Just (t, k)
+
+
+-- | Parse the given core expression, 
+--   and return it, along with its type, effect and closure.
+--
+--   If the expression had a parse error, undefined vars, or type error
+--   then print this to the console.
+--
+--   We include a flag to override the language profile to allow partially
+--   applied primitives. Although a paticular evaluator (or backend) may not
+--   support partially applied primitives, we want to accept them if we are
+--   only loading an expression to check its type.
+--
+cmdParseCheckExp 
+        :: (Ord n, Show n, Pretty n, Pretty (err (AnTEC () n)))
+        => Fragment n err       -- ^ The current language fragment.
+        -> ModuleMap (AnTEC () n) n -- ^ Current modules
+        -> Bool                 -- ^ Allow partial application of primitives.
+        -> Source               -- ^ Where this expression was sourced from.
+        -> String               -- ^ Text to parse.
+        -> IO (Maybe ( Exp (AnTEC () n) n))
+
+cmdParseCheckExp frag modules permitPartialPrims source str
+ = goLoad (fragmentLexExp frag (nameOfSource source) (lineStartOfSource source) str)
+ where
+        -- Override profile to allow partially applied primitives if we were
+        -- told to do so.
+        profile   = fragmentProfile frag
+        features  = profileFeatures profile
+        features' = features { featuresPartialPrims 
+                             = featuresPartialPrims features || permitPartialPrims}
+        profile'  = profile  { profileFeatures  = features' }
+        frag'     = frag     { fragmentProfile  = profile'  }
+
+        -- Parse and type check the expression.
+        goLoad toks
+         = case loadExp (fragmentProfile frag') modules (nameOfSource source) toks of
+              Left err
+               -> do    putStrLn $ renderIndent $ ppr err
+                        return Nothing
+
+              Right result
+               -> goCheckFragment result
+
+        -- Do fragment specific checks.
+        goCheckFragment x
+         = case fragmentCheckExp frag' x of
+             Just err 
+              -> do     putStrLn $ renderIndent $ ppr err
+                        return Nothing
+
+             Nothing  
+              -> do     return (Just x)
diff --git a/DDC/Driver/Command/Compile.hs b/DDC/Driver/Command/Compile.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/Compile.hs
@@ -0,0 +1,68 @@
+
+module DDC.Driver.Command.Compile
+        (cmdCompile)
+where
+import DDC.Driver.Stage
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language.Salt          as Salt
+import System.Directory
+import Control.Monad
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import Data.List
+import qualified DDC.Core.Pretty        as P
+
+
+-- | Compile a source module into a @.o@ file.
+-- 
+cmdCompile :: Config -> FilePath -> ErrorT String IO ()
+cmdCompile config filePath
+ = do   
+        -- Read in the source file.
+        exists  <- liftIO $ doesFileExist filePath
+        when (not exists)
+         $ throwError $ "No such file " ++ show filePath
+
+        src             <- liftIO $ readFile filePath
+        let source      = SourceFile filePath
+
+        -- Decide what to do based on file extension.
+        let make
+                -- Make a Core Lite module.
+                | isSuffixOf ".dcl" filePath
+                = liftIO 
+                $ pipeText (nameOfSource source) (lineStartOfSource source) src
+                $ stageLiteLoad     config source
+                [ stageLiteOpt      config source  
+                [ stageLiteToSalt   config source pipesSalt ]]
+
+                -- Make a Core Salt module.
+                | isSuffixOf ".dcs" filePath
+                = liftIO 
+                $ pipeText (nameOfSource source) (lineStartOfSource source) src
+                $ PipeTextLoadCore  Salt.fragment pipesSalt
+
+                -- Unrecognised.
+                | otherwise
+                = throwError $ "Don't know how to compile " ++ filePath
+
+            pipesSalt
+             = case configViaBackend config of
+                ViaLLVM
+                 -> [ PipeCoreStrip
+                    [ stageSaltOpt      config source
+                    [ stageSaltToLLVM   config source 
+                    [ stageCompileLLVM  config source filePath False ]]]]
+
+                ViaC
+                 -> [ PipeCoreStrip
+                    [ stageSaltOpt      config source
+                    [ stageCompileSalt  config source filePath False ]]]
+
+        -- Throw any errors that arose during compilation.
+        errs <- make
+        case errs of
+         []     -> return ()
+         es     -> throwError $ P.renderIndent $ P.vcat $ map P.ppr es
+
diff --git a/DDC/Driver/Command/Load.hs b/DDC/Driver/Command/Load.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/Load.hs
@@ -0,0 +1,159 @@
+
+module DDC.Driver.Command.Load
+        ( cmdReadModule
+        , cmdLoadFromFile
+        , cmdLoadFromString)
+where
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language
+import DDC.Core.Simplifier.Parser
+import DDC.Core.Module
+import DDC.Core.Load
+import DDC.Core.Pretty
+import DDC.Data.Canned
+import Control.DeepSeq
+import Control.Monad
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import Data.IORef
+import System.Directory
+import System.FilePath
+import System.IO
+import qualified Data.Map               as Map
+
+
+-- Read -----------------------------------------------------------------------
+-- | Load and typecheck a module.
+cmdReadModule 
+        :: (Ord n, Show n, Pretty n, NFData n)
+        => Fragment n err       -- ^ Language fragment.
+        -> FilePath             -- ^ Path to the module.
+        -> IO (Maybe (Module (AnTEC () n) n))
+
+cmdReadModule frag filePath
+ = do
+        -- Read in the source file.
+        exists  <- doesFileExist filePath
+        when (not exists)
+         $      error $ "No such file " ++ show filePath
+
+        src     <- readFile filePath
+        let source   = SourceFile filePath
+
+        cmdReadModule_parse filePath frag source src
+
+
+cmdReadModule_parse filePath frag source src
+ = do   ref     <- newIORef Nothing
+        errs    <- pipeText (nameOfSource source) (lineStartOfSource source) src
+                $  PipeTextLoadCore frag
+                   [ PipeCoreHacks (Canned (\m -> writeIORef ref (Just m) >> return m)) 
+                     [PipeCoreOutput SinkDiscard] ]
+
+        case errs of
+         [] -> do
+                readIORef ref
+
+         _ -> do
+                putStrLn $ "When reading " ++ filePath
+                mapM_ (hPutStrLn stderr . renderIndent . ppr) errs
+                return Nothing
+
+
+-------------------------------------------------------------------------------
+-- | Load and transform a module, printing the result to stdout.
+--   The current transform is set with the given string.
+cmdLoadFromFile
+        :: Maybe String         -- ^ Simplifier specification.
+        -> [FilePath]           -- ^ More modules to use as inliner templates.
+        -> FilePath             -- ^ Module file name.
+        -> ErrorT String IO ()
+
+cmdLoadFromFile strSimpl fsTemplates filePath
+ = case languageOfExtension (takeExtension filePath) of
+        Nothing       -> throwError $ "Unknown file extension."
+        Just language -> cmdLoad_language strSimpl fsTemplates filePath language
+
+cmdLoad_language Nothing _ filePath language
+ = configLoad_simpl language filePath
+
+cmdLoad_language (Just strSimpl) fsTemplates filePath language
+ | Language bundle      <- language
+ , modules              <- bundleModules       bundle
+ , rules                <- bundleRewriteRules  bundle
+ , mkNamT               <- bundleMakeNamifierT bundle
+ , mkNamX               <- bundleMakeNamifierX bundle
+ , fragment             <- bundleFragment      bundle
+ , readName             <- fragmentReadName    fragment
+ = do
+        let rules'          = Map.assocs rules
+
+        -- Load all the modues that we're using for inliner templates.
+        --  If any of these don't load then the 'cmdReadModule' function 
+        --  will display the errors.
+        mMoreModules
+         <- liftM sequence
+         $  mapM (liftIO . cmdReadModule fragment)
+                 fsTemplates
+
+        moreModules
+         <- case mMoreModules of
+                 Nothing -> throwError $ "Imported modules do not parse."
+                 Just ms -> return ms
+
+        -- Collect all definitions from modules
+        let templateModules
+                = moreModules ++ (Map.elems modules)
+
+        -- Simplifier details for the parser.
+        let details
+                = SimplifierDetails mkNamT mkNamX rules' 
+                        templateModules
+
+        case parseSimplifier readName details strSimpl of
+         Left err
+          -> throwError $ renderIndent $ ppr err
+
+         Right simpl
+          -> let bundle' = bundle { bundleSimplifier = simpl }
+             in  configLoad_simpl (Language bundle') filePath
+
+configLoad_simpl language filePath
+ = do   
+        -- Check that the file exists.
+        exists  <- liftIO $ doesFileExist filePath
+        when (not exists)
+         $ throwError $ "No such file " ++ show filePath
+
+        -- Read in the source file.
+        src     <- liftIO $ readFile filePath
+
+        cmdLoadFromString language (SourceFile filePath) src
+
+
+-------------------------------------------------------------------------------
+-- | Load and transform a module, 
+--   then print the result to @stdout@.
+cmdLoadFromString
+        :: Language             -- ^ Language definition
+        -> Source               -- ^ Source of the code.
+        -> String               -- ^ Program module text.
+        -> ErrorT String IO ()
+
+cmdLoadFromString language source str
+ | Language bundle      <- language
+ , fragment             <- bundleFragment   bundle
+ , simpl                <- bundleSimplifier bundle
+ , zero                 <- bundleStateInit  bundle
+ = do   errs    <- liftIO
+                $  pipeText (nameOfSource source) (lineStartOfSource source) str
+                $  PipeTextLoadCore  fragment
+                [  PipeCoreSimplify  fragment zero simpl
+                [  PipeCoreCheck     fragment
+                [  PipeCoreOutput    SinkStdout ]]]
+
+        case errs of
+         [] -> return ()
+         es -> throwError $ renderIndent $ vcat $ map ppr es
+
diff --git a/DDC/Driver/Command/Make.hs b/DDC/Driver/Command/Make.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/Make.hs
@@ -0,0 +1,66 @@
+
+module DDC.Driver.Command.Make
+        (cmdMake)
+where
+import DDC.Driver.Stage
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language.Salt          as Salt
+import System.Directory
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import Control.Monad
+import Data.List
+import qualified DDC.Core.Pretty        as P
+
+
+-- | Make a source module into an executable.
+cmdMake :: Config -> FilePath -> ErrorT String IO ()
+cmdMake config filePath
+ = do
+        -- Read in the source file.
+        exists  <- liftIO $ doesFileExist filePath
+        when (not exists)
+         $ throwError $ "No such file " ++ show filePath
+
+        src             <- liftIO $ readFile filePath
+        let source      = SourceFile filePath
+
+        -- Decide what to do based on file extension.
+        let make
+                -- Make a Core Lite module.
+                | isSuffixOf ".dcl" filePath
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) src
+                $ stageLiteLoad     config source
+                [ stageLiteOpt      config source  
+                [ stageLiteToSalt   config source pipesSalt ]]
+
+                -- Make a Core Salt module.
+                | isSuffixOf ".dcs" filePath
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) src
+                $ PipeTextLoadCore  Salt.fragment pipesSalt
+
+                -- Unrecognised.
+                | otherwise
+                = throwError $ "Don't know how to make " ++ filePath
+
+            pipesSalt
+             = case configViaBackend config of
+                ViaLLVM
+                 -> [ PipeCoreStrip
+                    [ stageSaltOpt      config source
+                    [ stageSaltToLLVM   config source 
+                    [ stageCompileLLVM  config source filePath True ]]]]
+
+                ViaC
+                 -> [ PipeCoreStrip
+                    [ stageSaltOpt      config source
+                    [ stageCompileSalt  config source filePath True ]]]
+
+        -- Throw any errors that arose during compilation.
+        errs <- make
+        case errs of
+         []     -> return ()
+         es     -> throwError $ P.renderIndent $ P.vcat $ map P.ppr es
diff --git a/DDC/Driver/Command/RewriteRules.hs b/DDC/Driver/Command/RewriteRules.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/RewriteRules.hs
@@ -0,0 +1,84 @@
+
+module DDC.Driver.Command.RewriteRules
+        ( cmdTryReadRules )
+where
+import DDC.Driver.Source
+import DDC.Build.Language
+import DDC.Core.Fragment
+import DDC.Core.Simplifier
+import DDC.Core.Module
+import DDC.Core.Lexer
+import DDC.Core.Pretty
+import DDC.Core.Transform.Reannotate
+import DDC.Core.Transform.Rewrite.Rule  hiding (Error)
+import DDC.Core.Transform.Rewrite.Parser
+import Control.DeepSeq
+import System.Directory
+import System.IO
+import qualified DDC.Base.Parser        as BP
+import qualified DDC.Core.Check         as C
+import qualified DDC.Type.Env                     as Env
+
+
+-- Read rewrite rules ---------------------------------------------------------
+-- | Load and typecheck a module's rewrite rules, using exported and imported
+--   definitions from module
+cmdTryReadRules 
+        :: (Ord n, Show n, Pretty n, NFData n)
+        => Fragment n err       -- ^ Language fragment.
+        -> FilePath             -- ^ Path to the module.
+        -> Module () n          -- ^ Module with types of imports and exports
+        -> IO (NamedRewriteRules () n)
+
+cmdTryReadRules frag filePath modu
+ = do
+        exists  <- doesFileExist filePath
+        -- Silently return an empty list if there is no rules file
+        case exists of
+         False -> return []
+         True  -> do
+            -- Read the source file
+            src        <- readFile filePath
+            let source =  SourceFile filePath
+            -- Parse and typecheck
+            cmdReadRules_parse filePath frag modu source src
+
+
+cmdReadRules_parse filePath frag modu source src
+ = case parse frag modu source src of
+    Left err -> do
+        putStrLn $ "When reading " ++ filePath
+        hPutStrLn stderr err
+        return []
+    Right rules -> return rules
+
+
+parse fragment modu source str
+ = case BP.runTokenParser describeTok source' pRuleMany
+          (fragmentLexExp fragment source' 0 str) of
+                Left err -> Left $ renderIndent $ ppr err
+                Right rules ->
+                  case mapM check' rules of
+                    Left err     -> Left  $ renderIndent $ ppr err
+                    Right rules' -> Right $ rules'
+ where
+    -- Typecheck, then clear annotations
+    check' (n,r)
+     = do r' <- checkRewriteRule config kinds' types' r
+          return (show n, reannotate (const ()) r')
+
+    config   = C.configOfProfile (fragmentProfile fragment)
+    kinds    = profilePrimKinds  (fragmentProfile fragment)
+    types    = profilePrimTypes  (fragmentProfile fragment)
+
+    kindsImp = moduleKindEnv modu
+    typesImp = moduleTypeEnv modu
+
+    kindsExp = modulesGetBinds $ moduleExportKinds modu
+    typesExp = modulesGetBinds $ moduleExportTypes modu
+
+    -- Final kind and type environments
+    kinds'	 = kinds `Env.union` kindsImp `Env.union` kindsExp
+    types'	 = types `Env.union` typesImp `Env.union` typesExp
+
+    source'  = nameOfSource source
diff --git a/DDC/Driver/Command/ToC.hs b/DDC/Driver/Command/ToC.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/ToC.hs
@@ -0,0 +1,70 @@
+
+module DDC.Driver.Command.ToC
+        (cmdToC)
+where
+import DDC.Driver.Stage
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language
+import DDC.Core.Fragment
+import System.FilePath
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import qualified DDC.Build.Language.Salt        as Salt
+import qualified DDC.Build.Language.Lite        as Lite
+import qualified DDC.Base.Pretty                as P
+
+
+-- | Parse, check, and convert a module to C.
+--
+--   The output is printed to @stdout@. 
+--
+cmdToC  :: Config       -- ^ Compiler configuration.
+        -> Language     -- ^ Language definition.
+        -> Source       -- ^ Source of the code.
+        -> String       -- ^ Program module text.
+        -> ErrorT String IO ()
+
+cmdToC config language source sourceText
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = do   
+        let fragName = profileName profile
+        let mSuffix  = case source of 
+                        SourceFile filePath     -> Just $ takeExtension filePath
+                        _                       -> Nothing
+
+        -- Decide what to do based on file extension and current fragment.
+        let compile
+                -- Compile a Core Lite module.
+                | fragName == "Lite" || mSuffix == Just ".dcl"
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) sourceText
+                $ PipeTextLoadCore Lite.fragment
+                [ PipeCoreStrip
+                [ stageLiteOpt     config source 
+                [ stageLiteToSalt  config source 
+                [ stageSaltOpt     config source
+                [ stageSaltToC     config source SinkStdout]]]]]
+
+                -- Compile a Core Salt module.
+                | fragName == "Salt" || mSuffix == Just ".dcs"
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) sourceText
+                $ PipeTextLoadCore Salt.fragment
+                [ PipeCoreStrip
+                [ stageSaltOpt     config source
+                [ stageSaltToC     config source SinkStdout]]]
+
+                -- Unrecognised.
+                | otherwise
+                = throwError "Don't know how to convert this to C"
+
+
+        -- Throw any errors that arose during compilation
+        errs <- compile
+        case errs of
+         []     -> return ()
+         es     -> throwError $ P.renderIndent $ P.vcat $ map P.ppr es
+
diff --git a/DDC/Driver/Command/ToLlvm.hs b/DDC/Driver/Command/ToLlvm.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/ToLlvm.hs
@@ -0,0 +1,70 @@
+
+module DDC.Driver.Command.ToLlvm
+        (cmdToLlvm)
+where
+import DDC.Driver.Stage
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language
+import DDC.Core.Fragment
+import System.FilePath
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import qualified DDC.Build.Language.Salt        as Salt
+import qualified DDC.Build.Language.Lite        as Lite
+import qualified DDC.Base.Pretty                as P
+
+
+-- | Parse, check and convert a  module to LLVM.
+--
+--   The output is printed to @stdout@. 
+--
+cmdToLlvm 
+        :: Config       -- ^ Compiler configuration.
+        -> Language     -- ^ Language definition.
+        -> Source       -- ^ Source of the code.
+        -> String       -- ^ Program module text.
+        -> ErrorT String IO ()
+
+cmdToLlvm config language source sourceText
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = do   let fragName = profileName profile
+        let mSuffix  = case source of 
+                        SourceFile filePath     -> Just $ takeExtension filePath
+                        _                       -> Nothing
+
+        -- Decide what to do based on file extension and current fragment.
+        let compile
+                -- Compile a Core Lite module.
+                | fragName == "Lite" || mSuffix == Just ".dcl"
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) sourceText
+                $ PipeTextLoadCore Lite.fragment
+                [ PipeCoreStrip
+                [ stageLiteOpt     config source
+                [ stageLiteToSalt  config source
+                [ stageSaltOpt     config source
+                [ stageSaltToLLVM  config source 
+                [ PipeLlvmPrint SinkStdout]]]]]]
+
+                -- Compile a Core Salt module.
+                | fragName == "Salt" || mSuffix == Just ".dcs"
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) sourceText
+                $ PipeTextLoadCore Salt.fragment
+                [ PipeCoreStrip
+                [ stageSaltOpt     config source
+                [ stageSaltToLLVM  config source
+                [ PipeLlvmPrint SinkStdout]]]]
+
+                -- Unrecognised.
+                | otherwise
+                = throwError $ "Don't know how to convert this to LLVM"
+
+        -- Throw any errors that arose during compilation
+        errs <- compile
+        case errs of
+         []     -> return ()
+         es     -> throwError $ P.renderIndent $ P.vcat $ map P.ppr es
diff --git a/DDC/Driver/Command/ToSalt.hs b/DDC/Driver/Command/ToSalt.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Command/ToSalt.hs
@@ -0,0 +1,76 @@
+
+module DDC.Driver.Command.ToSalt
+        (cmdToSalt)
+where
+import DDC.Driver.Stage
+import DDC.Driver.Source
+import DDC.Build.Pipeline
+import DDC.Build.Language
+import DDC.Core.Fragment
+import DDC.Core.Module
+import DDC.Data.Canned
+import System.FilePath
+import Control.Monad.Trans.Error
+import Control.Monad.IO.Class
+import qualified DDC.Build.Language.Salt        as Salt
+import qualified DDC.Build.Language.Lite        as Lite
+import qualified DDC.Base.Pretty                as P
+import qualified Data.Map                       as Map
+
+
+-- | Parse, check, and fully evaluate an expression.
+--
+--   The output is printed to @stdout@.
+---
+--   The Core -> Salt conversion only accepts A-normalised programs,
+--   so we normalize it along the way.
+--
+cmdToSalt 
+        :: Config       -- ^ Compiler configuration.
+        -> Language     -- ^ Language definition.
+        -> Source       -- ^ Source of the code.
+        -> String       -- ^ Program module text.
+        -> ErrorT String IO ()
+
+cmdToSalt config language source sourceText
+ | Language bundle      <- language
+ , fragment             <- bundleFragment  bundle
+ , profile              <- fragmentProfile fragment
+ = do   let fragName = profileName profile
+        let mSuffix  = case source of 
+                        SourceFile filePath     -> Just $ takeExtension filePath
+                        _                       -> Nothing
+
+        -- Decide what to do based on file extension and current fragment.
+        let compile
+                -- Compile a Core Lite module.
+                | fragName == "Lite" || mSuffix == Just ".dcl"
+                = liftIO
+                $ pipeText (nameOfSource source) (lineStartOfSource source) sourceText
+                $ PipeTextLoadCore Lite.fragment
+                [ PipeCoreStrip
+                [ stageLiteOpt     config source
+                [ stageLiteToSalt  config source
+                [ stageSaltOpt     config source
+                [ PipeCoreCheck    Salt.fragment
+                [ (if configSuppressCoreImports config
+                        then PipeCoreHacks    (Canned (\x -> return $ eraseImports x))
+                        else PipeCoreId)
+                [ PipeCoreOutput   SinkStdout]]]]]]]
+
+                -- Unrecognised.
+                | otherwise
+                = throwError $ "Don't know how to convert this to Salt"
+
+        -- Throw any errors that arose during compilation
+        errs <- compile
+        case errs of
+         []     -> return ()
+         es     -> throwError $ P.renderIndent $ P.vcat $ map P.ppr es
+
+
+-- | Erase the import list of a module.
+eraseImports :: Module a n -> Module a n
+eraseImports mm
+ = mm   { moduleImportKinds     = Map.empty
+        , moduleImportTypes     = Map.empty }
diff --git a/DDC/Driver/Output.hs b/DDC/Driver/Output.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Output.hs
@@ -0,0 +1,37 @@
+
+module DDC.Driver.Output
+        ( outDoc, outDocLn
+        , outStr, outStrLn
+        , chatStrLn)
+where
+import DDC.Base.Pretty
+
+
+-- | Output a document to the console.
+outDoc :: Doc -> IO ()
+outDoc doc
+        = putDoc   RenderIndent doc
+
+-- | Output a document and newline to the console.
+outDocLn :: Doc -> IO ()
+outDocLn doc
+        = putDocLn RenderIndent doc
+
+
+-- | Output a string to the console.
+outStr :: String -> IO ()
+outStr str
+        = putStr str
+
+
+-- | Output a string and newline to the console.
+outStrLn :: String -> IO ()
+outStrLn str
+        = putStrLn str
+
+
+-- | Output chatty 'ok' type responses.
+--   These are only displayed in the Interactive and Batch interfaces.
+chatStrLn :: String -> IO ()
+chatStrLn str
+        = putStrLn str
diff --git a/DDC/Driver/Source.hs b/DDC/Driver/Source.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Source.hs
@@ -0,0 +1,43 @@
+
+module DDC.Driver.Source
+        ( Source(..)
+        , lineStartOfSource
+        , nameOfSource)
+where
+
+-- | Where some source code was obtained from.
+--
+--   This is used when generating error messages.
+data Source
+        -- | Read directly from a file.
+        = SourceFile            FilePath 
+
+        -- | Supplied on the command line.
+        | SourceArgs            
+
+        -- | Typed into the console.
+        | SourceConsole         Int
+
+        -- | Part of a @.dcx@ batch file.
+        | SourceBatch           FilePath Int
+        deriving (Eq, Show)
+
+
+-- | Get the starting source line number to report for this source.
+lineStartOfSource :: Source -> Int
+lineStartOfSource ss
+ = case ss of
+        SourceFile{}            -> 1
+        SourceArgs{}            -> 1
+        SourceConsole i         -> i
+        SourceBatch _ i         -> i
+
+
+-- | Get the name of a source.
+nameOfSource :: Source -> String
+nameOfSource ss
+ = case ss of
+        SourceFile f            -> f
+        SourceArgs              -> "<arg>"
+        SourceConsole{}         -> "<console>"
+        SourceBatch{}           -> "<batch>"
diff --git a/DDC/Driver/Stage.hs b/DDC/Driver/Stage.hs
new file mode 100644
--- /dev/null
+++ b/DDC/Driver/Stage.hs
@@ -0,0 +1,302 @@
+-- | Compiler stages.
+--
+--     A compiler stage is a sequence of standard transformations.
+--     Each of the individual transformations are expressed as a pipeline from 
+--     "DDC.Build.Pipeline". The stages here run several pipelines each,
+--     and contain the code that can dump the intermediate program after
+--     each transformation.
+--
+module DDC.Driver.Stage
+        ( Config        (..)
+        , ViaBackend    (..)
+
+          -- * Lite stages
+        , stageLiteLoad
+        , stageLiteOpt
+        , stageLiteToSalt
+
+          -- * Salt stages
+        , stageSaltOpt
+        , stageSaltToC
+        , stageSaltToLLVM
+        , stageCompileSalt
+
+          -- * LLVM stages
+        , stageCompileLLVM)
+where
+import DDC.Driver.Source
+import DDC.Build.Builder
+import DDC.Build.Pipeline
+import DDC.Core.Transform.Namify
+import DDC.Core.Simplifier                      (Simplifier)
+import System.FilePath
+import Data.Maybe
+import qualified DDC.Core.Simplifier.Recipe     as S
+import qualified DDC.Build.Language.Salt        as Salt
+import qualified DDC.Build.Language.Lite        as Lite
+import qualified DDC.Core.Lite                  as Lite
+import qualified DDC.Core.Salt.Name             as Salt
+import qualified DDC.Core.Salt.Runtime          as Salt
+
+
+-- | Configuration for main compiler stages.
+data Config
+        = Config
+        { -- | Dump intermediate code.
+          configDump                    :: Bool
+
+          -- | Simplifiers to apply to intermediate code
+        , configSimplLite               :: Simplifier Int () Lite.Name
+        , configSimplSalt               :: Simplifier Int () Salt.Name
+
+          -- | Backend code generator to use
+        , configViaBackend              :: ViaBackend
+
+          -- | Runtime system configuration
+        , configRuntime                 :: Salt.Config
+
+          -- | The builder to use for the target architecture
+        , configBuilder                 :: Builder
+
+          -- | Suppress imports in Core modules
+        , configSuppressCoreImports     :: Bool
+
+          -- | Suppress the #import prelude in C modules
+        , configSuppressHashImports     :: Bool 
+
+          -- | Override output file
+        , configOutputFile              :: Maybe FilePath
+
+          -- | Override directory for build products
+        , configOutputDir               :: Maybe FilePath
+
+          -- | Keep intermediate .ddc.ll files
+        , configKeepLlvmFiles           :: Bool
+
+          -- | Keep intermediate .ddc.c files
+        , configKeepSeaFiles            :: Bool
+
+          -- | Keep intermediate .ddc.s files
+        , configKeepAsmFiles            :: Bool
+        }
+
+
+data ViaBackend
+        -- | Compile via the C backend.
+        = ViaC
+
+        -- | Compile via the LLVM backend.
+        | ViaLLVM
+        deriving Show
+
+
+-------------------------------------------------------------------------------
+-- | Type check Core Lite.
+stageLiteLoad
+        :: Config -> Source
+        -> [PipeCore () Lite.Name]
+        -> PipeText Lite.Name Lite.Error
+
+stageLiteLoad config source pipesLite
+ = PipeTextLoadCore Lite.fragment
+ [ PipeCoreStrip
+        ( PipeCoreOutput (dump config source "dump.lite.dcl")
+        : pipesLite ) ]
+
+
+-------------------------------------------------------------------------------
+-- | Optimise Core Lite.
+stageLiteOpt 
+        :: Config -> Source
+        -> [PipeCore () Lite.Name]
+        ->  PipeCore () Lite.Name
+
+stageLiteOpt config source pipes
+ = PipeCoreSimplify 
+        Lite.fragment
+        (0 :: Int) 
+        (configSimplLite config)
+        ( PipeCoreOutput (dump config source "dump.lite-opt.dcl") 
+        : pipes)
+
+
+-------------------------------------------------------------------------------
+-- | Optimise Core Salt.
+stageSaltOpt
+        :: Config -> Source
+        -> [PipeCore () Salt.Name]
+        -> PipeCore  () Salt.Name
+
+stageSaltOpt config source pipes
+ = PipeCoreSimplify 
+        Salt.fragment
+        (0 :: Int) 
+        (configSimplSalt config)        
+        ( PipeCoreOutput  (dump config source "dump.salt-opt.dcl")
+        : pipes )
+
+
+-------------------------------------------------------------------------------
+-- | Convert Core Lite to Core Salt.
+---
+--   The Lite to Salt transform requires the program to be normalised,
+--   and have type annotations.
+stageLiteToSalt 
+        :: Config -> Source
+        -> [PipeCore () Salt.Name] 
+        -> PipeCore  () Lite.Name
+
+stageLiteToSalt config source pipesSalt
+ = PipeCoreSimplify       Lite.fragment 0 normalizeLite
+   [ PipeCoreCheck        Lite.fragment
+     [ PipeCoreOutput     (dump config source "dump.lite-normalized.dcl")
+     , PipeCoreAsLite
+       [ PipeLiteToSalt   (buildSpec $ configBuilder config) 
+                          (configRuntime config)
+         ( PipeCoreOutput (dump config source "dump.salt.dcs")
+         : pipesSalt)]]]
+           
+ where  normalizeLite
+         = S.anormalize
+                (makeNamifier Lite.freshT)      
+                (makeNamifier Lite.freshX)
+
+
+-------------------------------------------------------------------------------
+-- | Convert Core Salt to C code.
+stageSaltToC
+        :: Config -> Source
+        -> Sink
+        -> PipeCore () Salt.Name
+
+stageSaltToC config source sink
+ = PipeCoreSimplify       Salt.fragment 0 normalizeSalt
+   [ PipeCoreCheck        Salt.fragment
+     [ PipeCoreOutput     (dump config source "dump.salt-normalized.dcs")
+     , PipeCoreAsSalt
+       [ PipeSaltTransfer
+         [ PipeSaltOutput (dump config source "dump.salt-transfer.dcs")
+         , PipeSaltPrint
+                (not $ configSuppressHashImports config)
+                (buildSpec $ configBuilder config)
+                sink ]]]]
+
+ where  normalizeSalt
+         = S.anormalize (makeNamifier Salt.freshT) 
+                        (makeNamifier Salt.freshX)
+
+
+-------------------------------------------------------------------------------
+-- | Compile Core Salt via C code.
+stageCompileSalt
+        :: Config -> Source
+        -> FilePath             -- ^ Path of original source file.
+                                --   Build products are placed into the same dir.
+        -> Bool                 -- ^ Should we link this into an executable
+        -> PipeCore () Salt.Name
+
+stageCompileSalt config source filePath shouldLinkExe
+ = let  -- Decide where to place the build products.
+        outputDir      = fromMaybe (takeDirectory filePath) (configOutputDir config)
+        outputDirBase  = dropExtension (replaceDirectory filePath outputDir)
+        cPath          = outputDirBase ++ ".ddc.c"
+        oPath          = outputDirBase ++ ".o"
+        exePathDefault = outputDirBase
+        exePath        = fromMaybe exePathDefault (configOutputFile config)
+   in
+        PipeCoreSimplify        Salt.fragment 0 normalizeSalt
+         [ PipeCoreCheck        Salt.fragment
+           [ PipeCoreOutput     (dump config source "dump.salt-normalized.dcs")
+           , PipeCoreAsSalt
+             [ PipeSaltTransfer
+               [ PipeSaltOutput (dump config source "dump.salt-transfer.dcs")
+               , PipeSaltCompile
+                        (buildSpec $ configBuilder config)
+                        (configBuilder config)
+                        cPath
+                        oPath
+                        (if shouldLinkExe 
+                                then Just exePath 
+                                else Nothing) 
+                        (configKeepSeaFiles config)
+                        ]]]]
+
+ where  normalizeSalt
+         = S.anormalize (makeNamifier Salt.freshT) 
+                        (makeNamifier Salt.freshX)
+
+
+-------------------------------------------------------------------------------
+-- | Convert Core Salt to LLVM.
+stageSaltToLLVM
+        :: Config -> Source
+        -> [PipeLlvm]
+        -> PipeCore () Salt.Name
+
+stageSaltToLLVM config source pipesLLVM
+ = PipeCoreSimplify Salt.fragment 0 normalizeSalt
+   [ PipeCoreCheck          Salt.fragment
+     [ PipeCoreOutput       (dump config source "dump.salt-normalized.dcs")
+     , PipeCoreAsSalt
+       [ PipeSaltTransfer
+         [ PipeSaltOutput   (dump config source "dump.salt-transfer.dcs")
+         , PipeSaltToLlvm   (buildSpec $ configBuilder config) 
+                            pipesLLVM ]]]]
+
+ where  normalizeSalt
+         = S.anormalize (makeNamifier Salt.freshT) 
+                        (makeNamifier Salt.freshX)
+
+
+-------------------------------------------------------------------------------
+-- | Compile LLVM code.
+stageCompileLLVM 
+        :: Config -> Source
+        -> FilePath             -- ^ Path of original source file.
+                                --   Build products are placed into the same dir.
+        -> Bool                 -- ^ Should we link this into an executable
+        -> PipeLlvm
+
+stageCompileLLVM config _source filePath shouldLinkExe
+ = let  -- Decide where to place the build products.
+        outputDir      = fromMaybe (takeDirectory filePath) (configOutputDir config)
+        outputDirBase  = dropExtension (replaceDirectory filePath outputDir)
+        llPath         = outputDirBase ++ ".ddc.ll"
+        sPath          = outputDirBase ++ ".ddc.s"
+        oPath          = outputDirBase ++ ".o"
+        exePathDefault = outputDirBase
+        exePath        = fromMaybe exePathDefault (configOutputFile config)
+   in   -- Make the pipeline for the final compilation.
+        PipeLlvmCompile
+          { pipeBuilder           = configBuilder config
+          , pipeFileLlvm          = llPath
+          , pipeFileAsm           = sPath
+          , pipeFileObject        = oPath
+          , pipeFileExe           = if shouldLinkExe 
+                                        then Just exePath 
+                                        else Nothing 
+          , pipeKeepLlvmFiles     = configKeepLlvmFiles config
+          , pipeKeepAsmFiles      = configKeepAsmFiles  config }
+
+
+------------------------------------------------------------------------------
+-- | If the Dump mode is set 
+--    then produce a SinkFile to write a module to a file, 
+--    otherwise produce SinkDiscard to drop it on the floor.
+dump :: Config -> Source -> String -> Sink
+dump config source dumpFile 
+        | configDump config
+        = let   outputDir
+                 | SourceFile filePath  <- source
+                 = fromMaybe (takeDirectory filePath) 
+                             (configOutputDir config)
+
+                 | otherwise
+                 = fromMaybe "."
+                             (configOutputDir config)
+
+          in    SinkFile $ outputDir </> dumpFile
+
+        | otherwise
+        = SinkDiscard
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+--------------------------------------------------------------------------------
+The Disciplined Disciple Compiler License (MIT style)
+
+Copyrite (K) 2007-2012 The Disciplined Disciple Compiler Strike Force
+All rights reversed.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+-------------------------------------------------------------------------------
+Under Australian law copyright is free and automatic.
+By contributing to DDC authors grant all rights they have regarding their
+contributions to the other members of the Disciplined Disciple Compiler Strike
+Force, past, present and future, as well as placing their contributions under
+the above license.
+
+Use "darcs show authors" to get a list of Strike Force members.
+
+--------------------------------------------------------------------------------
+Redistributions of libraries in ./external are governed by their own licenses:
+
+  - TinyPTC   GNU Lesser General Public License
+  
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/ddc-driver.cabal b/ddc-driver.cabal
new file mode 100644
--- /dev/null
+++ b/ddc-driver.cabal
@@ -0,0 +1,62 @@
+Name:           ddc-driver
+Version:        0.3.1.1
+License:        MIT
+License-file:   LICENSE
+Author:         The Disciplined Disciple Compiler Strike Force
+Maintainer:     Ben Lippmeier <benl@ouroborus.net>
+Build-Type:     Simple
+Cabal-Version:  >=1.6
+Stability:      experimental
+Category:       Compilers/Interpreters
+Homepage:       http://disciple.ouroborus.net
+Bug-reports:    disciple@ouroborus.net
+Synopsis:       Disciplined Disciple Compiler top-level driver.
+
+Description:    
+        This defines the top-level commands supported by the compiler,
+        such as @-make@ and @-compile@.
+
+Library
+  Build-depends:
+        base            == 4.6.*,
+        deepseq         == 1.3.*,
+        containers      == 0.5.*,
+        filepath        == 1.3.*,
+        process         == 1.1.*,
+        mtl             == 2.1.*,
+        haskell-src-exts == 1.13.*,
+        directory       == 1.2.*,
+        transformers    == 0.3.*,
+        ddc-base        == 0.3.1.*,
+        ddc-core        == 0.3.1.*,
+        ddc-core-eval   == 0.3.1.*,
+        ddc-core-simpl  == 0.3.1.*,
+        ddc-core-salt   == 0.3.1.*,
+        ddc-core-llvm   == 0.3.1.*,
+        ddc-build       == 0.3.1.*
+  
+  Exposed-modules:
+        DDC.Driver.Command.Ast
+        DDC.Driver.Command.BaseBuild
+        DDC.Driver.Command.Check
+        DDC.Driver.Command.Compile
+        DDC.Driver.Command.Load
+        DDC.Driver.Command.Make
+        DDC.Driver.Command.RewriteRules
+        DDC.Driver.Command.ToC
+        DDC.Driver.Command.ToLlvm
+        DDC.Driver.Command.ToSalt
+        DDC.Driver.Source
+        DDC.Driver.Stage
+
+  Other-modules:
+        DDC.Driver.Output
+
+  Extensions:
+        ExistentialQuantification
+        PatternGuards
+
+  ghc-options:
+        -Wall
+        -fno-warn-missing-signatures
+        -fno-warn-unused-do-bind
