packages feed

fregel-1.2.0: compiler/Spec.lhs

> {-# LANGUAGE FlexibleContexts,FlexibleInstances,MultiParamTypeClasses,FunctionalDependencies #-}

> module Spec where
> import Control.Monad.State
> import Data.List


BNF of the DSL (ver 1.0p2)


position of let-bindings is limited.

Program specification is I/O type definitions and a program body

  ProgramSpec := RecordSpec* Prog
  RecordSpec := 'data' Constructor '=' Constructor '{' Field '::' Type (',' Field '::' Type )* '}' 'deriving' '(' 'Eq' ',' 'Show' ')'
   -- simple version Constructor '{' Field '::' Type (',' Field '::' Type )* '}'
   -- not runnable in Haskell, though

> data DProgramSpec a = DProgramSpec [DRecordSpec a] (DProg a) a deriving (Show, Eq)
> data DRecordSpec a = DRecordSpec (DConstructor a) [(DField a, DType a)] a deriving (Show, Eq)

  
A program body is a graph function with ground definitions.
The argument is 'g'!  (this will be used in all global aggregations)

  Prog := Fun 'g' '=' 'let' GroundDefs 'in' GraphExpr
  GroundDefs := GroundDef (';' GraphDef)*    -- not indentation-based

> data DProg a = DProg (DFun a) [DGroundDef a] (DGraphExpr a) a deriving (Show, Eq)

A ground definition can contain definitions of vertex-compute functions.
A vertex-compute function receives two special tables Prev and Curr.

  GroundDef := DefVertComp | DefVertInit | DefGraphFun | DefGraphVar | SmplDef 
  DefVertComp := Fun 'v' 'prev' 'curr' '=' (Expr | 'let' SmplDefs 'in' Expr) 
  DefVertInit := Fun 'v' '=' (Expr | 'let' SmplDefs 'in' Expr) 
  DefGraphVar := Var '=' GraphExpr
  DefGraphFun := Fun Var '=' (GraphExpr | 'let' DefGraphVars 'in' GraphExpr)

> data DGroundDef a = DGDefVC (DDefVertComp a) a
>                   | DGDefVI (DDefVertInit a) a
>                   | DGDefGV (DDefGraphVar a) a
>                   | DGDefGF (DDefGraphFun a) a
>                   | DGDefSmpl (DSmplDef a) a 
>                    deriving (Show, Eq)
> data DDefVertComp a = DDefVertComp (DFun a) [DSmplDef a] (DExpr a) a deriving (Show, Eq)
> data DDefVertInit a = DDefVertInit (DFun a) [DSmplDef a] (DExpr a) a deriving (Show, Eq)
> data DDefGraphVar a = DDefGraphVar (DVar a) (DGraphExpr a) a deriving (Show, Eq)
> data DDefGraphFun a = DDefGraphFun (DFun a) (DVar a) [DDefGraphVar a] (DGraphExpr a) a deriving (Show, Eq)

A graph expression is made by 'pregel', 'gmap', 'gzip', 'giter', ... and restricted 'let' expressions.
-- pregel can be invoked on a variable and not on an expression

  GraphExpr := 'fregel' Fun Fun Termination Var
             | 'gmap' Fun Var
             | 'gzip' Var Var
             | 'giter' Fun Fun Termination Var
             | Var
  Termination := 'Fix'
               | '(' 'Iter' Expr ')'
               | '(' 'UntilAny' PredVExpr ')'
               | '(' 'UntilAll' PredVExpr ')'
               | '(' 'Until' PredExpr ')'
               | '(' 'While' PredExpr ')'
               | '(' Termination ')'

  UltilAny, UntilAll, While are replaced with Until + aux.
  
  PredExpr := '(' '\' 'g' '->' Expr ')'  # "\g->" is necessary to be run on Haskell
  PredVExpr := '(' '\' 'v' '->' Expr ')' # "\v->" is necessary to be run on Haskell
  DefGraphVars := DefGraphVar (';' DefGraphVar)*     -- not indentation-based

> data DGraphExpr a = DPregel (DFun a) (DFun a) (DTermination a) (DGraphExpr a) a -- (DVar a) a
>                   | DGMap (DFun a) (DGraphExpr a) a  -- (DVar a) a
>                   | DGZip (DGraphExpr a) (DGraphExpr a) a --(DVar a) (DVar a) a
>                   | DGIter (DFun a) (DFun a) (DTermination a) (DGraphExpr a) a -- (DVar a) a
>                   | DGVar (DVar a) a
>                    deriving (Show, Eq)
> data DTermination a = DTermF a
>                     | DTermI (DExpr a) a
>                     | DTermU (DExpr a) a
>                     | DTermV2H a           -- for internal use
>                      deriving (Show, Eq)

Definition of simple functions and variables (+ tuple binding).
(Is it necessary to distiguish these two?)

  SmplDef := DefFun | DefVar | DefTuple
  DefFun := Fun Var+ '=' (Expr | 'let' SmplDefs 'in' Expr)
  DefVar := Var '=' (Expr | 'let' SmplDefs 'in' Expr)
  DefTuple := '(' Var (',' Var)+ ')' '=' (Expr | 'let' SmplDefs 'in' Expr)
  SmplDefs := SmplDef (';' SmplDef)*             -- not indentation-based

> data DSmplDef a = DDefFun (DFun a) [DVar a] [DSmplDef a] (DExpr a) a
>                 | DDefVar (DVar a) [DSmplDef a] (DExpr a) a
>                 | DDefTuple [DVar a] [DSmplDef a] (DExpr a) a
>                  deriving (Show, Eq)

