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

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


module Derive.Show (deriveShow) where

import List(intersperse,partition)
import Maybe(isNothing,fromJust)
import Syntax(Exp(ExpVar,ExpCon,ExpLit,ExpApplication,PatWildcard),Fun(Fun)
             ,Rhs(Unguarded),Alt(Alt),Decl(DeclFun,DeclInstance,DeclPat)
             ,Decls(DeclsParse),Boxed(Boxed),Lit(LitChar,LitString,LitInt))
import MkSyntax(mkInt)
import IntState
import IdKind
import NT
import State
import Derive.Lib(syntaxType,syntaxCtxs)
import TokenId(tTrue,tShow,tshowParen,tshowChar,tshowString
              ,tshowsType,tshowsPrec,t_lessthan,t_dot,dropM,isTidOp,visImport)
import Nice(showsOp,showsVar)
import Id(Id)

deriveShow :: ((TokenId,IdKind) -> Id)
           -> Id -> Id -> [Id] -> [(Id,Id)] -> Pos -> a -> IntState -> (Decl Id,IntState)
deriveShow tidFun cls typ tvs ctxs pos =
 getUnique >>>= \d ->
 let expD = ExpVar pos d
     ishowsPrec = tidFun (tshowsPrec,Method)
     ishowsType = tidFun (tshowsType,Method)

     expShowsPrec = ExpVar pos ishowsPrec
     expShowsType = ExpVar pos ishowsType

     expTrue = ExpCon pos (tidFun (tTrue,Con))
     expShowString = ExpVar pos (tidFun (tshowString,Var))
     expShowParen = ExpVar pos (tidFun (tshowParen,Var))
     expShowSpace = ExpApplication pos [ExpVar pos (tidFun (tshowChar,Var)),ExpLit pos (LitChar Boxed ' ')]
     expLessThan = ExpVar pos (tidFun (t_lessthan,Var))
     expDot = ExpVar pos (tidFun (t_dot,Var))
 in
  getInfo typ >>>= \ typInfo -> 
  mapS getInfo (constrsI typInfo) >>>= \ constrInfos ->
  addInstMethod tShow (tidI typInfo) tshowsPrec (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) ishowsPrec >>>= \ fun ->
  addInstMethod tShow (tidI typInfo) tshowsType (NewType tvs [] ctxs [mkNTcons typ (map mkNTvar tvs)]) ishowsType >>>= \ funT ->
  mapS (mkShowFun expTrue expD expShowString expShowSpace expShowParen expShowsPrec expLessThan expDot pos) constrInfos >>>= \ funs ->
  mkShowFunTs expTrue expShowsType expShowParen expShowString expShowSpace expDot pos typInfo constrInfos >>>= \ funTs ->
  unitS $
    DeclInstance pos (syntaxCtxs pos ctxs) cls [syntaxType pos typ tvs] $
      DeclsParse [DeclFun pos fun funs
                 ,DeclFun pos funT funTs]



mkShowFun :: a -> Exp Id -> Exp Id -> Exp Id -> Exp Id -> Exp Id -> Exp Id -> Exp Id
          -> Pos -> Info -> b -> IntState -> (Fun Id,IntState)
