{-# LANGUAGE CPP
           , DataKinds
           , EmptyCase
           , ExistentialQuantification
           , FlexibleContexts
           , GADTs
           , GeneralizedNewtypeDeriving
           , KindSignatures
           , MultiParamTypeClasses
           , OverloadedStrings
           , PolyKinds
           , ScopedTypeVariables
           , TypeFamilies
           , TypeOperators
           #-}

{-# OPTIONS_GHC -Wall -fwarn-tabs #-}
-- |
-- Module      :  Language.Hakaru.Syntax.Rename 
-- Copyright   :  Copyright (c) 2016 the Hakaru team
-- License     :  BSD3
-- Maintainer  :
-- Stability   :  experimental
-- Portability :  GHC-only
--
-- Performs renaming of variables hints only (in Hakaru expressions) 
-- which hopefully has no effect on semantics but can produce prettier expressions
--
----------------------------------------------------------------
module Language.Hakaru.Syntax.Rename where

import           Control.Monad.Reader
import           Control.Monad.State
import           Data.Maybe                      (fromMaybe)
import           Data.Number.Nat

import           Language.Hakaru.Syntax.ABT
import           Language.Hakaru.Syntax.AST
import           Language.Hakaru.Syntax.AST.Eq   (Varmap)
import           Language.Hakaru.Syntax.Gensym
import           Language.Hakaru.Syntax.IClasses
import           Language.Hakaru.Syntax.Variable
import qualified Data.Text as Text 
import           Data.Text (Text) 
import           Data.Char 

#if __GLASGOW_HASKELL__ < 710
import           Control.Applicative
#endif

type Renamer = Text -> Text 

renameAST 
  :: forall abt xs a . (ABT Term abt)
  => Renamer 
  -> abt xs a
  -> abt xs a
renameAST r = start
  where
    start :: abt ys b -> abt ys b
    start = loop . viewABT

    loop :: View (Term abt) ys b -> abt ys b
    loop (Var v)    = var (renameVar r v)
    loop (Syn s)    = syn (fmap21 start s)
    loop (Bind v b) = bind (renameVar r v) (loop b) 

renameVar :: Renamer -> Variable a -> Variable a 
renameVar r v = v { varHint = r (varHint v) } 

removeUnicodeChars :: Text -> Text 
removeUnicodeChars = Text.filter isAscii