packages feed

bidirectionalization-combined-0.1: AST.hs

module AST where 

import Util 
import Text.PrettyPrint
import Data.List (groupBy)

import Debug.Trace 
import Control.Monad.State

data AST = AST [ Decl ]

instance Ppr AST where
    ppr (AST ds) = 
        let dss = groupBy isSameFunc ds
        in vcat $ punctuate (text "\n") $ map pprDecls dss 
        where 
          pprDecls (d:ds) =
              ppr d $$ pprDeclsSimp ds 
          pprDeclsSimp ds
              = vcat $ map (\(Decl f _ ps e) -> ppr (Decl f FTUndet ps e)) ds

instance Show AST where 
    show = show . ppr 

data Name 
    = Name     String 
    | IName    String [Int]
    | NCmpl    Name 
    | NTuple   Name 
    | NTupleV  Int      -- Variable Introduced by Tupling 
    | NTupleVC Int      -- Variable Introduced by Tupling 
    | NBwd     Name
    | NInv     Name 
    | NCConF   Name     -- Constructor Name in Complement (1)
    | NCConE   Int      -- Constructor Name in Complement (2)
    | NCConU   Name Int -- After Renaming  
          deriving (Eq,Ord)

instance Ppr Name where
    ppr  (Name s) = text s
    ppr  (IName s is) = text s <> text "_" <> 
                        (hcat $ punctuate (text "_") $ map ppr is)
    ppr  (NCmpl n)  = ppr n <> text "_Cmpl" 
    ppr  (NTuple n) = ppr n <> text "_T"  
    ppr  (NTupleV i)  = text "tv" <> ppr i
    ppr  (NTupleVC i) = text "tc" <> ppr i
    ppr  (NInv n)     = ppr n <> text "_I" 
    ppr  (NBwd n)     = ppr n <> text "_B"
    ppr  (NCConF n)   = text "C" <> ppr n
    ppr  (NCConE i)   = text "C" <> ppr i 
    ppr  (NCConU n i) = text "C" <> ppr n <> text "_" <> ppr i

instance Show Name where
    show = show . ppr 

data Decl = Decl Name FType [Pat] Exp

instance Ppr Decl where
    ppr (Decl fname ftype ps e) = 
        addSig (ppr fname <+> 
                    (hsep $ map pprChildP ps) $$
--                     parens (hsep $ punctuate comma (map ppr ps)) $$
                     nest 4 (text "=") $$
                     nest 6 (ppr e))
        where 
          addSig d = 
              case ftype of
                FTUndet -> empty <> d
                _       -> ppr fname <+> text "::" <+> ppr ftype $$ d            
instance Show Decl where
    show = show . ppr 

data Exp  = EVar ID Type Name 
          | EFun ID Type Name [Exp] -- Exp must be variable (treeless)
          | ECon ID Type Name [Exp]
       deriving (Ord,Eq)

type ID = Maybe Int

addPprType t d = 
    case t of 
      TUndet -> d
      _      -> parens ( d <> text "::" <> ppr t )


pprChildE e | isAtomicE e = ppr e 
            | otherwise   = parens (ppr e)
isAtomicE (EVar _ _ _)     = True
isAtomicE (EFun _ _ _ [])  = True
isAtomicE (ECon _ _ _ [])  = True
isAtomicE e | isAllListE e = True 
isAtomicE _                = False

pprListE (ECon _ _ (Name "Cons") [e1,ECon _ _ (Name "Nil") []]) 
    = ppr e1 
pprListE (ECon _ _ (Name "Cons") [e1,e2]) 
    = ppr e1 <> comma <+> pprListE e2 
pprListE (ECon _ _ (Name "Nil") []) 
    = empty

isAllListE (ECon _ _ (Name "Cons") [e1,e2])
    = isAllListE e2 
isAllListE (ECon _ _ (Name "Nil") []) 
    = True
isAllListE _ 
    = False 

instance Ppr Exp where
    ppr (EVar _ t vname)     
        = addPprType t (ppr vname)
    ppr (EFun _ t fname es) 
        = addPprType t $
            ppr fname <+>
                (hsep $ map pprChildE es)
--            parens (sep $ punctuate comma (map ppr es))          
    ppr e | isAllListE e
        = brackets (pprListE e )
    ppr (ECon _ _ (Name "Cons") [e1,e2]) 
        = pprChildE e1 <> text ":" <> ppr e2 
    ppr (ECon _ _ (Name "Unit") []) 
        = parens empty 
    ppr (ECon _ t cname []) 
        = addPprType t $ ppr cname 
    ppr (ECon _ t cname es)
        = addPprType t $ 
             ppr cname <+>
                 (hsep $ map pprChildE es)
--             parens (sep $ punctuate comma (map ppr es))


instance Show Exp where
    show = show . ppr 

data Pat  = PVar ID Type Name
          | PCon ID Type Name [Pat] 
       deriving (Ord,Eq)


pprChildP p | isAtomicP p = ppr p
            | otherwise   = parens (ppr p)
isAtomicP (PVar _ _ _)     = True
isAtomicP (PCon _ _ _ [])  = True
isAtomicP p | isAllListP p = True
isAtomicP _                = False

pprListP (PCon _ _ (Name "Cons") [p1, PCon _ _ (Name "Nil") []])
    = ppr p1
pprListP (PCon _ _ (Name "Cons") [p1,p2]) 
    = ppr p1 <> comma <+> pprListP p2 
pprListP (PCon _ _ (Name "Nil") []) 
    = empty

isAllListP (PCon _ _ (Name "Cons") [p1,p2])
    = isAllListP p2 
isAllListP (PCon _ _ (Name "Nil") []) 
    = True
isAllListP _ 
    = False 