mkShowFun expTrue expD expShowString expShowSpace expShowParen expShowsPrec expLessThan expDot pos constrInfo =
  let 
      fields = fieldsI constrInfo
      conTid = dropM (tidI constrInfo)
      con = ExpCon pos (uniqueI constrInfo)
      expShowsConOp = 
        ExpApplication pos 
          [expShowString,ExpLit pos (LitString Boxed (showsOp conTid ""))]
      expShowsConVar = 
        ExpApplication pos 
          [expShowString,ExpLit pos (LitString Boxed (showsVar conTid ""))]
  in case ntI constrInfo of
    NewType _ _ _ [nt] -> -- This constructor has no arguments
      unitS (Fun [expD,con] (Unguarded expShowsConVar) (DeclsParse []))

    NewType _ _ _ [a,b,r] | isTidOp conTid -> 
      -- Infix constructor with two arguments
      getUnique >>>= \ v1 ->
      getUnique >>>= \ v2 ->
      let (lp,p,rp) = case fixityI constrInfo of
                         (Infix,p)  -> (p,p,p)
                         (InfixR,p) -> (p+1,p,p)
                         (_,p)      -> (p,p,p+1)
          v1e = ExpVar pos v1
          v2e = ExpVar pos v2
      in unitS (
           Fun [expD,ExpApplication pos [con,v1e,v2e]]
             (Unguarded (ExpApplication pos 
               [expShowParen
               ,ExpApplication pos [expLessThan,mkInt pos p,expD]
               ,ExpApplication pos
                 [expDot
                 ,ExpApplication pos [expShowsPrec,mkInt pos lp,v1e] 
                 ,ExpApplication pos 
                   [expDot
                   ,expShowSpace
                   ,ExpApplication pos 
                     [expDot
                     ,expShowsConOp
                     ,ExpApplication pos 
                       [expDot
                       ,expShowSpace
                       ,ExpApplication pos [expShowsPrec,mkInt pos rp,v2e]]]]]]
             )) (DeclsParse []))

    NewType _ _ _ (_:nts) | any isNothing fields ->
      -- We only want a list with one element for each argument, the elements themselves are never used
      mapS ( \ _ -> unitS (ExpVar pos) =>>> getUnique) nts >>>= \ args ->
      let exp10 = ExpLit pos (LitInt Boxed 10)
          exp9 = ExpLit pos (LitInt Boxed 9)
          expShowsPrec10 arg = ExpApplication pos [expShowsPrec,exp10,arg]
      in unitS (
           Fun [expD,ExpApplication pos (con:args)]
             (Unguarded (ExpApplication pos 
               [expShowParen
               ,ExpApplication pos [expLessThan,exp9,expD]
               ,foldl ( \ acc arg -> 
                 ExpApplication pos 
                   [expDot
                   ,ExpApplication pos [expDot, acc ,expShowSpace]
                   ,expShowsPrec10 arg])
                 expShowsConVar
                 args
               ]))
             (DeclsParse []))

    NewType _ _ _ (_:nts) ->  -- named field labels must be shown
      mapS ( \ _ -> unitS (ExpVar pos) =>>> getUnique) nts >>>= \ args ->
      mapS (getInfo.fromJust) fields >>>= \ labels ->
      let exp10 = ExpLit pos (LitInt Boxed 10)
          exp9 = ExpLit pos (LitInt Boxed 9)
          expShowsPrec10 arg = ExpApplication pos [expShowsPrec,exp10,arg]
          expShowsLabel label = 
            ExpApplication pos 
              [expShowString
              ,ExpLit pos (LitString Boxed (showsVar (dropM (tidI label)) "="))]
          expShowsOpen  = 
            ExpApplication pos [expShowString,ExpLit pos (LitString Boxed "{")]
          expShowsClose = 
            ExpApplication pos [expShowString,ExpLit pos (LitString Boxed "}")]
          expShowsComma = 
            ExpApplication pos [expShowString,ExpLit pos (LitString Boxed ",")]
      in unitS (
           Fun [expD,ExpApplication pos (con:args)]
             (Unguarded 
               (ExpApplication pos 
                 [expShowParen
                 ,ExpApplication pos [expLessThan,exp9,expD]
                 ,( foldl (\acc item->
                   ExpApplication pos [expDot,acc,item]) expShowsConVar .
                   (expShowsOpen:) .
                   (++[expShowsClose]) .
                   intersperse expShowsComma .
                   zipWith (\label arg->
                              ExpApplication pos [expDot,expShowsLabel label,
                                                         expShowsPrec10 arg])
                           labels
                 ) args
                 ]))

--               ExpApplication pos [expDot,
--                 foldl ( \ acc (label,arg) ->
--                       ExpApplication pos [expDot,
--                         ExpApplication pos [expDot, acc ,
--                           ExpApplication pos [expDot, expShowSpace,
--                             expShowsLabel label]],
--                         expShowsPrec10 arg])
--                    (ExpApplication pos [expDot, expShowsConVar, expShowsOpen])
--                    (zip (map tidI labels) args),
--                  expShowsClose]])]

              (DeclsParse []))


