{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Data.Record.Anon.Internal.Plugin.TC.Row.KnownRow (
KnownRow(..)
, KnownRowField(..)
, FieldIndex
, toKnownRowField
, fromKnownRowField
, fromList
, inRowOrder
, inFieldOrder
, visibleMap
, lookup
, traverse
, NotSubRow(..)
, Source(..)
, Target(..)
, isSubRowOf
) where
import Prelude hiding (traverse, lookup)
import qualified Prelude
import Data.Either (partitionEithers)
import Data.List (sortBy)
import Data.Ord (comparing)
import Data.Record.Anon.Internal.Core.FieldName (FieldName)
import Data.Record.Anon.Internal.Util.SmallHashMap (SmallHashMap)
import Data.Record.Anon.Internal.Plugin.TC.Row.KnownField (KnownField(..))
import Data.Record.Anon.Internal.Plugin.TC.GhcTcPluginAPI
import qualified Data.Record.Anon.Internal.Util.SmallHashMap as HashMap
data KnownRow a = KnownRow {
forall a. KnownRow a -> [KnownRowField a]
knownRecordVector :: [KnownRowField a]
, forall a. KnownRow a -> SmallHashMap FieldName Int
knownRecordVisible :: SmallHashMap FieldName Int
, forall a. KnownRow a -> Bool
knownRecordAllVisible :: Bool
}
deriving (forall a b. a -> KnownRow b -> KnownRow a
forall a b. (a -> b) -> KnownRow a -> KnownRow b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> KnownRow b -> KnownRow a
$c<$ :: forall a b. a -> KnownRow b -> KnownRow a
fmap :: forall a b. (a -> b) -> KnownRow a -> KnownRow b
$cfmap :: forall a b. (a -> b) -> KnownRow a -> KnownRow b
Functor)
data KnownRowField a = KnownRowField {
forall a. KnownRowField a -> FieldName
knownRowFieldName :: FieldName
, forall a. KnownRowField a -> Int
knownRowFieldIndex :: FieldIndex
, forall a. KnownRowField a -> a
knownRowFieldInfo :: a
}
deriving (forall a b. a -> KnownRowField b -> KnownRowField a
forall a b. (a -> b) -> KnownRowField a -> KnownRowField b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> KnownRowField b -> KnownRowField a
$c<$ :: forall a b. a -> KnownRowField b -> KnownRowField a
fmap :: forall a b. (a -> b) -> KnownRowField a -> KnownRowField b
$cfmap :: forall a b. (a -> b) -> KnownRowField a -> KnownRowField b
Functor)
type FieldIndex = Int
fromKnownRowField :: KnownRowField a -> KnownField a
fromKnownRowField :: forall a. KnownRowField a -> KnownField a
fromKnownRowField KnownRowField a
field = KnownField {
knownFieldName :: FieldName
knownFieldName = forall a. KnownRowField a -> FieldName
knownRowFieldName KnownRowField a
field
, knownFieldInfo :: a
knownFieldInfo = forall a. KnownRowField a -> a
knownRowFieldInfo KnownRowField a
field
}
toKnownRowField :: KnownField a -> FieldIndex -> KnownRowField a
toKnownRowField :: forall a. KnownField a -> Int -> KnownRowField a
toKnownRowField KnownField a
field Int
ix = KnownRowField {
knownRowFieldName :: FieldName
knownRowFieldName = forall a. KnownField a -> FieldName
knownFieldName KnownField a
field
, knownRowFieldInfo :: a
knownRowFieldInfo = forall a. KnownField a -> a
knownFieldInfo KnownField a
field
, knownRowFieldIndex :: Int
knownRowFieldIndex = Int
ix
}
inRowOrder :: KnownRow a -> [KnownField a]
inRowOrder :: forall a. KnownRow a -> [KnownField a]
inRowOrder =
forall a b. (a -> b) -> [a] -> [b]
map forall a. KnownRowField a -> KnownField a
fromKnownRowField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. KnownRow a -> [KnownRowField a]
knownRecordVector
inFieldOrder :: KnownRow a -> [KnownField a]
inFieldOrder :: forall a. KnownRow a -> [KnownField a]
inFieldOrder =
forall a b. (a -> b) -> [a] -> [b]
map forall a. KnownRowField a -> KnownField a
fromKnownRowField
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing forall a. KnownRowField a -> Int
knownRowFieldIndex)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. KnownRow a -> [KnownRowField a]
knownRecordVector
visibleMap :: KnownRow a -> SmallHashMap FieldName (KnownRowField a)
visibleMap :: forall a. KnownRow a -> SmallHashMap FieldName (KnownRowField a)
visibleMap KnownRow{Bool
[KnownRowField a]
SmallHashMap FieldName Int
knownRecordAllVisible :: Bool
knownRecordVisible :: SmallHashMap FieldName Int
knownRecordVector :: [KnownRowField a]
knownRecordAllVisible :: forall a. KnownRow a -> Bool
knownRecordVisible :: forall a. KnownRow a -> SmallHashMap FieldName Int
knownRecordVector :: forall a. KnownRow a -> [KnownRowField a]
..} = ([KnownRowField a]
knownRecordVector forall a. [a] -> Int -> a
!!) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SmallHashMap FieldName Int
knownRecordVisible
fromList :: forall a.
[KnownRowField a]
-> KnownRow a
fromList :: forall a. [KnownRowField a] -> KnownRow a
fromList = [KnownRowField a]
-> Int
-> SmallHashMap FieldName Int
-> Bool
-> [KnownRowField a]
-> KnownRow a
go [] Int
0 forall k a. SmallHashMap k a
HashMap.empty Bool
True
where
go :: [KnownRowField a]
-> Int
-> SmallHashMap FieldName Int
-> Bool
-> [KnownRowField a]
-> KnownRow a
go :: [KnownRowField a]
-> Int
-> SmallHashMap FieldName Int
-> Bool
-> [KnownRowField a]
-> KnownRow a
go [KnownRowField a]
accFields !Int
nextIndex !SmallHashMap FieldName Int
accVisible !Bool
accAllVisible = \case
[] -> KnownRow {
knownRecordVector :: [KnownRowField a]
knownRecordVector = forall a. [a] -> [a]
reverse [KnownRowField a]
accFields
, knownRecordVisible :: SmallHashMap FieldName Int
knownRecordVisible = SmallHashMap FieldName Int
accVisible
, knownRecordAllVisible :: Bool
knownRecordAllVisible = Bool
accAllVisible
}
KnownRowField a
f:[KnownRowField a]
fs
| FieldName
name forall k a. (Hashable k, Ord k) => k -> SmallHashMap k a -> Bool
`HashMap.member` SmallHashMap FieldName Int
accVisible ->
[KnownRowField a]
-> Int
-> SmallHashMap FieldName Int
-> Bool
-> [KnownRowField a]
-> KnownRow a
go (KnownRowField a
f forall a. a -> [a] -> [a]
: [KnownRowField a]
accFields)
(forall a. Enum a => a -> a
succ Int
nextIndex)
SmallHashMap FieldName Int
accVisible
Bool
False
[KnownRowField a]
fs
| Bool
otherwise ->
[KnownRowField a]
-> Int
-> SmallHashMap FieldName Int
-> Bool
-> [KnownRowField a]
-> KnownRow a
go (KnownRowField a
f forall a. a -> [a] -> [a]
: [KnownRowField a]
accFields)
(forall a. Enum a => a -> a
succ Int
nextIndex)
(forall k a.
(Hashable k, Ord k) =>
k -> a -> SmallHashMap k a -> SmallHashMap k a
HashMap.insert FieldName
name Int
nextIndex SmallHashMap FieldName Int
accVisible)
Bool
accAllVisible
[KnownRowField a]
fs
where
name :: FieldName
name = forall a. KnownRowField a -> FieldName
knownRowFieldName KnownRowField a
f
lookup :: FieldName -> KnownRow a -> Maybe (KnownRowField a)
lookup :: forall a. FieldName -> KnownRow a -> Maybe (KnownRowField a)
lookup FieldName
field KnownRow{Bool
[KnownRowField a]
SmallHashMap FieldName Int
knownRecordAllVisible :: Bool
knownRecordVisible :: SmallHashMap FieldName Int
knownRecordVector :: [KnownRowField a]
knownRecordAllVisible :: forall a. KnownRow a -> Bool
knownRecordVisible :: forall a. KnownRow a -> SmallHashMap FieldName Int
knownRecordVector :: forall a. KnownRow a -> [KnownRowField a]
..} =
([KnownRowField a]
knownRecordVector forall a. [a] -> Int -> a
!!) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall k a. (Hashable k, Ord k) => k -> SmallHashMap k a -> Maybe a
HashMap.lookup FieldName
field SmallHashMap FieldName Int
knownRecordVisible
traverse :: forall m a b.
Applicative m
=> KnownRow a
-> (FieldName -> FieldIndex -> a -> m b)
-> m (KnownRow b)
traverse :: forall (m :: * -> *) a b.
Applicative m =>
KnownRow a -> (FieldName -> Int -> a -> m b) -> m (KnownRow b)
traverse KnownRow{Bool
[KnownRowField a]
SmallHashMap FieldName Int
knownRecordAllVisible :: Bool
knownRecordVisible :: SmallHashMap FieldName Int
knownRecordVector :: [KnownRowField a]
knownRecordAllVisible :: forall a. KnownRow a -> Bool
knownRecordVisible :: forall a. KnownRow a -> SmallHashMap FieldName Int
knownRecordVector :: forall a. KnownRow a -> [KnownRowField a]
..} FieldName -> Int -> a -> m b
f =
[KnownRowField b] -> KnownRow b
mkRow forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
Prelude.traverse KnownRowField a -> m (KnownRowField b)
f' [KnownRowField a]
knownRecordVector
where
mkRow :: [KnownRowField b] -> KnownRow b
mkRow :: [KnownRowField b] -> KnownRow b
mkRow [KnownRowField b]
updated = KnownRow {
knownRecordVector :: [KnownRowField b]
knownRecordVector = [KnownRowField b]
updated
, knownRecordVisible :: SmallHashMap FieldName Int
knownRecordVisible = SmallHashMap FieldName Int
knownRecordVisible
, knownRecordAllVisible :: Bool
knownRecordAllVisible = Bool
knownRecordAllVisible
}
f' :: KnownRowField a -> m (KnownRowField b)
f' :: KnownRowField a -> m (KnownRowField b)
f' (KnownRowField FieldName
nm Int
ix a
info) = forall a. FieldName -> Int -> a -> KnownRowField a
KnownRowField FieldName
nm Int
ix forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> FieldName -> Int -> a -> m b
f FieldName
nm Int
ix a
info
data NotSubRow =
TargetContainsShadowedFields
| SourceMissesFields [FieldName]
deriving (Int -> NotSubRow -> ShowS
[NotSubRow] -> ShowS
NotSubRow -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [NotSubRow] -> ShowS
$cshowList :: [NotSubRow] -> ShowS
show :: NotSubRow -> String
$cshow :: NotSubRow -> String
showsPrec :: Int -> NotSubRow -> ShowS
$cshowsPrec :: Int -> NotSubRow -> ShowS
Show, NotSubRow -> NotSubRow -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: NotSubRow -> NotSubRow -> Bool
$c/= :: NotSubRow -> NotSubRow -> Bool
== :: NotSubRow -> NotSubRow -> Bool
$c== :: NotSubRow -> NotSubRow -> Bool
Eq)
newtype Source a = Source { forall a. Source a -> a
getSource :: a } deriving (Int -> Source a -> ShowS
forall a. Show a => Int -> Source a -> ShowS
forall a. Show a => [Source a] -> ShowS
forall a. Show a => Source a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Source a] -> ShowS
$cshowList :: forall a. Show a => [Source a] -> ShowS
show :: Source a -> String
$cshow :: forall a. Show a => Source a -> String
showsPrec :: Int -> Source a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Source a -> ShowS
Show, forall a b. a -> Source b -> Source a
forall a b. (a -> b) -> Source a -> Source b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Source b -> Source a
$c<$ :: forall a b. a -> Source b -> Source a
fmap :: forall a b. (a -> b) -> Source a -> Source b
$cfmap :: forall a b. (a -> b) -> Source a -> Source b
Functor)
newtype Target a = Target { forall a. Target a -> a
getTarget :: a } deriving (Int -> Target a -> ShowS
forall a. Show a => Int -> Target a -> ShowS
forall a. Show a => [Target a] -> ShowS
forall a. Show a => Target a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Target a] -> ShowS
$cshowList :: forall a. Show a => [Target a] -> ShowS
show :: Target a -> String
$cshow :: forall a. Show a => Target a -> String
showsPrec :: Int -> Target a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Target a -> ShowS
Show, forall a b. a -> Target b -> Target a
forall a b. (a -> b) -> Target a -> Target b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Target b -> Target a
$c<$ :: forall a b. a -> Target b -> Target a
fmap :: forall a b. (a -> b) -> Target a -> Target b
$cfmap :: forall a b. (a -> b) -> Target a -> Target b
Functor)
isSubRowOf :: forall a b.
KnownRow a
-> KnownRow b
-> Either NotSubRow [(Target (KnownField a), Source (KnownRowField b))]
KnownRow a
target isSubRowOf :: forall a b.
KnownRow a
-> KnownRow b
-> Either
NotSubRow [(Target (KnownField a), Source (KnownRowField b))]
`isSubRowOf` KnownRow b
source =
if Bool -> Bool
not (forall a. KnownRow a -> Bool
knownRecordAllVisible KnownRow a
target) then
forall a b. a -> Either a b
Left NotSubRow
TargetContainsShadowedFields
else
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall x. [FieldName] -> x -> Either NotSubRow x
checkMissing
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. [Either a b] -> ([a], [b])
partitionEithers
forall a b. (a -> b) -> a -> b
$ forall a b. (a -> b) -> [a] -> [b]
map KnownField a
-> Either
FieldName (Target (KnownField a), Source (KnownRowField b))
findInSrc (forall a. KnownRow a -> [KnownField a]
inRowOrder KnownRow a
target)
where
findInSrc ::
KnownField a
-> Either FieldName (Target (KnownField a), Source (KnownRowField b))
findInSrc :: KnownField a
-> Either
FieldName (Target (KnownField a), Source (KnownRowField b))
findInSrc KnownField a
a =
case forall k a. (Hashable k, Ord k) => k -> SmallHashMap k a -> Maybe a
HashMap.lookup (forall a. KnownField a -> FieldName
knownFieldName KnownField a
a) (forall a. KnownRow a -> SmallHashMap FieldName (KnownRowField a)
visibleMap KnownRow b
source) of
Maybe (KnownRowField b)
Nothing -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ forall a. KnownField a -> FieldName
knownFieldName KnownField a
a
Just KnownRowField b
b -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ (forall a. a -> Target a
Target KnownField a
a, forall a. a -> Source a
Source KnownRowField b
b)
checkMissing :: [FieldName] -> x -> Either NotSubRow x
checkMissing :: forall x. [FieldName] -> x -> Either NotSubRow x
checkMissing [] x
x = forall a b. b -> Either a b
Right x
x
checkMissing [FieldName]
missing x
_ = forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ [FieldName] -> NotSubRow
SourceMissesFields [FieldName]
missing
instance Outputable a => Outputable (KnownRow a) where
ppr :: KnownRow a -> SDoc
ppr = forall a. Outputable a => a -> SDoc
ppr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. KnownRow a -> [KnownField a]
inRowOrder