content: {- |
  Module      :  Camfort.Specification.Units.Parser.Types
  Description :  Defines the representation of unit specifications resulting from parsing.
  Copyright   :  (c) 2017, Dominic Orchard, Andrew Rice, Mistral Contrastin, Matthew Danish
  License     :  Apache-2.0
  
  Maintainer  :  dom.orchard@gmail.com
  Stability   :  experimental
  -}
  
  {-# LANGUAGE DeriveDataTypeable #-}
  
  module Camfort.Specification.Units.Parser.Types
    ( UnitStatement(..)
    , UnitOfMeasure(..)
    , UnitPower(..)
    ) where
  
  import Data.Data (Data)
  import Data.List (intercalate)
  
  data UnitStatement =
     UnitAssignment (Maybe [String]) UnitOfMeasure
   | UnitAlias String UnitOfMeasure
    deriving (Eq, Data)
  
  instance Show UnitStatement where
    show (UnitAssignment (Just ss) uom)
      = "= unit (" ++ show uom ++ ") :: " ++ intercalate "," ss
    show (UnitAssignment Nothing uom)
      = "= unit (" ++ show uom ++ ")"
    show (UnitAlias s uom)
      = "= unit :: " ++ s ++ " = " ++ show uom
  
  data UnitOfMeasure =
     Unitless
   | UnitBasic String
   | UnitProduct UnitOfMeasure UnitOfMeasure
   | UnitQuotient UnitOfMeasure UnitOfMeasure
   | UnitExponentiation UnitOfMeasure UnitPower
   | UnitRecord [(String, UnitOfMeasure)]
    deriving (Data, Eq)
  
  instance Show UnitOfMeasure where
    show Unitless      = "1"
    show (UnitBasic s) = s
    show (UnitProduct uom1 uom2)
      = show uom1 ++ " " ++ show uom2
    show (UnitQuotient uom1 uom2)
      = show uom1 ++ " / " ++ show uom2
    show (UnitExponentiation uom expt)
      = show uom  ++ "** (" ++ show expt ++ ")"
    show (UnitRecord recs)
      = "record (" ++ intercalate ", "
        (map (\ (n, u) -> n ++ " :: " ++ show u) recs) ++ ")"
  
  data UnitPower =
     UnitPowerInteger Integer
   | UnitPowerRational Integer Integer
   deriving (Data, Eq)
  
  instance Show UnitPower where
    show (UnitPowerInteger i)      = show i
    show (UnitPowerRational i1 i2) = show i1 ++ "/" ++ show i2
  