mkShowFunTs :: Exp Id -> Exp Id -> Exp Id -> Exp Id -> Exp Id -> Exp Id 
            -> Pos -> Info -> [Info] 
            -> a -> IntState -> ([Fun Id],IntState)

mkShowFunTs expTrue expShowsType expShowParen expShowString expShowSpace expDot pos typInfo constrInfos =
  getUnique >>>= \ v ->
  let expA = ExpVar pos v
      expTypeStr = ExpApplication pos [expShowString,(ExpLit pos . LitString Boxed . show . dropM . tidI) typInfo]
  in
    case ntI typInfo of
      NewType [] [] [] _  ->
        unitS [Fun [expA] (Unguarded expTypeStr) (DeclsParse [])]
      NewType free exist _ _ ->
        mapS (\ f -> getUnique >>>= \ i -> unitS (f,i,ExpVar pos i)) 
          free >>>= \ fitypes ->
        mapS0 (\(f,i,ei)-> addNewLetBound i (visImport ('v':(show i)))) fitypes >>>
        mapS ( getType pos expA expShowsType expTrue expShowString constrInfos ) fitypes >>>= \ des ->
        case unzip des of
          (ds,es) ->
            unitS [Fun [expA]
                       (Unguarded (ExpApplication pos 
                         [expShowParen
                         ,expTrue
                         ,foldl ( \ acc e -> 
                           ExpApplication pos 
                             [expDot    
                             ,ExpApplication pos [expDot, acc ,expShowSpace]
                             ,e])
                           expTypeStr
                           es]))
                    (DeclsParse (concat ds))
                  ]      


getType :: Show a 
        => Pos -> Exp Id -> Exp Id -> b -> Exp Id -> [Info] -> (Id,a,Exp Id) 
        -> c -> d -> (([Decl Id],Exp Id),d)

getType pos expA expShowsType expTrue expShowString [] (f,i,iexp) =
  unitS ([],ExpApplication pos [expShowString,ExpLit pos (LitString Boxed ('?':'v':show i++"?"))])
getType pos expA expShowsType expTrue expShowString (info:infos) (f,i,iexp) =
  patConstr pos info f iexp >>>= \ qpat ->
  case qpat of
    Just pat -> 
      unitS ([DeclPat (Alt pat (Unguarded expA) (DeclsParse[]))]
            ,ExpApplication pos [expShowsType,iexp])
    Nothing -> 
      getType pos expA expShowsType expTrue expShowString infos (f,i,iexp)


patConstr :: Pos -> Info -> Id -> Exp Id -> a -> b -> (Maybe (Exp Id),b)

patConstr pos info f iexp =
  case ntI info of
    NewType free exist ctxs nts ->
      let ints =  (zip [0 .. ] . init) nts
      in case (partition (simpleNT . snd) .  filter (elem f . freeNT . snd)) ints of
          ([],[])      -> unitS Nothing
          ((i,nt):_,_) -> unitS (Just (ExpApplication pos (ExpCon pos (uniqueI info) : map (toExp i iexp) ints)))
          ([],xs)      -> unitS Nothing -- can do better here !!
 where
  toExp i iexp (i',_) = if i == i' then iexp else PatWildcard pos


simpleNT :: NT -> Bool
simpleNT (NTstrict nt) = simpleNT nt
simpleNT (NTvar v _) = True
simpleNT (NTany v) = True
simpleNT _ = False

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].