Expressions.
No anonimous function.
No let-expression ("let" is only allowed in the head of a function definition).

  Expr := If | Tuple | FunAp | Var | Const | FieldAccess | Aggr
        | '(' Expr ')'   -- this is for concrete syntax

  If := 'if' Expr 'then' Expr 'else' Expr
  Tuple := '(' Expr (',' Expr)+ ')'
  FunAp := Fun Expr+
         | Constructor Expr+
         | Expr '`' Fun '`' Expr
         | Expr BinOp Expr

  FieldAccess := (TableExpr | Edge ) (('.^' ('_fst' | '_snd'))* '.^' Field)?
  TableExpr := 'curr' Var | 'prev' Var | 'val' Var

Aggr := Agg '[' Expr '|' Gen (',' Expr )* ']'
      | Agg Expr '[' Expr '|' Gen (',' Expr )* ']'

  Edge := 'e'

  Gen := '(' 'e' ',' 'u' ')' '<-' 'is' 'v'
       | '(' 'e' ',' 'u' ')' '<-' 'rs' 'v'
       | 'u' '<-' 'g'   

> data DExpr a = DIf (DExpr a) (DExpr a) (DExpr a) a
>              | DTuple [DExpr a] a
>              | DFunAp (DFun a) [DExpr a] a
>              | DConsAp (DConstructor a) [DExpr a] a
>              | DFieldAcc (DTableExpr a) [DField a] a
>              | DFieldAccE (DEdge a) [DField a] a
>              | DAggr (DAgg a) (DExpr a) (DGen a) [DExpr a] a
>              | DCheckTerm (DExpr a) a -- Iwasaki: condition for termination
>              | DVExp (DVar a) a
>              | DCExp (DConst a) a
>              deriving (Show, Eq)
> data DGen a = DGenI a
>             | DGenO a
>             | DGenG a
>             | DGenTermG a  -- Iwasaki; aggregation for judging termination
>             deriving (Show, Eq)
> data DEdge a = DEdge a deriving (Show, Eq)
> data DTableExpr a = DPrev (DVar a) a
>                   | DCurr (DVar a) a
>                   | DVal (DVar a) a
>                   deriving (Show, Eq)

