packages feed

rest-rewrite-0.2.0: test/BagExample.hs

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE ImplicitParams #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}

module BagExample (mkBagGraph) where

import Prelude hiding (EQ, GT)


import           Control.Monad.Identity
import Language.REST.Dot
import Language.REST.ExploredTerms
import Language.REST.RESTDot
import Language.REST.OCToAbstract
import Language.REST.RewriteRule
import qualified Language.REST.Internal.MultiSet as M
import Language.REST.Internal.MultisetOrder
import Language.REST.Rest
import Language.REST.WQOConstraints as OC
import Language.REST.WQOConstraints.Strict as SC
import Language.REST.Internal.WorkStrategy
import Language.REST.Types
import Language.REST.SMT hiding (GTE)

import qualified Data.List as L
import qualified Data.HashSet as S
import qualified Data.Text as T
import GHC.Generics (Generic)
import           Data.Hashable

data PChar = PChar Char deriving (Eq, Ord, Generic, Hashable)

instance ToSMTVar PChar Int where
  toSMTVar c = SMTVar $ T.pack $ "char_" ++ show c

instance Show PChar where
  show (PChar c) = return c

data Bag = Bag String
  deriving (Eq, Ord, Generic, Hashable)

instance Show Bag where
  show = showBag


toMultiset :: Bag -> M.MultiSet PChar
toMultiset (Bag str) = M.fromList $ map PChar str


bag :: String -> Bag
bag = Bag

data Rewrite = Rewrite Bag (S.HashSet Bag)
  deriving (Eq, Ord, Generic, Hashable)

infixr 1 ~>
(~>) :: String -> [String] -> [String]
(~>) = (:)

instance RewriteRule IO Rewrite Bag where
  apply bag1 (Rewrite bag' result) | bag1 == bag' = return result
  apply _ _ | otherwise                           = return S.empty


fromPath :: [String] -> S.HashSet Rewrite
fromPath [] = S.empty
fromPath xs = S.fromList $ map go (zip xs (tail xs))
  where
    go :: (String, String) -> Rewrite
    go (x, y) = Rewrite (bag x) (S.singleton $ bag y)


fromPaths :: [[String]] -> S.HashSet Rewrite
fromPaths paths = S.unions $ map fromPath paths

start :: String
start = "AAB"

rules :: S.HashSet Rewrite
rules = fromPaths $
  [  start ~> "ACD" ~> "AAAA" ~> "ABDD" ~> []
  ,  start ~> "ABD" ~> "AB"  ~> "BBD" ~> []
  ]

showBag :: Bag -> String
showBag (Bag bag1) = "{ " ++ (L.intercalate ", " $ map return bag1) ++ " }"

showRule :: Rewrite -> String
showRule _ = ""


compareChar :: ConstraintGen impl PChar PChar Identity
compareChar impl GTE oc c1 c2 | c1 /= c2 = compareChar impl GT oc c1 c2
compareChar impl EQ  _  c1 c2 | c1 /= c2 = return $ OC.unsatisfiable impl
compareChar impl r   oc c1 c2            = return $ intersectRelation impl oc (c1, c2, r)


mkBagGraph :: IO ()
mkBagGraph =
  do
    (PathsResult paths, _) <- rest
      RESTParams
        { re           = S.empty
        , ru           = rules
        , toET         = id
        , target       = Nothing
        , workStrategy = bfs
        , ocImpl       = impl
        , initRes      = pathsResult
        , etStrategy   = ExploreWhenNeeded
        } (bag start)
    let prettyPrinter = PrettyPrinter showRule showBag show True
    writeDot "example" Tree prettyPrinter (toOrderedSet paths)
  where
    impl = lift SC.strictOC $ cmapConstraints toMultiset (multisetOrder compareChar)