packages feed

curry-base-0.2.8: Curry/ExtendedFlat/EraseTypes.hs

{-
  Erases type annotations an ExtendedFlat module.
  In functions, it preserves annotations that contain
  free type variables, i.e. type variables  which do
  not occur in the function's type signature.

  In the remaining type annotations, free type variables
  are replaced by the unit type ().

  (c) 2009, Holger Siegel.
-}

module Curry.ExtendedFlat.EraseTypes(eraseTypes) where

import Control.Monad.Reader
import qualified Data.Set as Set

import Curry.ExtendedFlat.Type
import Curry.ExtendedFlat.Goodies
import Curry.ExtendedFlat.MonadicGoodies


-- FIXME the use of lists is not very efficient,
-- but since the number of type variables is relatively
-- small, we stick with that for now.
type TVarSet = [TVarIndex]


eraseTypes :: Prog -> Prog
eraseTypes = updProg id id id (map eraseTypesInFunc) id


eraseTypesInFunc :: FuncDecl -> FuncDecl
eraseTypesInFunc (Func qname arity visty funtype rule)
    = Func qname arity visty funtype rule'
    where rule' = eraseTypesInRule (allTVars funtype) rule


eraseTypesInRule :: TVarSet -> Rule -> Rule
eraseTypesInRule sigtvars r@(External _) = r
eraseTypesInRule sigtvars (Rule vars expr)
    = Rule (map (eraseTypesInVar sigtvars) vars) (eraseTypesInExpr sigtvars expr)


eraseTypesInExpr :: TVarSet -> Expr -> Expr
eraseTypesInExpr sigtvars 
    = rnmAllVars (eraseTypesInVar sigtvars) .
      updQNames (eraseTypesInQName sigtvars)


eraseTypesInVar :: TVarSet -> VarIndex -> VarIndex
eraseTypesInVar sigtvars v
    = v {typeofVar = vt' }
    where 
      vt = typeofVar v
      usedtvars = maybe [] allTVars vt
      vt' | all (`elem` sigtvars) usedtvars
              = Nothing
          | otherwise
              = fmap (replaceFreeTypesWithEmptyTuple sigtvars) vt


eraseTypesInQName :: TVarSet -> QName -> QName
eraseTypesInQName sigtvars v
     = v {typeofQName = qt' }
    where 
      qt = typeofQName v
      usedtvars = maybe [] allTVars qt
      qt' | all (`elem` sigtvars) usedtvars
              = Nothing
          | otherwise
              = fmap (replaceFreeTypesWithEmptyTuple sigtvars) qt
                     

allTVars :: TypeExpr -> [TVarIndex]
allTVars t = go t []
    where
      go (TVar v)       is = v : is
      go (FuncType x e) is = go x (go e is)
      go (TCons _ ts)   is = foldr go is ts


replaceFreeTypesWithEmptyTuple :: TVarSet -> TypeExpr -> TypeExpr
replaceFreeTypesWithEmptyTuple usedtvars = updTVars foo
    where 
      foo tidx
          | tidx `elem` usedtvars = TVar tidx
          | otherwise = TCons (mkQName ("Prelude", "()")) []