packages feed

fregel-1.2.0: compiler/ASTTrans.hs

{-# Language TypeSynonymInstances,FlexibleInstances,MultiParamTypeClasses,FunctionalDependencies,RankNTypes,FlexibleContexts,KindSignatures,ScopedTypeVariables,DeriveGeneric,OverloadedStrings #-}

module ASTTrans
  (transIdElim, transCommElim, transInactivate, collectDPregel,
   dPregelStepArg, isDPregelFixStepArg, collectDConstr, DPregelStepArg,
   collectDependDSmplDef) where

import Spec
import ASTData

import Data.Maybe
import Data.List
import Numeric (showHex)

-- import GenSMT as GS
import Debug.Trace as DT

class ASTTrans a where
  elimId :: a -> a

instance ASTTrans (DProgramSpec a) where
  elimId (DProgramSpec rs p a) = DProgramSpec rs (elimId p) a

instance ASTTrans (DProg a) where
  elimId (DProg f defs e a) = DProg f (map elimId defs) e a

instance ASTTrans (DGroundDef a) where
  elimId (DGDefVC d a) = DGDefVC (elimId d) a
  elimId x = x

instance ASTTrans (DDefVertComp a) where
  elimId (DDefVertComp f ds e a) = DDefVertComp f (map elimId ds) e a

instance ASTTrans (DSmplDef a) where
  elimId (DDefVar f ds e a) = DDefVar f (map elimId ds) (elimId e) a
  elimId (DDefFun f vs ds e a) = DDefFun f vs (map elimId ds) (elimId e) a
  elimId x = x
  -- elimId (DDefTuple vs ds e a) = undefined

instance ASTTrans (DExpr a) where
  elimId (DFunAp f es a) = DFunAp f (map elimId es) a
  elimId (DAggr agg e g es a) = DAggr agg e g (idCheck e agg ++ es) a
  elimId x = x

idCheck :: DExpr a -> DAgg a -> [DExpr a]
idCheck e (DAggMin a) = [DFunAp (DBinOp "<" a) [e, DCExp (DCInt maxint a) a] a]
                        where maxint = 99999999
idCheck e (DAggMax a) =
  [DFunAp (DBinOp ">" a)
          [e, DFunAp (DFun "neg" a) [DCExp (DCInt maxint a) a] a] a]
  where maxint = 99999999
idCheck e (DAggSum a) = [DFunAp (DBinOp "!=" a) [e, DCExp (DCInt 0 a) a] a]
idCheck e (DAggProd a) = [DFunAp (DBinOp "!=" a) [e, DCExp (DCInt 1 a) a] a]
idCheck e (DAggAnd a) = [DFunAp (DBinOp "!=" a) [e, DCExp (DCBool True a) a] a]
idCheck e (DAggOr a) = [DFunAp (DBinOp "!=" a) [e, DCExp (DCBool False a) a] a]
idCheck e _ = []

transIdElim :: (Show a) => DProgramSpec a -> DProgramSpec a
transIdElim = elimId

class ASTTraverse a b | a -> b where
  collectDPregel :: a -> [b]
  collectDPregel _ = []

type DPregelStepArg a = (DFun a, DTermination a)

instance ASTTraverse (DProgramSpec a) (DPregelStepArg a) where
  collectDPregel (DProgramSpec _ prog _) = collectDPregel prog

instance ASTTraverse (DProg a) (DPregelStepArg a) where
  collectDPregel (DProg f gdefs gexpr _) =
    concatMap collectDPregel gdefs ++ collectDPregel gexpr

instance ASTTraverse (DGroundDef a) (DPregelStepArg a) where
  collectDPregel (DGDefGV gv _) = collectDPregel gv
  collectDPregel (DGDefGF gf _) = collectDPregel gf
  collectDPregel _ = []

instance ASTTraverse (DDefGraphVar a) (DPregelStepArg a) where
  collectDPregel (DDefGraphVar _ gexpr _) = collectDPregel gexpr

instance ASTTraverse (DDefGraphFun a) (DPregelStepArg a) where
  collectDPregel (DDefGraphFun _ _ gvs gexpr _) =
    concatMap collectDPregel gvs ++ collectDPregel gexpr

instance ASTTraverse (DGraphExpr a) (DPregelStepArg a) where
  collectDPregel (DPregel initfn stepfn term gexpr _) =
    (stepfn, term) : collectDPregel gexpr
  collectDPregel (DGMap _ gexpr _) = collectDPregel gexpr
  collectDPregel (DGZip gexpr1 gexpr2 _) =
    collectDPregel gexpr1 ++ collectDPregel gexpr2
  collectDPregel (DGIter _ _ _ gexpr _) = collectDPregel gexpr
  collectDPregel _ = []

dPregelStepArg :: String -> [DPregelStepArg a] -> Maybe (DTermination a)
dPregelStepArg name [] = Nothing
dPregelStepArg name ((DFun step _, term) : ds) =
  if name == step then Just term else dPregelStepArg name ds
dPregelStepArg name (_:ds) = dPregelStepArg name ds

isDPregelFixStepArg :: String -> [DPregelStepArg a] -> Bool
isDPregelFixStepArg name [] = False
isDPregelFixStepArg name ((DFun step _, DTermF _) : ds) =
  if name == step then True else isDPregelFixStepArg name ds
isDPregelFixStepArg name ((DFun step _, _) : ds) =
  if name == step then False else isDPregelFixStepArg name ds
isDPregelFixStepArg name (_:ds) = isDPregelFixStepArg name ds

collectDConstr :: DExpr a -> [DConstructor a]
collectDConstr (DIf e1 e2 e3 _) = collectDConstr e2 ++ collectDConstr e3
collectDConstr (DConsAp con es _) = [con]
collectDConstr _ = []

collectDependDSmplDef :: DSmplDef a -> [String]
collectDependDSmplDef (DDefFun f vars locals exp _) =
  collectDependLE (getNames f) vars locals exp

collectDependDSmplDef (DDefVar v locals exp _) =
  collectDependLE [] [v] locals exp

collectDependDSmplDef (DDefTuple vars locals exp _) =
  collectDependLE [] vars locals exp

collectDependLE :: [String] -> [DVar a] -> [DSmplDef a] -> DExpr a -> [String]
collectDependLE names vars locals exp =
  removeDup (freevs0 ++ freevs1)
  where boundvs = names ++ concatMap getNames vars ++ concatMap getNames locals
        freevs0 = removeDep boundvs (concatMap collectDependDSmplDef locals)
        freevs1 = removeDep boundvs (collectDependDExpr exp)

collectDependDExpr :: DExpr a -> [String]
collectDependDExpr (DIf e1 e2 e3 _) = concatMap collectDependDExpr [e1,e2,e3]
collectDependDExpr (DTuple es _) = concatMap collectDependDExpr es
collectDependDExpr (DFunAp fn es _) = concatMap collectDependDExpr es
collectDependDExpr (DConsAp con es _) = concatMap collectDependDExpr es
collectDependDExpr (DAggr ag e gen es _) = concatMap collectDependDExpr (e:es)
collectDependDExpr (DCheckTerm e _) = collectDependDExpr e
collectDependDExpr (DVExp v a) = getNames v
collectDependDExpr _ = []

removeDep :: (Eq a) => [a] -> [a] -> [a]
removeDep names deps = foldr delete deps names

removeDup :: (Eq a) => [a] -> [a]
removeDup [] = []
removeDup (x:xs) = x : delete x (removeDup xs)

transCommElim :: DGroundDef a -> DGroundDef a
transCommElim x = x

transInactivate :: DGroundDef a -> DGroundDef a
transInactivate = id

-- The following code is developed by Morihata

{-
transCommElim :: DProgramSpec a -> DProgramSpec a
transCommElim (DProgramSpec (r:rs) p a) = 
    let (con, flds, r') = transDataDecl r 
    in DProgramSpec (r' : rs) (transProg (con,flds) p) a

transDataDecl (DRecordSpec con flds a) = 
    let DField _ a' = fst (head flds)
    in (con, flds, 
        DRecordSpec con ((DField "__changed" a', DTBool a') : flds) a)

transProg con (DProg a defs b c) = DProg a (map (transDef con) defs) b c

transDef con (DGDefVI (DDefVertInit f defs  expr b) c) 
    = (DGDefVI (DDefVertInit f (map (transLet con False) defs) 
                                 (transExpr con False expr) b) c) 
transDef con (DGDefSmpl sd a) = DGDefSmpl (transLet con False sd) a
transDef con (DGDefVC (DDefVertComp f ldefs expr a) b) 
    = (DGDefVC (DDefVertComp f (map (transLet con True) ldefs) 
                                 (transExpr con True expr) a) b) 
transDef c a = a

transLet c flg (DDefFun f vars defs expr a) = 
    DDefFun f vars (map (transLet c flg) defs) (transExpr c flg expr) a
transLet c flg (DDefVar v defs expr a) = 
    DDefVar v (map (transLet c flg) defs) (transExpr c flg expr) a

transExpr c flg (DIf e1 e2 e3 a) = 
    DIf (transExpr c flg e1) (transExpr c flg e2) (transExpr c flg e3) a
transExpr c flg (DFunAp f exprs a) = 
    DFunAp f (map (transExpr c flg) exprs) a
transExpr c@(con,flds) flg (DConsAp con' exprs a) = 
    let exprs' = map (transExpr c flg) exprs
        equiv (DConstructor a _) (DConstructor b _) = a == b
    in if equiv con' con 
       then if flg 
            then let anyOf = foldr1 (\p r-> DFunAp (DBinOp "||" a) [p,r] a) 
                     preds = zipWith chkEq exprs' flds 
                     chkEq e (f,t) = DFunAp (DBinOp "==" a) 
                                     [e, DFieldAcc (DPrev (DVar "v" a) a) [f] a] a
                 in DConsAp con (anyOf preds : exprs') a
            else DConsAp con (DCExp (DCBool True a) a : exprs') a 
       else DConsAp con exprs' a
transExpr c flg  (DAggr agop e1 ge e2 a) = 
    let comChk = DFieldAcc (DPrev (DVar "u" a) a) [DField "__changed" a] a
    in DAggr agop e1 ge (comChk : e2) a
transExpr c flg a = a

transInactivate (DProgramSpec rs (DProg a defs expr c) d) = 
   (DProgramSpec rs (DProg a defs (transFregel expr) c) d)

transFregel (DPregel init step (DTermF a) expr b)  = 
    DPregel init step (DTermV2H a) expr b
-}