    -- | Types for the general graph colorer.
    module GraphBase (
            Triv,
            Graph (..),
            initGraph,
            graphMapModify,

            Node  (..),     newNode,
    )

    where

    import UniqSet
    import UniqFM

    -- | A fn to check if a node is trivially colorable
    --      For graphs who's color classes are disjoint then a node is 'trivially colorable'
    --      when it has less neighbors and exclusions than available colors for that node.
    --
    --      For graph's who's color classes overlap, ie some colors alias other colors, then
    --      this can be a bit more tricky. There is a general way to calculate this, but
    --      it's likely be too slow for use in the code. The coloring algorithm takes
    --      a canned function which can be optimised by the user to be specific to the
    --      specific graph being colored.
    --
    --      for details, see  "A Generalised Algorithm for Graph-Coloring Register Allocation"
    --                              Smith, Ramsey, Holloway - PLDI 2004.
    --
    type Triv k cls color
            =  cls                  -- the class of the node we're trying to color.
            -> UniqSet k            -- the node's neighbors.
            -> UniqSet color        -- the node's exclusions.
            -> Bool

    -- | The Interference graph.
    --      There used to be more fields, but they were turfed out in a previous revision.
    --      maybe we'll want more later..
    --
    data Graph k cls color
            = Graph {
            -- | All active nodes in the graph.
              graphMap              :: UniqFM (Node k cls color)  }

    -- | An empty graph.
    initGraph :: Graph k cls color
    initGraph
            = Graph
            { graphMap              = emptyUFM }

    -- | Modify the finite map holding the nodes in the graph.
    graphMapModify
            :: (UniqFM (Node k cls color) -> UniqFM (Node k cls color))
            -> Graph k cls color -> Graph k cls color

    graphMapModify f graph
            = graph { graphMap      = f (graphMap graph) }

    -- | Graph nodes.
    --      Represents a thing that can conflict with another thing.
    --      For the register allocater the nodes represent registers.
    --
    data Node k cls color
            = Node {
            -- | A unique identifier for this node.
              nodeId                :: k

            -- | The class of this node,
            --      determines the set of colors that can be used.
            , nodeClass             :: cls

            -- | The color of this node, if any.
            , nodeColor             :: Maybe color

            -- | Neighbors which must be colored differently to this node.
            , nodeConflicts         :: UniqSet k

            -- | Colors that cannot be used by this node.
            , nodeExclusions        :: UniqSet color

            -- | Colors that this node would prefer to be, in decending order.
            , nodePreference        :: [color]

            -- | Neighbors that this node would like to be colored the same as.
            , nodeCoalesce          :: UniqSet k }

    -- | An empty node.
    newNode :: k -> cls -> Node k cls color
    newNode k cls
            = Node
            { nodeId                = k
            , nodeClass             = cls
            , nodeColor             = Nothing
            , nodeConflicts         = emptyUniqSet
            , nodeExclusions        = emptyUniqSet
            , nodePreference        = []
            , nodeCoalesce          = emptyUniqSet }