packages feed

datafix-0.0.0.1: examples/Analyses/StrAnal/Arity.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies               #-}

module Analyses.StrAnal.Arity where

import           Algebra.Lattice
import           Algebra.PartialOrd
import           Data.IntMap.Strict (IntMap)
import qualified Data.IntMap.Strict as IntMap
import           Data.Maybe         (maybeToList)
import           Data.Ord           (Down (..))
import           GHC.Exts           (coerce)

import           Datafix.MonoMap

-- | Arity is totally ordered, but with the order turned
-- upside down. E.g., 'Arity 0' is the figurative 'top'
-- element and the instance for 'JoinSemiLattice' will
-- return the minimum of the two arities.
--
-- This corresponds to the intuition that more incoming
-- arguments is more valuable information to the analysis.
newtype Arity
  = Arity Int
  deriving (Eq, Num)

instance Show Arity where
  show (Arity i) = show i

instance Ord Arity where
  compare (Arity a) (Arity b) = compare (Down a) (Down b)

instance PartialOrd Arity where
  leq a b = a <= b

instance JoinSemiLattice Arity where
  Arity a \/ Arity b = Arity (min a b)

instance MeetSemiLattice Arity where
  Arity a /\ Arity b = Arity (max a b)

newtype ArityMap v
  = ArityMap (IntMap v)
  deriving (Eq, Show, Foldable)

-- | This can use an efficient 'IntMap' representation instead of the default
-- implementation using 'POMap'.
--
-- We must be careful with the 'Op' ordering, though.
instance MonoMapKey Arity where
  type MonoMap Arity = ArityMap
  empty = ArityMap IntMap.empty
  singleton (Arity n) v = ArityMap (IntMap.singleton n v)
  insert (Arity n) v (ArityMap m) = ArityMap (IntMap.insert n v m)
  delete (Arity n) (ArityMap m) = ArityMap (IntMap.delete n m)
  lookup (Arity n) (ArityMap m) = IntMap.lookup n m
  -- using GT here!
  lookupLT (Arity n) (ArityMap m) = coerce (maybeToList (IntMap.lookupGT n m))
  -- maxview!
  lookupMin (ArityMap m) = coerce (maybeToList (fst <$> IntMap.maxViewWithKey m))
  difference (ArityMap a) (ArityMap b) = ArityMap (IntMap.difference a b)
  keys (ArityMap m) = coerce (IntMap.keys m)
  insertWith f (Arity n) v (ArityMap m) = ArityMap (IntMap.insertWith f n v m)
  insertLookupWithKey f (Arity n) v (ArityMap m) =
    coerce (IntMap.insertLookupWithKey (coerce f) n v m)
  updateLookupWithKey f (Arity n) (ArityMap m) =
    coerce (IntMap.updateLookupWithKey (coerce f) n m)
  alter f (Arity n) (ArityMap m) = ArityMap (IntMap.alter (coerce f) n m)
  adjust f (Arity n) (ArityMap m) = ArityMap (IntMap.adjust (coerce f) n m)