language-qux-0.2.0.0: src/Language/Qux/Llvm/Builder.hs
{-|
Module : Language.Qux.Llvm.Builder
Description : Build utilities for the LLVM compiler.
Copyright : (c) Henry J. Wylde, 2015
License : BSD3
Maintainer : public@hjwylde.com
Build utilities for the LLVM compiler, see "Compiler".
-}
{-# OPTIONS_HADDOCK hide, prune #-}
{-# LANGUAGE FlexibleContexts #-}
module Language.Qux.Llvm.Builder where
import Control.Monad.State
import Data.Map (Map)
import qualified Data.Map as Map
import LLVM.General.AST
data Builder = Builder {
currentBlock :: Name,
blocks :: Map Name BlockBuilder,
counter :: Word
}
initialBuilder :: Builder
initialBuilder = Builder {
currentBlock = Name ".0",
blocks = Map.singleton (Name ".0") defaultBlockBuilder { name = Name ".0" },
counter = 1
}
data BlockBuilder = BlockBuilder {
name :: Name,
stack :: [Named Instruction],
term :: Maybe (Named Terminator)
}
defaultBlockBuilder :: BlockBuilder
defaultBlockBuilder = BlockBuilder {
name = error "no block name set",
stack = [],
term = Nothing
}
getBlock :: Monad m => MonadState Builder m => m Name
getBlock = gets currentBlock
setBlock :: Monad m => MonadState Builder m => Name -> m ()
setBlock name = modify $ \s -> s { currentBlock = name }
addBlock :: Monad m => MonadState Builder m => Name -> m ()
addBlock name' = modify $ \s -> s { blocks = Map.insert name' defaultBlockBuilder { name = name' } (blocks s) }
modifyBlock :: Monad m => MonadState Builder m => (BlockBuilder -> BlockBuilder) -> m ()
modifyBlock f = do
c <- current
modify $ \s -> s { blocks = Map.insert (name c) (f c) (blocks s) }
current :: Monad m => MonadState Builder m => m BlockBuilder
current = getBlock >>= \name -> gets (flip (Map.!) name . blocks)
append :: Monad m => MonadState Builder m => Named Instruction -> m ()
append instr = modifyBlock $ \b -> b { stack = stack b ++ [instr] }
terminate :: Monad m => MonadState Builder m => Named Terminator -> m ()
terminate term = modifyBlock $ \b -> b { term = Just term }
freeName :: Monad m => MonadState Builder m => m String
freeName = (("." ++) . show) <$> freeUnName
freeUnName :: Monad m => MonadState Builder m => m Word
freeUnName = gets counter <* modify (\s -> s { counter = counter s + 1 })