packages feed

INblobs-0.1.1: src/INRule.hs

{-| Module     : INRule
    Maitainer  : jmvilaca@di.uminho.pt

    
-}

module INRule 
    ( INRule
    , Mapping
    , MappingElement 
    , initial

    , getName,    setName
    , getLHS,     setLHS
    , getRHS,     setRHS
    , getMapping, setMapping
    , construct
   
    , updateLHS
    , updateRHS
    , updateMapping
    , copyLHS2RHS
    , copyLHSInterface2RHS
 
    , addMapping
    , showsMapping
    , isInterfaceNode
    ) where

import Network hiding (getName, setName) 
import Ports
import InfoKind
import Common
import qualified Data.IntMap as IntMap (empty)
import SpecialSymbols

import Data.List


data INRule g n e = INRule 
   { ruleName :: String                 -- ^ the name of the rule
   , ruleLHS  :: Network g n e  -- ^ the rule LHS network 
   , ruleRHS  :: Network g n e  -- ^ the rule RHS network 
   , ruleMaps :: Mapping                -- ^ mappings between the LHS and RHS
   } deriving (Show)

-- | @(n_i, n_j)@ means that node n_i in the LHS of the rule corresponds to node n_j in the RHS
-- @n_i@ and @n_j@ have to be interface nodes
type MappingElement = (NodeNr, NodeNr)
type Mapping = [MappingElement] 

showsMapping :: Mapping -> ShowS
showsMapping [] = showString "{}"
showsMapping (x:xs) =
	showChar '{' . showsE x . showl xs
  where showl []     = showChar '}'
	showl (x:xs) = showChar ',' . showsE x . showl xs
	showsE (from,to) = shows from . showString " |-> " . shows to

initial :: (InfoKind e g, InfoKind n g) => g -> n -> e -> INRule g n e
initial g n e =
   INRule { ruleName = "Rule 1"
           , ruleLHS  = Network.empty g n e 
           , ruleRHS  = Network.empty g n e
           , ruleMaps = []
   }

-- Set's e Get's
getName :: INRule g n e -> String
getName = ruleName

getLHS :: INRule g n e -> Network g n e
getLHS = ruleLHS 

getRHS :: INRule g n e -> Network g n e
getRHS = ruleRHS

getMapping :: INRule g n e -> Mapping
getMapping = ruleMaps

setName :: String -> INRule g n e -> INRule g n e
setName newRuleName rule = rule { ruleName = newRuleName}

setLHS :: Network g n e -> INRule g n e -> INRule g n e
setLHS newRuleLHS rule = rule { ruleLHS = newRuleLHS}

setRHS :: Network g n e -> INRule g n e -> INRule g n e
setRHS newRuleRHS rule = rule { ruleRHS = newRuleRHS}

setMapping :: Mapping -> INRule g n e -> INRule g n e
setMapping newRuleMaps rule = rule { ruleMaps = newRuleMaps}

construct :: String                   -- ^ rule name
             -> Network g n e -- ^ lhs
             -> Network g n e -- ^ rhs
             -> Mapping               -- ^ correspondences between 
                                      -- lhs and rhs interface
             -> INRule g n e
construct theRuleName lhs rhs mapping =
    INRule { ruleName = theRuleName
           , ruleLHS  = lhs 
           , ruleRHS  = rhs
           , ruleMaps = mapping
           }

-- update LHS and RHS networks and mapping

updateLHS :: (Network g n e -> Network g n e)
             -> INRule g n e -> INRule g n e
updateLHS networkFun rule = rule { ruleLHS = networkFun $ ruleLHS rule }

updateRHS :: (Network g n e -> Network g n e)
             -> INRule g n e -> INRule g n e
updateRHS networkFun rule = rule { ruleRHS = networkFun $ ruleRHS rule }

updateMapping :: (Mapping -> Mapping)
                  -> INRule g n e -> INRule g n e
updateMapping mapFun rule = rule { ruleMaps = mapFun $ ruleMaps rule }

copyLHS2RHS :: INRule g n e -> INRule g n e
copyLHS2RHS rule = 
   rule { ruleRHS  = lhs
        , ruleMaps = map (diag . fst) . filter isInterfaceNode $ getNodeAssocs lhs
        }
   where lhs = ruleLHS rule

copyLHSInterface2RHS :: INRule g n e -> INRule g n e
copyLHSInterface2RHS rule = 
   rule { ruleRHS  = setNodeAssocs lhs' . emptyNodesAndEdges $ ruleRHS rule                      
        , ruleMaps = map (diag . fst) $ lhs'
        }
   where lhs' = filter isInterfaceNode . getNodeAssocs $ ruleLHS rule
         emptyNodesAndEdges net = net { networkNodes = IntMap.empty
                                      , networkEdges = IntMap.empty }
                         
-- operations on Mappings
addMapping :: MappingElement -> Mapping -> Mapping
addMapping = insert  

-- auxiliar functions
isInterfaceNode :: (NodeNr, Node n) -> Bool
isInterfaceNode (_, node) = getShape node == interName
	where (interName, interDef) = interfaceSymbol