The identities must start with small letters or the underscore.
Prime symbols are allowed only at the end.

  BinOP := '+' | '-' | '*' | '/'
         | '==' | '!=' | '<' | '>' | '>=' | '<=' 
         | '&&' | '||'
  Agg := 'minimum' | 'maximum' | 'sum' | 'prod' | 'and' | 'or' | 'choice'
  Fun := [a-z_][a-zA-Z_0-9]*[']*
  Var := [a-z_][a-zA-Z_0-9]*[']*
  Field := [a-z_][a-zA-Z_0-9]*[']*
  Constructor := [A-Z][a-zA-Z_0-9]*[']*

> data DAgg a = DAggMin a
>             | DAggMax a
>             | DAggSum a
>             | DAggProd a
>             | DAggAnd a
>             | DAggOr a
>             | DAggChoice (DExpr a) a  -- random choice with default value
>             | DTupledAgg [DAgg a] a   -- for internal use
>               deriving (Show, Eq)
> data DConstructor a = DConstructor String a deriving (Show, Eq)
> data DFun a = DFun String a 
>             | DBinOp String a 
>               deriving (Show, Eq)
> data DVar a = DVar String a deriving (Show, Eq)
> data DField a = {- DFfst a | DFsnd a | -} DField String a deriving (Show, Eq)

Constants (integer, boolean, string, floating point number, ...)

 Const := Integer | Boolean | String | Double 

 Integer := '-'? ( [1-9][0-9]* | '0' )
 Boolean := 'True' | 'False'
 String  := '"' [^"]* '"'                  -- simple definition
 Double  := '-'? ( [1-9][0-9]* | '0' ) '.' [0-9]* 

> data DConst a = DCInt Int a 
>               | DCBool Bool a 
>               | DCString String a
>               | DCDouble Double a
>                 deriving (Show, Eq)

Types of each component in the I/O records.

 Type := 'Int' | 'Bool' | 'String' | 'Double' | '(' Type (',' Type)* ')'

> data DType a = DTInt a
>             | DTBool a
>             | DTString a
>             | DTDouble a
>             | DTTuple [DType a] a
>             | DTRecord (DConstructor a) [DType a] a  -- for internal use
>               deriving (Show, Eq)

------------------------- pretty printer? ------------------

> ppList :: String -> [String] -> String
> ppList c ss = foldr (\(s, c) r -> c ++ s ++ r) "" $ zip ss ("":repeat c)

> ppProgramSpec :: DProgramSpec a -> [String]
> ppProgramSpec (DProgramSpec rs p _) =
>   (concatMap ppRecordSpec rs) ++ ppProg p

> ppRecordSpec :: DRecordSpec a -> [String]
> ppRecordSpec (DRecordSpec c fts _) =
>   ["data " ++ ppConstructor c ++ " = " ++ ppConstructor c ++ "{" ++ ppfts ++ "} deriving (Eq, Show)"]
>   where ppfts = ppList ", " (map (\(f, t) -> ppField f++"::"++ppType t) fts)

> indentWith :: String -> [String] -> [String]
> indentWith s (l:ls) = (s++l) :map ((map (const ' ') s)++) ls
> indentWith s ([]) = []

> indent :: [String] -> [String]
> indent ls = indentWith "  " ls

> ppProg :: DProg a -> [String]
> ppProg (DProg f ds e _) = [ppFun f ++ " g = "] ++ rest
>   where rest = if length ds == 0 then indent (ppGraphExpr e)
>                else indent $ let_in (concat $ insList ";" "" $ map ppGroundDef ds) (ppGraphExpr e)

> let_in :: [String] -> [String] -> [String]
> let_in ds e = indentWith "let " ds ++ indentWith "in " e

> ppGroundDef :: DGroundDef a -> [String]
> ppGroundDef (DGDefVC d _) = ppDefVertComp d
> ppGroundDef (DGDefVI d _) = ppDefVertInit d
> ppGroundDef (DGDefGV d _) = ppDefGraphVar d 
> ppGroundDef (DGDefGF d _) = ppDefGraphFun d
> ppGroundDef (DGDefSmpl d _) = ppSmplDef d

> ppDefVertComp :: DDefVertComp a -> [String]
> ppDefVertComp (DDefVertComp f ds e _) =
>   if length ds == 0 then indentWith (ppFun f ++ " v prev curr = ") (ppExpr e)
>   else [ppFun f ++" v prev curr = "] ++ indent (let_in (concat $ insList ";" "" $map ppSmplDef ds) (ppExpr e))

> ppDefVertInit :: DDefVertInit a -> [String]
> ppDefVertInit (DDefVertInit f ds e _) =
>   if length ds == 0 then indentWith (ppFun f ++ " v = ") (ppExpr e)
>   else [ppFun f ++" v = "] ++ indent (let_in (concat $ insList ";" "" $map ppSmplDef ds) (ppExpr e))

> ppDefGraphVar :: DDefGraphVar a -> [String]
> ppDefGraphVar (DDefGraphVar v e _) =
>   indentWith (ppVar v ++ " = ") (ppGraphExpr e)
>   

> ppDefGraphFun :: DDefGraphFun a -> [String]
> ppDefGraphFun (DDefGraphFun f v ds e _) =
>   if length ds == 0
>   then header ++ indent (ppGraphExpr e)
>   else header ++ indent (let_in (concat $ insList ";" "" $ map ppDefGraphVar ds) (ppGraphExpr e))
>   where header = [ ppFun f ++ " " ++ (ppVar v) ++ " = " ]

> ppGraphExpr :: DGraphExpr a -> [String]  -- this is a singleton list (of String)
> ppGraphExpr (DPregel f0 ft t g _) =
>   [ppList " " (["fregel", ppFun f0, ppFun ft, ppTermination t] ++ (addParen $ ppGraphExpr g))]
> ppGraphExpr (DGMap f g _) =
>   [ppList " " (["gmap", ppFun f] ++ (addParen $ ppGraphExpr g))]
> ppGraphExpr (DGZip g1 g2 _) =
>   [ppList " " (["gzip"] ++ (addParen $ ppGraphExpr g1) ++ (addParen $ ppGraphExpr g2))]
> ppGraphExpr (DGIter f0 ft t g _) =
>   [ppList " " (["giter", ppFun f0, ppFun ft, ppTermination t] ++ (addParen $ ppGraphExpr g))]
> ppGraphExpr (DGVar g _) = 
>   [ppVar g]
> addParen [s] = ["(" ++ s ++ ")"]

> ppTermination :: DTermination a -> String
> ppTermination (DTermF _)= "Fix"
> ppTermination (DTermI e _) = "(Iter (" ++ ppList " " (ppExpr e) ++ "))"
> ppTermination (DTermU e _) = "(Until (\\g->" ++ ppList " " (ppExpr e) ++ "))"
> ppTermination (DTermV2H _) = "V2H"

> ppSmplDef :: DSmplDef a -> [String]
> ppSmplDef (DDefFun f vs ds e _) =
>   if length ds == 0
>   then header ++ indent (ppExpr e)
>   else header ++ indent (let_in (concat $ insList ";" "" $map ppSmplDef ds) (ppExpr e))
>   where header = [ ppFun f ++ " " ++ ppList " " (map ppVar vs) ++ " = " ]
> ppSmplDef (DDefVar v ds e _) = 
>   if length ds == 0
>   then header ++ indent (ppExpr e)
>   else header ++ indent (let_in (concat $ insList ";" "" $map ppSmplDef ds) (ppExpr e))
>   where header = [ ppVar v ++ " = "]
> ppSmplDef (DDefTuple vs ds e _) = 
>   if length ds == 0
>   then header ++ indent (ppExpr e)
>   else header ++ indent (let_in (concat $ insList ";" "" $map ppSmplDef ds) (ppExpr e))
>   where header = ["(" ++ ppList ", " (map ppVar vs) ++ ") = "]

> ppExpr :: DExpr a-> [String]
> ppExpr (DIf c t e _) = indentWith "if " (ppExpr c) ++
>                        indentWith "then " (ppExpr t) ++
>                        indentWith "else " (ppExpr e)
> ppExpr (DTuple es _) = indentWith "(" (concat $ insList "," ")" $ map ppExpr es)
> ppExpr (DFunAp (DBinOp o _) (e1:e2:[]) _) = [flatE e1 ++ " " ++ o ++ " " ++ flatE e2]
> ppExpr (DFunAp f es _) = [ppList " " (ppFun f: map flatE es)]
> ppExpr (DConsAp c es _) = [ppList " " (ppConstructor c: map flatE es)]
> ppExpr (DFieldAcc e fs _) = [ ppTableExpr e ++ (concat $ map ((".^"++).ppField) fs) ]
> ppExpr (DFieldAccE e fs _) = [ ppEdge e ++ (concat $ map ((".^"++).ppField) fs) ]
> ppExpr (DAggr a e g es _) =
>   [ppAgg a ++ " [ " ++ flatE2 e ++  " | " ++ ppGen g ++ ps ++ " ] "]
>   where ps = if length es == 0 then ""
>              else "," ++ ppList "," (map flatE es)
> ppExpr (DVExp v _) = [ppVar v]
> ppExpr (DCExp c _) = [ppConst c]

> ppTableExpr (DPrev v _) = "prev " ++ ppVar v
> ppTableExpr (DCurr v _) = "curr " ++ ppVar v
> ppTableExpr (DVal v _) = "val " ++ ppVar v

> ppEdge (DEdge _) = "e"

> ppAgg (DAggMin _)  = "minimum"
> ppAgg (DAggMax _)  = "maximum"
> ppAgg (DAggSum _)  = "sum"
> ppAgg (DAggProd _) = "prod"
> ppAgg (DAggAnd _)  = "and"
> ppAgg (DAggOr _)   = "or"
> ppAgg (DAggChoice x _) = "random " ++ flatE x

> ppGen (DGenI _) = "(e, u) <- is v"
> ppGen (DGenO _) = "(e, u) <- rs v"
> ppGen (DGenG _) = "u <- g"
> ppGen (DGenTermG _) = "u <- g"

> flatE :: DExpr a -> String
> flatE = enclose . ppList " " . ppExpr

> flatE2 :: DExpr a -> String
> flatE2 = ppList " " . ppExpr

> enclose :: String -> String
> enclose s = "(" ++ s ++ ")"

> insList :: String -> String -> [[String]] -> [[String]]
> insList c cl sss = map (\(ss, s) -> init ss ++ ((last ss++s):[])) $ reverse $ zip (reverse sss) (cl:repeat c)

> ppField (DField f _) = f
> -- ppField (DFfst _) = "_fst"
> -- ppField (DFsnd _) = "_snd"
> ppFun (DFun f _) = f
> ppFun (DBinOp f _) = "(" ++ f ++ ")"
> ppVar (DVar v _) = v
> ppType (DTInt _) = "Int"
> ppType (DTBool _) = "Bool"
> ppType (DTString _) = "String"
> ppType (DTDouble _) = "Double"
> ppType (DTTuple ts _) = "(" ++ ppList ", " (map ppType ts) ++ ")"
> ppType (DTRecord c [] _) = getName c
> ppType (DTRecord c ts _) = "(" ++ getName c ++ concatMap (" "++) (map ppType ts) ++ ")"
> ppConstructor (DConstructor c _) = c

> ppConst (DCInt i _) = show i
> ppConst (DCBool b _) = show b
> ppConst (DCString s _) = "\"" ++ s ++ "\""
> ppConst (DCDouble d _) = show d



> ppAST :: DProgramSpec a -> String
> ppAST = unlines . ppProgramSpec

> right (Right a) = a
> right (Left a) = error $ show a


> class PrettyShow a where
>     prettyShow :: a -> String

> flattening = removeMultiSpace . ppList " "
> removeMultiSpace s = map fst $ filter (\(a, b) -> not (a == ' ' && b == ' ')) $ zip s ('@':init s)

> instance PrettyShow (DProgramSpec a) where
>     prettyShow = flattening . ppProgramSpec 

> instance PrettyShow (DTermination a) where
>     prettyShow = ppTermination

> instance PrettyShow (DDefGraphFun a) where
>     prettyShow = flattening . ppDefGraphFun

> instance PrettyShow (DDefGraphVar a) where
>     prettyShow = flattening . ppDefGraphVar

> instance PrettyShow (DRecordSpec a) where
>     prettyShow = flattening . ppRecordSpec 

> instance PrettyShow (DProg a) where
>     prettyShow = flattening . ppProg

> instance PrettyShow (DGroundDef a) where
>     prettyShow = flattening . ppGroundDef

> instance PrettyShow (DExpr a) where
>     prettyShow = flattening . ppExpr

> instance PrettyShow (DSmplDef a) where
>     prettyShow = flattening . ppSmplDef

> instance PrettyShow (DDefVertInit a) where
>     prettyShow = flattening . ppDefVertInit

> instance PrettyShow (DDefVertComp a) where
>     prettyShow = flattening . ppDefVertComp

> class DAdditionalData a b | a -> b where
>     getData :: a -> b
>     setData :: b -> a -> a

> instance DAdditionalData (DProgramSpec a) a where
>     getData (DProgramSpec _ _ a) = a
>     setData b (DProgramSpec rs p _) = DProgramSpec rs p b

> instance DAdditionalData (DRecordSpec a) a where
>     getData (DRecordSpec _ _ a) = a
>     setData b (DRecordSpec c fs _) = DRecordSpec c fs b
> instance DAdditionalData (DProg a) a where
>     getData (DProg _ _ _ a) = a
>     setData b (DProg f ds e _) = DProg f ds e b

> instance DAdditionalData (DGroundDef a) a where
>     getData (DGDefVC _ a) = a
>     getData (DGDefVI _ a) = a
>     getData (DGDefGV _ a) = a
>     getData (DGDefGF _ a) = a
>     getData (DGDefSmpl _ a) = a
>     setData b (DGDefVC x _) = DGDefVC x b
>     setData b (DGDefVI x _) = DGDefVI x b
>     setData b (DGDefGV x _) = DGDefGV x b
>     setData b (DGDefGF x _) = DGDefGF x b
>     setData b (DGDefSmpl x _) = DGDefSmpl x b

> instance DAdditionalData (DDefVertComp a) a where
>     getData (DDefVertComp _ _ _ a) = a
>     setData b (DDefVertComp f ds e _) = DDefVertComp f ds e b

> instance DAdditionalData (DDefVertInit a) a where
>     getData (DDefVertInit _ _ _ a) = a
>     setData b (DDefVertInit f ds e _) = DDefVertInit f ds e b

> instance DAdditionalData (DDefGraphVar a) a where
>     getData (DDefGraphVar _ _ a) = a
>     setData b (DDefGraphVar v e _) = DDefGraphVar v e b

> instance DAdditionalData (DDefGraphFun a) a where
>     getData (DDefGraphFun _ _ _  _ a) = a
>     setData b (DDefGraphFun f v ds e _) = DDefGraphFun f v ds e b

> instance DAdditionalData (DGraphExpr a) a where
>     getData (DPregel _ _ _ _ a) = a
>     getData (DGMap _ _ a) = a
>     getData (DGZip _ _ a) = a
>     getData (DGIter _ _ _ _ a) = a
>     getData (DGVar _ a) = a
>     setData b (DPregel f0 ft x g _) = DPregel f0 ft x g b
>     setData b (DGMap f g _) = DGMap f g b
>     setData b (DGZip g1 g2 _) = DGZip g1 g2 b
>     setData b (DGIter f0 ft x g _) = DGIter f0 ft x g b
>     setData b (DGVar g _) = DGVar g b

> instance DAdditionalData (DTermination a) a where
>     getData (DTermF a) = a
>     getData (DTermI _ a) = a
>     getData (DTermU _ a) = a
>     getData (DTermV2H a) = a
>     setData b (DTermF _) = DTermF b
>     setData b (DTermI e _) = DTermI e b
>     setData b (DTermU e _) = DTermU e b
>     setData b (DTermV2H _) = DTermV2H b

> instance DAdditionalData (DSmplDef a) a where
>     getData (DDefFun _ _ _ _ a) = a
>     getData (DDefVar _ _ _ a) = a
>     getData (DDefTuple _ _ _ a) = a
>     setData b (DDefFun f vs ds e _) = DDefFun f vs ds e b
>     setData b (DDefVar v ds e _) = DDefVar v ds e b
>     setData b (DDefTuple vs ds e _) = DDefTuple vs ds e b

> instance DAdditionalData (DExpr a) a where
>     getData (DIf _ _ _ a) = a
>     getData (DTuple _ a) = a
>     getData (DFunAp _ _ a) = a
>     getData (DConsAp _ _ a) = a
>     getData (DFieldAcc _ _ a) = a
>     getData (DFieldAccE _ _ a) = a
>     getData (DAggr _ _ _ _ a) = a
>     getData (DVExp _ a) = a
>     getData (DCExp _ a) = a
>     setData b (DIf p t e _) = DIf p t e b
>     setData b (DTuple es _) = DTuple es b
>     setData b (DFunAp f es _) = DFunAp f es b
>     setData b (DConsAp c es _) = DConsAp c es b
>     setData b (DFieldAcc t fs _) = DFieldAcc t fs b
>     setData b (DFieldAccE e fs _) = DFieldAccE e fs b
>     setData b (DAggr a e g es _) = DAggr a e g es b
>     setData b (DVExp v _) = DVExp v b
>     setData b (DCExp v _) = DCExp v b

> instance DAdditionalData (DGen a) a where
>     getData (DGenI a) = a
>     getData (DGenO a) = a
>     getData (DGenG a) = a
>     getData (DGenTermG a) = a
>     setData b (DGenI _) = DGenI b
>     setData b (DGenO _) = DGenO b
>     setData b (DGenG _) = DGenG b
>     setData b (DGenTermG _) = DGenTermG b

> instance DAdditionalData (DEdge a) a where
>     getData (DEdge a) = a
>     setData b (DEdge _) = DEdge b

> instance DAdditionalData (DTableExpr a) a where
>     getData (DPrev _ a) = a
>     getData (DCurr _ a) = a
>     getData (DVal _ a) = a
>     setData b (DPrev v _) = DPrev v b
>     setData b (DCurr v _) = DCurr v b
>     setData b (DVal v _) = DVal v b


> instance DAdditionalData (DAgg a) a where
>     getData (DAggMin a) = a
>     getData (DAggMax a) = a
>     getData (DAggSum a) = a
>     getData (DAggProd a) = a
>     getData (DAggAnd a) = a
>     getData (DAggOr a) = a
>     getData (DAggChoice x a) = a
>     getData (DTupledAgg _ a) = a
>     setData b (DAggMin _) = DAggMin b
>     setData b (DAggMax _) = DAggMax b
>     setData b (DAggSum _) = DAggSum b
>     setData b (DAggProd _) = DAggProd b
>     setData b (DAggAnd _) = DAggAnd b
>     setData b (DAggOr _) = DAggOr b
>     setData b (DAggChoice x _) = DAggChoice x b
>     setData b (DTupledAgg ags _) = DTupledAgg ags b

> instance DAdditionalData (DConstructor a) a where
>     getData (DConstructor _ a) = a
>     setData b (DConstructor c _) = DConstructor c b

> instance DAdditionalData (DFun a) a where
>     getData (DFun _ a) = a
>     getData (DBinOp _ a) = a
>     setData b (DFun f _) = DFun f b
>     setData b (DBinOp f _) = DBinOp f b

> instance DAdditionalData (DVar a) a where
>     getData (DVar _ a) = a
>     setData b (DVar v _) = DVar v b

> instance DAdditionalData (DField a) a where
>     -- getData (DFfst a) = a
>     -- getData (DFsnd a) = a
>     getData (DField _ a) = a
>     -- setData b (DFfst _) = DFfst b
>     -- setData b (DFsnd _) = DFsnd b
>     setData b (DField f _) = DField f b

> instance DAdditionalData (DConst a) a where
>     getData (DCInt _ a) = a
>     getData (DCBool _ a) = a
>     getData (DCString _ a) = a
>     getData (DCDouble _ a) = a
>     setData b (DCInt c _) = DCInt c b
>     setData b (DCBool c _) = DCBool c b
>     setData b (DCString c _) = DCString c b
>     setData b (DCDouble c _) = DCDouble c b

> instance DAdditionalData (DType a) a where
>     getData (DTInt a) = a
>     getData (DTBool a) = a
>     getData (DTString a) = a
>     getData (DTDouble a) = a
>     getData (DTTuple _ a) = a
>     getData (DTRecord _ _ a) = a
>     setData b (DTInt _) = DTInt b
>     setData b (DTBool _) = DTBool b
>     setData b (DTString _) = DTString b
>     setData b (DTDouble _) = DTDouble b
>     setData b (DTTuple ts _) = DTTuple ts b
>     setData b (DTRecord c fs _) = DTRecord c fs b

> getName :: (DNamed a) => a -> String
> getName = head . getNames

> class DNamed a where
>     getNames :: a -> [String]
>     setNames :: a -> State [String] a

> nextName :: State [String] String
> nextName = do xs <- get; put (tail xs); return (head xs)

> instance DNamed (DFun a) where
>     getNames (DFun f _) = [f]
>     getNames (DBinOp f _) = [f]
>     setNames (DFun _ a) = 
>         do n <- nextName
>            return (DFun n a)
>     setNames (DBinOp _ a) = 
>         do n <- nextName
>            return (DFun n a)

> instance DNamed (DField a) where
>     getNames (DField f _) = [f]
>     setNames (DField _ a) = 
>         do n <- nextName
>            return (DField n a)

> instance DNamed (DVar a) where
>     getNames (DVar f _) = [f]
>     setNames (DVar _ a) = 
>         do n <- nextName
>            return (DVar n a)

> instance DNamed (DConstructor a) where
>     getNames (DConstructor c _) = [c]
>     setNames (DConstructor _ a) = 
>         do n <- nextName
>            return (DConstructor n a)

> instance DNamed (DRecordSpec a) where
>     getNames (DRecordSpec c fts _) = getNames c ++ concatMap getNames (map fst fts)
>     setNames (DRecordSpec c fts a) = 
>         do c' <- setNames c
>            fs' <- mapM setNames (map fst fts)
>            let fts' = zipWith (\ft f -> (f, snd ft)) fts fs'
>            return (DRecordSpec c' fts' a)

> instance DNamed (DGroundDef a) where
>     getNames (DGDefVI d _) = getNames d
>     getNames (DGDefVC d _) = getNames d
>     getNames (DGDefGV d _) = getNames d
>     getNames (DGDefGF d _) = getNames d
>     getNames (DGDefSmpl d _) = getNames d
>     setNames (DGDefVI d a) = do d' <- setNames d; return (DGDefVI d' a)
>     setNames (DGDefVC d a) = do d' <- setNames d; return (DGDefVC d' a)
>     setNames (DGDefGV d a) = do d' <- setNames d; return (DGDefGV d' a)
>     setNames (DGDefGF d a) = do d' <- setNames d; return (DGDefGF d' a)
>     setNames (DGDefSmpl d a) = do d' <- setNames d; return (DGDefSmpl d' a)

