{- |
Module      :  ./CSL/Fold.hs
Description :  folding functions for CSL terms and commands
Copyright   :  (c) Ewaryst.Schulz, DFKI 2010
License     :  GPLv2 or higher, see LICENSE.txt

Maintainer  :  Ewaryst.Schulz@dfki.de
Stability   :  provisional
Portability :  portable

folding functions for CSL terms and commands

-}

module CSL.Fold where

import Common.Id
import CSL.AS_BASIC_CSL (EXPRESSION (..), CMD (..), OpDecl, EXTPARAM , APInt, APFloat, OPID)

data Record a b = Record
    { Record a b -> CMD -> OpDecl -> b -> a
foldAss :: CMD -> OpDecl -> b -> a
    , Record a b -> CMD -> String -> [b] -> a
foldCmd :: CMD -> String -> [b] -> a
    , Record a b -> CMD -> [a] -> a
foldSequence :: CMD -> [a] -> a
    , Record a b -> CMD -> [(b, [a])] -> a
foldCond :: CMD -> [(b, [a])] -> a
    , Record a b -> CMD -> b -> [a] -> a
foldRepeat :: CMD -> b -> [a] -> a

    , Record a b -> EXPRESSION -> Token -> b
foldVar :: EXPRESSION -> Token -> b
    , Record a b -> EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
foldOp :: EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
    , Record a b -> EXPRESSION -> [b] -> Range -> b
foldList :: EXPRESSION -> [b] -> Range -> b
    , Record a b -> EXPRESSION -> Double -> Double -> Range -> b
foldInterval :: EXPRESSION -> Double -> Double -> Range -> b
    , Record a b -> EXPRESSION -> APInt -> Range -> b
foldInt :: EXPRESSION -> APInt -> Range -> b
    , Record a b -> EXPRESSION -> APFloat -> Range -> b
foldRat :: EXPRESSION -> APFloat -> Range -> b
    }

{- | Produces an error with given message on all entries. Use this if you
overwrite only the EXPRESSION part and you do not use the CMD part anyway
, e.g., if you use the record in foldTerm -}
emptyRecord :: String -> Record a b
emptyRecord :: String -> Record a b
emptyRecord s :: String
s =
    Record :: forall a b.
(CMD -> OpDecl -> b -> a)
-> (CMD -> String -> [b] -> a)
-> (CMD -> [a] -> a)
-> (CMD -> [(b, [a])] -> a)
-> (CMD -> b -> [a] -> a)
-> (EXPRESSION -> Token -> b)
-> (EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b)
-> (EXPRESSION -> [b] -> Range -> b)
-> (EXPRESSION -> Double -> Double -> Range -> b)
-> (EXPRESSION -> APInt -> Range -> b)
-> (EXPRESSION -> APFloat -> Range -> b)
-> Record a b
Record { foldAss :: CMD -> OpDecl -> b -> a
foldAss = String -> CMD -> OpDecl -> b -> a
forall a. HasCallStack => String -> a
error String
s
           , foldCmd :: CMD -> String -> [b] -> a
foldCmd = String -> CMD -> String -> [b] -> a
forall a. HasCallStack => String -> a
error String
s
           , foldSequence :: CMD -> [a] -> a
foldSequence = String -> CMD -> [a] -> a
forall a. HasCallStack => String -> a
error String
s
           , foldCond :: CMD -> [(b, [a])] -> a
foldCond = String -> CMD -> [(b, [a])] -> a
forall a. HasCallStack => String -> a
error String
s
           , foldRepeat :: CMD -> b -> [a] -> a
foldRepeat = String -> CMD -> b -> [a] -> a
forall a. HasCallStack => String -> a
error String
s

           , foldVar :: EXPRESSION -> Token -> b
foldVar = String -> EXPRESSION -> Token -> b
forall a. HasCallStack => String -> a
error String
s
           , foldOp :: EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
foldOp = String -> EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
forall a. HasCallStack => String -> a
error String
s
           , foldList :: EXPRESSION -> [b] -> Range -> b
foldList = String -> EXPRESSION -> [b] -> Range -> b
forall a. HasCallStack => String -> a
error String
s
           , foldInterval :: EXPRESSION -> Double -> Double -> Range -> b
foldInterval = String -> EXPRESSION -> Double -> Double -> Range -> b
forall a. HasCallStack => String -> a
error String
s
           , foldInt :: EXPRESSION -> APInt -> Range -> b
foldInt = String -> EXPRESSION -> APInt -> Range -> b
forall a. HasCallStack => String -> a
error String
s
           , foldRat :: EXPRESSION -> APFloat -> Range -> b
foldRat = String -> EXPRESSION -> APFloat -> Range -> b
forall a. HasCallStack => String -> a
error String
s
           }

