|
|
|
|
|
|
Synopsis |
|
|
|
|
State and types
|
|
type CTable = Map ConstItem CRef |
|
data CState |
The internal compiler state
flags,state - saved external items
maxDepth - the biggest depth we reached in this function
constIds - the list of free constant ids
consts - the current constant table
labels - the list of free labels
env - where each variable can be found
depth - the current stack depth
fails - a list of fail handlers (still used?)
evals - the set of variables that we know to be evaluated
| Constructors | | Instances | |
|
|
initCompileState :: Flags -> IntState -> CState |
|
type STCompiler a = State CState a |
|
type InsCode = [UseIns] -> [UseIns] |
|
type Compiler a = STCompiler (InsCode, a) |
|
data CMode |
compiler mode information
| Constructors | CMode | | isStrict :: Bool | | isTraced :: Bool | | isProjected :: Bool | |
|
|
|
|
cStrict :: CMode -> CMode |
|
cLazy :: CMode -> CMode |
|
cTraced :: CMode -> CMode |
|
cUntraced :: CMode -> CMode |
|
cUnproject :: CMode -> CMode |
|
data Where |
where we can find a variable
| Constructors | | Instances | |
|
|
shiftWhere :: Int -> Where -> Where |
shift a where by an offset, if it's on the stack
|
|
Monadic plumbing
|
|
the underlying state of the compiler, recording stack depth, environment
etc. is monadic, ontop of this combinators are provided to plug together
the outputted code, which are also monad like in nature.
needless to say the internal details of how this works are complicated,
however, conceptually it's quite easy.
p =>> q
runs the monad for compiler p, then the one for compiler q and then
joins the instructions generated together.
p =>>= \ x -> q
does the same as the above but this time it's assumed p is returning something
besides just the code that is generated, which is then used as a local variable
in defining q.
for example:
newLabel =>>= \ j ->
ins (JUMP j)
calls the monad to generate a new internal label, and joins its code (i.e. none)
with the code for a JUMP to address provided by newLabel.
|
|
(=>>=) :: Compiler a -> (a -> Compiler b) -> Compiler b |
|
(=>>) :: Compiler () -> Compiler a -> Compiler a |
|
mapC :: (a -> Compiler b) -> [a] -> Compiler [b] |
|
mapC_ :: (a -> Compiler ()) -> [a] -> Compiler () |
|
simply :: a -> Compiler a |
|
liftC :: STCompiler a -> Compiler a |
|
block :: InsCode -> Compiler () |
|
State manipulation functions
|
|
shiftStack :: Int -> Compiler () |
shift the stack by the given amount, also offsets the stack stored variables in
the environment and changes the maxDepth if appropriate
|
|
getFlags :: Compiler Flags |
get the flags
|
|
getDepth :: Compiler Int |
get the current depth
|
|
setDepth :: Int -> Compiler () |
set the current depth
|
|
bindArgs :: [Id] -> Compiler () |
bind the argument list
|
|
bind :: Bool -> Id -> Int -> Compiler () |
bind an identifier to a stack location
|
|
whereIs :: Id -> Compiler (Maybe Where) |
find out where an identifier is stored
|
|
addConst :: ConstItem -> Compiler CRef |
add a const to the consttable, if it's not there already
|
|
isEvaled :: Id -> Compiler Bool |
find out whether a variable has been evaluated already
|
|
evaled :: Id -> Compiler () |
mark that a variable has been evaluated
|
|
newLabel :: Compiler Label |
allocate a new compiler label and return it
|
|
newLabels :: Int -> Compiler [Label] |
allocate some new labels
|
|
branch :: Compiler () -> Compiler Int |
take a compiler and compile it in its own environment,
saving and restoring the appropriate local state elements
give the depth on return.
|
|
mergeDepths :: Label -> String -> [Int] -> Compiler () |
merge together a list of depths taken from branching, checks they are all the same
and sets the depth to that
|
|
pushFail :: Label -> Compiler () |
push a fail on the fail stack
|
|
popFail :: Compiler () |
pop a fail from the fail stack
|
|
getFail :: Compiler (Label, Int) |
get the failure on the fail of the stack
|
|
getIntState :: Compiler IntState |
get the internal state
|
|
Produced by Haddock version 0.8 |