instance Ppr Pat where
    ppr (PVar _ t vname)     
        = addPprType t (ppr vname)
    ppr e | isAllListP e
        = brackets (pprListP e )
    ppr (PCon _ _ (Name "Cons") [p1,p2]) 
        = pprChildP p1 <> text ":" <> ppr p2 
    ppr (PCon _ _ (Name "Unit") []) -- never happens 
        = parens empty 
    ppr (PCon _ t cname [])
        = addPprType t (ppr cname)
    ppr (PCon _ t cname ps)
        = addPprType t $ ppr cname 
           <+> (hsep $ map pprChildP ps)
--           <> parens (sep $ punctuate comma (map ppr ps))
          
instance Show Pat where
    show = show . ppr 

data FType 
    = TFun [Int] [Type] Type -- Quantified Vars, Input Types, Output Type.
      -- e.g. forall a. [a] -> a 
      --      ==> TFun [TVar 1] [ TCon "[]" [TVar 1] ] (TVar 1)
    | FTUndet
      deriving (Eq,Ord)

instance Ppr FType where
    ppr (FTUndet) = text "??"
    ppr (TFun is ts t) =
        (case is of 
          [] -> empty 
          _  -> text "forall" <+>
                hsep (map pprTV is) <>
                text ".")
         <+> argType <+>
             ppr t 
        where
          argType = 
              case ts of 
                []  -> empty 
                [t] -> ppr t <+> text "->" 
                _   -> 
                    parens (sep $ punctuate comma (map ppr ts)) 
                               <+> text "->"
          pprTV i = text ("t" ++ show i)
             
instance Show FType where
    show = show . ppr 

data Type = TUndet           -- PlaceHolder
          | TVar Int         -- Type Variable
          | TCon Name [Type] -- e.g. [Int], Map Int [Char]
            deriving (Eq,Ord)
            
instance Ppr Type where
    ppr (TUndet)        = text "?"
    ppr (TVar i)        = text ("t" ++ show i) 
    ppr (TCon (Name "Unit") []) =
        parens empty 
    ppr (TCon (Name "List") [t]) = 
        brackets $ ppr t
    ppr (TCon tname ts) =
        ppr tname <+> 
             hsep (map (\t -> f t (ppr t)) ts)
        where
          f (TUndet) x = x
          f (TVar i) x = x 
          f (TCon tname []) x = x
          f _ x = parens x
instance Show Type where 
    show = show . ppr 



typeofP (PVar _ t _)   = t 
typeofP (PCon _ t _ _) = t 
typeofE (EVar _ t _)   = t 
typeofE (ECon _ t _ _) = t
typeofE (EFun _ t _ _) = t 


idofP (PVar t _ _)   = t 
idofP (PCon t _ _ _) = t 
idofE (EVar t _ _)   = t 
idofE (ECon t _ _ _) = t
idofE (EFun t _ _ _) = t 

varsP p = snub $ vp p
    where vp (PVar _ _ x)    = [x]
          vp (PCon _ _ _ ps) = concatMap vp ps
varsE e = snub $ ve e 
    where ve (EVar _ _ x)    = [x]
          ve (ECon _ _ _ es) = concatMap ve es
          ve (EFun _ _ _ es) = concatMap ve es


-- assignIDsAST :: AST -> AST
assignIDsAST (AST decls) = 
    AST $ evalState (mapM assignIDsD decls) 10

assignIDsD :: Decl -> State Int (Decl) 
assignIDsD (Decl f t ps e) = 
    do { ps' <- mapM assignIDsP ps 
       ; e   <- assignIDsE e 
       ; return $ Decl f t ps e }
    where
      uniq = do { i <- get; put (i+1) ; return $ Just (i+1) }
      assignIDsE (EVar _ t x) = 
          do { i <- uniq
             ; return $ EVar i t x }
      assignIDsE (ECon _ t c es) = 
          do { i <- uniq 
             ; es' <- mapM assignIDsE es
             ; return $ ECon i t c es' }
      assignIDsE (EFun _ t f es) = 
          do { i <- uniq 
             ; es' <- mapM assignIDsE es
             ; return $ EFun i t f es' }

      assignIDsP (PVar _ t x) =
          do { i <- uniq
             ; return $ PVar i t x }
      assignIDsP (PCon _ t c ps) = 
          do { i <- uniq
             ; ps' <- mapM assignIDsP ps 
             ; return $ PCon i t c ps' }

isSameFunc (Decl f _ _ _) (Decl g _ _ _) = f == g 


-- After Tupling

data TAST  = TAST [TDecl]
data TDecl = TDecl Name [Pat] [Exp] [VDecl] -- f(ps) = es where ... 
data VDecl = VDecl [Name] Name [Name]          -- vs = f(us)

parensIfMultiple []  = parens empty 
parensIfMultiple [p] = p
parensIfMultiple ps  = parens (hsep $ punctuate comma ps)

instance Ppr TAST where 
    ppr (TAST tdecls) = 
        let tdeclss = groupBy (\(TDecl f _ _ _) (TDecl g _ _ _) -> f == g) tdecls 
        in vcat $ punctuate (text "\n") $ map (\tdecls -> vcat $ map ppr tdecls) tdeclss


instance Ppr TDecl where
    ppr (TDecl f ps es vdecls) =
        ppr f <+> parensIfMultiple (map ppr ps) $$
            nest 4 (text "=" <+> parensIfMultiple (map ppr es)) $$
            if null vdecls then 
                empty 
            else 
                (nest 6 (text "where") $$
                 nest 8 (vcat $ map ppr vdecls))
instance Ppr VDecl where
    ppr (VDecl vs f us) = parensIfMultiple (map ppr vs)
                          <+> text "=" <+> ppr f <>
                          parensIfMultiple (map ppr us)