PSCi
PSCi
supportModule
prepare the evaluator environment and name the module S
as support module $PSCI.Support
.
module S where
import Prelude
import Control.Monad.Eff
import Control.Monad.Eff.Console
import Control.Monad.Eff.Unsafe
class Eval a where
eval :: a -> Eff (console :: CONSOLE) Unit
instance evalShow :: (Show a) => Eval a where
eval = print
instance evalEff :: (Eval a) => Eval (Eff eff a) where
eval x = unsafeInterleaveEff x >>= eval
The interpreter monad:
newtype PSCI a = PSCI { runPSCI :: InputT (StateT PSCiState IO) a }
deriving (Functor, Applicative, Monad)
-- From psci/Types.hs
data PSCiState = PSCiState
{ psciImportedModules :: [ImportedModule]
, _psciLoadedModules :: Map FilePath [P.Module]
, psciForeignFiles :: Map P.ModuleName FilePath
, psciLetBindings :: [P.Declaration]
, psciNodeFlags :: [String]
}
And next, some very dirty work
- Find
node
executable - Load history
- Load modules
ImportedModule
-- From psci/Types.hs
--
-- | All of the data that is contained by an ImportDeclaration in the AST.
-- That is:
--
-- * A module name, the name of the module which is being imported
-- * An ImportDeclarationType which specifies whether there is an explicit
-- import list, a hiding list, or neither.
-- * If the module is imported qualified, its qualified name in the importing
-- module. Otherwise, Nothing.
type ImportedModule = (P.ModuleName, P.ImportDeclarationType, Maybe P.ModuleName)
And some user-friendly stuff till...
psciIO
: life IO
operation into PSCI
monad.
createTemporaryModuleXXX
: The volatile is like a container with type of Module
. FIXME: How is that sensible?
runMake
: Approximately fromMake a
toIO a
makeIO
: Approximately fromIO a
toMake a
make :: PSCiState -> [P.Module] -> P.Make P.Environment
this basically turns configuration into runnable environment.
The evaluator: handleExpression :: P.Expr -> PSCI ()
Take declarations and updates the environment: handleDecls :: [P.Declaration] -> PSCI ()
Dynamic import: handleImport :: ImportedModule -> PSCI ()
Typing & Kinding: handleTypeOf :: P.Expr -> PSCI ()
, handleKindOf :: P.Type -> PSCI ()
And after that, the rest functions are mostly interactive-specific utilities.
Comments:
This module can be pretty useful. You can load a interpreter and run some PureScript code anytime your want.
For the compile-time interpreting, the key is to keep the compiler-state and PSCiState
synced. And sane preparation of environment can also be a problem.
For the PSCi-on-the-web, only difference is "console" becomes "socket". And by using UNIX redirect techniques, we can write a third-party web server doing process invocation directly. It can be in PureScript as well! But if you are going to sell such thing to community, it has to be easy to deploy as well!