-- | The identity transformation
idRecord :: Record CMD EXPRESSION
idRecord :: Record CMD EXPRESSION
idRecord =
    Record :: forall a b.
(CMD -> OpDecl -> b -> a)
-> (CMD -> String -> [b] -> a)
-> (CMD -> [a] -> a)
-> (CMD -> [(b, [a])] -> a)
-> (CMD -> b -> [a] -> a)
-> (EXPRESSION -> Token -> b)
-> (EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b)
-> (EXPRESSION -> [b] -> Range -> b)
-> (EXPRESSION -> Double -> Double -> Range -> b)
-> (EXPRESSION -> APInt -> Range -> b)
-> (EXPRESSION -> APFloat -> Range -> b)
-> Record a b
Record { foldAss :: CMD -> OpDecl -> EXPRESSION -> CMD
foldAss = \ v :: CMD
v _ _ -> CMD
v
           , foldCmd :: CMD -> String -> [EXPRESSION] -> CMD
foldCmd = \ v :: CMD
v _ _ -> CMD
v
           , foldSequence :: CMD -> [CMD] -> CMD
foldSequence = CMD -> [CMD] -> CMD
forall a b. a -> b -> a
const
           , foldCond :: CMD -> [(EXPRESSION, [CMD])] -> CMD
foldCond = CMD -> [(EXPRESSION, [CMD])] -> CMD
forall a b. a -> b -> a
const
           , foldRepeat :: CMD -> EXPRESSION -> [CMD] -> CMD
foldRepeat = \ v :: CMD
v _ _ -> CMD
v

           , foldVar :: EXPRESSION -> Token -> EXPRESSION
foldVar = EXPRESSION -> Token -> EXPRESSION
forall a b. a -> b -> a
const
           , foldOp :: EXPRESSION
-> OPID -> [EXTPARAM] -> [EXPRESSION] -> Range -> EXPRESSION
foldOp = \ v :: EXPRESSION
v _ _ _ _ -> EXPRESSION
v
           , foldList :: EXPRESSION -> [EXPRESSION] -> Range -> EXPRESSION
foldList = \ v :: EXPRESSION
v _ _ -> EXPRESSION
v
           , foldInterval :: EXPRESSION -> Double -> Double -> Range -> EXPRESSION
foldInterval = \ v :: EXPRESSION
v _ _ _ -> EXPRESSION
v
           , foldInt :: EXPRESSION -> APInt -> Range -> EXPRESSION
foldInt = \ v :: EXPRESSION
v _ _ -> EXPRESSION
v
           , foldRat :: EXPRESSION -> APFloat -> Range -> EXPRESSION
foldRat = \ v :: EXPRESSION
v _ _ -> EXPRESSION
v
           }

{- | Passes the transformation through the CMD part and is the identity
on the EXPRESSION part -}
passRecord :: Record CMD EXPRESSION
passRecord :: Record CMD EXPRESSION
passRecord =
    Record CMD EXPRESSION
