packages feed

ddc-tools (empty) → 0.3.1.1

raw patch · 27 files changed

+3186/−0 lines, 27 filesdep +basedep +containersdep +ddc-basebuild-type:Customsetup-changed

Dependencies added: base, containers, ddc-base, ddc-build, ddc-code, ddc-core, ddc-core-eval, ddc-core-llvm, ddc-core-salt, ddc-core-simpl, ddc-driver, directory, filepath, haskeline, haskell-src-exts, mtl, process, transformers

Files

+ LICENSE view
@@ -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+  
+ Setup.hs view
@@ -0,0 +1,37 @@+import Distribution.Simple+import Distribution.Simple.Setup+import Distribution.Simple.LocalBuildInfo+import Distribution.PackageDescription+import System.FilePath+import System.Exit+import System.Cmd++main    = defaultMainWithHooks hooks++hooks   = simpleUserHooks+        { postInst      = hookPostInstall }+++-- Build the base library from the ddc-code package after we've installed ddc.+hookPostInstall +        :: Args+        -> InstallFlags+        -> PackageDescription+        -> LocalBuildInfo+        -> IO ()++hookPostInstall _args _flags desc buildInfo+ = do   putStrLn "Building base libraries..."++        -- Find out where Cabal has put the DDC executable.+        let installDirs = absoluteInstallDirs desc buildInfo NoCopyDest+        let ddcExe      =   (bindir $ installDirs)+                        </> (fromPathTemplate $ progPrefix buildInfo)+                        ++  "ddc" +                        <.> (fromPathTemplate $ progSuffix buildInfo)++        -- Run the basebuild command, which builds the library.+        code            <- system $ ddcExe ++ " -basebuild -O"+        case code of+         ExitFailure _  -> error "Failed!"+         ExitSuccess    -> return ()
+ ddc-tools.cabal view
@@ -0,0 +1,130 @@+Name:           ddc-tools+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:     Custom+Cabal-Version:  >=1.6+Stability:      experimental+Category:       Compilers/Interpreters+Homepage:       http://disciple.ouroborus.net+Bug-reports:    disciple@ouroborus.net+Synopsis:       Disciplined Disciple Compiler command line tools.+Description:    Disciplined Disciple Compiler command line tools.++Executable ddc-check+    hs-source-dirs:+        src/ddc-check++    Build-depends:+        base            == 4.6.*,+        ddc-core        == 0.3.1.*++    Main-is:+        Main.hs++    Other-modules: +        Config++    Extensions:+        PatternGuards++Executable ddc+    hs-source-dirs:+        src/ddc-main++    Build-depends:+        base            == 4.6.*,+        containers      == 0.5.*,+        process         == 1.1.*,+        filepath        == 1.3.*,+        haskeline       == 0.7.*,+        haskell-src-exts== 1.13.*,+        directory       == 1.2.*,+        mtl             == 2.1.*,+        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.*,+        ddc-driver      == 0.3.1.*,+        ddc-code        == 0.3.1.*++    Main-is:+        Main.hs++    Other-modules:+        DDC.Main.Args+        DDC.Main.Config+        DDC.Main.Help+        DDC.Main.OptLevels++    Extensions:+        PatternGuards++Executable ddci-core+    hs-source-dirs:+        src/ddci-core++    Build-depends:+        base            == 4.6.*,+        containers      == 0.5.*,+        process         == 1.1.*,+        filepath        == 1.3.*,+        haskeline       == 0.7.*,+        haskell-src-exts== 1.*,+        directory       == 1.2.*,+        mtl             == 2.1.*,+        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.*,+        ddc-driver      == 0.3.1.*++    Main-is:+        Main.hs+  +    Other-modules:+        DDCI.Core.Command.Eval+        DDCI.Core.Command.Help+        DDCI.Core.Command.Set+        DDCI.Core.Command.Trans+        DDCI.Core.Command.TransInteract+        DDCI.Core.Command.With+        DDCI.Core.Interface.Args+        DDCI.Core.Interface.Batch+        DDCI.Core.Interface.Interactive+        DDCI.Core.Stats.Trace+        DDCI.Core.Command+        DDCI.Core.Input+        DDCI.Core.Mode+        DDCI.Core.Output+        DDCI.Core.Rewrite+        DDCI.Core.State++    Extensions:+        DoAndIfThenElse+        PatternGuards+        ParallelListComp+        FlexibleContexts+        ExistentialQuantification+        MultiParamTypeClasses+        FunctionalDependencies+        TypeSynonymInstances+        FlexibleInstances+        StandaloneDeriving+        KindSignatures+        RankNTypes+        ScopedTypeVariables++    ghc-options:+        -Wall+        -fno-warn-missing-signatures+        -fno-warn-unused-do-bind
+ src/ddc-check/Config.hs view
@@ -0,0 +1,87 @@++module Config where+import DDC.Build.Language+import qualified DDC.Build.Language.Lite        as Lite+import System.FilePath+import System.Exit+++-- | DDC type checker command line interface config.+data Config+        = Config+        { -- | Source file to load, or Nothing to read source from stdin.+          configSourceFile      :: Maybe String++          -- | Language fragment to check.+        , configLanguage        :: Language ++          -- | If true then don't print checked source file to stdout.+        , configQuiet           :: Bool }+++-- | Default command line configuration.+defaultConfig :: Config+defaultConfig+        = Config+        { configSourceFile      = Nothing+        , configLanguage        = Language Lite.bundle+        , configQuiet           = False }+++-- | Parse command line arguments.+parseArgs :: [String] -> Config -> IO Config+parseArgs [] config     +        = return config++parseArgs args@(arg : more) config+        -- Display usage help.+        | arg == "-help" || arg == "--help"+        = do    putStr usage+                exitWith ExitSuccess++        -- Set quiet mode.+        | arg == "-quiet"+        = do    parseArgs more $ config { configQuiet   = True }++        -- Set the language fragment manually.+        | "-language" : lang : rest     <- args+        = case lookup lang languages of+           Just l  -> parseArgs rest $ config { configLanguage = l }+           Nothing -> error $ unlines+                        [ "unknown language " ++ lang+                        , "  options are: " ++ (show $ map fst languages) ]++        -- Try to guess the language fragment based on the file name extension.+        | fileName : [] <- args+        , extension     <- takeExtension fileName+        = case languageOfExtension extension of+           Just language+            -> return+            $  config { configSourceFile   = Just fileName+                      , configLanguage     = language }++           Nothing +            ->  error $ "unrecognised extension " ++ show extension++        | otherwise+        = do    putStr usage+                error  $ "unknown argument " ++ show arg+++-- | Command line usage information.+usage :: String+usage +        = unlines+        [ "Disciplined Disciple Compiler type checker."+        , ""+        , " Usage:"+        , "  ddc-check [flags]           Read input from stdin."+        , "  ddc-check [flags] <file>    Read input from file."+        , ""+        , " Flags:"+        , "  -help                       Display this help."+        , "  -quiet                      Don't print checked module to stdout."+        , "  -language <fragment>        Set the language fragment.  (default Lite)"+        , "     fragment one of " ++ (show $ map fst languages)+        , "" ]+
+ src/ddc-check/Main.hs view
@@ -0,0 +1,56 @@++-- | Command-line interface to the DDC type checker, which is also +--   possible via the plain 'ddc' command.+--+--   This code is provided as an example of how to drive the DDC+--   compiler framework.+--+module Main where+import Config+import DDC.Build.Language+import DDC.Build.Pipeline+import DDC.Core.Pretty+import System.IO+import System.Environment+++main :: IO ()+main + = do   args    <- getArgs+        config  <- parseArgs args defaultConfig++        -- Get the source text.+        --  either from a file or stdin+        (source, sourceName)+          <- case configSourceFile config of+                Just fileName   +                 -> do  src     <- readFile fileName+                        return  (src, fileName)++                Nothing +                 -> do  src     <- hGetContents stdin+                        return  (src, "<stdin>")++        -- Check with the configured language fragment.+        runLanguage config source sourceName (configLanguage config)+++runLanguage config source sourceName language+ | Language bundle      <- language+ , fragment             <- bundleFragment bundle+ = do   +        -- In quiet mode just drop the checked module on the floor.+        let sink+                | configQuiet config    = SinkDiscard+                | otherwise             = SinkStdout++        -- Loading the core code automatically check it+        -- against the provided fragment.+        errs    <- pipeText sourceName 1 source+                $  PipeTextLoadCore  fragment+                [  PipeCoreOutput    sink ]++        -- If the pipeline died with errors, +        --  then print them.+        mapM_ (putStrLn . renderIndent . ppr) errs+
+ src/ddc-main/DDC/Main/Args.hs view
@@ -0,0 +1,207 @@++-- | Parsing of command line configuation arguments.+module DDC.Main.Args +        ( parseArgs+        , help)+where+import DDC.Main.Config+import DDC.Main.Help+import Data.Char+++-- | Parse command line arguments.+parseArgs :: [String] -> Config -> IO Config+parseArgs [] config+        = return config++parseArgs args config+        -- General ------------------------------+        | flag : _              <- args+        , elem flag ["-version", "--version"]+        = return+        $ config { configMode   = ModeVersion }++        | flag : _              <- args+        , elem flag ["-h", "-help", "--help"]+        = return +        $ config { configMode   = ModeHelp }++        | flag : file : rest    <- args+        , elem flag ["-make", "--make" ]+        = parseArgs rest+        $ setMode config $ ModeMake file++        | "-basebuild" : rest   <- args+        = parseArgs rest+        $ setMode config $ ModeBaseBuild++        -- Compilation --------------------------+        | flag : file : rest <- args+        , elem flag ["-c", "-compile", "--compile"]+        = parseArgs rest+        $ setMode config $ ModeCompile file++        | "-basedir" : path : rest <- args+        = parseArgs rest+        $ config { configBaseDir = path }++        | flag         : file : rest     <- args+        , elem flag    ["-o", "-output"]+        = parseArgs rest+        $ config { configOutputFile = Just file }++        | "-fvia-c"    : rest      <- args+        = parseArgs rest+        $ config { configViaBackend = ViaC }++        | "-fvia-llvm" : rest   <- args+        = parseArgs rest+        $ config { configViaBackend = ViaLLVM }++        | flag : dir : rest     <- args+        , elem flag    ["-output-dir"]+        = parseArgs rest+        $ config { configOutputDir  = Just dir }++        -- Optimisation -------------------------+        | "-O0" : rest          <- args+        = parseArgs rest+        $ config { configOptLevelLite   = OptLevel0 +                 , configOptLevelSalt   = OptLevel0 }++        | flag : rest          <- args+        , elem flag     [ "-O", "-O1" ]+        = parseArgs rest+        $ config { configOptLevelLite   = OptLevel1+                 , configOptLevelSalt   = OptLevel1 }++        -- Intermediates ------------------------+        | flag : rest   <- args+        , elem flag ["-keep-ll-files", "-keep-llvm-files" ]+        = parseArgs rest+        $ config { configKeepLlvmFiles = True }++        | flag : rest      <- args+        , elem flag ["-keep-c-files",  "-keep-sea-files" ]+        = parseArgs rest+        $ config { configKeepSeaFiles = True }++        | flag : rest      <- args+        , elem flag ["-keep-s-files", "-keep-asm-files" ]+        = parseArgs rest+        $ config { configKeepAsmFiles = True }++        -- Runtime ------------------------------+        | "-run-heap" : bytes : rest    <- args+        , all isDigit bytes+        = parseArgs rest+        $ config  { configRuntimeHeapSize = read bytes }++        -- Checking -----------------------------+        | "-check" : file : rest    <- args+        = parseArgs rest+        $ config { configMode  = ModeCheck file }++        -- Transformation -----------------------+        | "-load"   : file : rest <- args+        = parseArgs rest+        $ setMode config $ ModeLoad file++        | "-trans" : trans : rest   <- args+        = parseArgs rest+        $ config { configTrans = Just trans }++        | "-with"  : file  : rest   <- args+        = parseArgs rest+        $ config { configWith  = configWith config ++ [file] }++        -- Conversion ---------------------------+        | "-to-salt" : file : rest  <- args+        = parseArgs rest+        $ setMode config $ ModeToSalt file++        | "-to-c"    : file : rest  <- args+        = parseArgs rest+        $ setMode config $ ModeToC file++        | "-to-llvm" : file : rest  <- args+        = parseArgs rest+        $ setMode config $ ModeToLLVM file++        -- Debugging ----------------------------+        | "-dump"   : rest        <- args+        = parseArgs rest+        $ config { configDump   = True }++        | "-ast"   : file : rest  <- args+        = parseArgs rest+        $ setMode config $ ModeAST file++        | "-print-builder" : rest <- args+        = parseArgs rest+        $ setMode config ModePrintBuilder++        | "-print-basedir" : rest <- args+        = parseArgs rest+        $ setMode config ModePrintBaseDir++        -- If we get some other argument starting with '-' then assume it's+        -- a flag we don't support.+        | arg : _               <- args+        , '-' : _               <- arg+        = error $ "Cannot parse arguments " ++ show args++        -- Otherwise, treat the argument as a source file to make.+        | arg : rest            <- args+        = parseArgs rest+        $ setMode config (ModeMake arg)++        | otherwise+        = error $ "Cannot parse arguments " ++ show args+++-- | Set the major mode of DDC.+-- +--   We can't have two major modes like '-make' and '-compile' set at the same time.+--   If this happens then `error`.+setMode :: Config -> Mode -> Config+setMode config newMode+ | ModeMake{}    <- configMode config+ , ModeMake{}    <- newMode+ = error "Multi-module compilation is not supported yet."++ | ModeCompile{} <- configMode config+ , ModeCompile{} <- newMode+ = error "Multi-module compilation is not supported yet."++ | otherwise+ = case flagOfMode newMode of+    Nothing     +     -> error "DDC.Main.Args.setMode: not setting mode to ModeNone"++    Just newFlag+     -> case flagOfMode $ configMode config of+         Nothing        -> config { configMode = newMode }+         Just oldFlag   -> error $ "Cannot use " ++ newFlag ++ " with " ++ oldFlag+++-- | Get the flag used to set DDC to this mode.+flagOfMode :: Mode -> Maybe String+flagOfMode mode+ = case mode of+        ModeNone{}              -> Nothing+        ModeVersion{}           -> Just "-version"+        ModeHelp{}              -> Just "-help"+        ModeCheck{}             -> Just "-check"+        ModeLoad{}              -> Just "-load"+        ModeCompile{}           -> Just "-compile"+        ModeMake{}              -> Just "-make"+        ModeAST{}               -> Just "-ast"+        ModeToSalt{}            -> Just "-to-salt"+        ModeToC{}               -> Just "-to-c"+        ModeToLLVM{}            -> Just "-to-llvm"+        ModeBaseBuild{}         -> Just "-basebuild"+        ModePrintBuilder{}      -> Just "-print-builder"+        ModePrintBaseDir{}      -> Just "-print-basedir"++
+ src/ddc-main/DDC/Main/Config.hs view
@@ -0,0 +1,168 @@+{-# LANGUAGE CPP #-}++-- | Define the command line configuation arguments.+module DDC.Main.Config+        ( Mode         (..)+        , OptLevel     (..)+        , D.ViaBackend (..)+        , Config       (..)++        , getDefaultConfig+        , defaultBuilderConfig)+where+import DDC.Code.Config+import DDC.Build.Builder+import System.FilePath+import qualified DDC.Driver.Stage               as D+++-- | The main command that we're running.+data Mode+        -- | Don't do anything+        = ModeNone++        -- | Display the version string.+        | ModeVersion++        -- | Display the help page.+        | ModeHelp++        -- | Parse and type-check a module.+        | ModeCheck     FilePath++        -- | Parse, type-check and transform a module.+        | ModeLoad      FilePath++        -- | Compile a .dcl or .dce into an object file.+        | ModeCompile   FilePath++        -- | Compile a .dcl or .dce into an executable file.+        | ModeMake      FilePath++        -- | Pretty print a module's AST.+        | ModeAST       FilePath++        -- | Convert a module to Salt.+        | ModeToSalt    FilePath++        -- | Convert a module to C.+        | ModeToC       FilePath++        -- | Convert a module to LLVM.+        | ModeToLLVM    FilePath++        -- | Build the base libraries and runtime.+        | ModeBaseBuild++        -- | Print the builder info for this platform.+        | ModePrintBuilder++        -- | Print where the runtime and base libraries are intalled.+        | ModePrintBaseDir+        deriving (Eq, Show)+++data OptLevel+        -- | Don't do any optimisations.+        = OptLevel0++        -- | Do standard optimisations.+        | OptLevel1+        deriving Show+++-- | DDC config.+data Config+        = Config+        { -- | The main compilation mode.+          configMode            :: Mode ++          -- Compilation --------------+          -- | Directory holding the runtime and base library code.+        , configBaseDir         :: FilePath++          -- | Redirect output to this file.+        , configOutputFile      :: Maybe FilePath++          -- | Redirect output to this directory.+        , configOutputDir       :: Maybe FilePath ++          -- | What backend to use for compilation+        , configViaBackend      :: D.ViaBackend++          -- Optimisation -------------+          -- | What optimisation levels to use+        , configOptLevelLite    :: OptLevel+        , configOptLevelSalt    :: OptLevel++          -- | Paths to modules to use as inliner templates.+        , configWithLite        :: [FilePath]+        , configWithSalt        :: [FilePath]++          -- Runtime -------------------+          -- | Default size of heap for compiled program.+        , configRuntimeHeapSize :: Integer++          -- Intermediates -------------+        , configKeepLlvmFiles   :: Bool+        , configKeepSeaFiles    :: Bool+        , configKeepAsmFiles    :: Bool++          -- Transformation ------------+          -- | String containing the transform definition to apply with+          --   the -load command. We can't parse this definition until+          --   we know what language we're dealing with.+        , configTrans           :: Maybe String++          -- | Other modules to use for inliner templates.+        , configWith            :: [FilePath]++          -- Debugging -----------------+          -- | Dump intermediate representations.+        , configDump            :: Bool }+        deriving (Show)+++-- | Default configuation.+getDefaultConfig :: IO Config+getDefaultConfig+ = do   baseDir <- locateBaseLibrary++        return $ Config+          { configMode            = ModeNone + +            -- Compilation --------------+          , configBaseDir         = baseDir+          , configOutputFile      = Nothing+          , configOutputDir       = Nothing+          , configViaBackend      = D.ViaLLVM+ +            -- Optimisation -------------+          , configOptLevelLite    = OptLevel0+          , configOptLevelSalt    = OptLevel0+          , configWithLite        = []+          , configWithSalt        = []+ +            -- Runtime ------------------+          , configRuntimeHeapSize = 65536+ +            -- Intermediates ------------+          , configKeepLlvmFiles   = False+          , configKeepSeaFiles    = False+          , configKeepAsmFiles    = False+ +            -- Transformation -----------+          , configTrans           = Nothing+          , configWith            = []+ +            -- Debugging ----------------+         , configDump            = False }+++-- | Get the builder configuation from the ddc configuration.+defaultBuilderConfig :: Config -> BuilderConfig+defaultBuilderConfig config+        = BuilderConfig+        { builderConfigBaseSrcDir = configBaseDir config +        , builderConfigBaseLibDir = configBaseDir config </> "build" }+
+ src/ddc-main/DDC/Main/Help.hs view
@@ -0,0 +1,87 @@++module DDC.Main.Help where++-- | The version identifier string.+version :: String+version = "The Disciplined Disciple Compiler, version 0.3.0"+++-- | What to print when we have no input files.+hello :: String+hello   = unlines+        [ "ddc: no input files"+        , "For usage information, try the -help option." ]+++-- | The command-line help page.+help :: String+help    = unlines+        [ version+        , ""+        , "General:"+        , "     -help              Display this help."+        , "     -version           Display the version string."+        , ""+        , "Compilation:"+        , "     -make     FILE     Compile a module into an executable file."+        , " -c, -compile  FILE     Compile a module into an object file."+        , ""+        , " -o, -output   FILE     Redirect output to this file."+        , "     -output-dir DIR    Redirect output to this directory."+        , ""+        , "     -fvia-llvm         Compile via the LLVM backend  (default)"+        , "     -fvia-c            Compile via the C backend."+        , ""+        , "     -keep-ll-files     Keep intermediate .ll files."+        , "     -keep-c-files      Keep intermediate .c files."+        , "     -keep-s-files      Keep intermediate .s files."+        , ""+        , "Optimisation:"+        , "     -O0                No optimisations.             (default)"+        , " -O, -O1                Do standard optimisations."+        , ""+        , "Runtime for compiled program:"+        , "     -run-heap BYTES    Size of fixed heap            (65536)"+        , ""+        , "Checking:"+        , "     -check    FILE     Parse and type check a core module."+        , ""+        , "Conversion:"+        , "     -to-salt  FILE     Convert a module to Disciple Core Salt."+        , "     -to-c     FILE     Convert a module to C code."+        , "     -to-llvm  FILE     Convert a module to LLVM code."+        , ""+        , "Debugging:"+        , "     -dump              Dump intermediate representations."+        , "     -ast      FILE     Pretty print the AST of a module."+        , ""+        , "Configuration:"+        , "     -basedir  DIR      Path to the runtime and base library code."+        , "     -print-basedir     Print directory holding the runtime and base libraries."+        , "     -print-builder     Print external builder info for this platform."+        , ""+        , "Transformation:"+        , "     -load     FILE     Parse, type check and transform a module."+        , "     -trans    TRANS    Set the transformation to use with -load."+        , "     -with     FILE     Use this module for inliner templates with -load."+        , ""+        , "    TRANS   ::= "+        , "     { TRANS }          Parenthesis."+        , "     fix N TRANS        Transform to a fixpoint, or bail out after N iterations."+        , "     TRANS; TRANS       Sequence two transforms."+        , "     Id                 Return the original program unharmed."+        , "     Anonymize          Anonymize names to deBruijn form."+        , "     Namify             Introduce fresh names for deBruijn binders."+        , "     Snip               Introduce let-bindings for nested applications."+        , "     SnipOver            ... and over-applications."+        , "     Flatten            Flatten nested let-bindings."+        , "     Beta               Perform beta-reduction for value arguments."+        , "     BetaLets            ... introducing new let-bindings for redex arguments."+        , "     Bubble             Float casts outwards, and combine similar ones."+        , "     Prune              Erase unused, ineffectual let-bindings."+        , "     Forward            Float let-bindings forward into their use sites."+        , "     Rewrite            Perform rule based rewriting."+        , "     Elaborate          Introduce default witnesses for unconstrained regions."+        , "     Inline MODULE[NAME..] Perform inlining. Use '-with' to add source modules." ]++        
+ src/ddc-main/DDC/Main/OptLevels.hs view
@@ -0,0 +1,188 @@++-- | Define the default optimisation levels.+module DDC.Main.OptLevels +        ( getSimplLiteOfConfig+        , getSimplSaltOfConfig)+where+import DDC.Main.Config+import DDC.Driver.Command.Load+import DDC.Driver.Command.RewriteRules+import DDC.Build.Builder+import DDC.Build.Platform+import DDC.Core.Module+import DDC.Core.Transform.Inline+import DDC.Core.Transform.Namify+import DDC.Core.Transform.Reannotate+import DDC.Core.Simplifier                      (Simplifier)+import System.FilePath+import Control.Monad+import Data.Monoid+import Data.Maybe+import qualified DDC.Core.Simplifier            as S+import qualified DDC.Core.Simplifier.Recipe     as S+import qualified DDC.Core.Lite                  as Lite+import qualified DDC.Core.Salt                  as Salt+import qualified DDC.Build.Language.Salt        as Salt+import qualified DDC.Build.Language.Lite        as Lite+import qualified Data.Map                       as Map+import qualified Data.Set                       as Set+++-- | Get the simplifier for Lite code from the config.+--   This also reads up all the modules we use for inliner templates.+--+--   We don't want to delay this until all arguments are parsed, +--   because the simplifier spec also contains the list of modules used+--   as inliner templates, so we need to wait until they're all specified.+--+getSimplLiteOfConfig +        :: Config -> Builder +        -> IO (Simplifier Int () Lite.Name)++getSimplLiteOfConfig config builder+ = case configOptLevelLite config of+        OptLevel0       -> opt0_lite config+        OptLevel1       -> opt1_lite config builder+++-- | Get the simplifier for Salt code from the config.+--+getSimplSaltOfConfig +        :: Config -> Builder+        -> IO (Simplifier Int () Salt.Name)++getSimplSaltOfConfig config builder+ = case configOptLevelSalt config of+        OptLevel0       -> opt0_salt config+        OptLevel1       -> opt1_salt config builder+++-- Level 0 --------------------------------------------------------------------+-- This just passes the code through unharmed.++-- | Level 0 optimiser for Core Lite code.+opt0_lite :: Config -> IO (Simplifier Int () Lite.Name)+opt0_lite _+        = return $ S.Trans S.Id+++-- | Level 0 optimiser for Core Salt code.+opt0_salt :: Config -> IO (Simplifier Int () Salt.Name)+opt0_salt _+        = return $ S.Trans S.Id+++-- Level 1 --------------------------------------------------------------------+-- Do full optimsiations.++-- | Level 1 optimiser for Core Lite code.+opt1_lite +        :: Config -> Builder+        -> IO (Simplifier Int () Lite.Name)++opt1_lite config _builder+ = do+        -- Auto-inline basic numeric code.+        let inlineModulePaths+                =  [ configBaseDir config </> "lite/base/Data/Numeric/Int.dcl"+                   , configBaseDir config </> "lite/base/Data/Numeric/Nat.dcl" ]+                ++ (configWithLite config)++        -- Load all the modules that we're using for inliner templates.+        --  If any of these don't load then the 'cmdReadModule' function +        --  will display the errors.+        minlineModules+                <- liftM sequence+                $  mapM (cmdReadModule Lite.fragment)+                        inlineModulePaths++        let inlineModules+                = map (reannotate (const ()))+                $ fromMaybe (error "Imported modules do not parse.")+                            minlineModules++        let inlineSpec+                = Map.fromList+                [ (ModuleName ["Int"], InlineSpecAll (ModuleName ["Int"]) Set.empty)+                , (ModuleName ["Nat"], InlineSpecAll (ModuleName ["Nat"]) Set.empty) ]++        -- Optionally load the rewrite rules for each 'with' module+        rules <- mapM (\(m,file) -> cmdTryReadRules Lite.fragment (file ++ ".rules") m)+              $  inlineModules `zip` inlineModulePaths++        let rules' = concat rules++        -- Simplifier to convert to a-normal form.+        let normalizeLite+                = S.anormalize+                        (makeNamifier Lite.freshT)      +                        (makeNamifier Lite.freshX)+++        -- Perform rewrites before inlining+        return  $  (S.Trans $ S.Rewrite rules')+                <> (S.Trans $ S.Inline+                            $ lookupTemplateFromModules inlineSpec inlineModules)+                <> S.Fix 5 (S.beta +                                <> S.bubble      <> S.flatten +                                <> normalizeLite <> S.forward+                                <> (S.Trans $ S.Rewrite rules'))+++-- | Level 1 optimiser for Core Salt code.+opt1_salt +        :: Config -> Builder+        -> IO (Simplifier Int () Salt.Name)++opt1_salt config builder+ = do   +        -- Auto-inline the low-level code from the runtime system+        --   that constructs and destructs objects.+        let targetWidth+                = archPointerWidth $ platformArch $ buildTarget builder++        -- The runtime system code comes in different versions, +        --  depending on the pointer width of the target architecture.+        let inlineModulePaths+                =  [ configBaseDir config +                        </> "salt/runtime" ++ show targetWidth </> "Object.dcs"]+                ++ configWithSalt config++        -- 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.+        minlineModules+                <- liftM sequence+                $  mapM (cmdReadModule Salt.fragment)+                        inlineModulePaths++        let inlineModules+                = map (reannotate (const ()))+                $ fromMaybe (error "Imported modules do not parse.")+                            minlineModules++        let inlineSpec+                = Map.fromList+                [ (ModuleName ["Object"], InlineSpecAll (ModuleName ["Int"]) Set.empty) ]++        -- Optionally load the rewrite rules for each 'with' module+        rules <- mapM (\(m,file) -> cmdTryReadRules Salt.fragment (file ++ ".rules") m)+              $  inlineModules `zip` inlineModulePaths+        let rules' = concat rules+++        -- Simplifier to convert to a-normal form.+        let normalizeSalt+                = S.anormalize+                        (makeNamifier Salt.freshT)      +                        (makeNamifier Salt.freshX)+        +        -- Perform rewrites before inlining+        return  $  (S.Trans $ S.Rewrite rules')+                <> (S.Trans $ S.Inline +                            $ lookupTemplateFromModules inlineSpec inlineModules)+                <> S.Fix 5 (S.beta +                                <> S.bubble      <> S.flatten +                                <> normalizeSalt <> S.forward+                                <> (S.Trans $ S.Rewrite rules'))+
+ src/ddc-main/Main.hs view
@@ -0,0 +1,198 @@++-- | Unix-style command line interface to DDC.+--    This interface exports commands that work on whole modules at a time,+--    and does unix-style command line argument parsing.+--+import DDC.Main.Config+import DDC.Main.Help+import DDC.Main.Args+import DDC.Main.OptLevels+import DDC.Driver.Command.Load+import DDC.Driver.Command.Check+import DDC.Driver.Command.Compile+import DDC.Driver.Command.Make+import DDC.Driver.Command.Ast+import DDC.Driver.Command.BaseBuild+import DDC.Driver.Command.ToSalt+import DDC.Driver.Command.ToC+import DDC.Driver.Command.ToLlvm+import DDC.Driver.Source+import DDC.Build.Builder+import DDC.Build.Language+import DDC.Base.Pretty+import System.Environment+import System.IO+import System.Exit+import System.FilePath+import Control.Monad.Trans.Error+import qualified DDC.Driver.Stage       as Driver+import qualified DDC.Core.Salt.Runtime  as Runtime+++main :: IO ()+main+ = do   args    <- getArgs++        -- Get the default configuration.+        --  This contains static information such as where the code+        --  for the base libraries and runtime system is installed.+        config0 <- getDefaultConfig++        -- Update the static config with dynamic config read from+        --   the command-line arguments.+        config  <- parseArgs args config0++        -- Run the main compiler.+        run config+++run :: Config -> IO ()+run config+ = case configMode config of+        -- We didn't get any arguments on the command line.+        ModeNone+         ->     putStr hello++        -- Display the version string.+        ModeVersion+         ->     putStrLn version++        -- Display the help page.+        ModeHelp+         ->     putStrLn help++        -- Parse and type check a module.+        ModeCheck filePath+         -> do  language        <- languageFromFilePath filePath+                case language of +                 Language bundle+                  -> do  mm      <- runErrorT +                                 $ cmdCheckModuleFromFile (bundleFragment bundle) filePath+                         case mm of+                          Left err        +                           -> do putStrLn err+                                 exitWith $ ExitFailure 1++                          Right _+                           -> return ()+++        -- Parse, type check and transform a module.+        ModeLoad filePath+         ->     runError $ cmdLoadFromFile +                                (configTrans config) +                                (configWith config) +                                filePath++        -- Compile a module to object code.+        ModeCompile filePath+         -> do  dconfig  <- getDriverConfig config+                runError $ cmdCompile dconfig filePath+++        -- Compile a module into an executable.+        ModeMake filePath+         -> do  dconfig  <- getDriverConfig config+                runError $ cmdMake    dconfig filePath+++        -- Pretty print the AST of a module.+        ModeAST filePath+         -> do  language        <- languageFromFilePath filePath+                str             <- readFile filePath+                cmdAstModule +                        language+                        (SourceFile filePath) +                        str+++        -- Convert a module to Salt.+        ModeToSalt filePath+         -> do  language        <- languageFromFilePath filePath+                dconfig         <- getDriverConfig config+                str             <- readFile filePath+                runError $ cmdToSalt dconfig language (SourceFile filePath) str+++        -- Convert a module to C+        ModeToC filePath+         -> do  language        <- languageFromFilePath filePath+                dconfig         <- getDriverConfig config+                str             <- readFile filePath+                runError $ cmdToC dconfig language (SourceFile filePath) str+++        -- Convert a module to LLVM+        ModeToLLVM filePath+         -> do  language        <- languageFromFilePath filePath+                dconfig         <- getDriverConfig config+                str             <- readFile filePath+                runError $ cmdToLlvm dconfig language (SourceFile filePath) str++        -- Build the runtime and base libraries.+        ModeBaseBuild+         -> do  dconfig         <- getDriverConfig config+                runError $ cmdBaseBuild dconfig++        -- Print the external builder info for this platform.+        ModePrintBuilder+         -> do  dconfig         <- getDriverConfig config+                putStrLn $ renderIndent $ ppr (Driver.configBuilder dconfig)++        -- Print where the runtime and base libraries are installed.+        ModePrintBaseDir+         ->     putStrLn $ configBaseDir config+++-- | Get the compile driver from the config.+getDriverConfig :: Config -> IO Driver.Config+getDriverConfig config+ = do   Just builder    <- determineDefaultBuilder (defaultBuilderConfig config)+        simplLite       <- getSimplLiteOfConfig config builder+        simplSalt       <- getSimplSaltOfConfig config builder++        return  $ Driver.Config+                { Driver.configDump                     = configDump config+                , Driver.configSimplLite                = simplLite+                , Driver.configSimplSalt                = simplSalt+                , Driver.configViaBackend               = configViaBackend config++                , Driver.configRuntime               +                        = Runtime.Config+                        { Runtime.configHeapSize        = configRuntimeHeapSize config }++                , Driver.configBuilder                  = builder+                , Driver.configSuppressCoreImports      = False+                , Driver.configSuppressHashImports      = False+                , Driver.configOutputFile               = configOutputFile config+                , Driver.configOutputDir                = configOutputDir  config +                , Driver.configKeepLlvmFiles            = configKeepLlvmFiles config+                , Driver.configKeepSeaFiles             = configKeepSeaFiles  config+                , Driver.configKeepAsmFiles             = configKeepAsmFiles  config }+++-- | Determine the current language based on the file extension of this path, +--   and slurp out a bundle of stuff specific to that language from the config.+languageFromFilePath :: FilePath -> IO Language+languageFromFilePath filePath+ = case languageOfExtension (takeExtension filePath) of+        Nothing +         -> do  hPutStrLn stderr "Unknown file extension."+                exitWith $ ExitFailure 1++        Just ext +         -> return ext+++-- | Print errors to stderr and set the exit code.+runError :: ErrorT String IO () -> IO ()+runError m+ = do   result  <- runErrorT m+        case result of+         Left err       +          -> do hPutStrLn stderr err+                exitWith $ ExitFailure 1++         Right _+          -> return ()+
+ src/ddci-core/DDCI/Core/Command.hs view
@@ -0,0 +1,265 @@++module DDCI.Core.Command+        ( Command(..)+        , commands+        , readCommand+        , handleCmd)+where+import DDCI.Core.Command.Help+import DDCI.Core.Command.Set+import DDCI.Core.Command.Eval+import DDCI.Core.Command.Trans+import DDCI.Core.Command.TransInteract+import DDCI.Core.Command.With+import DDCI.Core.State+import DDC.Driver.Command.Ast+import DDC.Driver.Command.Check+import DDC.Driver.Command.Load+import DDC.Driver.Command.Compile+import DDC.Driver.Command.Make+import DDC.Driver.Command.ToSalt+import DDC.Driver.Command.ToC+import DDC.Driver.Command.ToLlvm+import System.IO+import Control.Monad.Trans.Error+import Data.List+++-- Command --------------------------------------------------------------------+-- | The commands that the interpreter supports.+data Command+        = CommandBlank          -- ^ No command was entered.+        | CommandUnknown        -- ^ Some unknown (invalid) command.+        | CommandHelp           -- ^ Display the interpreter help.+        | CommandSet            -- ^ Set a mode.+        | CommandLoad           -- ^ Load a module.+        | CommandKind           -- ^ Show the kind of a type.+        | CommandUniverse       -- ^ Show the universe of a type.+        | CommandUniverse1      -- ^ Given a type, show the universe of the original thing.+        | CommandUniverse2      -- ^ Given a kind, show the universe of the original thing.+        | CommandUniverse3      -- ^ Given a sort, show the universe of the original thing.+        | CommandEquivType      -- ^ Check if two types are equivalent.+        | CommandWitType        -- ^ Show the type of a witness.+        | CommandExpCheck       -- ^ Check an expression.+        | CommandExpType        -- ^ Check an expression, showing its type.+        | CommandExpEffect      -- ^ Check an expression, showing its effect.+        | CommandExpClosure     -- ^ Check an expression, showing its closure.+        | CommandExpRecon       -- ^ Reconstruct type annotations on binders.+        | CommandEval           -- ^ Evaluate an expression.+        | CommandTrans          -- ^ Transform an expression.+        | CommandTransEval      -- ^ Transform then evaluate an expression.+        | CommandTransInteract  -- ^ Interactively transform an expression.++        | CommandAst            -- ^ Show the AST of an expression.++        | CommandCompile        -- ^ Compile a file.+        | CommandMake           -- ^ Compile and link and executable.++        | CommandToSalt         -- ^ Convert a module to Disciple Salt.+        | CommandToC            -- ^ Convert a module to C code.+        | CommandToLlvm         -- ^ Convert a module to LLVM code.++        | CommandWith           -- ^ Add a module to the inliner table.+	| CommandWithLite+	| CommandWithSalt+        deriving (Eq, Show)+++-- | Names used to invoke each command.+--   Short names that form prefixes of other ones must come later+--   in the list. Eg ':with-lite' after ':with'+commands :: [(String, Command)]+commands + =      [ (":help",             CommandHelp)+        , (":?",                CommandHelp)+        , (":set",              CommandSet)+        , (":load",             CommandLoad)+        , (":kind",             CommandKind)+        , (":universe1",        CommandUniverse1)+        , (":universe2",        CommandUniverse2)+        , (":universe3",        CommandUniverse3)+        , (":universe",         CommandUniverse)+        , (":tequiv",           CommandEquivType)+        , (":wtype",            CommandWitType)+        , (":check",            CommandExpCheck)+        , (":recon",            CommandExpRecon)+        , (":type",             CommandExpType)+        , (":effect",           CommandExpEffect)+        , (":closure",          CommandExpClosure)+        , (":eval",             CommandEval)+        , (":trun",             CommandTransEval)+        , (":tinteract",        CommandTransInteract)+        , (":trans",            CommandTrans)+        , (":ast",              CommandAst) +        , (":compile",          CommandCompile)+        , (":make",             CommandMake)+        , (":to-salt",          CommandToSalt)+        , (":to-c",             CommandToC)+        , (":to-llvm",          CommandToLlvm) +        , (":with-lite",        CommandWithLite)+        , (":with-salt",        CommandWithSalt) +        , (":with",             CommandWith) ]+++-- | Read the command from the front of a string.+readCommand :: String -> Maybe (Command, String)+readCommand ss+        | null $ words ss+        = Just (CommandBlank,   ss)++        | (cmd, rest) : _ <- [ (cmd, drop (length str) ss) +                                        | (str, cmd)      <- commands+                                        , isPrefixOf str ss ]+        = Just (cmd, rest)++        | ':' : _       <- ss+        = Just (CommandUnknown, ss)++        | otherwise+        = Nothing+++-- Commands -------------------------------------------------------------------+-- | Handle a single line of input.+handleCmd :: State -> Command -> Source -> String -> IO State+handleCmd state CommandBlank _ _+ = return state++handleCmd state cmd source line+ = do   state'  <- handleCmd1 state cmd source line+        return state'++handleCmd1 state cmd source line+ = case cmd of+        CommandBlank+         -> return state++        CommandUnknown+         -> do  putStr $ unlines+                 [ "unknown command."+                 , "use :? for help." ]++                return state++        CommandHelp+         -> do  putStr help+                return state++        CommandSet+         -> do  state'  <- cmdSet state line+                return state'++        CommandLoad+         -> do  runError $ cmdLoadFromString (stateLanguage state) source line+                return state++        CommandKind       +         -> do  cmdShowKind  (stateLanguage state) source line+                return state++        CommandUniverse+         -> do  cmdUniverse  (stateLanguage state) source line+                return state++        CommandUniverse1+         -> do  cmdUniverse1 (stateLanguage state) source line+                return state++        CommandUniverse2+         -> do  cmdUniverse2 (stateLanguage state) source line+                return state++        CommandUniverse3+         -> do  cmdUniverse3 (stateLanguage state) source line+                return state++        CommandEquivType+         -> do  cmdTypeEquiv (stateLanguage state) source line+                return state++        CommandWitType    +         -> do  cmdShowWType (stateLanguage state) source line+                return state++        CommandExpCheck   +         -> do  cmdShowType  (stateLanguage state) ShowTypeAll source line+                return state++        CommandExpType  +         -> do  cmdShowType  (stateLanguage state) ShowTypeValue source line+                return state++        CommandExpEffect  +         -> do  cmdShowType  (stateLanguage state) ShowTypeEffect source line+                return state++        CommandExpClosure +         -> do  cmdShowType  (stateLanguage state) ShowTypeClosure source line+                return state++        CommandExpRecon+         -> do  cmdExpRecon  (stateLanguage state) source line+                return state++        CommandEval       +         -> do  cmdEval state source line+                return state++        CommandTrans+         -> do  cmdTrans state source line+                return state+        +        CommandTransEval+         -> do  cmdTransEval state source line+                return state+        +        CommandTransInteract+         -> do  cmdTransInteract state source line+        +        CommandAst+         -> do  cmdAstExp (stateLanguage state) source line+                return state++        CommandToSalt+         -> do  config  <- getDriverConfigOfState state+                runError $ cmdToSalt config (stateLanguage state) source line+                return    state++        CommandToC+         -> do  config  <- getDriverConfigOfState state+                runError $ cmdToC    config (stateLanguage state) source line+                return state++        CommandToLlvm+         -> do  config  <- getDriverConfigOfState state+                runError $ cmdToLlvm config (stateLanguage state) source line+                return state++        CommandCompile+         -> do  config  <- getDriverConfigOfState state+                runError $ cmdCompile config line+                return state++        CommandMake+         -> do  config  <- getDriverConfigOfState state+                runError $ cmdMake config line+                return state++        CommandWith+         ->     cmdWith state source line++        CommandWithLite+         ->     cmdWithLite state source line++        CommandWithSalt+         ->     cmdWithSalt state source line+++-- | Just print errors to stdout and continue the session.+runError :: ErrorT String IO () -> IO ()+runError m+ = do   result  <- runErrorT m+        case result of+         Left err       -> hPutStrLn stdout err+         Right _        -> return ()+
+ src/ddci-core/DDCI/Core/Command/Eval.hs view
@@ -0,0 +1,244 @@++module DDCI.Core.Command.Eval+        ( cmdStep+        , cmdEval+        , evalExp)+where+import DDCI.Core.Stats.Trace+import DDCI.Core.Output+import DDCI.Core.State+import DDC.Driver.Command.Check+import DDC.Core.Eval.Env+import DDC.Core.Eval.Step+import DDC.Core.Eval.Name+import DDC.Core.Transform.Reannotate+import DDC.Core.Exp+import DDC.Core.Check+import DDC.Core.Pretty+import DDC.Core.Collect+import DDC.Core.Compounds+import DDC.Type.Equiv+import DDC.Type.Subsumes+import Control.Monad+import DDC.Core.Eval.Store                      (Store)+import qualified DDC.Core.Eval.Store            as Store+import qualified Data.Set                       as Set+import qualified DDC.Build.Language.Eval        as Eval+import qualified Data.Map		     as Map+import Data.Typeable+import DDC.Core.Module (ModuleMap)+import Data.Maybe (fromMaybe)+++-- | Parse, check, and single step evaluate an expression.+cmdStep :: State -> Source -> String -> IO ()+cmdStep state source str+ | Language bundle      <- stateLanguage state+ , modules0             <- bundleModules bundle+ , (modules :: Maybe (ModuleMap (AnTEC () Name) Name))+			<- gcast modules0+ , modules'		<- fromMaybe Map.empty modules+ = cmdParseCheckExp Eval.fragment modules' False source str >>= goStore + where+        -- Expression had a parse or type error.+        goStore Nothing+         = return ()++        -- Expression is well-typed.+        goStore (Just x)+         = let  -- The evaluator doesn't accept any annotations+                x_stripped = reannotate (const ()) x++                -- Create the initial store.+                store      = startingStoreForExp x_stripped++           in   goStep store x++        goStep store x+         = do   _       <- forcePrint state store x+                return ()+++-- | Parse, check, and fully evaluate an expression.+cmdEval :: State -> Source -> String -> IO ()+cmdEval state source str+ | Language bundle      <- stateLanguage state+ , modules0             <- bundleModules bundle+ , (modules :: Maybe (ModuleMap (AnTEC () Name) Name))+			<- gcast modules0+ , modules'		<- fromMaybe Map.empty modules+ = cmdParseCheckExp Eval.fragment modules' False source str >>= goEval+ where+    -- Expression had a parse or type error.+    goEval Nothing+     =	return ()++    -- Expression is well-typed.+    goEval (Just expr)+     =	evalExp state expr+++-- | Evaluate an already parsed and type-checked expression.+--   Exported so transforms can test with it.+evalExp :: State -> Exp (AnTEC () Name) Name -> IO ()+evalExp state x0+ = do   +        -- The evaluator doesn't want any annotations+        let x0_stripped = reannotate (const ()) x0++        -- Create the initial store.+	let store = startingStoreForExp x0_stripped++	-- Print starting expression.+	when (Set.member TraceEval  $ stateModes state)+	 $ outDocLn state (text "* STEP: " <> ppr x0_stripped)++	-- Print starting store.+	when (Set.member TraceStore $ stateModes state)+	 $ do   putStrLn $ renderIndent $ ppr store+		outStr   state "\n"++	goStep store x0++    where+	goStep store x+	 = do mResult <- forcePrint state store x+	      case mResult of+	       Nothing            +                -> return ()++	       Just (store', x') +                -> goStep store' x'+ ++-- | Create a starting store for the given expression.+--   We pre-allocate any region handles in the expression, +--   and ensure that the next region to be allocated is higher+--   than all of these.+startingStoreForExp :: Exp () Name -> Store+startingStoreForExp xx+ =  let+        -- Gather up all the region handles already in the expression.+        rs      = [ r | UPrim (NameRgn r) _ <- Set.toList $ collectBound xx]++        -- Decide what new region should be allocated first.+        -- Region 0 is reserved for thunks.+        iAllocBump+         | _ : _         <- rs+         , Rgn iR        <- maximum rs+         = iR++         | otherwise+         = 0++        store  = Store.initial++    in  store+        { Store.storeNextRgn = Store.storeNextRgn store + iAllocBump+        , Store.storeRegions = Store.storeRegions store `Set.union` Set.fromList rs+        , Store.storeGlobal  = Store.storeGlobal  store `Set.union` Set.fromList rs }+++-- | Perform a single step of evaluation and print what happened.+forcePrint +        :: State+        -> Store +        -> Exp (AnTEC a Name) Name +        -> IO (Maybe (Store, Exp (AnTEC () Name) Name))++forcePrint state store x+ = let  +        -- Get the type, effect and closure of the original expression.+        Just annot  = takeAnnotOfExp x+        tX          = annotType annot+        effX        = annotEffect annot+        cloX        = annotClosure annot++        -- The evaluator doesn't want any type annotations on the expresison.+        x_stripped = reannotate (const ()) x++   in case force store x_stripped of+        StepProgress store' x_stripped'+         -> case checkExp (configOfProfile Eval.profile) +                        primKindEnv primTypeEnv x_stripped' of+             Left err+              -> do +                    -- Print intermediate expression.+                    when (Set.member TraceEval  $ stateModes state)+                     $ do outDocLn state $ text "* STEP: " <> ppr x_stripped'++                    -- Print intermediate store+                    when (Set.member TraceStore $ stateModes state)+                     $ do putStrLn $ renderIndent $ ppr store'+                          outStr   state "\n"+                +                    putStrLn $ renderIndent+                     $ vcat [ text "* OFF THE RAILS!"+                            , ppr err+                            , empty ]++                    return $ Nothing+                      +             Right (x', tX', effX', cloX')+              -> do +                    -- Print intermediate expression.+                    when (Set.member TraceEval  $ stateModes state)+                     $ do outDocLn state $ text "* STEP: " <> ppr x'++                    -- Print intermediate store+                    when (Set.member TraceStore $ stateModes state)+                     $ do putStrLn $ renderIndent $ ppr store'+                          putStr "\n"+                +                    -- Check expression has the same type as before,+                    -- and that the effect and closure are no greater.+                    let deathT = not $ equivT    tX tX'+                    let deathE = not $ subsumesT kEffect  effX effX'++                    -- ISSUE #290: locations don't reveal closure information.+--                  let deathC = not $ subsumesT kClosure cloX cloX'+                    let death  = deathT || deathE -- deathC+++                    when death+                     $ putStrLn $ renderIndent+                     $ vcat [ empty+                            , text "* OFF THE RAILS! ************************"+                            , text "Starting expression:" +                            , indent 4 $ ppr x+                            , empty+                            , text "Has type:",    indent 4 $ ppr tX+                            , text "Has efect:",   indent 4 $ ppr effX+                            , text "Has closure:", indent 4 $ ppr cloX+                            , empty+                            , text "Reduced expression:"+                            , indent 4 $ ppr x'+                            , empty+                            , text "Has type:",    indent 4 $ ppr tX'+                            , text "Has effect:",  indent 4 $ ppr effX'+                            , text "Has closure:", indent 4 $ ppr cloX' ]++                    if death +                     then return Nothing+                     else return $ Just (store', x')+    +        StepDone+         -> do  -- Load the final expression back from the store to display.+                outDocLn state $ ppr $ traceStore store x_stripped+                return Nothing+        +        StepStuck+         -> do  outDocLn state +                 $ vcat [ text "* STUCK!"+                        , empty]++                return Nothing++        StepMistyped err+         -> do  putStrLn $ renderIndent+                 $ vcat [ text "* OFF THE RAILS!"+                        , ppr err+                        , empty]++                return Nothing+
+ src/ddci-core/DDCI/Core/Command/Help.hs view
@@ -0,0 +1,112 @@++module DDCI.Core.Command.Help where++help :: String+help    = unlines+        [ "-------------------------------------------------------------------- Usage --"+        , ""+        , " On the command line"+        , "   Prefix commands with '-'"+        , "      $ ddci-core -check \"\\(x : Unit). x\""+        , ""+        , "   Read input from a file with ':'"+        , "      $ ddci-core -set lang Salt -load: SomeFile.dcs"+        , ""+        , " Interactively"+        , "   Prefix commands with ':'"+        , "      > :check \\(x : Unit). x"+        , ""+        , "   Split commands over multiple lines with '..', terminating with ';;'"+        , "      > :check.."+        , "      \\(x : Unit). x;;"+        , ""+        , "   Read input from a file with '<'"+        , "      > :load< SomeFile.dcs"+        , ""+        , "   Expressions in the Eval fragment can be evaluated at the prompt."+        , "      > addInt [:R0# R0# R0#:] (2 [R0#] ()) (3 [R0#] ())"+        , "      5"+        , ""+        , "----------------------------------------------------------------- Commands --"+        , "General"+        , "    :quit               Exit DDCi-core." +        , "    :help               Display this help page." +        , ""+        , "Modes"+        , "    :set                    Display active modes and program transform."+        , "    :set +MODE              Enable a mode."+        , "    :set /MODE              Disable a mode."+        , "    :set lang      LANG     Set the language fragment."+        , "    :set builder   BUILDER  Set the builder."+        , "    :set outputdir DIR      Set the output directory."+        , "    :set output    FILE     Set the output file."+        , "    :set trans     TRANS    Set the program transform."+        , ""+        , "    :set rule NAME [an : kn] ... (xn : tn) ... exp1 = exp2"+        , "                        Add a rewrite rule to the database."+        , ""+        , "    :with      PATH     Use this module for 'set trans' inlining."+        , "    :with-lite PATH      ... use Lite module during -compile or -make cmds."+        , "    :with-salt PATH      ... use Salt module during -compile or -make cmds."+        , ""+        , "   MODE    ::="+        , "    Indent              Pretty print expressions with indenting."+        , "    TraceEval           Show the expression at every step when evaluating."+        , "    TraceStore          Show the store at every step when evaluating."+        , "    SuppressImports     Suppress the import list when printing modules."+        , ""+        , "   LANG    ::="+        , "    Lite | Salt | Zero | Eval"+        , ""+        , "   BUILDER ::= "+        , "    x86_32-darwin | x86_64-darwin | x86_32-linux  | x86_64-linux"+        , "    x86_32-cygwin | ppc32-linux"+        , ""+        , "   TRANS   ::= "+        , "    { TRANS }           Parenthesis."+        , "    fix N TRANS         Transform to a fixpoint, or bail out after N iters."+        , "    TRANS; TRANS        Sequence two transforms."+        , "    Id                  Return the original program unharmed."+        , "    Anonymize           Anonymize names to deBruijn form."+        , "    Namify              Introduce fresh names for deBruijn binders."+        , "    Snip                Introduce let-bindings for nested applications."+        , "    SnipOver             ... and over-applications."+        , "    Flatten             Flatten nested let-bindings."+        , "    Beta                Perform beta-reduction for value arguments."+        , "    BetaLets             ... introducing new let-bindings for redex arguments."+        , "    Bubble              Float casts outwards, and combine similar ones."+        , "    Prune               Erase unused, ineffectual let-bindings."+        , "    Forward             Float let-bindings forward into their use sites."+        , "    Rewrite             Perform rule based rewriting. Use 'set rule' to add rules."+        , "    Inline              Perform inlining. Use 'with' to add source modules."+        , "    Elaborate           Introduce default witnesses for unconstrained regions."+        , ""+        , "Type Commands"+        , "    :kind     TYPE      Show the kind of a type."+        , "    :tequiv   TYPE TYPE Check if two types are equivalent."+        , ""+        , "Witness Commands"+        , "    :wtype    WITNESS   Show the type of a witness expression."+        , ""+        , "Expression Commands"+        , "    :check     EXP      Show the type, effect and closure of an exp."+        , "    :type      EXP      Show the type    of an expression."+        , "    :effect    EXP      Show the effect  of an expression."+        , "    :closure   EXP      Show the closure of an expression." +        , "    :eval      EXP      Evaluate an expression."+        , "    :ast       EXP      Show the abstract syntax tree of a exp." +        , ""+        , "    :trans     EXP      Transform the given expression."+        , "    :trun      EXP      Transform the given expression then evaluate it."+        , "    :tinteract EXP      Enter interactive transformation mode."+        , ""+        , "Module Commands"+        , "    :compile   PATH     Compile the module at this path to an object file."+        , "    :make      PATH     Make the module at this path into an executable."+        , ""+        , "    :load      MODULE   Type check and desugar module source code."+        , "    :to-salt   MODULE   Convert module source code to Salt."+        , "    :to-c      MODULE   Convert module source code to C."+        , "    :to-llvm   MODULE   Convert module source code to LLVM."+        , ""+        ]
+ src/ddci-core/DDCI/Core/Command/Set.hs view
@@ -0,0 +1,164 @@++-- | Display and toggle active interpreter modes.+module DDCI.Core.Command.Set+        ( Mode(..)+        , cmdSet)+where+import DDCI.Core.State+import DDCI.Core.Mode+import DDCI.Core.Output+import DDC.Build.Builder+import DDC.Build.Language+import DDC.Core.Fragment+import DDC.Core.Simplifier.Parser+import DDC.Base.Pretty+import Control.Monad+import Data.Char+import Data.List+import qualified DDCI.Core.Rewrite		as R+import qualified Data.Map			as Map+import qualified Data.Set                       as Set+++cmdSet ::  State -> String -> IO State++-- Display the active modes.+cmdSet state []+ | Language bundle      <- stateLanguage state+ , fragment             <- bundleFragment   bundle+ , modules              <- bundleModules    bundle+ , simpl                <- bundleSimplifier bundle+ = do+        let langName    = profileName (fragmentProfile fragment)++        putStrLn $ renderIndent+         $ vcat  [ text "Modes:      " <> text (show $ Set.toList $ stateModes state)+                 , text "Language:   " <> text langName+                 , text "Simplifier: " <> ppr  simpl+                 , text "Builder:    " <> text (show $ liftM builderName $ stateBuilder state) ]+         <$> vcat (text "With:       " : map ppr (Map.keys modules))+         <$> vcat (text "With Lite:  " : map ppr (Map.keys (stateWithLite state)))+         <$> vcat (text "With Salt:  " : map ppr (Map.keys (stateWithSalt state)))++        return state++-- Toggle active modes.+cmdSet state cmd+ | ["lang", name]       <- words cmd+ = do   case lookup name languages of+         Just language+          -> do putStrLn "ok"+                return $ state { stateLanguage = language }++         Nothing+          -> do putStrLn "unknown language"+                return state++ | "trans" : rest       <- words cmd+ , Language bundle      <- stateLanguage state+ , modules              <- bundleModules       bundle+ , rules                <- bundleRewriteRules  bundle + , mkNamT               <- bundleMakeNamifierT bundle+ , mkNamX               <- bundleMakeNamifierX bundle+ , fragment             <- bundleFragment      bundle+ = do   case parseSimplifier +                (fragmentReadName fragment)+                (SimplifierDetails+                        mkNamT mkNamX +                        (Map.assocs rules) +                        (Map.elems  modules))+                (concat $ intersperse " " rest) of++         Left _err+          -> do putStrLn $ "transform spec parse error"+                return state++         Right simpl+          -> do chatStrLn state "ok"+                let bundle'     = bundle { bundleSimplifier = simpl }+                return $ state { stateLanguage = Language bundle' }+++ | ("rule", rest)       <- R.parseFirstWord cmd+ , Language bundle      <- stateLanguage state+ , fragment             <- bundleFragment      bundle+ , modules              <- bundleModules       bundle+ , rules                <- bundleRewriteRules  bundle + = case R.parseRewrite fragment modules rest of+	Right (R.SetAdd name rule)+	 -> do	chatStrLn state $ "ok, added " ++ name+		let rules'  = Map.insert name rule rules+                let bundle' = bundle { bundleRewriteRules = rules' }+		return $ state { stateLanguage = Language bundle' }++	Right (R.SetRemove name)+	 -> do	chatStrLn state $ "ok, removed " ++ name+		let rules'  = Map.delete name rules+                let bundle' = bundle { bundleRewriteRules = rules' }+                return $ state { stateLanguage = Language bundle' }++	Right R.SetList+	 -> do	let rules' = Map.toList rules+		mapM_ (uncurry $ R.showRule state 0) rules'+		return state+	+	Left e+	 -> do	chatStrLn state e+		return state++ | "builder" : name : []     <- words cmd+ = do   config  <- getDefaultBuilderConfig+        case find (\b -> builderName b == name) (builders config) of+         Nothing+          -> do  putStrLn "unknown builder"+                 return state++         Just builder+          -> do  chatStrLn state "ok"+                 return state { stateBuilder = Just builder }++ | "outputdir" : dir : []    <- words cmd+ = return $ state { stateOutputDir  = Just dir }++ | "output" : file : []      <- words cmd+ = return $ state { stateOutputFile = Just file }++ | otherwise+ = case parseModeChanges cmd of+        Just changes+         -> do  let state'  = foldr (uncurry adjustMode) state changes+                chatStrLn state "ok"+                return state'+        +        Nothing+         -> do  chatStrLn state "mode parse error"+                return state+++-- | Parse a string of mode changes.+parseModeChanges :: String -> Maybe [(Bool, Mode)]+parseModeChanges str+        = sequence $ map parseModeChange $ words str+++-- | Parse a mode change setting.+--   "Mode" or "+Mode" to enable. "-Mode" to disable.+parseModeChange  :: String -> Maybe (Bool, Mode)+parseModeChange str+ = case str of+        ('+' : strMode)+         | Just mode    <- readMode strMode+         -> Just (True, mode)+        +        ('/' : strMode)+         | Just mode    <- readMode strMode+         -> Just (False, mode)++        (c : strMode)+         | isUpper c +         , Just mode    <- readMode (c : strMode)+         -> Just (True, mode)++        _ -> Nothing++
+ src/ddci-core/DDCI/Core/Command/Trans.hs view
@@ -0,0 +1,170 @@+{-# OPTIONS -Werror #-}++module DDCI.Core.Command.Trans+        ( cmdTrans+	, cmdTransEval+	, applyTransAndCheck)+where+import DDCI.Core.Command.Eval+import DDCI.Core.Output+import DDCI.Core.State+import DDC.Driver.Command.Check+import DDC.Core.Fragment+import DDC.Core.Transform.Reannotate+import DDC.Core.Simplifier+import DDC.Core.Check+import DDC.Core.Exp+import DDC.Core.Compounds+import DDC.Type.Equiv+import DDC.Type.Subsumes+import DDC.Base.Pretty+import DDC.Type.Env                             as Env+import qualified Control.Monad.State.Strict     as S+import qualified DDC.Build.Language.Eval        as Eval+import qualified DDC.Core.Eval.Name             as Eval+import qualified Data.Set               as Set+import Data.Typeable+import Control.Monad+import DDC.Core.Module+++-- Trans ----------------------------------------------------------------------+-- | Apply the current transform to an expression.+cmdTrans :: State -> Source -> String -> IO ()+cmdTrans state source str+ | Language bundle      <- stateLanguage state+ , fragment             <- bundleFragment   bundle+ , modules              <- bundleModules    bundle+ , simpl                <- bundleSimplifier bundle+ , zero                 <- bundleStateInit  bundle+ , profile              <- fragmentProfile  fragment+ =   cmdParseCheckExp fragment modules True source str + >>= goStore profile modules zero simpl+ where+        -- Expression had a parse or type error.+        goStore _ _ _ _ Nothing+         = do   return ()++        -- Expression is well-typed.+        goStore profile modules zero simpl (Just x)+         = do   let kenv    = modulesExportKinds modules (profilePrimKinds profile)+                let tenv    = modulesExportTypes modules (profilePrimTypes profile)++                tr <- applyTransAndCheck state profile kenv tenv zero simpl x+		case tr of+		  Nothing -> return ()+		  Just x' -> outDocLn state $ ppr x'+++-- TransEval ------------------------------------------------------------------+-- | Apply the current transform to an expression,+--   then evaluate and display the result+cmdTransEval :: State -> Source -> String -> IO ()+cmdTransEval state source str+ | Language bundle      <- stateLanguage    state+ , fragment             <- bundleFragment   bundle+ , modules0             <- bundleModules    bundle+ , zero                 <- bundleStateInit  bundle+ , simpl0               <- bundleSimplifier bundle+ , profile0             <- fragmentProfile  fragment++ -- The evaluator only works on expressions with Eval.Names, + --   The actual name type is an existential of Bundle, + --   so we use gcast to check whether the bundle is really+ --   set to Eval.+ , Just (profile :: Profile Eval.Name) <- gcast profile0 + , Just (SimplBox simpl)               <- gcast (SimplBox simpl0)+ , Just (modules :: ModuleMap (AnTEC () Eval.Name) Eval.Name)+				       <- gcast modules0+ = do   result'  <- cmdParseCheckExp Eval.fragment modules False source str +        case result' of+         Nothing         -> return ()+         Just xx+          -> do let kenv    = modulesExportKinds modules (profilePrimKinds profile)+                let tenv    = modulesExportTypes modules (profilePrimTypes profile)++                -- Apply the current transform.+                tr      <- applyTransAndCheck state profile kenv tenv zero simpl xx++                case tr of+                 Nothing -> return ()+                 Just x'+                     -- Evaluate the transformed expression.+                  -> do outDocLn state $ ppr x'+                        evalExp state x'+                        return ()++ | otherwise+ = outDocLn state $ text "Language must be set to Eval for :teval"+++-- Proxies to help with type casting.+--   The 'gcast' function will only cast the rightmost 'n' of a type,+--   But there is also an 'n' attached to the annotation type of+--   the simplifier. We use the proxy to cast both occurrences at once.+data SimplBox s n+        = SimplBox (Simplifier s (AnTEC () n) n)+++-- Trans ----------------------------------------------------------------------+-- | Transform an expression, or display errors+applyTransAndCheck +        :: (Eq n, Ord n, Pretty n, Show n, Show a)+        => State+        -> Profile n+        -> Env n                        -- Kind Environment.+        -> Env n                        -- Type Environment.+        -> s+        -> Simplifier s (AnTEC a n) n+        -> Exp (AnTEC a n) n+        -> IO (Maybe (Exp (AnTEC () n) n))++applyTransAndCheck state profile kenv tenv zero simpl xx+ = do+        let Just annot  = takeAnnotOfExp xx+        let t1          = annotType    annot+        let eff1        = annotEffect  annot+        let clo1        = annotClosure annot++         -- Apply the simplifier.+        let tx          = flip S.evalState zero+                        $ applySimplifierX profile kenv tenv simpl xx+	+	let x'          = reannotate (const ()) $ result tx++	when (Set.member TraceTrans $ stateModes state)+	 $ case (resultInfo tx) of+	   TransformInfo inf+	    -> outDocLn state +            $  text "* TRANSFORM INFORMATION: " <$> indent 4 (ppr inf) <$> text ""++        -- Check that the simplifier perserved the type of the expression.+        case checkExp (configOfProfile profile) kenv tenv x' of+          Right (x2, t2, eff2, clo2)+           |  equivT t1 t2+           ,  subsumesT kEffect  eff1 eff2+           ,  subsumesT kClosure clo1 clo2+           -> do return (Just x2)++           | otherwise+           -> do putStrLn $ renderIndent $ vcat+                    [ text "* CRASH AND BURN: Transform is not type preserving."+                    , ppr x'+                    , text ":: 1 " <+> ppr t1+                    , text ":: 2 " <+> ppr t2+                    , text ":!:1 " <+> ppr eff1+                    , text ":!:2 " <+> ppr eff2+                    , text ":$:1 " <+> ppr clo1+                    , text ":$:2 " <+> ppr clo2 ]+                 return Nothing++          Left err+           -> do putStrLn $ renderIndent $ vcat+                    [ text "* CRASH AND BURN: Type error in transformed program."+                    , ppr err+                    , text "" ]++                 outDocLn state $ text "Transformed expression:"+                 outDocLn state $ ppr x'+                 return Nothing+
+ src/ddci-core/DDCI/Core/Command/TransInteract.hs view
@@ -0,0 +1,116 @@+module DDCI.Core.Command.TransInteract+        ( cmdTransInteract+	, cmdTransInteractLoop)+where+import DDCI.Core.Command.Trans+import DDCI.Core.Output+import DDCI.Core.State+import DDC.Driver.Command.Check+import DDC.Build.Language+import DDC.Core.Fragment+import DDC.Core.Simplifier.Parser+import DDC.Core.Compounds+import DDC.Core.Check+import DDC.Core.Module+import DDC.Base.Pretty+import qualified Data.Map                       as Map+++-- TransInteract --------------------------------------------------------------+-- | Apply the current transform to an expression.+cmdTransInteract :: State -> Source -> String -> IO State+cmdTransInteract state source str+ | Language bundle      <- stateLanguage state+ , fragment             <- bundleFragment   bundle+ , modules              <- bundleModules    bundle+ =   cmdParseCheckExp fragment modules True source str + >>= goStore bundle+ where+        -- Expression had a parse or type error.+        goStore _ Nothing+         = do   return state++        -- Expression is well-typed.+        goStore bundle (Just xx)+         = do   +                let Just annot  = takeAnnotOfExp xx+                let t1          = annotType annot+                let eff1        = annotEffect annot+                let clo1        = annotClosure annot++                let hist   = TransHistory+			     { historyExp	    = (xx, t1, eff1, clo1)+			     , historySteps	    = []+                             , historyBundle        = bundle }++		return state { stateTransInteract = Just hist }+++cmdTransInteractLoop :: State -> String -> IO State+cmdTransInteractLoop state str+ | Just hist    <- stateTransInteract state+ , TransHistory (x,t,e,c) steps bundle <- hist+ , fragment     <- bundleFragment bundle+ , profile      <- fragmentProfile fragment+ = case str of+    ":back" -> do+	let steps' = case steps of+		      []     -> []+		      (_:ss) -> ss++	putStrLn "Going back: "+	let x' = case steps' of+		   []    -> x+		   ((xz,_):_) -> xz+	outDocLn state $ ppr x'++	let hist'      = TransHistory (x,t,e,c) steps' bundle+	return state { stateTransInteract = Just hist' }++    ":done" -> do+	let simps = reverse $ map (indent 4 . ppr . snd) steps+	outStrLn state "* TRANSFORM SEQUENCE:"+	mapM_ (outDocLn state) simps+	return state { stateTransInteract = Nothing }++    _	    -> do++ 	let tr = parseSimplifier +                    (fragmentReadName fragment)+		    (SimplifierDetails+                        (bundleMakeNamifierT bundle) +                        (bundleMakeNamifierX bundle)+        		(Map.assocs $ bundleRewriteRules bundle) +                        (Map.elems  $ bundleModules      bundle))+		    str++	let x' = case steps of+		[]    -> x+		((xz,_):_) -> xz++	case tr of+            Left _err -> do+                putStrLn "Error parsing simplifier"+                return state++	    Right tr' -> do+                let kenv    = modulesExportKinds+                                (bundleModules bundle) +                                (profilePrimKinds profile)++                let tenv    = modulesExportTypes+                                (bundleModules bundle) +                                (profilePrimTypes profile)++		x_trans <- applyTransAndCheck state profile kenv tenv+			    (bundleStateInit bundle) tr' x'++		case x_trans of+		    Nothing -> return state+		    Just x_trans' -> do+			outDocLn state $ ppr x_trans'+			let steps' = (x_trans', tr') : steps+		        let hist'  = TransHistory (x,t,e,c) steps' bundle+			return state { stateTransInteract = Just hist' }++ | otherwise = error "No transformation history!"
+ src/ddci-core/DDCI/Core/Command/With.hs view
@@ -0,0 +1,85 @@++module DDCI.Core.Command.With+        (cmdWith, cmdWithLite, cmdWithSalt)+where+import DDCI.Core.State+import DDC.Driver.Source+import DDC.Core.Pretty+import DDC.Build.Pipeline+import DDC.Core.Module+import DDC.Data.Canned+import System.Directory+import Control.Monad+import Data.IORef+import Data.Char+import qualified Data.Map                       as Map+import qualified DDC.Build.Language.Lite        as Lite+import qualified DDC.Build.Language.Salt        as Salt+++-- | Add a module to the inliner table.+cmdWith :: State -> Source -> String -> IO State+cmdWith state _source str+ | Language bundle      <- stateLanguage  state+ , modules              <- bundleModules  bundle+ , fragment             <- bundleFragment bundle+ = do   res <- cmdWith_load fragment str+	case res of+	  Nothing  -> return state+	  Just mdl +           -> do+		let modules' = Map.insert (moduleName mdl) mdl modules +                let bundle'  = bundle { bundleModules = modules' }+		return $ state { stateLanguage = Language bundle' }+++cmdWithLite :: State -> Source -> String -> IO State+cmdWithLite state _source str+ = do   res <- cmdWith_load Lite.fragment str+	case res of+	  Nothing  -> return state+	  Just mdl ->+		return $ state+		       { stateWithLite = Map.insert (moduleName mdl) mdl (stateWithLite state) }++cmdWithSalt :: State -> Source -> String -> IO State+cmdWithSalt state _source str+ = do   res <- cmdWith_load Salt.fragment str+	case res of+	  Nothing  -> return state+	  Just mdl ->+		return $ state+		       { stateWithSalt = Map.insert (moduleName mdl) mdl (stateWithSalt state) }+++cmdWith_load frag str+ = do	-- Always treat the string as a filename+        let source   = SourceFile str++        -- Read in the source file.+        let filePath = dropWhile isSpace str+        exists  <- doesFileExist filePath+        when (not exists)+         $      error $ "No such file " ++ show filePath++        src     <- readFile filePath++	cmdWith_parse frag source src+++cmdWith_parse 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+                putStrLn "ok"+                readIORef ref++         _ -> do+                mapM_ (putStrLn . renderIndent . ppr) errs+                return Nothing+
+ src/ddci-core/DDCI/Core/Input.hs view
@@ -0,0 +1,161 @@++module DDCI.Core.Input+        ( InputState    (..)+        , Input         (..) +        , readInput+        , eatLine)+where+import DDCI.Core.State+import DDCI.Core.Command+import DDCI.Core.Command.TransInteract+import DDC.Data.ListUtils+import System.Directory+import Data.List+import Data.Char+++-- InputState ----------------------------------------------------------------------+-- Interpreter input state+data InputState+        = InputState+        { -- Command that we're still receiving input for,+          -- along with the line number it started on.+          inputCommand     :: Maybe (Command, Int)++          -- Input mode.+        , _inputMode        :: Input++          -- The current line number in the command stream.+        , inputLineNumber   :: Int++          -- Accumulation of current input buffer.+        , _inputAcc         :: String }+++-- | How we're reading the input expression.+data Input+        -- | Read input line-by-line, using a backslash at the end of the+        --   line to continue to the next.+        = InputLine++        -- | Read input as a block terminated by a double semicolon (;;)+        | InputBlock++        -- | Read input from a file specified on the prompt+        | InputFile     FilePath+        deriving (Eq, Show)+++-- | Read the input mode from the front of a string.+readInput :: String -> (Input, String)+readInput ss+        | isPrefixOf ".." ss+        = (InputBlock, drop 2 ss)++        | isPrefixOf "<" ss+        , filePath      <- dropWhile isSpace (drop 1 ss)+        = (InputFile filePath, drop (length filePath) ss)++        | otherwise+        = (InputLine, ss)+++-- Eat ------------------------------------------------------------------------+-- Eating input lines.+eatLine :: State -> InputState -> String -> IO (State, InputState)+eatLine state (InputState mCommand inputMode lineNumber acc) line+ | Just _ <- stateTransInteract state+ = do+	state' <- cmdTransInteractLoop state line+	return (state', InputState mCommand inputMode (lineNumber+1) acc)++ | otherwise+ = do   +        -- If this is the first line then try to read the command and+        --  input mode from the front so we know how to continue.+        -- If we can't read an explicit command then assume this is +        --  an expression to evaluate.+        let (cmd, lineStart, (input, rest))+             = case mCommand of+                -- We haven't started a command yet.+                Nothing+                 -> case readCommand line of+                     Just (cmd', rest') -> (cmd',        lineNumber, readInput rest')+                     Nothing            -> (CommandEval, lineNumber, (InputLine, line))+                +                -- We've already started a command, and this is more input for it.+                Just (cmd', lineStart')+                 -> (cmd', lineStart', (inputMode, line))++        let source +                -- We were instructed to read the program from a file.+                -- Report this file as the source location, independent+                -- of how we were instructed to read it.+                | InputFile filePath    <- input+                = SourceFile filePath++                -- The program was embedded in the command stream.+                | otherwise+                = case stateInterface state of+                        InterfaceArgs           -> SourceArgs+                        InterfaceConsole        -> SourceConsole lineStart+                        InterfaceBatch file     -> SourceBatch   file lineStart+++        case input of+         -- For line-by-line mode, if the line ends with backslash then keep+         -- reading, otherwise run the command.+         -- We also convert the backslash to a newline so the source+         -- position comes out right in parser error messages.+         InputLine+          | not $ null rest+          , last rest == '\\'+          , Just initRest       <- takeInit rest+          -> do return ( state+                       , InputState (Just (cmd, lineStart)) input+                                (lineNumber + 1)+                                (acc ++ initRest ++ "\n"))++          | otherwise+          -> do state'  <- handleCmd state cmd source (acc ++ rest)+                return ( state'+                       , InputState Nothing InputLine+                                (lineNumber + 1)+                                [])+++         -- For block mode, if the line ends with ';;' then run the command,+         -- otherwise keep reading.+         InputBlock+          | isSuffixOf ";;" rest+          -> do let rest' = take (length rest - 2) rest+                state'  <- handleCmd state cmd source (acc ++ rest')+                return ( state'+                       , InputState Nothing InputLine+                                (lineNumber + 1)+                                [])++          | otherwise+          ->    return ( state+                       , InputState (Just (cmd, lineStart)) input+                                (lineNumber + 1)+                                (acc ++ rest ++ "\n"))++         -- Read input from a file+         InputFile filePath+          -> do exists          <- doesFileExist filePath+                if exists +                 then do        +                        contents  <- readFile filePath+                        state'    <- handleCmd state cmd source contents+                        return  ( state'+                                , InputState Nothing InputLine+                                        (lineNumber + 1)+                                        [])+                 else do+                        putStrLn "No such file."+                        return  ( state+                                , InputState Nothing InputLine+                                        (lineNumber + 1)+                                        [])+
+ src/ddci-core/DDCI/Core/Interface/Args.hs view
@@ -0,0 +1,47 @@++module DDCI.Core.Interface.Args+        (runArgs)+where+import DDCI.Core.Command.Help+import DDCI.Core.Command+import DDCI.Core.State+import DDC.Data.ListUtils+import Data.List+++-- | Run in unix command-line mode, reading commands from a list of arguments.+runArgs :: [String] -> IO ()+runArgs args+ = do   let state    = initState InterfaceArgs++        -- If the help command is one of the arguments then just+        -- display the help and don't do anything else.+        if elem "--help" args +         then putStr help+         else loop state args++ where +        -- No more args, we're done.+        loop _state []+         = do   return ()++        loop state (('-':cmdColon) : filePath : rest)+         | isSuffixOf ":" cmdColon+         , Just cmdStr          <- takeInit cmdColon+         , Just (cmd, [])       <- readCommand (':' : cmdStr)+         = do   contents        <- readFile filePath+                state'          <- handleCmd state cmd (SourceFile filePath) +                                        contents+                loop state' rest++        loop state (('-':cmdStr) : rest)+         | Just (cmd, [])       <- readCommand (':' : cmdStr)+         , (argss, more)        <- break (isPrefixOf "-") rest+         = do   state'          <- handleCmd state cmd SourceArgs +                                        (concat $ intersperse " " argss)+                loop state' more++        loop _state xs+         = error $  "Cannot parse arguments: "+                 ++ intercalate " " xs+
+ src/ddci-core/DDCI/Core/Interface/Batch.hs view
@@ -0,0 +1,51 @@++module DDCI.Core.Interface.Batch+        (runBatch)+where+import DDCI.Core.State+import DDCI.Core.Input+import Data.List+++-- | Run in batch mode, reading commands from the given string.+runBatch :: FilePath -> String -> IO ()+runBatch filePath str+ = do   let state       = initState (InterfaceBatch filePath)+        let inputState  = InputState Nothing InputLine 1 []+        loop state inputState (lines str)+ where +        -- No more lines, we're done.+        -- There might be a command in the buffer though.+        loop state inputState []+         = do   eatLine state inputState []+                return ()++        loop state inputState (l:ls)+         -- Echo comment lines back.+         |  isPrefixOf "--" l+         = do   putStrLn l+                let inputState'+                        = inputState +                        { inputLineNumber = inputLineNumber inputState + 1 }++                loop state inputState' ls++         -- Echo blank lines back if we're between commands.+         | Nothing      <- inputCommand inputState+         , null l+         = do   putStr "\n"+                let inputState'+                        = inputState +                        { inputLineNumber = inputLineNumber inputState + 1 }++                loop state inputState' ls++         -- Quit the program.+         | isPrefixOf ":quit" l+         = do   return ()++         -- Handle a line of input.+         | otherwise+         = do   (state', inputState')  <- eatLine state inputState l+                loop state' inputState' ls+
+ src/ddci-core/DDCI/Core/Interface/Interactive.hs view
@@ -0,0 +1,58 @@++module DDCI.Core.Interface.Interactive+        ( runInteractive)+where+import DDCI.Core.Input+import DDCI.Core.State+import Data.List+import Data.Maybe+import qualified System.Console.Haskeline       as HL+import qualified System.Console.Haskeline.IO    as HL+++-- Interactive ----------------------------------------------------------------+-- | Run an interactive session, reading commands from the console.+runInteractive :: IO ()+runInteractive+ = do   putStrLn "DDCi-core, version 0.3.0: http://disciple.ouroborus.net."+        putStrLn "Type :help for help."++        -- Setup terminal mode.+        loopInteractive+++-- | The main REPL loop.+loopInteractive :: IO ()+loopInteractive + = do   hlState         <- HL.initializeInput HL.defaultSettings+        let state       = initState InterfaceConsole+        let inputState  = InputState Nothing InputLine 1 []+        loop state inputState hlState+ where  +        loop state inputState hlState +         = do   -- If this isn't the first line then print the prompt.+                let prompt = if isJust (inputCommand inputState)+                             then ""+			     else if isJust (stateTransInteract state)+			     then "trans> "+                             else "> "+         +                -- Read a line from the user and echo it back.+                line    <- getInput hlState prompt++                if  isPrefixOf ":quit" line+                 || isPrefixOf ":q"    line+                 then return ()+                 else do+                        (state', inputState')+                                <- eatLine state inputState line++                        loop state' inputState' hlState+++-- | Get an input line from the console, using given prompt+getInput :: HL.InputState -> String -> IO String+getInput hlState prompt+ = do   line <- HL.queryInput hlState (HL.getInputLine prompt)+        return (fromMaybe ":quit" line)+
+ src/ddci-core/DDCI/Core/Mode.hs view
@@ -0,0 +1,46 @@++module DDCI.Core.Mode+        ( Mode(..)+        , readMode)+where+++-- | DDCI mode flags.+data Mode+        -- | Display the expression at each step in the evaluation.+        =  TraceEval++        -- | Display the store state at each step in the evaluation.+        |  TraceStore++        -- | Render expressions displayed to user using indenting.+        |  Indent++        -- | Suppress import lists when printing modules+        |  SuppressImports++        -- | When pretty printing Salt modules as C code,+        --  include the #includes etc needed for compilation.+        |  SaltPrelude++        -- | Dump all intermediate versions of the code during compilation.+        |  Dump++	-- | Display information about each transformation step+	|  TraceTrans+        deriving (Eq, Ord, Show)+++-- | Parse a mode from a string.+readMode :: String -> Maybe Mode+readMode str+ = case str of+        "TraceEval"             -> Just TraceEval+        "TraceStore"            -> Just TraceStore+        "Indent"                -> Just Indent+        "SuppressImports"       -> Just SuppressImports+        "SaltPrelude"           -> Just SaltPrelude+        "Dump"                  -> Just Dump+        "TraceTrans"            -> Just TraceTrans+        _                       -> Nothing+
+ src/ddci-core/DDCI/Core/Output.hs view
@@ -0,0 +1,49 @@++module DDCI.Core.Output+        ( outDoc, outDocLn+        , outStr, outStrLn+        , chatStrLn)+where+import DDCI.Core.State+import DDC.Base.Pretty+import qualified Data.Set       as Set+++-- | Output a document to the console.+outDoc :: State -> Doc -> IO ()+outDoc state doc+        | Set.member Indent $ stateModes state+        = putDocLn RenderIndent doc++        | otherwise+        = putDocLn RenderPlain doc+++outDocLn :: State -> Doc -> IO ()+outDocLn state doc+        | Set.member Indent $ stateModes state+        = putDocLn RenderIndent doc++        | otherwise+        = putDocLn RenderPlain doc+++-- | Output a string to the console.+outStr :: State -> String -> IO ()+outStr _state str+        = putStr str+++outStrLn :: State -> String -> IO ()+outStrLn _state str+        = putStrLn str+++-- | Output chatty 'ok' type responses.+--   These are only displayed in the Interactive and Batch interfaces.+chatStrLn :: State -> String -> IO ()+chatStrLn state str+ = case stateInterface state of+        InterfaceConsole        -> putStrLn str+        InterfaceBatch _        -> putStrLn str+        _                       -> return ()
+ src/ddci-core/DDCI/Core/Rewrite.hs view
@@ -0,0 +1,100 @@++module DDCI.Core.Rewrite+        ( SetRuleCommand(..)+        , parseFirstWord+	, parseRewrite+	, showRule )+where+import DDC.Base.Pretty+import DDC.Build.Language+import DDC.Core.Lexer+import DDC.Core.Fragment                hiding (Error)+import DDC.Core.Transform.Rewrite.Rule  hiding (Error)+import DDC.Core.Transform.Rewrite.Parser+import DDCI.Core.State+import DDCI.Core.Output+import Data.Char+import qualified DDC.Core.Check         as C+import qualified DDC.Base.Parser        as BP++import DDC.Core.Module+import Data.Map                         (Map)+++-- | :set rule command+data SetRuleCommand a n+        = SetAdd    +                { setRuleName   :: String +                , setRuleRule   :: RewriteRule a n }++        | SetRemove +                { setRuleName   :: String }++	| SetList+        deriving (Eq, Show)++type Error = String+++-- | Return first word and remainder of string+parseFirstWord :: String -> (String,String)+parseFirstWord s = break isSpace $ dropWhile isSpace s+++-- | Parse a :set rule command+--   +name rule, name rule:  add rewrite rule+--   -name                   remove rule+parseRewrite +        :: (Ord n, Show n, Pretty n)+        => Fragment n err +	-> Map ModuleName (Module (C.AnTEC () n) n)+        -> String +        -> Either Error (SetRuleCommand (C.AnTEC () n) n)++parseRewrite fragment modules str+ = case dropWhile isSpace str of+	[]		-> Right SetList+	('+':rest)	-> parseAdd fragment modules rest++	('-':rest)	+         -> let (name,_) = parseFirstWord rest +            in Right $ SetRemove name++	rest            -> parseAdd fragment modules rest+++-- | Parse add rule+parseAdd+        :: (Ord n, Show n, Pretty n)+        => Fragment n err+	-> Map ModuleName (Module (C.AnTEC () n) n)+        -> String +        -> Either Error (SetRuleCommand (C.AnTEC () n) n)++parseAdd fragment modules str+ | (name, rest) <- parseFirstWord str+ = case BP.runTokenParser describeTok "<interactive>" pRule+          (fragmentLexExp fragment "interactive" 0 rest) of+                Left err -> Left $ renderIndent $ ppr err+                Right rule ->+                  case checkRewriteRule config kinds' types' rule of+                    Left err    -> Left  $ renderIndent $ ppr err+                    Right rule' -> Right $ SetAdd name rule'+ where+        config   = C.configOfProfile (fragmentProfile fragment)+	kinds	 = profilePrimKinds  (fragmentProfile fragment)+	types	 = profilePrimTypes  (fragmentProfile fragment)++	kinds'	 = modulesExportKinds modules kinds+	types'	 = modulesExportTypes modules types+++-- | Display rule+showRule :: (Eq n, Pretty n)+         => State -> Int -> String -> RewriteRule a n -> IO ()++showRule state indentBy name rule+ = do	putStr $ (take indentBy $ repeat '\t') ++ name ++ " "+	outDocLn state+	 $  ppr rule+
+ src/ddci-core/DDCI/Core/State.hs view
@@ -0,0 +1,190 @@++module DDCI.Core.State+        ( State         (..)+        , Bundle        (..)+        , initState+        , getDriverConfigOfState++        , TransHistory	(..)++        , Interface     (..)+        , Source        (..)++        , Language      (..)+        , languages+        , getDefaultBuilderConfig+        , getActiveBuilder++        , Mode          (..)+        , adjustMode)+where+import DDCI.Core.Mode+import DDC.Code.Config+import DDC.Driver.Source+import DDC.Build.Builder+import DDC.Build.Language+import DDC.Core.Check+import DDC.Core.Exp+import DDC.Core.Module+import DDC.Core.Simplifier+import DDC.Base.Pretty                          hiding ((</>))+import Data.Typeable+import System.FilePath+import Data.Map                                 (Map)+import Data.Set                                 (Set)+import qualified DDC.Build.Language.Eval        as Eval+import qualified DDC.Core.Salt                  as Salt+import qualified DDC.Core.Lite                  as Lite+import qualified DDC.Core.Simplifier            as S+import qualified DDC.Core.Salt.Runtime          as Runtime+import qualified DDC.Driver.Stage               as D+import qualified Data.Map                       as Map+import qualified Data.Set                       as Set+++-- | Interpreter state.+--   This is adjusted by interpreter commands.+data State+        = State+        { -- | ddci interface state.+          stateInterface        :: Interface++          -- | ddci mode flags.+        , stateModes            :: Set Mode ++          -- | Source language to accept.+        , stateLanguage         :: Language++          -- | Maps of modules we can use as inliner templates.+        , stateWithLite         :: Map ModuleName (Module (AnTEC () Lite.Name) Lite.Name)+        , stateWithSalt         :: Map ModuleName (Module (AnTEC () Salt.Name) Salt.Name)++          -- | Simplifier to apply to core program.+        , stateSimplLite        :: Simplifier Int () Lite.Name+        , stateSimplSalt        :: Simplifier Int () Salt.Name++          -- | Force the builder to this one, this sets the address width etc.+          --   If Nothing then query the host system for the default builder.+        , stateBuilder          :: Maybe Builder++          -- | Output file for @compile@ and @make@ commands.+        , stateOutputFile       :: Maybe FilePath ++          -- | Output dir for @compile@ and @make@ commands+        , stateOutputDir        :: Maybe FilePath++	  -- | Interactive transform mode+	, stateTransInteract	:: Maybe TransHistory}++++data TransHistory+	= forall s n err+        .  (Typeable n, Ord n, Show n, Pretty n)+	=> TransHistory+	{ -- | Original expression and its types+	  historyExp		:: (Exp (AnTEC () n) n, Type n, Effect n, Closure n) ++	  -- | Keep history of steps so we can go back and construct final sequence+	, historySteps		:: [(Exp (AnTEC () n) n, Simplifier s (AnTEC () n) n)]++          -- | Bundle for the language that we're transforming.+        , historyBundle         :: Bundle s n err }+++-- | What interface is being used.+data Interface+        -- | Read commands from unix command-line args.+        = InterfaceArgs++        -- | Read commands interactively from the console.+        | InterfaceConsole++        -- | Read commands from the file with this name.+        | InterfaceBatch        FilePath+        deriving (Eq, Show)+++-- | Adjust a mode setting in the state.+adjustMode +        :: Bool         -- ^ Whether to enable or disable the mode.        +        -> Mode         -- ^ Mode to adjust.+        -> State+        -> State++adjustMode True mode state+        = state { stateModes    = Set.insert mode (stateModes state) }++adjustMode False mode state+        = state { stateModes    = Set.delete mode (stateModes state) }+++-- | The initial state.+initState :: Interface -> State+initState interface+        = State+        { stateInterface        = interface+        , stateModes            = Set.empty +        , stateLanguage         = Eval.language+        , stateWithLite         = Map.empty+        , stateWithSalt         = Map.empty+        , stateSimplLite        = S.Trans S.Id+        , stateSimplSalt        = S.Trans S.Id+        , stateBuilder          = Nothing  +        , stateOutputFile       = Nothing+        , stateOutputDir        = Nothing+	, stateTransInteract	= Nothing }+++-- | Slurp out the relevant parts of the DDCI stage into a driver config.+getDriverConfigOfState :: State -> IO D.Config+getDriverConfigOfState state+ = do   builder <- getActiveBuilder state+        return +         $ D.Config+         { D.configDump                  = Set.member Dump (stateModes state)+         , D.configViaBackend            = D.ViaLLVM++         -- ISSUE #300: Allow the default heap size to be set when+         --   compiling the program.+         , D.configRuntime+                = Runtime.Config+                { Runtime.configHeapSize = 65536 }++         , D.configOutputFile            = stateOutputFile state+         , D.configOutputDir             = stateOutputDir  state+         , D.configSimplLite             = stateSimplLite  state+         , D.configSimplSalt             = stateSimplSalt  state+         , D.configBuilder               = builder+         , D.configSuppressCoreImports   = Set.member SuppressImports (stateModes state)+         , D.configSuppressHashImports   = not $ Set.member SaltPrelude (stateModes state) +         , D.configKeepLlvmFiles         = False+         , D.configKeepSeaFiles          = False+         , D.configKeepAsmFiles          = False }+++-- | Holds platform independent builder info.+getDefaultBuilderConfig :: IO BuilderConfig+getDefaultBuilderConfig+ = do   baseLibraryPath <- locateBaseLibrary+        return $ BuilderConfig+          { builderConfigBaseSrcDir     = baseLibraryPath+          , builderConfigBaseLibDir     = baseLibraryPath </> "build" }+++-- | Get the active builder.+--   If one is set explicitly in the state then use that, +--   otherwise query the host system to determine the builder.+--   If that fails as well then 'error'.+getActiveBuilder :: State -> IO Builder +getActiveBuilder state + = case stateBuilder state of+        Just builder          -> return builder+        Nothing         +         -> do  config   <- getDefaultBuilderConfig +                mBuilder <- determineDefaultBuilder config+                case mBuilder of+                 Nothing      -> error "getActiveBuilder unrecognised host platform"+                 Just builder -> return builder++
+ src/ddci-core/DDCI/Core/Stats/Trace.hs view
@@ -0,0 +1,82 @@++module DDCI.Core.Stats.Trace+        (traceStore)+where+import DDC.Core.Eval.Store+import DDC.Core.Eval.Name+import DDC.Type.Compounds+import DDC.Core.Compounds+import DDC.Core.Exp+import qualified Data.Set       as Set+import Data.Set                 (Set)+++-- | Replace non-recursive store locations in an expression by their values.+--  +--   * If the value is recursive then we just leave the original store location.+--   * Constructors in the result just have *0 for their type annotation.+--+traceStore :: Store -> Exp () Name -> Exp () Name+traceStore store xx+        = traceStoreX store Set.empty xx+++-- | Trace an expression.+traceStoreX :: Store -> Set Name -> Exp () Name -> Exp () Name+traceStoreX store entered xx+ = let down = traceStoreX store entered+   in  case xx of+        XVar{}  -> xx++        XCon _ dc+         | Just n@(NameLoc l)     <- takeNameOfDaCon dc+         , not $ Set.member n entered+         , Just sbind           <- lookupBind l store+         -> traceStoreX store (Set.insert n entered) (expOfSBind sbind)++        XCon{}          -> xx+        XApp  a x1 x2   -> XApp  a (down x1) (down x2)+        XLAM  a b x     -> XLAM  a b (down x)+        XLam  a b  x    -> XLam  a b (down x)+        XLet  a ls x    -> XLet  a (traceStoreLs store entered ls) (down x)+        XCase a x alts  -> XCase a (down x) (map (traceStoreA store entered) alts)+        XCast a c x     -> XCast a c (down x)+        XType{}         -> xx+        XWitness{}      -> xx+++-- | Trace lets.+traceStoreLs :: Store -> Set Name -> Lets () Name -> Lets () Name+traceStoreLs store entered ls+ = let down = traceStoreX store entered +   in case ls of+        LLet m b x      -> LLet m b (down x)+        LRec bxs        -> LRec [(b, down x) | (b, x) <- bxs]+        LLetRegions{}   -> ls+        LWithRegion{}   -> ls+++-- | Trace case alts.+traceStoreA  :: Store -> Set Name -> Alt () Name  -> Alt () Name+traceStoreA store entered (AAlt p x)+        = AAlt p (traceStoreX store entered x)+++-- | Convert a store binding to an expression.+expOfSBind :: SBind -> Exp () Name+expOfSBind sbind+ = case sbind of+        SObj dcTag lsArgs+         -> xApps () (XCon () dcTag) (map expOfLoc lsArgs)++        SLams fbs x+         -> makeXLamFlags () fbs x++        SThunk x+         -> x+++-- | Convert a store location to a constructor expression.+expOfLoc :: Loc -> Exp () Name+expOfLoc l = XCon () (mkDaConSolid (NameLoc l) (tBot kData))+
+ src/ddci-core/Main.hs view
@@ -0,0 +1,58 @@++-- | Interactive interface to DDC.+--      This also accepts interpreter commands as arguments on the command-line.+--      If you want a more unixy inferface then use the ddc-main interface instead.+module Main where+import DDCI.Core.Command.Help+import DDCI.Core.Interface.Args+import DDCI.Core.Interface.Batch+import DDCI.Core.Interface.Interactive+import DDCI.Core.State+import DDC.Driver.Command.Make+import System.Environment+import System.IO+import Control.Monad.Trans.Error+import Data.List+++main :: IO ()+main + = do   args    <- getArgs+        case args of+         []      -> runInteractive++         -- Display the help.+         ["--help"]+          ->    putStr help++         -- Run commands from a file in batch mode.+         ["--batch", filePath]+          -> do file    <- readFile filePath+                runBatch filePath file++         -- Make a file, depending on what the extension is.+         -- This gets us  --make on the command line as well as -make+         -- so we behave more like GHC.+         ["--make",  filePath]+          -> do let state       = initState (InterfaceBatch filePath)+                config          <- getDriverConfigOfState state+                runError $ cmdMake config filePath++         -- Run a Disciple-Core-Exchange file.+         [filePath]+          | isSuffixOf ".dcx" filePath+          -> do file    <- readFile filePath+                runBatch filePath file++        +         _       -> runArgs args+++-- | Just print errors to stdout and continue the session.+runError :: ErrorT String IO () -> IO ()+runError m+ = do   result  <- runErrorT m+        case result of+         Left err       -> hPutStrLn stdout err+         Right _        -> return ()+