> instance DNamed (DProgramSpec a) where
>     getNames (DProgramSpec _ p _) = getNames p
>     setNames (DProgramSpec rs p a) = do p' <- setNames p; return (DProgramSpec rs p' a)

> instance DNamed (DProg a) where
>     getNames (DProg f _ _ _) = getNames f
>     setNames (DProg f ds e a) = do f' <- setNames f; return (DProg f' ds e a)

> instance DNamed (DDefVertComp a) where
>     getNames (DDefVertComp f _ _ _) = getNames f
>     setNames (DDefVertComp f ds e a) = do f' <- setNames f; return (DDefVertComp f' ds e a)

> instance DNamed (DDefVertInit a) where
>     getNames (DDefVertInit f _ _ _) = getNames f
>     setNames (DDefVertInit f ds e a) = do f' <- setNames f; return (DDefVertInit f' ds e a)

> instance DNamed (DDefGraphVar a) where
>     getNames (DDefGraphVar v _ _) = getNames v
>     setNames (DDefGraphVar v e a) = do v' <- setNames v; return (DDefGraphVar v' e a)

> instance DNamed (DDefGraphFun a) where
>     getNames (DDefGraphFun f _ _ _ _) = getNames f
>     setNames (DDefGraphFun f vs ds e a) = do f' <- setNames f; return (DDefGraphFun f' vs ds e a)

