{- |
    Module      :  $Header$
    Description :  Curry language extensions
    Copyright   :  (c) 2013 - 2014 Björn Peemöller
                       2016        Finn Teegen
    License     :  BSD-3-clause

    Maintainer  :  bjp@informatik.uni-kiel.de
    Stability   :  experimental
    Portability :  portable

    This module provides the data structures for Curry language extensions.
-}

module Curry.Syntax.Extension
  ( -- * Extensions
    Extension (..), KnownExtension (..), classifyExtension, kielExtensions
    -- * Tools
  , Tool (..), classifyTool
  ) where

import Data.Char           (toUpper)

import Curry.Base.Ident    (Ident (..))
import Curry.Base.Position

-- |Specified language extensions, either known or unknown.
data Extension
  = KnownExtension   Position KnownExtension -- ^ a known extension
  | UnknownExtension Position String         -- ^ an unknown extension
    deriving (Eq, Read, Show)

instance HasPosition Extension where
  getPosition (KnownExtension   p _) = p
  getPosition (UnknownExtension p _) = p

  setPosition p (KnownExtension   _ e) = KnownExtension   p e
  setPosition p (UnknownExtension _ e) = UnknownExtension p e

-- |Known language extensions of Curry.
data KnownExtension
  = AnonFreeVars              -- ^ anonymous free variables
  | CPP                       -- ^ C preprocessor
  | FunctionalPatterns        -- ^ functional patterns
  | NegativeLiterals          -- ^ negative literals
  | NoImplicitPrelude         -- ^ no implicit import of the prelude
    deriving (Eq, Read, Show, Enum, Bounded)

-- |Classifies a 'String' as an 'Extension'
classifyExtension :: Ident -> Extension
classifyExtension i = case reads extName of
  [(e, "")] -> KnownExtension   (getPosition i) e
  _         -> UnknownExtension (getPosition i) extName
  where extName = idName i

-- |'Extension's available by Kiel's Curry compilers.
kielExtensions :: [KnownExtension]
kielExtensions = [AnonFreeVars, FunctionalPatterns]

-- |Different Curry tools which may accept compiler options.
data Tool = KICS2 | PAKCS | CYMAKE | FRONTEND | UnknownTool String
    deriving (Eq, Read, Show)

-- |Classifies a 'String' as a 'Tool'
classifyTool :: String -> Tool
classifyTool str = case reads (map toUpper str) of
  [(t, "")] -> t
  _         -> UnknownTool str