Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/src/compiler98/NT.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


-- | Warning: there are a bunch of comments on the positional fields
-- of constructors in this module (perhaps the constructors should be
-- record constructors so that they can have docstrings on their
-- fields?)

module NT ( NT(..), NewType(..), Kind(..)
        , mkNTvar, mkNTexist, mkNTcons
        , anyNT, consNT, freeNT, freshNT, polyNT, strTVar
        , sndNTvar, strNT, strictNT, transCtxs, useNT
        , contextNT, ntContext2Pair, stripNT, anyVarNT
        ) where


import Id(Id, strTVar)
import Util.Extra(mixComma,mixSpace,mix)
import Char

infixr 5 :->:
data Kind = Star | Kind :->: Kind deriving (Eq,Ord)

-- | Perhaps @NewType@ is a type schema?  It quantifies variables over
-- an arrow of 'NT's.
data NewType = NoType
             | NewType [Id]       -- universally quantified type variables
                       [Id]       -- existentially quantified type variables
                       [(Id,Id)]  -- context (class, type variable)
                       [NT]       -- simple types 
                                  -- ex.: [Int,Char,Bool] = Int->Char->Bool
             deriving (Eq)

instance Show NewType where
  showsPrec d (NoType) =  showString " -- no type --"
  showsPrec d (NewType free exist ctxs nts) = 
    showString (strTVarsCtxsNTs free ctxs nts)

data NT = NTany   Id       -- ^ can be instantiated with unboxed 
                           -- (needed during type checking)
        | NTvar   Id Kind
        | NTexist Id Kind
        | NTstrict NT
        | NTapp   NT NT
        | NTcons  Id Kind [NT]  -- ^ combines constructor + application
        | NTcontext Id Id  -- ^ context (class, type variable)
                           -- purpose here completely unclear (used?)
         deriving (Eq,Ord)

mkNTvar, mkNTexist :: Id -> NT
mkNTvar v = NTvar v Star        -- simple tyvar
mkNTexist v = NTexist v Star    -- simple tyvar

mkNTcons :: Id -> [NT] -> NT
mkNTcons i nts = NTcons i kind nts
 -- where kind = foldr (:->:) Star (map kindNT nts)
    where kind = Star -- error "kind inference is not implemented correctly"