idRecord { foldAss :: CMD -> OpDecl -> EXPRESSION -> CMD
foldAss = (OpDecl -> EXPRESSION -> CMD) -> CMD -> OpDecl -> EXPRESSION -> CMD
forall a b. a -> b -> a
const OpDecl -> EXPRESSION -> CMD
Ass
             , foldCmd :: CMD -> String -> [EXPRESSION] -> CMD
foldCmd = (String -> [EXPRESSION] -> CMD)
-> CMD -> String -> [EXPRESSION] -> CMD
forall a b. a -> b -> a
const String -> [EXPRESSION] -> CMD
Cmd
             , foldSequence :: CMD -> [CMD] -> CMD
foldSequence = ([CMD] -> CMD) -> CMD -> [CMD] -> CMD
forall a b. a -> b -> a
const [CMD] -> CMD
Sequence
             , foldCond :: CMD -> [(EXPRESSION, [CMD])] -> CMD
foldCond = ([(EXPRESSION, [CMD])] -> CMD)
-> CMD -> [(EXPRESSION, [CMD])] -> CMD
forall a b. a -> b -> a
const [(EXPRESSION, [CMD])] -> CMD
Cond
             , foldRepeat :: CMD -> EXPRESSION -> [CMD] -> CMD
foldRepeat = (EXPRESSION -> [CMD] -> CMD) -> CMD -> EXPRESSION -> [CMD] -> CMD
forall a b. a -> b -> a
const EXPRESSION -> [CMD] -> CMD
Repeat
             }

-- | Passes the transformation through both, the CMD and the EXPRESSION part
passAllRecord :: Record CMD EXPRESSION
passAllRecord :: Record CMD EXPRESSION
passAllRecord =
    Record CMD EXPRESSION
passRecord { foldVar :: EXPRESSION -> Token -> EXPRESSION
foldVar = (Token -> EXPRESSION) -> EXPRESSION -> Token -> EXPRESSION
forall a b. a -> b -> a
const Token -> EXPRESSION
Var
               , foldOp :: EXPRESSION
-> OPID -> [EXTPARAM] -> [EXPRESSION] -> Range -> EXPRESSION
foldOp = (OPID -> [EXTPARAM] -> [EXPRESSION] -> Range -> EXPRESSION)
-> EXPRESSION
-> OPID
-> [EXTPARAM]
-> [EXPRESSION]
-> Range
-> EXPRESSION
forall a b. a -> b -> a
const OPID -> [EXTPARAM] -> [EXPRESSION] -> Range -> EXPRESSION
Op
               , foldList :: EXPRESSION -> [EXPRESSION] -> Range -> EXPRESSION
foldList = ([EXPRESSION] -> Range -> EXPRESSION)
-> EXPRESSION -> [EXPRESSION] -> Range -> EXPRESSION
forall a b. a -> b -> a
const [EXPRESSION] -> Range -> EXPRESSION
List
               , foldInterval :: EXPRESSION -> Double -> Double -> Range -> EXPRESSION
foldInterval = (Double -> Double -> Range -> EXPRESSION)
-> EXPRESSION -> Double -> Double -> Range -> EXPRESSION
forall a b. a -> b -> a
const Double -> Double -> Range -> EXPRESSION
Interval
               , foldInt :: EXPRESSION -> APInt -> Range -> EXPRESSION
foldInt = (APInt -> Range -> EXPRESSION)
-> EXPRESSION -> APInt -> Range -> EXPRESSION
forall a b. a -> b -> a
const APInt -> Range -> EXPRESSION
Int
               , foldRat :: EXPRESSION -> APFloat -> Range -> EXPRESSION
foldRat = (APFloat -> Range -> EXPRESSION)
-> EXPRESSION -> APFloat -> Range -> EXPRESSION
forall a b. a -> b -> a
const APFloat -> Range -> EXPRESSION
Rat
               }

{- | Passes the transformation through the 'CMD' part by concatenating the
processed list from left to right and identity on expression part -}
listCMDRecord :: Record [a] EXPRESSION
listCMDRecord :: Record [a] EXPRESSION
listCMDRecord =
    Record CMD EXPRESSION
