From 43826cfee2107d88856d288365fc3828c9517e82 Mon Sep 17 00:00:00 2001
From: Ben Orchard <thefirstmuffinman@gmail.com>
Date: Sat, 15 Jun 2024 16:54:57 +0100
Subject: [PATCH] derive Ord instance for all core AST types

Requested in #282 . Note that `Eq` was already derived.
---
 src/Language/Fortran/AST.hs                 | 78 ++++++++++-----------
 src/Language/Fortran/AST/AList.hs           |  4 +-
 src/Language/Fortran/AST/Literal.hs         |  2 +-
 src/Language/Fortran/AST/Literal/Boz.hs     |  2 +-
 src/Language/Fortran/AST/Literal/Complex.hs |  4 +-
 src/Language/Fortran/AST/Literal/Real.hs    |  9 ++-
 6 files changed, 51 insertions(+), 48 deletions(-)

diff --git a/src/Language/Fortran/AST.hs b/src/Language/Fortran/AST.hs
index eed0f570..3041e5b6 100644
--- a/src/Language/Fortran/AST.hs
+++ b/src/Language/Fortran/AST.hs
@@ -172,7 +172,7 @@ data TypeSpec a = TypeSpec
   , typeSpecSpan :: SrcSpan
   , typeSpecBaseType :: BaseType
   , typeSpecSelector :: Maybe (Selector a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | The "kind selector" of a declaration statement. Tightly bound to
 --   'TypeSpec'.
@@ -195,16 +195,16 @@ data Selector a = Selector
   , selectorSpan :: SrcSpan
   , selectorLength :: Maybe (Expression a)
   , selectorKind   :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data MetaInfo = MetaInfo { miVersion :: FortranVersion, miFilename :: String }
-  deriving stock (Eq, Show, Data, Generic)
+  deriving stock (Eq, Ord, Show, Data, Generic)
 
 -- Program structure definition
 data ProgramFile a = ProgramFile
   { programFileMeta :: MetaInfo
   , programFileProgramUnits :: [ ProgramUnit a ]
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 pfSetFilename :: String -> ProgramFile a -> ProgramFile a
 pfSetFilename fn (ProgramFile mi pus) = ProgramFile (mi { miFilename = fn }) pus
@@ -259,7 +259,7 @@ data ProgramUnit a =
   | PUComment                       -- ^ Program unit-level comment
       a SrcSpan
       (Comment a)
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 type Prefixes a = Maybe (AList Prefix a)
 type Suffixes a = Maybe (AList Suffix a)
@@ -277,7 +277,7 @@ emptyPrefixSuffix = (emptyPrefixes, emptySuffixes)
 data Prefix a = PfxRecursive a SrcSpan
               | PfxElemental a SrcSpan
               | PfxPure a SrcSpan
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- see C1241 & C1242 (Fortran2003)
 validPrefixSuffix :: PrefixSuffix a -> Bool
@@ -291,7 +291,7 @@ validPrefixSuffix (mpfxs, msfxs) =
     sfxs = aStrip' msfxs
 
 data Suffix a = SfxBind a SrcSpan (Maybe (Expression a))
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 programUnitBody :: ProgramUnit a -> [Block a]
 programUnitBody (PUMain _ _ _ bs _)              = bs
@@ -323,7 +323,7 @@ programUnitSubprograms PUBlockData{}               = Nothing
 programUnitSubprograms PUComment{}                 = Nothing
 
 newtype Comment a = Comment String
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Block a =
     BlStatement                              -- ^ Statement
@@ -391,7 +391,7 @@ data Block a =
   | BlComment                                -- ^ Block-level comment
                 a SrcSpan
                 (Comment a)
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Statement a  =
     StDeclaration
@@ -615,7 +615,7 @@ data Statement a  =
   -- Following is a temporary solution to a complicated FORMAT statement
   -- parsing problem.
   | StFormatBogus         a SrcSpan String
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- R1214 proc-decl is procedure-entity-name [=> null-init]
 data ProcDecl a = ProcDecl
@@ -623,12 +623,12 @@ data ProcDecl a = ProcDecl
   , procDeclSpan       :: SrcSpan
   , procDeclEntityName :: Expression a
   , procDeclInitName   :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- R1212 proc-interface is interface-name or declaration-type-spec
 data ProcInterface a = ProcInterfaceName a SrcSpan (Expression a)
                      | ProcInterfaceType a SrcSpan (TypeSpec a)
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Part of a FORALL statement. Introduced in Fortran 95.
 data ForallHeader a = ForallHeader
@@ -636,7 +636,7 @@ data ForallHeader a = ForallHeader
   , forallHeaderSpan    :: SrcSpan
   , forallHeaderHeaders :: [ForallHeaderPart a]
   , forallHeaderScaling :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data ForallHeaderPart a = ForallHeaderPart
   { forallHeaderPartAnno   :: a
@@ -645,13 +645,13 @@ data ForallHeaderPart a = ForallHeaderPart
   , forallHeaderPartStart  :: Expression a
   , forallHeaderPartEnd    :: Expression a
   , forallHeaderPartStride :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Only = Exclusive | Permissive
-  deriving stock (Eq, Show, Data, Generic)
+  deriving stock (Eq, Ord, Show, Data, Generic)
 
 data ModuleNature = ModIntrinsic | ModNonIntrinsic
-  deriving stock (Eq, Show, Data, Generic)
+  deriving stock (Eq, Ord, Show, Data, Generic)
 
 -- | Part of USE statement. /(F2018 14.2.2)/
 --
@@ -664,7 +664,7 @@ data Use a =
   | UseID
         a SrcSpan
         (Expression a) -- ^ name
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- TODO potentially should throw Maybe String into ArgumentExpression too?
 data Argument a = Argument
@@ -672,7 +672,7 @@ data Argument a = Argument
   , argumentSpan :: SrcSpan
   , argumentName :: Maybe String
   , argumentExpr :: ArgumentExpression a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Extra data type to disambiguate between plain variable arguments and
 --   expression arguments (due to apparent behaviour of some Fortran compilers
@@ -683,7 +683,7 @@ data Argument a = Argument
 data ArgumentExpression a
   = ArgExpr              (Expression a)
   | ArgExprVar a SrcSpan Name
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 instance Annotated ArgumentExpression where
     getAnnotation = \case
@@ -729,17 +729,17 @@ data Attribute a =
   | AttrTarget a SrcSpan
   | AttrValue a SrcSpan
   | AttrVolatile a SrcSpan
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Intent = In | Out | InOut
-  deriving stock (Eq, Show, Data, Generic)
+  deriving stock (Eq, Ord, Show, Data, Generic)
 
 data ControlPair a = ControlPair
   { controlPairAnno :: a
   , controlPairSpan :: SrcSpan
   , controlPairName :: Maybe String
   , controlPairExpr :: Expression a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Part of ALLOCATE statement.
 --
@@ -754,7 +754,7 @@ data AllocOpt a =
         a SrcSpan
         (Expression a) -- ^ scalar character variable
   | AOSource a SrcSpan (Expression a)
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | List of names for an IMPLICIT statement.
 data ImpList a = ImpList
@@ -762,14 +762,14 @@ data ImpList a = ImpList
   , impListSpan :: SrcSpan
   , impListType :: TypeSpec a
   , impListElements :: AList ImpElement a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data ImpElement a = ImpElement
   { impElementAnno :: a
   , impElementSpan :: SrcSpan
   , impElementFrom :: Char
   , impElementTo   :: Maybe Char
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | A single COMMON block definition.
 --
@@ -779,14 +779,14 @@ data CommonGroup a = CommonGroup
   , commonGroupSpan :: SrcSpan
   , commonGroupName :: Maybe (Expression a)
   , commonGroupVars :: AList Declarator a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Namelist a = Namelist
   { namelistAnno :: a
   , namelistSpan :: SrcSpan
   , namelistName :: Expression a
   , namelistVars :: AList Expression a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | The part of a DATA statement describing a single set of initializations.
 --
@@ -799,7 +799,7 @@ data DataGroup a = DataGroup
   , dataGroupSpan         :: SrcSpan
   , dataGroupNames        :: AList Expression a
   , dataGroupInitializers :: AList Expression a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Field types in pre-Fortran 90 non-standard structure/record/union
 --   extension.
@@ -821,13 +821,13 @@ data StructureItem a =
         (Maybe String)          -- ^ Substructure name
         String                  -- ^ Field name
         (AList StructureItem a) -- ^ Substructure fields
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data UnionMap a = UnionMap
   { unionMapAnno   :: a
   , unionMapSpan   :: SrcSpan
   , unionMapFields :: AList StructureItem a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data FormatItem a =
     FIFormatList            a             SrcSpan   (Maybe String) (AList FormatItem a)
@@ -838,7 +838,7 @@ data FormatItem a =
   | FIFieldDescriptorAIL    a             SrcSpan   (Maybe Integer)   Char          Integer
   | FIBlankDescriptor       a             SrcSpan   Integer
   | FIScaleFactor           a             SrcSpan   Integer
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Part of the newer (Fortran 2003?) FLUSH statement.
 --
@@ -856,7 +856,7 @@ data FlushSpec a
   | FSErr
         a SrcSpan
         (Expression a) -- ^ statement label
-    deriving stock (Eq, Show, Data, Generic, Functor)
+    deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data DoSpecification a = DoSpecification
   { doSpecAnno      :: a
@@ -864,7 +864,7 @@ data DoSpecification a = DoSpecification
   , doSpecInitial   :: Statement a -- ^ Guaranteed to be 'StExpressionAssign'
   , doSpecLimit     :: Expression a
   , doSpecIncrement :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Expression a =
     ExpValue         a SrcSpan (Value a)
@@ -885,7 +885,7 @@ data Expression a =
   -- ^ Array initialisation
   | ExpReturnSpec    a SrcSpan (Expression a)
   -- ^ Function return value specification
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data Index a =
     IxSingle a SrcSpan (Maybe String) (Expression a)
@@ -893,7 +893,7 @@ data Index a =
             (Maybe (Expression a)) -- ^ Lower index
             (Maybe (Expression a)) -- ^ Upper index
             (Maybe (Expression a)) -- ^ Stride
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Values and literals.
 --
@@ -925,7 +925,7 @@ data Value a
   | ValType         String
   | ValStar
   | ValColon                   -- see R402 / C403 in Fortran2003 spec.
-    deriving stock    (Eq, Show, Data, Generic, Functor)
+    deriving stock    (Eq, Ord, Show, Data, Generic, Functor)
     deriving anyclass (NFData, Out)
 
 -- | Declarators. R505 entity-decl from F90 ISO spec.
@@ -949,12 +949,12 @@ data Declarator a = Declarator
   , declaratorType     :: DeclaratorType a
   , declaratorLength   :: Maybe (Expression a)
   , declaratorInitial  :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data DeclaratorType a
   = ScalarDecl
   | ArrayDecl (AList DimensionDeclarator a)
-  deriving stock (Eq, Show, Data, Generic, Functor)
+  deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 -- | Set a 'Declarator''s initializing expression only if it has none already.
 setInitialisation :: Declarator a -> Expression a -> Declarator a
@@ -968,7 +968,7 @@ data DimensionDeclarator a = DimensionDeclarator
   , dimDeclSpan :: SrcSpan
   , dimDeclLower :: Maybe (Expression a)
   , dimDeclUpper :: Maybe (Expression a)
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 data UnaryOp =
     Plus
diff --git a/src/Language/Fortran/AST/AList.hs b/src/Language/Fortran/AST/AList.hs
index 502c33e8..ec564d4d 100644
--- a/src/Language/Fortran/AST/AList.hs
+++ b/src/Language/Fortran/AST/AList.hs
@@ -21,7 +21,7 @@ data AList t a = AList
   { alistAnno :: a
   , alistSpan :: SrcSpan
   , alistList :: [t a]
-  } deriving stock (Eq, Show, Data, Generic)
+  } deriving stock (Eq, Ord, Show, Data, Generic)
 
 instance Functor t => Functor (AList t) where
   fmap f (AList a s xs) = AList (f a) s (map (fmap f) xs)
@@ -76,7 +76,7 @@ data ATuple t1 t2 a = ATuple
   , atupleSpan :: SrcSpan
   , atupleFst  :: t1 a
   , atupleSnd  :: t2 a
-  } deriving stock (Eq, Show, Data, Generic, Functor)
+  } deriving stock (Eq, Ord, Show, Data, Generic, Functor)
 
 instance FirstParameter (ATuple t1 t2 a) a
 instance SecondParameter (ATuple t1 t2 a) SrcSpan
diff --git a/src/Language/Fortran/AST/Literal.hs b/src/Language/Fortran/AST/Literal.hs
index 63e09859..9b08e14c 100644
--- a/src/Language/Fortran/AST/Literal.hs
+++ b/src/Language/Fortran/AST/Literal.hs
@@ -14,7 +14,7 @@ import Text.PrettyPrint.GenericPretty ( Out )
 data KindParam a
   = KindParamInt a SrcSpan String -- ^ @[0-9]+@
   | KindParamVar a SrcSpan Name   -- ^ @[a-z][a-z0-9]+@ (case insensitive)
-    deriving stock    (Eq, Show, Data, Typeable, Generic, Functor)
+    deriving stock    (Eq, Ord, Show, Data, Typeable, Generic, Functor)
     deriving anyclass (NFData, Out)
 
 instance FirstParameter  (KindParam a) a
diff --git a/src/Language/Fortran/AST/Literal/Boz.hs b/src/Language/Fortran/AST/Literal/Boz.hs
index fb0a6e3c..34113786 100644
--- a/src/Language/Fortran/AST/Literal/Boz.hs
+++ b/src/Language/Fortran/AST/Literal/Boz.hs
@@ -71,7 +71,7 @@ instance Eq BozPrefix where
                                 _                            -> False
 
 data Conforming = Conforming | Nonconforming
-    deriving stock    (Eq, Show, Generic, Data, Typeable, Ord)
+    deriving stock    (Eq, Ord, Show, Generic, Data, Typeable)
     deriving anyclass (NFData, Out)
 
 -- | UNSAFE. Parses a BOZ literal constant string.
diff --git a/src/Language/Fortran/AST/Literal/Complex.hs b/src/Language/Fortran/AST/Literal/Complex.hs
index c59ca1a7..adc40bc8 100644
--- a/src/Language/Fortran/AST/Literal/Complex.hs
+++ b/src/Language/Fortran/AST/Literal/Complex.hs
@@ -27,7 +27,7 @@ data ComplexLit a = ComplexLit
   , complexLitPos      :: SrcSpan
   , complexLitRealPart :: ComplexPart a
   , complexLitImagPart :: ComplexPart a
-  } deriving stock    (Eq, Show, Data, Typeable, Generic, Functor)
+  } deriving stock    (Eq, Ord, Show, Data, Typeable, Generic, Functor)
     deriving anyclass (NFData, Out)
 
 instance FirstParameter  (ComplexLit a) a
@@ -51,7 +51,7 @@ data ComplexPart a
   = ComplexPartReal   a SrcSpan RealLit (Maybe (KindParam a)) -- ^ signed real lit
   | ComplexPartInt    a SrcSpan String  (Maybe (KindParam a)) -- ^ signed int  lit
   | ComplexPartNamed  a SrcSpan Name                          -- ^ named constant
-    deriving stock    (Eq, Show, Data, Typeable, Generic, Functor)
+    deriving stock    (Eq, Ord, Show, Data, Typeable, Generic, Functor)
     deriving anyclass (NFData, Out)
 
 instance FirstParameter  (ComplexPart a) a
diff --git a/src/Language/Fortran/AST/Literal/Real.hs b/src/Language/Fortran/AST/Literal/Real.hs
index 77f43b09..a5abc4ef 100644
--- a/src/Language/Fortran/AST/Literal/Real.hs
+++ b/src/Language/Fortran/AST/Literal/Real.hs
@@ -40,13 +40,15 @@ data RealLit = RealLit
   -- ^ A string representing a signed decimal.
   -- ^ Approximate regex: @-? ( [0-9]+ \. [0-9]* | \. [0-9]+ )@
   , realLitExponent    :: Exponent
-  } deriving (Eq, Show, Data, Typeable, Generic, NFData, Out, Ord)
+  } deriving stock (Eq, Ord, Show, Data, Typeable, Generic)
+    deriving anyclass (NFData, Out)
 
 -- | An exponent is an exponent letter (E, D) and a signed integer.
 data Exponent = Exponent
   { exponentLetter :: ExponentLetter
   , exponentNum    :: String
-  } deriving (Eq, Show, Data, Typeable, Generic, NFData, Out, Ord)
+  } deriving stock (Eq, Ord, Show, Data, Typeable, Generic)
+    deriving anyclass (NFData, Out)
 
 -- Note: Some Fortran language references include extensions here. HP's F90
 -- reference provides a Q exponent letter which sets kind to 16.
@@ -54,7 +56,8 @@ data ExponentLetter
   = ExpLetterE -- ^ KIND=4 (float)
   | ExpLetterD -- ^ KIND=8 (double)
   | ExpLetterQ -- ^ KIND=16 ("quad", rare? extension)
-    deriving (Eq, Show, Data, Typeable, Generic, NFData, Out, Ord)
+    deriving stock (Eq, Ord, Show, Data, Typeable, Generic)
+    deriving anyclass (NFData, Out)
 
 -- | Prettify a 'RealLit' in a Haskell-compatible way.
 prettyHsRealLit :: RealLit -> String