kindNT :: NT -> Kind
kindNT (NTany _) = Star
kindNT (NTvar _ k) = k
kindNT (NTexist _ k) = k
kindNT (NTapp nt1 nt2) = case (kindNT nt1) of (_:->:k) -> k
kindNT (NTcons _ k nts) = foldl (\(_:->:k') _ -> k') k nts
kindNT (NTcontext _ _) = Star

stripNT :: NT -> Id
stripNT (NTany   v)   = v
stripNT (NTvar   v _) = v
stripNT (NTexist v _) = v
stripNT (NTapp (NTvar v _) nt ) = v
stripNT nt = error ("stripNT on " ++ show nt)

strictNT :: NT -> Bool
strictNT (NTstrict _) = True
strictNT _ = False

ntContext2Pair :: NT -> (Id, Id)
ntContext2Pair (NTcontext c a) = (c,a)

contextNT :: NT -> Bool
contextNT (NTcontext _ _) = True
contextNT  _ = False


{- | Determine the type constructors that occur in the given type -}
consNT :: NT -> [Id]

consNT nt =
  consNT' nt []
 where
  consNT' (NTstrict nt) r = consNT' nt r
  consNT' (NTapp t1 t2) r = consNT' t1 (consNT' t2 r)
  consNT' (NTcons c _ nts) r = c:foldr consNT' r nts
  consNT' _ r = r

{- |
Same as consNT except that constructor from NTcontext goes also into result.
used only in module 'Export'
-}
useNT :: NT -> [Id]

useNT (NTany  a)    = []
useNT (NTvar  a _)  = []
useNT (NTexist a _) = []
useNT (NTstrict t) = useNT t
useNT (NTapp t1 t2) =  useNT t1 ++ useNT t2
useNT (NTcons a _ tas) =  a:concatMap useNT tas
useNT (NTcontext c v) =  [c]


{- | Determine type variables that occur in given type. -}
freeNT :: NT -> [Id]

freeNT (NTany  a)    = [a]
freeNT (NTvar  a _)  = [a]
freeNT (NTexist a _) = [a]
freeNT (NTstrict t) = freeNT t
freeNT (NTapp t1 t2) =  freeNT t1 ++ freeNT t2
freeNT (NTcons a _ tas) =  concat (map freeNT tas)


{- |
Exchange type variables according to given mapping in given type. 
(not existentially quantified vars.
-}
freshNT :: (Id -> Id) -> NT -> NT

freshNT tv (NTany  a)   = NTany (tv a)
freshNT tv (NTvar  a k) = NTvar (tv a) k
freshNT tv t@(NTexist  a _) = t
freshNT tv (NTstrict t) = {- NTstrict -}  (freshNT tv t)
freshNT tv (NTapp t1 t2) =  NTapp (freshNT tv t1) (freshNT tv t2)
freshNT tv (NTcons a k tas) =  NTcons a k (map (freshNT tv) tas)
freshNT tv (NTcontext c v) =  NTcontext c (tv v)

anyNT :: [Id] -> NT -> NT
anyNT av t@(NTany  a)    = t
anyNT av t@(NTvar  a _)  = if a `elem` av then NTany a else t
anyNT av t@(NTexist a _) = t
anyNT av (NTstrict t) = NTstrict (anyNT av t)
anyNT av (NTapp t1 t2) =  NTapp (anyNT av t1) (anyNT av t2)
anyNT av (NTcons a k tas) =  NTcons a k (map (anyNT av) tas)

polyNT :: [Id] -> NT -> NT
polyNT fv t@(NTany  a) = if a `elem` fv then mkNTvar a else t
polyNT fv t@(NTvar  a _) = t
polyNT fv t@(NTexist a _) = t
polyNT fv (NTstrict t) = NTstrict (polyNT fv t)
polyNT fv (NTapp t1 t2) = NTapp (polyNT fv t1) (polyNT fv t2)
polyNT fv (NTcons a k tas) = NTcons a k (map (polyNT fv) tas)

-- | FIXME: Isn't this type a tad more general than appropriate for the name?
transCtxs :: (a -> b) -> (c -> d) -> [(c, a)] -> [(d, b)]
transCtxs tv tc ctxs = map (\(c,v) -> (tc c,tv v)) ctxs 



{- | Show function for 'NT', parameterised by show functions for 
constructors\/class names and for type variables.
-}
strNT :: (Id -> String) -> (Id -> String) -> NT -> String

strNT c p (NTany  a) = p a++"#"
strNT c p (NTvar  a _) = p a
strNT c p (NTexist a _) = p a++"?"
strNT c p (NTstrict t) = "!" ++ strNT c p t
strNT c p (NTapp t1 t2) = "(" ++ strNT c p t1  ++ " " ++ strNT c p t2 ++ ")"
strNT c p (NTcons a _ []) = c a
strNT c p (NTcons a _ tas) = "(" ++ c a ++ " " ++ mixSpace (map (strNT c p) tas) ++ ")"
strNT c p (NTcontext a v) = "(" ++ c a ++ " " ++ p a ++ ") => "

instance Show NT where
  showsPrec d nt = ((strNT show (show ::(Id->String)) nt)++)

strCtxs ::  [(Id,Id)] -> String
strCtxs [] = ""
strCtxs ctxs = "(" ++ mixComma (map ( \ (c,v) -> show c ++ ' ':strTVar v ) ctxs) ++ ") => "

strTVs :: [Id] -> String
strTVs [] = ""
strTVs tvs =  "\\/ " ++ mixSpace (map strTVar tvs) ++ " . "

strTVarsCtxsNTs :: [Id] -> [(Id, Id)] -> [NT] -> [Char]
strTVarsCtxsNTs tvs ctxs [] =  strTVs tvs ++ strCtxs ctxs ++ " -"
strTVarsCtxsNTs tvs ctxs nts =  
  strTVs tvs ++ strCtxs ctxs ++ mix " -> " (map (strNT show strTVar) nts)


sndNTvar :: (a, Id) -> (a, NT)
sndNTvar (c,v) = (c,mkNTvar v) -- used for ctxs         *** KIND??


anyVarNT :: NT -> Maybe Id
anyVarNT (NTany tvn) = Just tvn
anyVarNT (NTvar tvn _) = Just tvn
anyVarNT _ = Nothing

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.