content: {-# LANGUAGE DefaultSignatures         #-}
  {-# LANGUAGE EmptyCase                 #-}
  {-# LANGUAGE ExistentialQuantification #-}
  {-# LANGUAGE FlexibleContexts          #-}
  {-# LANGUAGE FlexibleInstances         #-}
  {-# LANGUAGE GADTs                     #-}
  {-# LANGUAGE InstanceSigs              #-}
  {-# LANGUAGE KindSignatures            #-}
  {-# LANGUAGE RankNTypes                #-}
  {-# LANGUAGE ScopedTypeVariables       #-}
  {-# LANGUAGE StandaloneDeriving        #-}
  {-# LANGUAGE TemplateHaskell           #-}
  {-# LANGUAGE TypeFamilies              #-}
  {-# LANGUAGE TypeInType                #-}
  {-# LANGUAGE TypeOperators             #-}
  {-# LANGUAGE UndecidableInstances      #-}
  {-# LANGUAGE TypeApplications          #-}
  {-# LANGUAGE CPP                       #-}
  
  -- singletons-2.7 onwards requires StandaloneKindSignatures for TH functions
  #if MIN_VERSION_singletons(2,7,0)
  {-# LANGUAGE StandaloneKindSignatures  #-}
  #endif
  
  {-|
  
  Data kinds and corresponding singletons (via the @singletons@ library) for kinds
  used in various places in "Language.Fortran.Model".
  
  As documentation in Template Haskell is not yet supported, documentation for
  each data type is given here.
  
  == 'Precision'
  
  The precision, in bits, of an intrinsic Fortran data type.
  
  == 'BasicType'
  
  The basic type of an intrinsic Fortran data type.
  
  == 'OpKind'
  
  TODO
  
  == 'precMax'
  
  Finds the maximum of two precisions. Use 'PrecMax' at the type level and 'sPrecMax' for singletons.
  
  == 'basicTypeMax'
  
  Finds the \'largest\' (with respect to the size of the set it semantically
  represents) of numeric basic types. Also works with non-numeric basic types, but
  the result in that case is unspecified. Use 'BasicTypeMax' at the type level and
  'sBasicTypeMax' for singletons.
  
  -}
  module Language.Fortran.Model.Singletons where
  
  #if MIN_VERSION_singletons(3,0,0)
  import Prelude.Singletons
  import Data.Ord.Singletons
  #else
  import Data.Singletons.Prelude
  #endif
  
  import Data.Singletons.TH
  
  $(singletons
    [d|
  
    data Precision
      = P8
      | P16
      | P32
      | P64
      | P128
      deriving (Eq, Ord)
  
    data BasicType
      -- NB. The order of the constructors is very important for the derived 'Ord'
      -- instance! Numeric basicTypes that can represent smaller sets of numbers must be
      -- earlier in the list.
      = BTInt
      | BTReal
      | BTLogical
      | BTChar
      deriving (Eq, Ord)
  
    data OpKind
      = OKLit
      | OKNum
      | OKEq
      | OKRel
      | OKLogical
      | OKLookup
      | OKDeref
      | OKWriteArr
      | OKWriteData
  
    precMax :: Precision -> Precision -> Precision
    precMax = max
  
    basicTypeMax :: BasicType -> BasicType -> BasicType
    basicTypeMax = max
     |])
  
  -- These are derived outside the TH splice because we don't need them at the
  -- type level so we don't want to waste compilation time on type-level versions
  -- of them.
  
  deriving instance Show Precision
  deriving instance Show BasicType
  
  deriving instance Eq OpKind
  deriving instance Ord OpKind
  deriving instance Show OpKind
  