-- Compiler Toolkit: compiler state management basics
--
-- Author : Manuel M. T. Chakravarty
-- Created: 7 November 97
--
-- Version $Revision: 1.1.1.1 $
--
-- Copyright (C) [1997..1999] Manuel M. T. Chakravarty
--
-- This file is free software; you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation; either version 2 of the License, or
-- (at your option) any later version.
--
-- This file is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
--- DESCRIPTION ---------------------------------------------------------------
--
-- This module provides basic types and services used to realize the state
-- management of the compiler.
--
--- DOCU ----------------------------------------------------------------------
--
-- language: Haskell 98
--
-- * The monad `PreCST' is an instance of `STB' where the base state is fixed.
-- However, the base state itself is parametrized by an extra state
-- component that can be instantiated by the compiler that uses the toolkit
-- (to store information like compiler switches) -- this is the reason for
-- adding the prefix `Pre'.
--
-- * The module exports the details of the `BaseState' etc as they have to be
-- know by `State'. The latter ensures the necessary abstraction for
-- modules that do not belong to the state management.
--
-- * Due to this module, the state management modules can share internal
-- information about the data types hidden to the rest of the system.
--
-- * The following state components are maintained:
--
-- + idBS (triple of strings) -- version, copyright, and disclaimer
-- + errorsBS (type `ErrorState') -- keeps track of raised errors
-- + namesBS (type `NameSupply') -- provides unique names
-- + extraBS (generic type) -- extra compiler-dependent state
-- information, e.g., for compiler
-- switches
--
--- TODO ----------------------------------------------------------------------
--
module StateBase (PreCST(..), ErrorState(..), BaseState(..),
nop, yield, (+>=), (+>), fixCST,
unpackCST, readCST, writeCST, transCST, liftIO)
where
import Position (Position)
import UNames (NameSupply)
import StateTrans (STB,
fixSTB, readGeneric, writeGeneric, transGeneric, readBase,
transBase)
import qualified
StateTrans (liftIO)
import Errors (ErrorLvl(..), Error)
infixr 1 +>=, +>
-- state used in the whole compiler
-- --------------------------------
-- form of the error state
--
-- * when no error was raised yet, the error level is the lowest possible one
--
data ErrorState = ErrorState ErrorLvl -- worst error level that was raised
Int -- number of errors (excl warnings)
[Error] -- already raised errors
-- base state (EXPORTED)
--
data BaseState e = BaseState {
idTKBS :: (String, String, String), -- toolkit id
idBS :: (String, String, String), -- compiler id
errorsBS :: ErrorState,
suppliesBS :: [NameSupply],
extraBS :: e -- extra state
}
-- the compiler state transformer (EXPORTED)
--
newtype PreCST e s a = CST (STB (BaseState e) s a)
instance Monad (PreCST e s) where
return = yield
(>>=) = (+>=)
(>>) = (+>)
-- unwrapper coercion function (EXPORTED)
--
unpackCST :: PreCST e s a -> STB (BaseState e) s a
unpackCST m = let CST m' = m in m'
-- monad operations
-- ----------------
-- the monad's unit
--
yield :: a -> PreCST e s a
yield a = CST $ return a
-- the monad's bind
--
(+>=) :: PreCST e s a -> (a -> PreCST e s b) -> PreCST e s b
m +>= k = CST $ unpackCST m >>= (\a -> unpackCST (k a))
-- bind dropping the result of the first state transfomer
--
(+>) :: PreCST e s a -> PreCST e s b -> PreCST e s b
k +> m = k +>= const m
-- unit with no result
--
nop :: PreCST e s ()
nop = yield ()
-- fixpoint combinator in the monad (EXPORTED)
--
fixCST :: (a -> PreCST e s a) -> PreCST e s a
fixCST m = CST $ fixSTB (unpackCST . m)
-- generic state manipulation
-- --------------------------
-- given a reader function for the state, wrap it into an CST monad (EXPORTED)
--
readCST :: (s -> a) -> PreCST e s a
readCST f = CST $ readGeneric f
-- given a new state, inject it into an CST monad (EXPORTED)
--
writeCST :: s -> PreCST e s ()
writeCST s' = CST $ writeGeneric s'
-- given a transformer function for the state, wrap it into an CST monad
-- (EXPORTED)
--
transCST :: (s -> (s, a)) -> PreCST e s a
transCST f = CST $ transGeneric f
-- interaction with the encapsulated `IO' monad
-- --------------------------------------------
-- lifts an `IO' state transformer into `CST'
--
liftIO :: IO a -> PreCST e s a
liftIO m = CST $ (StateTrans.liftIO m)