> instance DNamed (DSmplDef a) where
>     getNames (DDefFun f _ _ _ _) = getNames f
>     getNames (DDefVar v _ _ _) = getNames v
>     getNames (DDefTuple vs _ _ _) = concatMap getNames vs
>     setNames (DDefFun f vs ds e a) = do f' <- setNames f; return (DDefFun f' vs ds e a)
>     setNames (DDefVar v ds e a) = do v' <- setNames v; return (DDefVar v' ds e a)
>     setNames (DDefTuple vs ds e a) = do vs' <- mapM setNames vs; return (DDefTuple vs' ds e a)

> instance DNamed (DGen a) where
>     getNames (DGenI _) = ["e", "u"]
>     getNames (DGenO _) = ["e", "u"]
>     getNames (DGenG _) = ["u"]
>     getNames (DGenTermG _) = ["u"]
>     setNames (DGenI a) = do nextName; nextName; return (DGenI a)
>     setNames (DGenO a) = do nextName; nextName; return (DGenO a)
>     setNames (DGenG a) = do nextName; return (DGenG a)
>     setNames (DGenTermG a) = do nextName; return (DGenTermG a)


> mmapData f = map (mapData f)

> class DAdditionalData2 a b c d | a c -> b d where
>     mapData :: (b -> c) -> a -> d

