Pfe4Cmds.hs

module Pfe4Cmds where

import PfeParse(runCmds,moduleArgs,moduleArgs',just,qualIds,( #@ ),(<@),
		kwOption)
import Pfe3Cmds(pfe3Cmds)

import PFE0(pput,epput)
import PFE2(getExports)
import PFE4(runPFE4,topTypes,typeCheck,rewriteAndTypeCheck,modEnv)
import PFE_Rewrites
import Ents(Ent(..))
import QualNames(mkUnqual,unqual)
import Relations(relToList)
import TypedIds(isValue,IdTy(MethodOf),owner,belongsTo,idTy)
import TI(Typing(..),TypeInfo(..),tdom,envFrom,topVal,topType,ppKinded)
import TiInstanceDB(InstEntry(..))
import HasBaseName(getBaseName)
import HsIdent(HsIdentI(..),accHsIdent2,getHSName,mapHsIdent)
import SrcLoc(srcLoc)
import UniqueNames(orig,Orig(G),noSrcLoc)
import MUtils(( # ),( <# ),apBoth)
import PrettyPrint
import PrettySymbols hiding (not)
import PrettyUtil(ppContext,ppWhere)
import Products((><))
import OpTypes(cmpBy)
import List(partition,sortBy)

The type checker can return different types, so to avoid an ambiguity when the result is used only for pretty printing, the function tcOutput can be passed in to restrict the result type.

pfe4 ext tcOutput = runPFE4Cmds ext (pfe4Cmds tcOutput)

runPFE4Cmds ext = runCmds (runPFE4 ext)

pfe4Cmds tcOutput=
    pfe3Cmds ++
    [("tc",       (tcmd tcrw,     "type check and display decorated modules")),
     ("types",    (tcmd0 types,    "show types/kinds of top-level entities")),
     ("typeof",   (tqcmd typeof,  "show types of named top-level entities")),
     ("kindof",   (tqcmd kindof,  "show kinds of named top-level entities")),
     ("instances",(tcmd0 instances,"list instances defined in a module")),
     ("iface",    (tcmd0 ppIfaces, "show the interfaces of modules")),
     ("usedtypes",(tcmd0 utypes,   "show what types identifers are used at"))]
  where
    tcmd0 f = moduleArgs (f tcOutput)
    tcmd f = moduleArgs' rwopts (f tcOutput)
    tqcmd f = qualIds (f tcOutput)

    rwopts = o pmRewrite ## o pbRewrite ## o lcRewrite

    o rw@(Rewrite n _) = (\ b -> if b then rw else idRw) # kwOption ('-':n)
    rw1 ## rw2 = compRw #@ rw1 <@ rw2

instances tcOutput ms =
  do pfe4info <- tcOutput # topTypes (Just ms)
     pput.vcat $ [ppContext ps<+>p |(m,(_,(_,(insts,_))))<-pfe4info,
		                    m `elem` ms,
		                    (p,IE _ _ ps)<-insts]

types tcOutput ms =
  do pfe4info <- tcOutput # topTypes (Just ms)
     pput.vcat $ [map (fmap fst) ks$$ts |(m,(_,(_,(_,(ks,ts)))))<-pfe4info,
		                    m `elem` ms]

typeof tcOutput qids =
  do pfe4info <- tcOutput # topTypes (Just (map fst qids))
     mapM_ (typeof1 pfe4info) qids
{-
typeof1 pfe4info (m,s) = pput (vcat bs)
  where
    q=topVal m s
    bs = [b|(m',(_,(_,(_,(ks,ts)))))<-pfe4info,
		m'==m,
		b@(x:>:_)<-ts,
		getHSName x==q]
-}
kindof tcOutput qids =
  do pfe4info <- tcOutput # topTypes (Just (map fst qids))
     mapM_ (kindof1 pfe4info) qids
{-
kindof1 pfe4info (m,s) = pput (vcat bs)
  where
    q=topType m s
    bs = [fmap fst b|(m',(_,(_,(_,(ks,ts)))))<-pfe4info,
		     m'==m,
		     b@(x:>:_)<-ks,
		     getHSName x==q]
-}
typeof1 = info1 snd id
kindof1 = info1 fst fst

info1 envsel infosel pfe4info (m,s) = pput (vcat bs)
  where
    q=topType m s
    bs = [fmap infosel b|Just env<-[modEnv pfe4info m],
		     b@(x:>:_)<-envsel env,
		     getHSName x==q]

utypes tcOutput ms =
  do pfe4info <- tcOutput # typeCheck (Just ms)
     mapM_ (utypes1' pfe4info) ms
  where
    utypes1' pfe4info mn =
        maybe (epput $ "Unknown module:"<+>mn) utypes1
		      (lookup "fl".fst.snd=<<lookup mn pfe4info)
      where
        utypes1 m =
          pput (mn<>":"$$
		nest 2 (vcat.map u.sortBy (cmpBy fst).map pos.snd.envFrom $ m))

        pos xt@(x:>:_) = (srcLoc x,xt)

        u (pos,x:>:(sc,optt)) =
	    sep [x<+>"at"<+>pos<+>"::",
		 nest 4 (maybe (ppi sc) ppi optt)]

tc tcOutput ms = pptc ms =<< (tcOutput # typeCheck (just ms))

pptc ms = pptc' "" ms

pptc' rname ms pfe4info =
  pput.vcat $ [tm |(m,(_,(tms,_)))<-pfe4info, m `elem` ms,(n,tm)<-tms,n==rname++"fl"]

tcrw tcOutput rw@(Rewrite rwn _) ms =
  pptc' rwn ms . tcOutput =<< rewriteAndTypeCheck rw (just ms)

ppIfaces tcOutput ms =
  do exports <- getExports (Just ms)
     pfe4info <- tcOutput # topTypes (Just ms)
     mapM_ (pput.ppIface.iface exports pfe4info) ms

moduleInterface m =
  do exports <- getExports (Just [m])
     types <- topTypes (Just [m])
     return (iface exports types m)

iface expRels pfe4info m =
    (m,((types><kinds).partition isValue.map snd.relToList.snd
        # lookup m expRels))
  where
    kinds = map (info fst id)
    types = map (info snd id)

    info envsel infosel e@(Ent m' n _) = (e,i)
      where
        Just env = conv . envsel # modEnv pfe4info m'
	i = lift n (infosel # lookup (mkUnqual(getBaseName n)) env)


    conv env = [(unqual' (getBaseName x),y)|x:>:y<-env]
    unqual' = unqual `asTypeOf` id

    lift x = maybe (error $ pp $ "Not found:"<+>x) id
      
ppIface (m,Nothing) = "Unknown module:"<+>m
ppIface (m,Just (ts,ks)) =
    kw "module"<+>modn m<>":" $$
    nest 2 (vcat (map ppTInfo ks) $$
	    "" $$
	    vcat (map ppVInfo vs))
  where
    (subs,vs) = partition isExportedSubordinate ts

    ppV = accHsIdent2 ppi con
    ppTInfo (e,(k,ti)) = ppTypeInfo e k ti
    ppVInfo (Ent m' n _,ty) = {-ppName m'-}ppV n<+>el<+>ty
    {-
    ppName m' n =
      if m'==m
      then ppi n
      else m'<>"."<>n
    -}

    isExportedValue (x:>:_) = mapHsIdent orig x `elem` values

    isExportedSubordinate (e,_) = maybe False (`elem` types) (origOwner e)

    ppTypeInfo e@(Ent m n idty) k ti =
	case ti of
          Data    -> ppData "data"
	  Newtype -> ppData "newtype"
	  Class ps aks pds allms ->
	      sep [kw "class"<+>
		   sep [ppContext ps,
			tcon n<+>hsep (map ppKinded aks)<+>ppDeps vds],
		   nest 2 $ ppWhere (map ppi visms++more)]
	    where
	      as = tdom aks
              vds = map (apBoth (map (as!!))) pds
	      (visms,hidms) = partition isExportedValue allms
	      more = if null hidms then [] else [kw "..."]
	  Synonym as t ->
              sep [kw "type"<+>tcon n<+>hsep as<+>equals,nest 4 (ppi t)]
	  Tyvar -> var n<+>el<+>k -- ??
      where
        o = ent2orig e

        ppData dkw =
	    sep [kw dkw<+>tcon n<+>el<+>k,
		 nest 2 $ ppWhere (map ppVInfo ss)]
	  where
	    ss = filter ((==Just o).origOwner.fst) subs

    ppDeps [] = empty
    ppDeps ds = kw "|"<+>ppiFSeq (map ppDep ds)
    ppDep (as,bs) = hsep as<+>rarrow<+>hsep bs

    values = map (ent2orig.fst) ts
    types = map (ent2orig.fst) ks

    ent2orig (Ent m n _) = mapHsIdent (\n->G m n noSrcLoc) (getBaseName n)

    origOwner (Ent m n idty) = fmap orig (owner idty)
      where orig t = ent2orig (Ent m (HsCon t) undefined)

Plain-text version of Pfe4Cmds.hs | Valid HTML?