packages feed

cryptol-3.6.0: src/Cryptol/ModuleSystem/NamingEnv/Types.hs

{-# LANGUAGE DeriveAnyClass    #-}
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

module Cryptol.ModuleSystem.NamingEnv.Types where

import           Data.List(partition)
import           Data.Map.Strict            (Map)
import qualified Data.Map.Strict            as Map
import qualified Data.Set                   as Set

import           Control.DeepSeq            (NFData)
import           GHC.Generics               (Generic)

import           Cryptol.ModuleSystem.Name
import           Cryptol.ModuleSystem.Names
import           Cryptol.Parser.Name
import           Cryptol.Utils.Ident
import           Cryptol.Utils.PP

-- | The 'NamingEnv' is used by the renamer to determine what
-- identifiers refer to.
newtype NamingEnv = NamingEnv (Map Namespace (Map PName Names))
  deriving (Show,Generic,NFData)

instance Monoid NamingEnv where
  mempty = NamingEnv Map.empty
  {-# INLINE mempty #-}

instance Semigroup NamingEnv where
  NamingEnv l <> NamingEnv r =
    NamingEnv (Map.unionWith (Map.unionWith (<>)) l r)

instance PP NamingEnv where
  ppPrec _ (NamingEnv mps) = vcat $ map ppNS $ Map.toList mps
    where
    isPrel x =
      case nameModPathMaybe x of
        Nothing -> False
        Just p -> topModuleFor p == preludeName
    
    skip (x,as) (count, defs) =
      let (ps,qs) = partition isPrel (namesToList as)
      in ( count + length ps
         , if null qs then defs else (x,namesFromSet (Set.fromList qs)) : defs
      )

    ppNS (ns,xs) =
      withPPCfg (\cfg ->
        let (skipped,shown)
              | not (ppcfgHidePreludeNames cfg) = (0,Map.toList xs)
              | otherwise = foldr skip (0,[]) (Map.toList xs)
            skippedDoc = if skipped > 0 then "Skipped" <+> int skipped <+> "names from `Cryptol" else mempty
        in nest 2 (vcat (pp ns : skippedDoc : map ppNm shown))
        )
    ppNm (x,as)  = pp x <+> "->" <+> commaSep (map pp (namesToList as))

-- | Move names in the constructor namespace to the value namespace.
-- This is handy when checking for ambiguities.
consToValues :: NamingEnv -> NamingEnv
consToValues (NamingEnv mps) =
  NamingEnv $
  case Map.updateLookupWithKey (\_ _ -> Nothing) NSConstructor mps of
    (Nothing, mp1) -> mp1
    (Just conMap, mp1) -> Map.insertWith (Map.unionWith (<>)) NSValue conMap mp1