> instance DAdditionalData2 (DProgramSpec a) a c (DProgramSpec c) where
>     mapData f (DProgramSpec rs p a) = DProgramSpec (mmapData f rs) (mapData f p) (f a)

> instance DAdditionalData2 (DRecordSpec a) a c (DRecordSpec c) where
>     mapData f (DRecordSpec c fs a) = DRecordSpec (mapData f c) fs' (f a)
>                                      where fs' = zip (mmapData f $ map fst fs) (mmapData f $ map snd fs)
> instance DAdditionalData2 (DProg a) a c (DProg c) where
>     mapData f (DProg f' ds e a) = DProg (mapData f f') (mmapData f ds) (mapData f e) (f a)

> instance DAdditionalData2 (DGroundDef a) a c (DGroundDef c) where
>     mapData f (DGDefVI x a) = DGDefVI (mapData f x) (f a)
>     mapData f (DGDefVC x a) = DGDefVC (mapData f x) (f a)
>     mapData f (DGDefGV x a) = DGDefGV (mapData f x) (f a)
>     mapData f (DGDefGF x a) = DGDefGF (mapData f x) (f a)
>     mapData f (DGDefSmpl x a) = DGDefSmpl (mapData f x) (f a)

> instance DAdditionalData2 (DDefVertComp a) a c (DDefVertComp c) where
>     mapData f (DDefVertComp f' ds e a) = DDefVertComp (mapData f f') (mmapData f ds) (mapData f e) (f a)

