tock-mirror/fco2/ParseState.hs
2007-05-05 00:26:26 +00:00

194 lines
5.8 KiB
Haskell

-- | Compiler state.
module ParseState where
import Data.Generics
import Data.Map (Map)
import qualified Data.Map as Map
import Control.Monad.State
import qualified AST as A
import Errors
import Metadata
-- | State necessary for compilation.
data ParseState = ParseState {
-- Set by Main (from command-line options)
psVerboseLevel :: Int,
psParseOnly :: Bool,
psOutputFile :: String,
-- Set by preprocessor
psSourceFiles :: Map String String,
psIndentLinesIn :: [String],
psIndentLinesOut :: [String],
-- Set by Parse
psLocalNames :: [(String, A.Name)],
psMainLocals :: [(String, A.Name)],
psNames :: Map String A.NameDef,
psNameCounter :: Int,
psTypeContext :: [Maybe A.Type],
psLoadedFiles :: [String],
psWarnings :: [String],
-- Set by passes
psNonceCounter :: Int,
psFunctionReturns :: Map String [A.Type],
psPulledItems :: [[A.Structured -> A.Structured]],
psAdditionalArgs :: Map String [A.Actual]
}
deriving (Show, Data, Typeable)
instance Show (A.Structured -> A.Structured) where
show p = "(function on Structured)"
emptyState :: ParseState
emptyState = ParseState {
psVerboseLevel = 0,
psParseOnly = False,
psOutputFile = "-",
psSourceFiles = Map.empty,
psIndentLinesIn = [],
psIndentLinesOut = [],
psLocalNames = [],
psMainLocals = [],
psNames = Map.empty,
psNameCounter = 0,
psTypeContext = [],
psLoadedFiles = [],
psWarnings = [],
psNonceCounter = 0,
psFunctionReturns = Map.empty,
psPulledItems = [],
psAdditionalArgs = Map.empty
}
-- | Class of monads which keep a ParseState.
-- (This is just shorthand for the equivalent MonadState constraint.)
class MonadState ParseState m => PSM m
instance MonadState ParseState m => PSM m
--{{{ name definitions
-- | Add the definition of a name.
defineName :: PSM m => A.Name -> A.NameDef -> m ()
defineName n nd
= modify $ (\ps -> ps { psNames = Map.insert (A.nameName n) nd (psNames ps) })
-- | Find the definition of a name.
lookupName :: (PSM m, Die m) => A.Name -> m A.NameDef
lookupName n
= do ps <- get
case Map.lookup (A.nameName n) (psNames ps) of
Just nd -> return nd
Nothing -> die $ "cannot find name " ++ A.nameName n
--}}}
--{{{ warnings
-- | Add a warning.
addWarning :: PSM m => Meta -> String -> m ()
addWarning m s = modify (\ps -> ps { psWarnings = msg : psWarnings ps })
where msg = "Warning: " ++ show m ++ ": " ++ s
--}}}
--{{{ pulled items
-- | Enter a pulled-items context.
pushPullContext :: PSM m => m ()
pushPullContext = modify (\ps -> ps { psPulledItems = [] : psPulledItems ps })
-- | Leave a pulled-items context.
popPullContext :: PSM m => m ()
popPullContext = modify (\ps -> ps { psPulledItems = tail $ psPulledItems ps })
-- | Add a pulled item to the collection.
addPulled :: PSM m => (A.Structured -> A.Structured) -> m ()
addPulled item
= modify (\ps -> case psPulledItems ps of
(l:ls) -> ps { psPulledItems = (item:l):ls })
-- | Do we currently have any pulled items?
havePulled :: PSM m => m Bool
havePulled
= do ps <- get
case psPulledItems ps of
([]:_) -> return False
_ -> return True
-- | Apply pulled items to a Structured.
applyPulled :: PSM m => A.Structured -> m A.Structured
applyPulled ast
= do ps <- get
case psPulledItems ps of
(l:ls) -> do put $ ps { psPulledItems = [] : ls }
return $ foldl (\p f -> f p) ast l
--}}}
--{{{ type contexts
-- | Enter a type context.
pushTypeContext :: PSM m => Maybe A.Type -> m ()
pushTypeContext t
= modify (\ps -> ps { psTypeContext = t : psTypeContext ps })
-- | Leave a type context.
popTypeContext :: PSM m => m ()
popTypeContext
= modify (\ps -> ps { psTypeContext = tail $ psTypeContext ps })
-- | Get the current type context, if there is one.
getTypeContext :: PSM m => m (Maybe A.Type)
getTypeContext
= do ps <- get
case psTypeContext ps of
(Just c):_ -> return $ Just c
_ -> return Nothing
--}}}
--{{{ nonces
-- | Generate a throwaway unique name.
makeNonce :: PSM m => String -> m String
makeNonce s
= do ps <- get
let i = psNonceCounter ps
put ps { psNonceCounter = i + 1 }
return $ s ++ "_n" ++ show i
-- | Generate and define a nonce specification.
defineNonce :: PSM m => Meta -> String -> A.SpecType -> A.NameType -> A.AbbrevMode -> m A.Specification
defineNonce m s st nt am
= do ns <- makeNonce s
let n = A.Name m A.ProcName ns
let nd = A.NameDef {
A.ndMeta = m,
A.ndName = ns,
A.ndOrigName = ns,
A.ndNameType = nt,
A.ndType = st,
A.ndAbbrevMode = am,
A.ndPlacement = A.Unplaced
}
defineName n nd
return $ A.Specification m n st
-- | Generate and define a no-arg wrapper PROC around a process.
makeNonceProc :: PSM m => Meta -> A.Process -> m A.Specification
makeNonceProc m p
= defineNonce m "wrapper_proc" (A.Proc m A.PlainSpec [] p) A.ProcName A.Abbrev
-- | Generate and define a variable abbreviation.
makeNonceIs :: PSM m => String -> Meta -> A.Type -> A.AbbrevMode -> A.Variable -> m A.Specification
makeNonceIs s m t am v
= defineNonce m s (A.Is m am t v) A.VariableName am
-- | Generate and define an expression abbreviation.
makeNonceIsExpr :: PSM m => String -> Meta -> A.Type -> A.Expression -> m A.Specification
makeNonceIsExpr s m t e
= defineNonce m s (A.IsExpr m A.ValAbbrev t e) A.VariableName A.ValAbbrev
-- | Generate and define a variable.
makeNonceVariable :: PSM m => String -> Meta -> A.Type -> A.NameType -> A.AbbrevMode -> m A.Specification
makeNonceVariable s m t nt am
= defineNonce m s (A.Declaration m t) nt am
--}}}