idRecord { foldAss :: CMD -> OpDecl -> EXPRESSION -> [a]
foldAss = \ _ _ _ -> []
             , foldCmd :: CMD -> String -> [EXPRESSION] -> [a]
foldCmd = \ _ _ _ -> []
             , foldSequence :: CMD -> [[a]] -> [a]
foldSequence = ([[a]] -> [a]) -> CMD -> [[a]] -> [a]
forall a b. a -> b -> a
const [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
             , foldCond :: CMD -> [(EXPRESSION, [[a]])] -> [a]
foldCond = \ _ -> [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[a]] -> [a])
-> ([(EXPRESSION, [[a]])] -> [[a]]) -> [(EXPRESSION, [[a]])] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((EXPRESSION, [[a]]) -> [[a]]) -> [(EXPRESSION, [[a]])] -> [[a]]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (EXPRESSION, [[a]]) -> [[a]]
forall a b. (a, b) -> b
snd
             , foldRepeat :: CMD -> EXPRESSION -> [[a]] -> [a]
foldRepeat = \ _ _ -> [[a]] -> [a]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
             }

{- | Returns the first constant on the CMD part and the second
on the EXPRESSION part -}
constRecord :: a -> b -> Record a b
constRecord :: a -> b -> Record a b
constRecord a :: a
a b :: b
b =
    Record :: forall a b.
(CMD -> OpDecl -> b -> a)
-> (CMD -> String -> [b] -> a)
-> (CMD -> [a] -> a)
-> (CMD -> [(b, [a])] -> a)
-> (CMD -> b -> [a] -> a)
-> (EXPRESSION -> Token -> b)
-> (EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b)
-> (EXPRESSION -> [b] -> Range -> b)
-> (EXPRESSION -> Double -> Double -> Range -> b)
-> (EXPRESSION -> APInt -> Range -> b)
-> (EXPRESSION -> APFloat -> Range -> b)
-> Record a b
Record { foldAss :: CMD -> OpDecl -> b -> a
foldAss = \ _ _ _ -> a
a
           , foldCmd :: CMD -> String -> [b] -> a
foldCmd = \ _ _ _ -> a
a
           , foldSequence :: CMD -> [a] -> a
foldSequence = \ _ _ -> a
a
           , foldCond :: CMD -> [(b, [a])] -> a
foldCond = \ _ _ -> a
a
           , foldRepeat :: CMD -> b -> [a] -> a
foldRepeat = \ _ _ _ -> a
a

           , foldVar :: EXPRESSION -> Token -> b
foldVar = \ _ _ -> b
b
           , foldOp :: EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
foldOp = \ _ _ _ _ _ -> b
b
           , foldList :: EXPRESSION -> [b] -> Range -> b
foldList = \ _ _ _ -> b
b
           , foldInterval :: EXPRESSION -> Double -> Double -> Range -> b
foldInterval = \ _ _ _ _ -> b
b
           , foldInt :: EXPRESSION -> APInt -> Range -> b
foldInt = \ _ _ _ -> b
b
           , foldRat :: EXPRESSION -> APFloat -> Range -> b
foldRat = \ _ _ _ -> b
b
           }

foldCMD :: Record a b -> CMD -> a
foldCMD :: Record a b -> CMD -> a
foldCMD r :: Record a b
r f :: CMD
f = case CMD
f of
   Ass c :: OpDecl
c def :: EXPRESSION
def -> Record a b -> CMD -> OpDecl -> b -> a
forall a b. Record a b -> CMD -> OpDecl -> b -> a
foldAss Record a b
r CMD
f OpDecl
c (b -> a) -> b -> a
forall a b. (a -> b) -> a -> b
$ Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r EXPRESSION
def
   Cmd s :: String
s l :: [EXPRESSION]
l -> Record a b -> CMD -> String -> [b] -> a
forall a b. Record a b -> CMD -> String -> [b] -> a
foldCmd Record a b
r CMD
f String
s ([b] -> a) -> [b] -> a
forall a b. (a -> b) -> a -> b
$ (EXPRESSION -> b) -> [EXPRESSION] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r) [EXPRESSION]
l
   Sequence l :: [CMD]