> instance DAdditionalData2 (DDefVertInit a) a c (DDefVertInit c) where
>     mapData f (DDefVertInit f' ds e a) = DDefVertInit (mapData f f') (mmapData f ds) (mapData f e) (f a)

> instance DAdditionalData2 (DDefGraphVar a) a c (DDefGraphVar c) where
>     mapData f (DDefGraphVar v e a) = DDefGraphVar (mapData f v) (mapData f e) (f a)

> instance DAdditionalData2 (DDefGraphFun a) a c (DDefGraphFun c) where
>     mapData f (DDefGraphFun f' v ds e a) = DDefGraphFun (mapData f f') (mapData f v) (mmapData f ds) (mapData f e) (f a)

> instance DAdditionalData2 (DGraphExpr a) a c (DGraphExpr c) where
>     mapData f (DPregel f0 ft x g a) = DPregel (mapData f f0) (mapData f ft) (mapData f x) (mapData f g) (f a)
>     mapData f (DGMap f' g a) = DGMap (mapData f f') (mapData f g) (f a)
>     mapData f (DGZip g1 g2 a) = DGZip (mapData f g1) (mapData f g2) (f a)
>     mapData f (DGIter f0 ft x g a) = DGIter (mapData f f0) (mapData f ft) (mapData f x) (mapData f g) (f a)
>     mapData f (DGVar g a) = DGVar (mapData f g) (f a)

> instance DAdditionalData2 (DTermination a) a c (DTermination c) where
>     mapData f (DTermF a) = DTermF (f a)
>     mapData f (DTermI e a) = DTermI (mapData f e) (f a)
>     mapData f (DTermU e a) = DTermU (mapData f e) (f a)
>     mapData f (DTermV2H a) = DTermV2H (f a)

> instance DAdditionalData2 (DSmplDef a) a c (DSmplDef c) where
>     mapData f (DDefFun f' vs ds e a) = DDefFun (mapData f f') (mmapData f vs) (mmapData f ds) (mapData f e) (f a)
>     mapData f (DDefVar v ds e a) = DDefVar (mapData f v) (mmapData f ds) (mapData f e) (f a)
>     mapData f (DDefTuple vs ds e a) = DDefTuple (mmapData f vs) (mmapData f ds) (mapData f e) (f a)

> instance DAdditionalData2 (DExpr a) a c (DExpr c) where
>     mapData f (DIf p t e a) = DIf (mapData f p) (mapData f t) (mapData f e) (f a)
>     mapData f (DTuple es a) = DTuple (mmapData f es) (f a)
>     mapData f (DFunAp f' es a) = DFunAp (mapData f f') (mmapData f es) (f a)
>     mapData f (DConsAp c es a) = DConsAp (mapData f c) (mmapData f es) (f a)
>     mapData f (DFieldAcc t fs a) = DFieldAcc (mapData f t) (mmapData f fs) (f a)
>     mapData f (DFieldAccE e fs a) = DFieldAccE (mapData f e) (mmapData f fs) (f a)
>     mapData f (DAggr a' e g es a) = DAggr (mapData f a') (mapData f e) (mapData f g) (mmapData f es) (f a)
>     mapData f (DVExp v a) = DVExp (mapData f v) (f a)
>     mapData f (DCExp v a) = DCExp (mapData f v) (f a)

> instance DAdditionalData2 (DGen a) a c (DGen c) where
>     mapData f (DGenI a) = DGenI (f a)
>     mapData f (DGenO a) = DGenO (f a)
>     mapData f (DGenG a) = DGenG (f a)
>     mapData f (DGenTermG a) = DGenTermG (f a)

> instance DAdditionalData2 (DEdge a) a c (DEdge c) where
>     mapData f (DEdge a) = DEdge (f a)

