From b16309f88922301fdbfbee8776478fa7446dc525 Mon Sep 17 00:00:00 2001 From: Christian Gram Kalhauge <chrg@dtu.dk> Date: Tue, 6 Feb 2024 09:18:48 +0100 Subject: [PATCH] Add negative labels --- bin/rtree-c/Main.hs | 6 ++--- bin/rtree-c/ReduceC.hs | 18 ++++++++------ src/Control/Monad/Reduce.hs | 16 ++++++------ src/Control/RTree.hs | 22 +++++++++-------- src/Data/Valuation.hs | 49 +++++++++++++++++++++++++++++++------ 5 files changed, 76 insertions(+), 35 deletions(-) diff --git a/bin/rtree-c/Main.hs b/bin/rtree-c/Main.hs index 727b715..278c3a8 100644 --- a/bin/rtree-c/Main.hs +++ b/bin/rtree-c/Main.hs @@ -6,6 +6,7 @@ {-# LANGUAGE OverloadedStrings #-} import Control.RTree +import Data.Valuation qualified as Val import ReduceC @@ -15,7 +16,6 @@ import Control.Monad import Control.Monad.Trans import Data.Foldable import Data.Functor -import Data.Map.Strict qualified as Map import Data.Text qualified as Text import GHC.Stack import Language.C qualified as C @@ -106,7 +106,7 @@ run = do check' f val c = do logInfo "Checking predictate" when debug do - pPrint [(void k, v) | (k, v) <- Map.toList val] + pPrint [(void k, v) | (k, v) <- Val.toPairs val] pPrint (void c) when pedandic do liftIO $ copyFile file (file <.> "last") @@ -163,7 +163,7 @@ run = do l <- (if expmode then ireduceExp else ireduce) (check' file) - (Map.singleton (C.internalIdent "main") True) + (Val.singleton (Val.is $ C.internalIdent "main")) (ReduceC.reduceC c) output file l diff --git a/bin/rtree-c/ReduceC.hs b/bin/rtree-c/ReduceC.hs index 90fde90..e6174f3 100644 --- a/bin/rtree-c/ReduceC.hs +++ b/bin/rtree-c/ReduceC.hs @@ -9,6 +9,8 @@ module ReduceC where import Control.Monad.Reduce +import qualified Data.Valuation as Val + import Control.Applicative import Control.Monad.Trans import Control.Monad.Trans.Maybe @@ -102,7 +104,7 @@ cCTypeSpecifier = \case -- C.CUInt128Type a -> pure () C.CFloatNType{} -> pure () C.CTypeDef i _ -> do - givenThat i + givenThat (Val.is i) pure () (C.CTypeOfExpr e _) -> cCExpression e (C.CTypeOfType t _) -> cCDeclaration t @@ -140,7 +142,7 @@ mrCFunctionDef (C.CFunDef spc dec cdecls smt ni) = do cCDeclr :: (MonadReduce Lab m) => C.CDeclarator C.NodeInfo -> MaybeT m () cCDeclr (C.CDeclr x dd _ _ _) = do mapM_ cCDerivedDeclarator dd - givenWith x + givenWith (Val.is <$> x) where cCDerivedDeclarator = \case C.CPtrDeclr ts _ -> mapM_ cCTypeQualifier ts @@ -153,13 +155,13 @@ cCDeclr (C.CDeclr x dd _ _ _) = do mapM_ cCAttr attr cCFunParams f cCFunParams = \case - C.CFunParamsOld o -> mapM_ givenThat o + C.CFunParamsOld o -> mapM_ (givenThat . Val.is) o C.CFunParamsNew o _ -> mapM_ cCDeclaration o cCAttr :: (MonadReduce Lab m) => C.CAttribute C.NodeInfo -> MaybeT m () cCAttr (C.CAttr i e _) = do mapM_ cCExpression e - givenThat i + givenThat (Val.is i) rCStatement :: (MonadReduce Lab m) => C.CStatement C.NodeInfo -> m (C.CStatement C.NodeInfo) rCStatement = \case @@ -197,12 +199,12 @@ rCStatement = \case C.CCont ni -> pure (C.CCont ni) C.CLabel i s [] ni -> -- todo fix attrs - splitOn i (rCStatement s) do + splitOn (Val.is i) (rCStatement s) do s' <- rCStatement s pure $ C.CLabel i s' [] ni C.CGoto i ni -> -- todo fix attrs - splitOn i (pure $ C.CExpr Nothing ni) do + splitOn (Val.is i) (pure $ C.CExpr Nothing ni) do pure $ C.CGoto i ni C.CWhile e s dow ni -> do e' <- zrCExpression e @@ -231,7 +233,7 @@ zrCExpression e = orZero <$> runMaybeT (mrCExpression e) mrCExpression :: (MonadReduce Lab m) => C.CExpression C.NodeInfo -> MaybeT m (C.CExpression C.NodeInfo) mrCExpression = \case C.CVar i ni -> do - givenThat i + givenThat (Val.is i) pure $ C.CVar i ni C.CCall e es ni -> do e' <- mrCExpression e @@ -260,7 +262,7 @@ mrCExpression = \case C.CIndex e1 e2 ni -> onBothExpr e1 e2 \e1' e2' -> pure $ C.CIndex e1' e2' ni C.CMember e i b ni -> do - givenThat i + givenThat (Val.is i) e' <- mrCExpression e pure $ C.CMember e' i b ni C.CComma items ni -> do diff --git a/src/Control/Monad/Reduce.hs b/src/Control/Monad/Reduce.hs index 640407a..72bb47e 100644 --- a/src/Control/Monad/Reduce.hs +++ b/src/Control/Monad/Reduce.hs @@ -49,6 +49,8 @@ import Control.Monad.Trans.Maybe import qualified Data.List.NonEmpty as NE import Data.Maybe +import Data.Valuation (Truth (..)) + -- {- | A reducer should extract itself -- @ -- extract . red = id @@ -63,7 +65,7 @@ class (Monad m) => MonadReduce l m | m -> l where -- | Split the world into the a reduced world (left) without an element and a world -- with that element (right). Optionally, labeled with l. - splitWith :: Maybe l -> m i -> m i -> m i + splitWith :: Maybe (Truth l) -> m i -> m i -> m i splitWith l r1 r2 = checkWith l >>= \case False -> r1 @@ -71,8 +73,8 @@ class (Monad m) => MonadReduce l m | m -> l where {-# INLINE splitWith #-} -- | Check with returns a boolean, that can be used to split the input into a world where - -- an optional label is true and where it is false. - checkWith :: Maybe l -> m Bool + -- the optional truth assignement is satisfiable and where it is not. + checkWith :: Maybe (Truth l) -> m Bool checkWith l = splitWith l (pure False) (pure True) {-# INLINE checkWith #-} @@ -96,7 +98,7 @@ r1 |> r2 = r2 <| r1 infixl 3 |> -- | Split on a label. -splitOn :: (MonadReduce l m) => l -> m i -> m i -> m i +splitOn :: (MonadReduce l m) => Truth l -> m i -> m i -> m i splitOn l = splitWith (Just l) {-# INLINE splitOn #-} @@ -106,7 +108,7 @@ check = checkWith Nothing {-# INLINE check #-} -- | Split the world on a labeled fact. False it does not happen, and True it does happen. -checkThat :: (MonadReduce l m) => l -> m Bool +checkThat :: (MonadReduce l m) => Truth l -> m Bool checkThat l = checkWith (Just l) {-# INLINE checkThat #-} @@ -116,12 +118,12 @@ given = givenWith Nothing {-# INLINE given #-} -- | Continues if the labeled fact is true. -givenWith :: (MonadReduce l m, MonadPlus m) => Maybe l -> m () +givenWith :: (MonadReduce l m, MonadPlus m) => Maybe (Truth l) -> m () givenWith l = splitWith l mzero (pure ()) {-# INLINE givenWith #-} -- | Continues if the labeled fact is true. -givenThat :: (MonadReduce l m, MonadPlus m) => l -> m () +givenThat :: (MonadReduce l m, MonadPlus m) => Truth l -> m () givenThat l = givenWith (Just l) {-# INLINE givenThat #-} diff --git a/src/Control/RTree.hs b/src/Control/RTree.hs index eaf7424..506eccc 100644 --- a/src/Control/RTree.hs +++ b/src/Control/RTree.hs @@ -42,17 +42,18 @@ import Control.Monad.Reduce import qualified Data.Valuation as Val type Valuation = Val.Valuation +type Truth = Val.Truth data RTree l i - = SplitWith (Maybe l) (RTree l i) !(RTree l i) + = SplitWith (Maybe (Truth l)) (RTree l i) !(RTree l i) | Done i deriving (Functor) extract :: (Ord l) => Valuation l -> RTree l i -> i extract v = \case - SplitWith ml lhs rhs -> case ml >>= Val.truthValue v of - Just False -> extract v lhs - _ -> extract v rhs + SplitWith ml lhs rhs -> case ml >>= Val.condition v of + Just v' -> extract v' rhs + _ -> extract v lhs Done i -> i instance Applicative (RTree l) where @@ -79,10 +80,11 @@ reduce p = checkgo checkgo v r = p (extract v r) *> go v r go v = \case Done i -> pure i - SplitWith (Just l) lhs rhs -> case Val.truthValue v l of - Just True -> checkgo v rhs - Just False -> checkgo v lhs - Nothing -> checkgo (Val.setTruthValue v l False) lhs <|> go (Val.setTruthValue v l True) rhs + SplitWith (Just l) lhs rhs -> case Val.truthValue v (Val.label l) of + Just t + | t == Val.truth l -> checkgo v rhs + | otherwise -> checkgo v lhs + Nothing -> checkgo (Val.withTruth v $ Val.not l) lhs <|> go (Val.withTruth v l) rhs SplitWith Nothing lhs rhs -> (checkgo v lhs <|> go v rhs) {-# INLINE reduce #-} @@ -104,10 +106,10 @@ instance (Monad m, Ord l) => MonadReduce l (IRTreeT l m) where ReState (uncons -> (a, as)) v -> pure (a, ReState as v) Just l -> \case - ReState as v@((`Val.truthValue` l) -> Just x) -> + ReState as v@((`Val.truthValue` Val.label l) -> Just x) -> pure (x, ReState as v) ReState (uncons -> (a, as)) v -> - pure (a, ReState as (Val.setTruthValue v l a)) + pure (a, ReState as (Val.withTruth v (if a then l else Val.not l))) where uncons [] = (True, []) uncons (a : as) = (a, as) diff --git a/src/Data/Valuation.hs b/src/Data/Valuation.hs index 443269b..6c73c62 100644 --- a/src/Data/Valuation.hs +++ b/src/Data/Valuation.hs @@ -14,10 +14,16 @@ module Data.Valuation ( toPairs, -- * Access - setTruthValue, + withTruth, truthValue, condition, + -- * Truth + Truth (..), + not, + is, + isNot, + -- * Helpers viaMap, viaMapF, @@ -26,34 +32,61 @@ module Data.Valuation ( import Data.Functor.Identity import qualified Data.Map.Strict as Map +import Prelude hiding (not) +import qualified Prelude + +-- | A Single truth assignment +data Truth l = Truth + { label :: !l + , truth :: !Bool + } + +is :: l -> Truth l +is l = Truth{label = l, truth = True} +{-# INLINE is #-} + +isNot :: l -> Truth l +isNot l = Truth{label = l, truth = False} +{-# INLINE isNot #-} + +not :: Truth l -> Truth l +not (Truth l t) = Truth l (Prelude.not t) + newtype Valuation l = Valuation {toMap :: Map.Map l Bool} -singleton :: (Ord l) => l -> Bool -> Valuation l -singleton l t = fromMap $ Map.singleton l t +singleton :: (Ord l) => Truth l -> Valuation l +singleton (Truth l t) = fromMap $ Map.singleton l t +{-# INLINE singleton #-} viaMap :: (Map.Map l Bool -> Map.Map l Bool) -> Valuation l -> Valuation l viaMap fn = runIdentity . viaMapF (Identity . fn) +{-# INLINE viaMap #-} viaMapF :: (Functor f) => (Map.Map l Bool -> f (Map.Map l Bool)) -> Valuation l -> f (Valuation l) viaMapF fn = fmap fromMap . fn . toMap +{-# INLINE viaMapF #-} fromMap :: Map.Map l Bool -> Valuation l fromMap = Valuation +{-# INLINE fromMap #-} fromPairs :: (Ord l) => [(l, Bool)] -> Valuation l fromPairs = Valuation . Map.fromList +{-# INLINE fromPairs #-} toPairs :: Valuation l -> [(l, Bool)] toPairs = Map.toList . toMap +{-# INLINE toPairs #-} truthValue :: (Ord l) => Valuation l -> l -> Maybe Bool truthValue (Valuation m) = (`Map.lookup` m) +{-# INLINE truthValue #-} {- | Conditions a valuation with key value pair, if it conficts with the valuation, it returns Nothing -} -condition :: (Ord l) => Valuation l -> l -> Bool -> Maybe (Valuation l) -condition v l t = +condition :: (Ord l) => Valuation l -> Truth l -> Maybe (Valuation l) +condition v (Truth l t) = viaMapF ( Map.alterF \case @@ -62,6 +95,8 @@ condition v l t = l ) v +{-# INLINE condition #-} -setTruthValue :: (Ord l) => Valuation l -> l -> Bool -> Valuation l -setTruthValue v l t = viaMap (Map.insert l t) v +withTruth :: (Ord l) => Valuation l -> Truth l -> Valuation l +withTruth v (Truth l t) = viaMap (Map.insert l t) v +{-# INLINE withTruth #-} -- GitLab