ddc-tools-0.4.1.1: src/ddci-core/DDCI/Core/Command.hs
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.TransInteract
import DDCI.Core.Command.With
import DDCI.Core.State
import DDCI.Core.Mode as Mode
import DDC.Driver.Command.Check
import DDC.Driver.Command.Load
import DDC.Driver.Command.Trans
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 DDC.Driver.Command.Tetra.Boxing
import DDC.Driver.Command.Flow.Prep
import DDC.Driver.Command.Flow.Rate
import DDC.Driver.Command.Flow.Lower
import DDC.Driver.Command.Flow.Concretize
import DDC.Driver.Command.Flow.Wind
import DDC.Driver.Command.Flow.Melt
import DDC.Driver.Command.Flow.Thread
import DDC.Type.Universe
import qualified DDC.Core.Flow as Flow
import qualified Data.Set as Set
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.
| CommandSort -- ^ Show the sort of a kind.
| CommandKind -- ^ Show the kind of a spec.
| CommandEquivType -- ^ Check if two types are equivalent.
| CommandWitType -- ^ Show the type of a witness.
| CommandExpCheck -- ^ Check the type of an expression.
| CommandExpSynth -- ^ Synthesize the type of an expression, including existentials.
| 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.
-- Generic transformations
| CommandTrans -- ^ Transform an expression.
| CommandTransEval -- ^ Transform then evaluate an expression.
| CommandTransInteract -- ^ Interactively transform an expression.
-- Make and compile
| CommandCompile -- ^ Compile a file.
| CommandMake -- ^ Compile and link and executable.
-- Conversion to machine code
| CommandToSalt -- ^ Convert a module to Disciple Salt.
| CommandToC -- ^ Convert a module to C code.
| CommandToLlvm -- ^ Convert a module to LLVM code.
-- Core Tetra specific passes.
| CommandTetraBoxing -- ^ Manage boxing of numeric types.
-- Core Flow specific passes
| CommandFlowRate -- ^ Perform rate inference
| CommandFlowPrep -- ^ Prepare a Core Flow module for lowering.
| CommandFlowLower Flow.Config -- ^ Prepare and Lower a Core Flow module.
| CommandFlowConcretize -- ^ Convert operations on type level rates to concrete ones.
| CommandFlowMelt -- ^ Melt compound data structures.
| CommandFlowWind -- ^ Wind loop primops into tail recursive loops.
| CommandFlowThread -- ^ Thread a world token through lowered code.
-- Inline control
| 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)
, (":sort", CommandSort)
, (":kind", CommandKind)
, (":tequiv", CommandEquivType)
, (":wtype", CommandWitType)
, (":check", CommandExpCheck)
, (":synth", CommandExpSynth)
, (":recon", CommandExpRecon)
, (":type", CommandExpType)
, (":effect", CommandExpEffect)
, (":closure", CommandExpClosure)
, (":eval", CommandEval)
-- Generic transformations
, (":trun", CommandTransEval)
, (":tinteract", CommandTransInteract)
, (":trans", CommandTrans)
-- Conversion to machine code.
, (":to-salt", CommandToSalt)
, (":to-c", CommandToC)
, (":to-llvm", CommandToLlvm)
-- Core Tetra specific passes
, (":tetra-boxing", CommandTetraBoxing)
-- Core Flow specific passes
, (":flow-rate", CommandFlowRate)
, (":flow-prep", CommandFlowPrep)
, (":flow-lower-kernel", CommandFlowLower Flow.defaultConfigKernel)
, (":flow-lower-vector", CommandFlowLower Flow.defaultConfigVector)
, (":flow-lower", CommandFlowLower Flow.defaultConfigScalar)
, (":flow-concretize", CommandFlowConcretize)
, (":flow-melt", CommandFlowMelt)
, (":flow-wind", CommandFlowWind)
, (":flow-thread", CommandFlowThread)
-- Make and Compile
, (":compile", CommandCompile)
, (":make", CommandMake)
-- Inliner control
, (":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
= let lang = stateLanguage state
traceCheck = Set.member TraceCheck (stateModes state)
in 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 configDriver <- getDriverConfigOfState state
runError
$ cmdLoadCoreFromString
configDriver
(stateLanguage state) source line
return state
CommandSort
-> do cmdShowType lang UniverseKind source line
return state
CommandKind
-> do cmdShowType lang UniverseSpec source line
return state
CommandEquivType
-> do cmdTypeEquiv lang source line
return state
CommandWitType
-> do cmdShowWType lang source line
return state
CommandExpCheck
-> do cmdShowSpec lang ShowSpecAll False traceCheck source line
return state
CommandExpType
-> do cmdShowSpec lang ShowSpecData False traceCheck source line
return state
CommandExpEffect
-> do cmdShowSpec lang ShowSpecEffect False traceCheck source line
return state
CommandExpClosure
-> do cmdShowSpec lang ShowSpecClosure False traceCheck source line
return state
CommandExpSynth
-> do cmdShowSpec lang ShowSpecAll True traceCheck source line
return state
CommandExpRecon
-> do cmdExpRecon lang source line
return state
CommandEval
-> do cmdEval state source line
return state
-- Generic transformations --------------
CommandTrans
-> do configDriver <- getDriverConfigOfState state
runError
$ cmdTransDetect
configDriver
(stateLanguage state)
(Set.member Mode.TraceTrans $ stateModes state)
source line
return state
CommandTransEval
-> do cmdTransEval state source line
return state
CommandTransInteract
-> do cmdTransInteract state source line
-- Conversion to machine code -----------
CommandToSalt
-> do config <- getDriverConfigOfState state
runError $ cmdToSaltCoreFromString config lang source line
return state
CommandToC
-> do config <- getDriverConfigOfState state
runError $ cmdToSeaCoreFromString config lang source line
return state
CommandToLlvm
-> do config <- getDriverConfigOfState state
runError $ cmdToLlvmCoreFromString config lang source line
return state
-- Core Tetra specific passes -----------
CommandTetraBoxing
-> do configDriver <- getDriverConfigOfState state
runError $ cmdTetraBoxing configDriver source line
return state
-- Core Flow specific passes ------------
CommandFlowRate
-> do configDriver <- getDriverConfigOfState state
runError $ cmdFlowRate configDriver source line
return state
CommandFlowPrep
-> do config <- getDriverConfigOfState state
runError $ cmdFlowPrep config source line
return state
CommandFlowLower configLower
-> do configDriver <- getDriverConfigOfState state
runError $ cmdFlowLower configDriver configLower source line
return state
CommandFlowConcretize
-> do config <- getDriverConfigOfState state
runError $ cmdFlowConcretize config source line
return state
CommandFlowMelt
-> do config <- getDriverConfigOfState state
runError $ cmdFlowMelt config source line
return state
CommandFlowWind
-> do config <- getDriverConfigOfState state
runError $ cmdFlowWind config source line
return state
CommandFlowThread
-> do config <- getDriverConfigOfState state
runError $ cmdFlowThread config source line
return state
-- Make and Compile ---------------------
CommandCompile
-> do config <- getDriverConfigOfState state
runError $ cmdCompile config line
return state
CommandMake
-> do config <- getDriverConfigOfState state
runError $ cmdMake config line
return state
-- Inliner Control ----------------------
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 ()