-- Copyright (c) 2020-2023, Shayne Fletcher. All rights reserved.
-- SPDX-License-Identifier: BSD-3-Clause.

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE CPP #-}
#include "ghclib_api.h"

module Language.Haskell.GhclibParserEx.GHC.Hs.ExtendInstances (
    HsExtendInstances(..), extendInstances, astEq, astListEq)
where

-- At times, there are terms in Haskell syntax we work with that are
-- not in `Eq`, `Show` or `Ord` and we need them to be.

-- This work-around resorts to implementing Eq and Ord via
-- lexicographic string comparisons. As long as two different terms
-- never map to the same string, basing `Eq` and `Ord` on their string
-- representations rather than the terms themselves, leads to
-- identical results.

#if defined (GHC_9_10) || defined (GHC_9_8) || defined (GHC_9_6) || defined (GHC_9_4) || defined(GHC_9_2) || defined (GHC_9_0)
import GHC.Utils.Outputable
#else
import Outputable
#endif
import Data.Data
import Data.Function
import Language.Haskell.GhclibParserEx.Dump

newtype HsExtendInstances a =
  HsExtendInstances { forall a. HsExtendInstances a -> a
unextendInstances :: a }
    deriving HsExtendInstances a -> SDoc
forall a. Outputable a => HsExtendInstances a -> SDoc
forall a. (a -> SDoc) -> Outputable a
ppr :: HsExtendInstances a -> SDoc
$cppr :: forall a. Outputable a => HsExtendInstances a -> SDoc
Outputable

extendInstances :: a -> HsExtendInstances a
extendInstances :: forall a. a -> HsExtendInstances a
extendInstances = forall a. a -> HsExtendInstances a
HsExtendInstances

-- Use 'showAstData'. This is preferable to 'ppr' in that trees that
-- only differ in arrangement due to fixities will produce differing
-- string representations.
toStr :: Data a => HsExtendInstances a -> String
toStr :: forall a. Data a => HsExtendInstances a -> String
toStr (HsExtendInstances a
e) =
#if defined (GHC_9_10) || defined (GHC_9_8) || defined (GHC_9_6) || defined (GHC_9_4) || defined (GHC_9_2)
  forall a. Outputable a => a -> String
showPprUnsafe forall a b. (a -> b) -> a -> b
$ forall a. Data a => BlankSrcSpan -> BlankEpAnnotations -> a -> SDoc
showAstData BlankSrcSpan
BlankSrcSpan BlankEpAnnotations
BlankEpAnnotations a
e
#else
  showSDocUnsafe $ showAstData BlankSrcSpan e
#endif

instance Data a => Eq (HsExtendInstances a) where == :: HsExtendInstances a -> HsExtendInstances a -> Bool
(==) HsExtendInstances a
a HsExtendInstances a
b = forall a. Data a => HsExtendInstances a -> String
toStr HsExtendInstances a
a forall a. Eq a => a -> a -> Bool
== forall a. Data a => HsExtendInstances a -> String
toStr HsExtendInstances a
b
instance Data a => Ord (HsExtendInstances a) where compare :: HsExtendInstances a -> HsExtendInstances a -> Ordering
compare = forall a. Ord a => a -> a -> Ordering
compare forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` forall a. Data a => HsExtendInstances a -> String
toStr

astEq :: Data a => a -> a -> Bool
astEq :: forall a. Data a => a -> a -> Bool
astEq a
a a
b = forall a. a -> HsExtendInstances a
extendInstances a
a forall a. Eq a => a -> a -> Bool
== forall a. a -> HsExtendInstances a
extendInstances a
b

astListEq :: Data a => [a] -> [a] -> Bool
astListEq :: forall a. Data a => [a] -> [a] -> Bool
astListEq [a]
as [a]
bs = forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
as forall a. Eq a => a -> a -> Bool
== forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
bs Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall a. Data a => a -> a -> Bool
astEq) (forall a b. [a] -> [b] -> [(a, b)]
zip [a]
as [a]
bs)

-- Use 'ppr' for 'Show'.
instance Outputable a => Show (HsExtendInstances a) where
  show :: HsExtendInstances a -> String
show (HsExtendInstances a
e) =
#if defined (GHC_9_10) || defined (GHC_9_8) || defined(GHC_9_6) || defined(GHC_9_2)
    forall a. Outputable a => a -> String
showPprUnsafe forall a b. (a -> b) -> a -> b
$ forall a. Outputable a => a -> SDoc
ppr a
e
#else
    showSDocUnsafe $ ppr e
#endif