> instance DAdditionalData2 (DTableExpr a) a c (DTableExpr c) where
>     mapData f (DPrev v a) = DPrev (mapData f v) (f a)
>     mapData f (DCurr v a) = DCurr (mapData f v) (f a)
>     mapData f (DVal v a) = DVal (mapData f v) (f a)


> instance DAdditionalData2 (DAgg a) a c (DAgg c) where
>     mapData f (DAggMin a) = DAggMin (f a)
>     mapData f (DAggMax a) = DAggMax (f a)
>     mapData f (DAggSum a) = DAggSum (f a)
>     mapData f (DAggProd a) = DAggProd (f a)
>     mapData f (DAggAnd a) = DAggAnd (f a)
>     mapData f (DAggOr a) = DAggOr (f a)
>     mapData f (DAggChoice x a) = DAggChoice (mapData f x) (f a)
>     mapData f (DTupledAgg ags a) = DTupledAgg (mmapData f ags) (f a)

> instance DAdditionalData2 (DConstructor a) a c (DConstructor c) where
>     mapData f (DConstructor c a) = DConstructor c (f a)

> instance DAdditionalData2 (DFun a) a c (DFun c) where
>     mapData f (DFun f' a) = DFun f' (f a)
>     mapData f (DBinOp f' a) = DBinOp f' (f a)

> instance DAdditionalData2 (DVar a) a c (DVar c) where
>     mapData f (DVar v a) = DVar v (f a)

> instance DAdditionalData2 (DField a) a c (DField c) where
>     -- mapData f (DFfst a) = DFfst (f a)
>     -- mapData f (DFsnd a) = DFsnd (f a)
>     mapData f (DField f' a) = DField f' (f a)

> instance DAdditionalData2 (DConst a) a c (DConst c) where
>     mapData f (DCInt c a) = DCInt c (f a)
>     mapData f (DCBool c a) = DCBool c (f a)
>     mapData f (DCString c a) = DCString c (f a)
>     mapData f (DCDouble c a) = DCDouble c (f a)

> instance DAdditionalData2 (DType a) a c (DType c) where
>     mapData f (DTInt a) = DTInt (f a)
>     mapData f (DTBool a) = DTBool (f a)
>     mapData f (DTString a) = DTString (f a)
>     mapData f (DTDouble a) = DTDouble (f a)
>     mapData f (DTTuple ts a) = DTTuple (mmapData f ts) (f a)
>     mapData f (DTRecord c fs a) = DTRecord (mapData f c) (mmapData f fs) (f a)


generaing all subexpressions of the given one

> subExprs :: DExpr a -> [DExpr a]
> subExprs (x@(DIf p t e _)) = x : (subExprs p ++ subExprs t ++ subExprs e)
> subExprs (x@(DTuple es _)) = x : concatMap subExprs es
> subExprs (x@(DFunAp f es _)) = x : concatMap subExprs es
> subExprs (x@(DConsAp c es _)) = x : concatMap subExprs es
> subExprs (x@(DFieldAcc t fs a)) = map (\fs -> DFieldAcc t fs (case fs of [] -> getData t ; otherwise -> getData (last fs))) (reverse $ inits fs) ++ [DVExp v va]
>                                   where v = getTableVar t
>                                         va = getData v
> subExprs (x@(DFieldAccE e fs a)) = map (\fs -> DFieldAccE e fs (case fs of [] -> getData e ; otherwise -> getData (last fs))) (reverse $ inits fs) 
> subExprs (x@(DAggr a e g es _)) = x:subExprs e ++ concatMap subExprs es
> subExprs (x@(DVExp v _)) = [x]
> subExprs (x@(DCExp v _)) = [x]
> getTableVar (DPrev v a) = v
> getTableVar (DCurr v a) = v
> getTableVar (DVal v a) = v


Expression builders

> dd = "" -- dummy data
> 
> expIf p t e = DIf p t e dd
> 
> expBin bop e1 e2 = DFunAp (DBinOp bop dd) [e1, e2] dd
> 
> expFieldAcc tbl v fs = DFieldAcc te (map (\f -> DField f dd) fs) dd
>   where te | tbl == "prev" = DPrev (DVar v dd) dd
>            | tbl == "curr" = DCurr (DVar v dd) dd
>            | tbl == "val"  = DVal  (DVar v dd) dd
> 
> expConstructor c es = DConsAp (DConstructor c dd) es dd
> expConstructor' c es ac a = DConsAp (DConstructor c ac) es a
>
> expFun f es = DFunAp (DFun f dd) es dd
>
> expInt i = DCExp (DCInt i dd) dd
> expBool b = DCExp (DCBool b dd) dd
>
> expVar v = DVExp (DVar v dd) dd
> 
> expAggr agg body gen ps = DAggr agg' body gen' ps dd
>   where agg' | agg == "minimum" = DAggMin dd
>              | agg == "maximum" = DAggMax dd
>              | agg == "sum"     = DAggSum dd
>              | agg == "prod"    = DAggProd dd
>              | agg == "and"     = DAggAnd dd
>              | agg == "or"      = DAggOr dd
>         gen' | gen == "g"       = DGenG dd
>              | gen == "tg"      = DGenTermG dd
>              | gen == "is"      = DGenI dd
>              | gen == "rs"      = DGenO dd
> 
> expCheckTerm v = DCheckTerm (expVar v) dd
>
> defVar v defs e = DDefVar (DVar v dd) defs e dd
>
> defFun f vs defs e = DDefFun (DFun f dd) (map (\v -> DVar v dd) vs) defs e dd
>
> defVertComp f defs e = DDefVertComp (DFun f dd) defs e dd
>
> (^==) = expBin "=="
> (^&&) = expBin "&&"
> (^>) = expBin ">"