l -> Record a b -> CMD -> [a] -> a
forall a b. Record a b -> CMD -> [a] -> a
foldSequence Record a b
r CMD
f ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ (CMD -> a) -> [CMD] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> CMD -> a
forall a b. Record a b -> CMD -> a
foldCMD Record a b
r) [CMD]
l
   Cond l :: [(EXPRESSION, [CMD])]
l -> Record a b -> CMD -> [(b, [a])] -> a
forall a b. Record a b -> CMD -> [(b, [a])] -> a
foldCond Record a b
r CMD
f ([(b, [a])] -> a) -> [(b, [a])] -> a
forall a b. (a -> b) -> a -> b
$ ((EXPRESSION, [CMD]) -> (b, [a]))
-> [(EXPRESSION, [CMD])] -> [(b, [a])]
forall a b. (a -> b) -> [a] -> [b]
map (EXPRESSION, [CMD]) -> (b, [a])
cf [(EXPRESSION, [CMD])]
l where
                     cf :: (EXPRESSION, [CMD]) -> (b, [a])
cf (x :: EXPRESSION
x, y :: [CMD]
y) = (Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r EXPRESSION
x, (CMD -> a) -> [CMD] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> CMD -> a
forall a b. Record a b -> CMD -> a
foldCMD Record a b
r) [CMD]
y)
   Repeat c :: EXPRESSION
c l :: [CMD]
l -> Record a b -> CMD -> b -> [a] -> a
forall a b. Record a b -> CMD -> b -> [a] -> a
foldRepeat Record a b
r CMD
f (Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r EXPRESSION
c) ([a] -> a) -> [a] -> a
forall a b. (a -> b) -> a -> b
$ (CMD -> a) -> [CMD] -> [a]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> CMD -> a
forall a b. Record a b -> CMD -> a
foldCMD Record a b
r) [CMD]
l

foldTerm :: Record a b -> EXPRESSION -> b
foldTerm :: Record a b -> EXPRESSION -> b
foldTerm r :: Record a b
r t :: EXPRESSION
t = case EXPRESSION
t of
    Var tok :: Token
tok -> Record a b -> EXPRESSION -> Token -> b
forall a b. Record a b -> EXPRESSION -> Token -> b
foldVar Record a b
r EXPRESSION
t Token
tok
    Op s :: OPID
s epl :: [EXTPARAM]
epl al :: [EXPRESSION]
al rg :: Range
rg -> Record a b -> EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
forall a b.
Record a b -> EXPRESSION -> OPID -> [EXTPARAM] -> [b] -> Range -> b
foldOp Record a b
r EXPRESSION
t OPID
s [EXTPARAM]
epl ((EXPRESSION -> b) -> [EXPRESSION] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r) [EXPRESSION]
al) Range
rg
    List l :: [EXPRESSION]
l rg :: Range
rg -> Record a b -> EXPRESSION -> [b] -> Range -> b
forall a b. Record a b -> EXPRESSION -> [b] -> Range -> b
foldList Record a b
r EXPRESSION
t ((EXPRESSION -> b) -> [EXPRESSION] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map (Record a b -> EXPRESSION -> b
forall a b. Record a b -> EXPRESSION -> b
foldTerm Record a b
r) [EXPRESSION]
l) Range
rg
    Interval from :: Double
from to :: Double
to rg :: Range
rg -> Record a b -> EXPRESSION -> Double -> Double -> Range -> b
forall a b.
Record a b -> EXPRESSION -> Double -> Double -> Range -> b
foldInterval Record a b
r EXPRESSION
t Double
from Double
to Range
rg
    Int i :: APInt
i rg :: Range
rg -> Record a b -> EXPRESSION -> APInt -> Range -> b
forall a b. Record a b -> EXPRESSION -> APInt -> Range -> b
foldInt Record a b
r EXPRESSION
t APInt
i Range
rg
    Rat f :: APFloat
f rg :: Range
rg -> Record a b -> EXPRESSION -> APFloat -> Range -> b
forall a b. Record a b -> EXPRESSION -> APFloat -> Range -> b
foldRat Record a b
r EXPRESSION
t APFloat
f Range
rg