Changed the C/C++ backends to read GenOps from a reader-monad rather than passing the ops around (rough draft)
This commit is contained in:
parent
ecf4ceee35
commit
df832b450d
|
@ -17,7 +17,7 @@ with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
-- | Generate C code from the mangled AST.
|
-- | Generate C code from the mangled AST.
|
||||||
module GenerateC (call, CGen, cgenOps, cintroduceSpec, genComma, genCPasses, generate, generateC, genLeftB, genMeta, genName, genRightB, GenOps(..), indexOfFreeDimensions, seqComma, SubscripterFunction, withIf ) where
|
module GenerateC (call, CGen, CGen', cgenOps, cintroduceSpec, fget, genComma, genCPasses, generate, generateC, genLeftB, genMeta, genName, genRightB, GenOps(..), indexOfFreeDimensions, seqComma, SubscripterFunction, withIf ) where
|
||||||
|
|
||||||
import Data.Char
|
import Data.Char
|
||||||
import Data.Generics
|
import Data.Generics
|
||||||
|
@ -25,6 +25,7 @@ import Data.List
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
import Control.Monad.Error
|
import Control.Monad.Error
|
||||||
|
import Control.Monad.Reader
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
import Control.Monad.Writer
|
import Control.Monad.Writer
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
@ -52,7 +53,8 @@ genCPasses =
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
--{{{ monad definition
|
--{{{ monad definition
|
||||||
type CGen = WriterT [String] PassM
|
type CGen' = WriterT [String] PassM
|
||||||
|
type CGen = ReaderT GenOps CGen'
|
||||||
|
|
||||||
instance Die CGen where
|
instance Die CGen where
|
||||||
dieReport = throwError
|
dieReport = throwError
|
||||||
|
@ -175,8 +177,50 @@ data GenOps = GenOps {
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Call an operation in GenOps.
|
-- | Call an operation in GenOps.
|
||||||
|
{-
|
||||||
call :: (GenOps -> GenOps -> t) -> GenOps -> t
|
call :: (GenOps -> GenOps -> t) -> GenOps -> t
|
||||||
call f ops = f ops ops
|
call f ops = f ops ops
|
||||||
|
-}
|
||||||
|
|
||||||
|
class CGenCall a where
|
||||||
|
call :: (GenOps -> GenOps -> a) -> GenOps -> a
|
||||||
|
|
||||||
|
instance CGenCall (a -> CGen z) where
|
||||||
|
-- call :: (GenOps -> GenOps -> a -> CGen b) -> a -> CGen b
|
||||||
|
call f _ x0 = do ops <- ask
|
||||||
|
f ops ops x0
|
||||||
|
|
||||||
|
instance CGenCall (a -> b -> CGen z) where
|
||||||
|
call f _ x0 x1
|
||||||
|
= do ops <- ask
|
||||||
|
f ops ops x0 x1
|
||||||
|
|
||||||
|
instance CGenCall (a -> b -> c -> CGen z) where
|
||||||
|
call f _ x0 x1 x2
|
||||||
|
= do ops <- ask
|
||||||
|
f ops ops x0 x1 x2
|
||||||
|
|
||||||
|
instance CGenCall (a -> b -> c -> d -> CGen z) where
|
||||||
|
call f _ x0 x1 x2 x3
|
||||||
|
= do ops <- ask
|
||||||
|
f ops ops x0 x1 x2 x3
|
||||||
|
|
||||||
|
instance CGenCall (a -> b -> c -> d -> e -> CGen z) where
|
||||||
|
call f _ x0 x1 x2 x3 x4
|
||||||
|
= do ops <- ask
|
||||||
|
f ops ops x0 x1 x2 x3 x4
|
||||||
|
|
||||||
|
-- A bit of a mind-boggler, but this is essentially for genSlice
|
||||||
|
instance CGenCall (a -> b -> c -> d -> (CGen x, y -> CGen z)) where
|
||||||
|
call f _ x0 x1 x2 x3
|
||||||
|
= (do ops <- ask
|
||||||
|
fst $ f ops ops x0 x1 x2 x3
|
||||||
|
,\y -> do ops <- ask
|
||||||
|
(snd $ f ops ops x0 x1 x2 x3) y
|
||||||
|
)
|
||||||
|
|
||||||
|
fget :: (GenOps -> a) -> CGen a
|
||||||
|
fget = asks
|
||||||
|
|
||||||
-- | Operations for the C backend.
|
-- | Operations for the C backend.
|
||||||
cgenOps :: GenOps
|
cgenOps :: GenOps
|
||||||
|
@ -264,9 +308,7 @@ cgenOps = GenOps {
|
||||||
|
|
||||||
--{{{ top-level
|
--{{{ top-level
|
||||||
generate :: GenOps -> A.AST -> PassM String
|
generate :: GenOps -> A.AST -> PassM String
|
||||||
generate ops ast
|
generate ops ast = execWriterT (runReaderT (call genTopLevel undefined ast) ops) >>* concat
|
||||||
= do (a, out) <- runWriterT (call genTopLevel ops ast)
|
|
||||||
return $ concat out
|
|
||||||
|
|
||||||
generateC :: A.AST -> PassM String
|
generateC :: A.AST -> PassM String
|
||||||
generateC = generate cgenOps
|
generateC = generate cgenOps
|
||||||
|
@ -415,7 +457,8 @@ cgenType _ (A.Chan _ _ t) = tell ["Channel*"]
|
||||||
cgenType ops t@(A.List {}) = tell [subRegex (mkRegex "[^A-Za-z0-9]") (show t) ""]
|
cgenType ops t@(A.List {}) = tell [subRegex (mkRegex "[^A-Za-z0-9]") (show t) ""]
|
||||||
|
|
||||||
cgenType ops t
|
cgenType ops t
|
||||||
= case call getScalarType ops t of
|
= do f <- fget getScalarType
|
||||||
|
case f ops t of
|
||||||
Just s -> tell [s]
|
Just s -> tell [s]
|
||||||
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
||||||
|
|
||||||
|
@ -456,7 +499,8 @@ cgenBytesIn ops m t v
|
||||||
call genType ops t
|
call genType ops t
|
||||||
tell [")"]
|
tell [")"]
|
||||||
genBytesIn' ops t
|
genBytesIn' ops t
|
||||||
= case call getScalarType ops t of
|
= do f <- fget getScalarType
|
||||||
|
case f ops t of
|
||||||
Just s -> tell ["sizeof(", s, ")"]
|
Just s -> tell ["sizeof(", s, ")"]
|
||||||
Nothing -> diePC m $ formatCode "genBytesIn' %" t
|
Nothing -> diePC m $ formatCode "genBytesIn' %" t
|
||||||
|
|
||||||
|
@ -886,7 +930,8 @@ cgenSizeSuffix _ dim = tell ["_sizes[", dim, "]"]
|
||||||
|
|
||||||
cgenTypeSymbol :: GenOps -> String -> A.Type -> CGen ()
|
cgenTypeSymbol :: GenOps -> String -> A.Type -> CGen ()
|
||||||
cgenTypeSymbol ops s t
|
cgenTypeSymbol ops s t
|
||||||
= case call getScalarType ops t of
|
= do f <- fget getScalarType
|
||||||
|
case f ops t of
|
||||||
Just ct -> tell ["occam_", s, "_", ct]
|
Just ct -> tell ["occam_", s, "_", ct]
|
||||||
Nothing -> call genMissingC ops $ formatCode "genTypeSymbol %" t
|
Nothing -> call genMissingC ops $ formatCode "genTypeSymbol %" t
|
||||||
|
|
||||||
|
@ -1297,7 +1342,8 @@ cdeclareInit ops m t@(A.Array ds t') var _
|
||||||
sequence_ $ intersperse (tell ["*"]) [case dim of A.Dimension d -> tell [show d] | dim <- ds]
|
sequence_ $ intersperse (tell ["*"]) [case dim of A.Dimension d -> tell [show d] | dim <- ds]
|
||||||
tell [");"]
|
tell [");"]
|
||||||
_ -> return ()
|
_ -> return ()
|
||||||
init <- return (\sub -> call declareInit ops m t' (sub var) Nothing)
|
fdeclareInit <- fget declareInit
|
||||||
|
init <- return (\sub -> fdeclareInit ops m t' (sub var) Nothing)
|
||||||
call genOverArray ops m var init
|
call genOverArray ops m var init
|
||||||
cdeclareInit ops m rt@(A.Record _) var _
|
cdeclareInit ops m rt@(A.Record _) var _
|
||||||
= Just $ do fs <- recordFields m rt
|
= Just $ do fs <- recordFields m rt
|
||||||
|
@ -1311,8 +1357,10 @@ cdeclareInit ops m rt@(A.Record _) var _
|
||||||
call genSizeSuffix ops (show i)
|
call genSizeSuffix ops (show i)
|
||||||
tell ["=", show n, ";"]
|
tell ["=", show n, ";"]
|
||||||
| (i, A.Dimension n) <- zip [0..(length ds - 1)] ds]
|
| (i, A.Dimension n) <- zip [0..(length ds - 1)] ds]
|
||||||
doMaybe $ call declareInit ops m t v Nothing
|
fdeclareInit <- fget declareInit
|
||||||
initField t v = doMaybe $ call declareInit ops m t v Nothing
|
doMaybe $ fdeclareInit ops m t v Nothing
|
||||||
|
initField t v = do fdeclareInit <- fget declareInit
|
||||||
|
doMaybe $ fdeclareInit ops m t v Nothing
|
||||||
cdeclareInit ops m _ v (Just e)
|
cdeclareInit ops m _ v (Just e)
|
||||||
= Just $ call genAssign ops m [v] $ A.ExpressionList m [e]
|
= Just $ call genAssign ops m [v] $ A.ExpressionList m [e]
|
||||||
cdeclareInit _ _ _ _ _ = Nothing
|
cdeclareInit _ _ _ _ _ = Nothing
|
||||||
|
@ -1339,7 +1387,8 @@ CHAN OF INT c IS d: Channel *c = d;
|
||||||
cintroduceSpec :: GenOps -> A.Specification -> CGen ()
|
cintroduceSpec :: GenOps -> A.Specification -> CGen ()
|
||||||
cintroduceSpec ops (A.Specification m n (A.Declaration _ t init))
|
cintroduceSpec ops (A.Specification m n (A.Declaration _ t init))
|
||||||
= do call genDeclaration ops t n False
|
= do call genDeclaration ops t n False
|
||||||
case call declareInit ops m t (A.Variable m n) init of
|
fdeclareInit <- fget declareInit
|
||||||
|
case fdeclareInit ops m t (A.Variable m n) init of
|
||||||
Just p -> p
|
Just p -> p
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
cintroduceSpec ops (A.Specification _ n (A.Is _ am t v))
|
cintroduceSpec ops (A.Specification _ n (A.Is _ am t v))
|
||||||
|
@ -1452,7 +1501,8 @@ cgenForwardDeclaration _ _ = return ()
|
||||||
|
|
||||||
cremoveSpec :: GenOps -> A.Specification -> CGen ()
|
cremoveSpec :: GenOps -> A.Specification -> CGen ()
|
||||||
cremoveSpec ops (A.Specification m n (A.Declaration _ t _))
|
cremoveSpec ops (A.Specification m n (A.Declaration _ t _))
|
||||||
= case call declareFree ops m t var of
|
= do fdeclareFree <- fget declareFree
|
||||||
|
case fdeclareFree ops m t var of
|
||||||
Just p -> p
|
Just p -> p
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
where
|
where
|
||||||
|
@ -1537,7 +1587,8 @@ cgenProcess ops p = case p of
|
||||||
cgenAssign :: GenOps -> Meta -> [A.Variable] -> A.ExpressionList -> CGen ()
|
cgenAssign :: GenOps -> Meta -> [A.Variable] -> A.ExpressionList -> CGen ()
|
||||||
cgenAssign ops m [v] (A.ExpressionList _ [e])
|
cgenAssign ops m [v] (A.ExpressionList _ [e])
|
||||||
= do t <- typeOfVariable v
|
= do t <- typeOfVariable v
|
||||||
case call getScalarType ops t of
|
f <- fget getScalarType
|
||||||
|
case f ops t of
|
||||||
Just _ -> doAssign v e
|
Just _ -> doAssign v e
|
||||||
Nothing -> case t of
|
Nothing -> case t of
|
||||||
-- Assignment of channel-ends, but not channels, is possible (at least in Rain):
|
-- Assignment of channel-ends, but not channels, is possible (at least in Rain):
|
||||||
|
|
|
@ -584,7 +584,8 @@ cppgenArraySizesLiteral ops n t@(A.Array ds _) =
|
||||||
-- | Changed because we initialise channels and arrays differently in C++
|
-- | Changed because we initialise channels and arrays differently in C++
|
||||||
cppdeclareInit :: GenOps -> Meta -> A.Type -> A.Variable -> Maybe A.Expression -> Maybe (CGen ())
|
cppdeclareInit :: GenOps -> Meta -> A.Type -> A.Variable -> Maybe A.Expression -> Maybe (CGen ())
|
||||||
cppdeclareInit ops m t@(A.Array ds t') var _
|
cppdeclareInit ops m t@(A.Array ds t') var _
|
||||||
= Just $ do init <- return (\sub -> call declareInit ops m t' (sub var) Nothing)
|
= Just $ do fdeclareInit <- fget declareInit
|
||||||
|
init <- return (\sub -> fdeclareInit ops m t' (sub var) Nothing)
|
||||||
call genOverArray ops m var init
|
call genOverArray ops m var init
|
||||||
case t' of
|
case t' of
|
||||||
A.Chan A.DirUnknown _ _ ->
|
A.Chan A.DirUnknown _ _ ->
|
||||||
|
@ -610,8 +611,10 @@ cppdeclareInit ops m rt@(A.Record _) var _
|
||||||
tell ["_actual,tockDims("]
|
tell ["_actual,tockDims("]
|
||||||
infixComma [tell [show n] | (A.Dimension n) <- ds]
|
infixComma [tell [show n] | (A.Dimension n) <- ds]
|
||||||
tell ["));"]
|
tell ["));"]
|
||||||
doMaybe $ call declareInit ops m t v Nothing
|
fdeclareInit <- fget declareInit
|
||||||
initField t v = doMaybe $ call declareInit ops m t v Nothing
|
doMaybe $ fdeclareInit ops m t v Nothing
|
||||||
|
initField t v = do fdeclareInit <- fget declareInit
|
||||||
|
doMaybe $ fdeclareInit ops m t v Nothing
|
||||||
cppdeclareInit ops m _ v (Just e)
|
cppdeclareInit ops m _ v (Just e)
|
||||||
= Just $ call genAssign ops m [v] $ A.ExpressionList m [e]
|
= Just $ call genAssign ops m [v] $ A.ExpressionList m [e]
|
||||||
cppdeclareInit _ _ _ _ _ = Nothing
|
cppdeclareInit _ _ _ _ _ = Nothing
|
||||||
|
@ -623,7 +626,8 @@ cppdeclareFree _ _ _ _ = Nothing
|
||||||
-- | Changed to work properly with declareFree to free channel arrays.
|
-- | Changed to work properly with declareFree to free channel arrays.
|
||||||
cppremoveSpec :: GenOps -> A.Specification -> CGen ()
|
cppremoveSpec :: GenOps -> A.Specification -> CGen ()
|
||||||
cppremoveSpec ops (A.Specification m n (A.Declaration _ t _))
|
cppremoveSpec ops (A.Specification m n (A.Declaration _ t _))
|
||||||
= do case call declareFree ops m t var of
|
= do fdeclareFree <- fget declareFree
|
||||||
|
case fdeclareFree ops m t var of
|
||||||
Just p -> p
|
Just p -> p
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
where
|
where
|
||||||
|
@ -916,7 +920,8 @@ cppgenType ops (A.Mobile t@(A.List {})) = call genType ops t
|
||||||
cppgenType ops (A.Mobile t) = call genType ops t >> tell ["*"]
|
cppgenType ops (A.Mobile t) = call genType ops t >> tell ["*"]
|
||||||
cppgenType ops (A.List t) = tell ["tockList<"] >> call genType ops t >> tell [">/**/"]
|
cppgenType ops (A.List t) = tell ["tockList<"] >> call genType ops t >> tell [">/**/"]
|
||||||
cppgenType ops t
|
cppgenType ops t
|
||||||
= case call getScalarType ops t of
|
= do fgetScalarType <- fget getScalarType
|
||||||
|
case fgetScalarType ops t of
|
||||||
Just s -> tell [s]
|
Just s -> tell [s]
|
||||||
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
Nothing -> call genMissingC ops $ formatCode "genType %" t
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ module GenerateCTest (tests) where
|
||||||
|
|
||||||
import Control.Monad.Error
|
import Control.Monad.Error
|
||||||
import Control.Monad.State
|
import Control.Monad.State
|
||||||
|
import Control.Monad.Reader
|
||||||
import Control.Monad.Writer
|
import Control.Monad.Writer
|
||||||
import Data.Generics
|
import Data.Generics
|
||||||
import Data.List (isInfixOf, intersperse)
|
import Data.List (isInfixOf, intersperse)
|
||||||
|
@ -102,31 +103,37 @@ assertGenFail n act
|
||||||
then return ()
|
then return ()
|
||||||
else assertFailure $ n ++ " pass succeeded when expected to fail, output: " ++ (subRegex (mkRegex "/\\*\\*/") (concat ss) "")
|
else assertFailure $ n ++ " pass succeeded when expected to fail, output: " ++ (subRegex (mkRegex "/\\*\\*/") (concat ss) "")
|
||||||
|
|
||||||
|
evalCGen :: CGen () -> GenOps -> CompState -> IO (Either Errors.ErrorReport [String])
|
||||||
|
evalCGen act ops state = evalStateT (runErrorT $ execWriterT $ runReaderT act ops) state
|
||||||
|
|
||||||
|
evalCGen' :: CGen' () -> CompState -> IO (Either Errors.ErrorReport [String])
|
||||||
|
evalCGen' act state = evalStateT (runErrorT $ execWriterT act) state
|
||||||
|
|
||||||
-- | Checks that running the test for the C and C++ backends produces the right output for each.
|
-- | Checks that running the test for the C and C++ backends produces the right output for each.
|
||||||
testBothS ::
|
testBothS ::
|
||||||
String -- ^ Test Name
|
String -- ^ Test Name
|
||||||
-> String -- ^ C expected
|
-> String -- ^ C expected
|
||||||
-> String -- ^ C++ expected
|
-> String -- ^ C++ expected
|
||||||
-> (GenOps -> CGen ()) -- ^ Actual
|
-> CGen () -- ^ Actual
|
||||||
-> (State CompState ()) -- ^ State transformation
|
-> (State CompState ()) -- ^ State transformation
|
||||||
-> Test
|
-> Test
|
||||||
|
|
||||||
testBothS testName expC expCPP act startState = TestList
|
testBothS testName expC expCPP act startState = TestList
|
||||||
[TestCase $ assertGen (testName ++ "/C") expC $ (evalStateT (runErrorT (execWriterT $ act cgenOps)) state)
|
[TestCase $ assertGen (testName ++ "/C") expC $ evalCGen act cgenOps state
|
||||||
,TestCase $ assertGen (testName ++ "/C++") expCPP $ (evalStateT (runErrorT (execWriterT $ act cppgenOps)) state) ]
|
,TestCase $ assertGen (testName ++ "/C++") expCPP $ evalCGen act cppgenOps state]
|
||||||
where
|
where
|
||||||
state = execState startState emptyState
|
state = execState startState emptyState
|
||||||
|
|
||||||
-- | Checks that both the C and C++ backends fail on the given input.
|
-- | Checks that both the C and C++ backends fail on the given input.
|
||||||
testBothFailS :: String -> (GenOps -> CGen ()) -> (State CompState ()) -> Test
|
testBothFailS :: String -> CGen () -> (State CompState ()) -> Test
|
||||||
testBothFailS testName act startState = TestList
|
testBothFailS testName act startState = TestList
|
||||||
[TestCase $ assertGenFail (testName ++ "/C") (evalStateT (runErrorT (execWriterT $ act cgenOps)) state)
|
[TestCase $ assertGenFail (testName ++ "/C") (evalCGen act cgenOps state)
|
||||||
,TestCase $ assertGenFail (testName ++ "/C++") (evalStateT (runErrorT (execWriterT $ act cppgenOps)) state) ]
|
,TestCase $ assertGenFail (testName ++ "/C++") (evalCGen act cppgenOps state) ]
|
||||||
where
|
where
|
||||||
state = execState startState emptyState
|
state = execState startState emptyState
|
||||||
|
|
||||||
-- | Checks that the given output of a backend satisfies the given regex, and returns the matched groups.
|
-- | Checks that the given output of a backend satisfies the given regex, and returns the matched groups.
|
||||||
testRS :: String -> String -> CGen () -> State CompState () -> IO [String]
|
testRS :: String -> String -> CGen' () -> State CompState () -> IO [String]
|
||||||
testRS testName exp act startState = assertGenR testName exp (evalStateT (runErrorT (execWriterT act)) state)
|
testRS testName exp act startState = assertGenR testName exp (evalStateT (runErrorT (execWriterT act)) state)
|
||||||
where
|
where
|
||||||
state = execState startState emptyState
|
state = execState startState emptyState
|
||||||
|
@ -135,7 +142,7 @@ testRS testName exp act startState = assertGenR testName exp (evalStateT (runErr
|
||||||
testBothSameS ::
|
testBothSameS ::
|
||||||
String -- ^ Test Name
|
String -- ^ Test Name
|
||||||
-> String -- ^ C and C++ expected
|
-> String -- ^ C and C++ expected
|
||||||
-> (GenOps -> CGen ()) -- ^ Actual
|
-> CGen () -- ^ Actual
|
||||||
-> (State CompState ()) -- ^ State transformation
|
-> (State CompState ()) -- ^ State transformation
|
||||||
-> Test
|
-> Test
|
||||||
testBothSameS n e a s = testBothS n e e a s
|
testBothSameS n e a s = testBothS n e e a s
|
||||||
|
@ -145,29 +152,32 @@ testBothR ::
|
||||||
String -- ^ Test Name
|
String -- ^ Test Name
|
||||||
-> String -- ^ C expected
|
-> String -- ^ C expected
|
||||||
-> String -- ^ C++ expected
|
-> String -- ^ C++ expected
|
||||||
-> (GenOps -> CGen ()) -- ^ Actual
|
-> CGen () -- ^ Actual
|
||||||
-> Test
|
-> Test
|
||||||
testBothR n eC eCPP a = TestList [TestCase $ (testRS n eC (a cgenOps) (return ())) >> return (), TestCase $ (testRS n eCPP (a cppgenOps) (return ())) >> (return ())]
|
testBothR n eC eCPP a = TestList
|
||||||
|
[TestCase $ (testRS n eC (runReaderT a cgenOps) (return ())) >> return ()
|
||||||
|
,TestCase $ (testRS n eCPP (runReaderT a cppgenOps) (return ())) >> (return ())]
|
||||||
|
|
||||||
-- | Like testBothR, but where the output of the C and C++ passes is expected to be the same.
|
-- | Like testBothR, but where the output of the C and C++ passes is expected to be the same.
|
||||||
testBothSameR :: String -> String -> (GenOps -> CGen ()) -> Test
|
testBothSameR :: String -> String -> CGen () -> Test
|
||||||
testBothSameR n e a = testBothR n e e a
|
testBothSameR n e a = testBothR n e e a
|
||||||
|
|
||||||
-- | Like testBothFailS, but with the default beginning state.
|
-- | Like testBothFailS, but with the default beginning state.
|
||||||
testBothFail :: String -> (GenOps -> CGen ()) -> Test
|
testBothFail :: String -> CGen () -> Test
|
||||||
testBothFail a b = testBothFailS a b (return ())
|
testBothFail a b = testBothFailS a b (return ())
|
||||||
|
|
||||||
-- | Like testBothS, but with the default beginning state.
|
-- | Like testBothS, but with the default beginning state.
|
||||||
testBoth :: String -> String -> String -> (GenOps -> CGen ()) -> Test
|
testBoth :: String -> String -> String -> CGen () -> Test
|
||||||
testBoth a b c d = testBothS a b c d (return ())
|
testBoth a b c d = testBothS a b c d (return ())
|
||||||
|
|
||||||
-- | Like testBothSameS, but with the default beginning state.
|
-- | Like testBothSameS, but with the default beginning state.
|
||||||
testBothSame :: String -> String -> (GenOps -> CGen ()) -> Test
|
testBothSame :: String -> String -> CGen () -> Test
|
||||||
testBothSame a b c = testBothSameS a b c (return ())
|
testBothSame a b c = testBothSameS a b c (return ())
|
||||||
|
|
||||||
-- | These functions are all helper functions that are like call, but turn the call
|
-- | These functions are all helper functions that are like call, but turn the call
|
||||||
-- into a function suitable to pass to all the test functions; i.e. a function
|
-- into a function suitable to pass to all the test functions; i.e. a function
|
||||||
-- parameterised solely by the GenOps.
|
-- parameterised solely by the GenOps.
|
||||||
|
{-
|
||||||
tcall :: (GenOps -> GenOps -> a -> b) -> a -> (GenOps -> b)
|
tcall :: (GenOps -> GenOps -> a -> b) -> a -> (GenOps -> b)
|
||||||
tcall f x = (\o -> f o o x)
|
tcall f x = (\o -> f o o x)
|
||||||
|
|
||||||
|
@ -182,6 +192,13 @@ tcall4 f a b c d = (\o -> f o o a b c d)
|
||||||
|
|
||||||
tcall5 :: (GenOps -> GenOps -> a0 -> a1 -> a2 -> a3 -> a4 -> b) -> a0 -> a1 -> a2 -> a3 -> a4 -> (GenOps -> b)
|
tcall5 :: (GenOps -> GenOps -> a0 -> a1 -> a2 -> a3 -> a4 -> b) -> a0 -> a1 -> a2 -> a3 -> a4 -> (GenOps -> b)
|
||||||
tcall5 func a b c d e = (\o -> func o o a b c d e)
|
tcall5 func a b c d e = (\o -> func o o a b c d e)
|
||||||
|
-}
|
||||||
|
tcall f = call f undefined
|
||||||
|
tcall2 f = call f undefined
|
||||||
|
tcall3 f = call f undefined
|
||||||
|
tcall4 f = call f undefined
|
||||||
|
tcall5 f = call f undefined
|
||||||
|
|
||||||
|
|
||||||
-- | Overrides a specified function in GenOps to return the given value
|
-- | Overrides a specified function in GenOps to return the given value
|
||||||
override1 ::
|
override1 ::
|
||||||
|
@ -291,29 +308,30 @@ testArraySizes = TestList
|
||||||
,testBothFail "genArraySizesLiteral 2" (tcall2 genArraySizesLiteral foo $ A.Array [A.Dimension 6, A.UnknownDimension] A.Int)
|
,testBothFail "genArraySizesLiteral 2" (tcall2 genArraySizesLiteral foo $ A.Array [A.Dimension 6, A.UnknownDimension] A.Int)
|
||||||
,testBothSame "genArraySize 0" "const int*foo_sizes=@;" (tcall3 genArraySize True at foo)
|
,testBothSame "genArraySize 0" "const int*foo_sizes=@;" (tcall3 genArraySize True at foo)
|
||||||
,testBothSame "genArraySize 1" "const int foo_sizes[]=@;" (tcall3 genArraySize False at foo)
|
,testBothSame "genArraySize 1" "const int foo_sizes[]=@;" (tcall3 genArraySize False at foo)
|
||||||
,testBothSame "genArrayLiteralElems 0" "$" $ (tcall genArrayLiteralElems [A.ArrayElemExpr undefined]) . unfolded
|
,testBothSame "genArrayLiteralElems 0" "$" $ unfolded (tcall genArrayLiteralElems [A.ArrayElemExpr undefined])
|
||||||
,testBothSame "genArrayLiteralElems 1" "$,$,$" $ (tcall genArrayLiteralElems [A.ArrayElemExpr undefined, A.ArrayElemExpr undefined, A.ArrayElemExpr undefined]) . unfolded
|
,testBothSame "genArrayLiteralElems 1" "$,$,$" $ unfolded (tcall genArrayLiteralElems [A.ArrayElemExpr undefined, A.ArrayElemExpr undefined, A.ArrayElemExpr undefined])
|
||||||
,testBothSame "genArrayLiteralElems 2" "$,$,$" $ (tcall genArrayLiteralElems [A.ArrayElemExpr undefined, A.ArrayElemArray [A.ArrayElemExpr undefined, A.ArrayElemExpr undefined]]) . unfolded
|
,testBothSame "genArrayLiteralElems 2" "$,$,$" $ unfolded (tcall genArrayLiteralElems [A.ArrayElemExpr undefined, A.ArrayElemArray [A.ArrayElemExpr undefined, A.ArrayElemExpr undefined]])
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
unfolded = (\ops -> ops {genUnfoldedExpression = override1 dollar})
|
unfolded = local (\ops -> ops {genUnfoldedExpression = override1 dollar})
|
||||||
|
|
||||||
testActuals :: Test
|
testActuals :: Test
|
||||||
testActuals = TestList
|
testActuals = TestList
|
||||||
[
|
[
|
||||||
-- C adds a prefix comma (to follow Process* me) but C++ does not:
|
-- C adds a prefix comma (to follow Process* me) but C++ does not:
|
||||||
testBoth "genActuals 0" ",@,@" "@,@" $ (tcall genActuals [undefined, undefined]) . (\ops -> ops {genActual = override1 at})
|
testBoth "genActuals 0" ",@,@" "@,@" $ overActual (tcall genActuals [undefined, undefined])
|
||||||
,testBothSame "genActuals 1" "" $ (tcall genActuals [])
|
,testBothSame "genActuals 1" "" $ (tcall genActuals [])
|
||||||
|
|
||||||
--For expressions, genExpression should be called:
|
--For expressions, genExpression should be called:
|
||||||
,testBothSame "genActual 0" "$" $ (tcall genActual $ A.ActualExpression A.Bool (A.True undefined)) . over
|
,testBothSame "genActual 0" "$" $ over (tcall genActual $ A.ActualExpression A.Bool (A.True undefined))
|
||||||
|
|
||||||
--For abbreviating arrays, C++ should call genExpression/genVariable, whereas C should do its foo,foo_sizes thing:
|
--For abbreviating arrays, C++ should call genExpression/genVariable, whereas C should do its foo,foo_sizes thing:
|
||||||
,testBoth "genActual 1" "@,@_sizes" "$" $ (tcall genActual $ A.ActualExpression (A.Array undefined undefined) (A.ExprVariable undefined $ A.Variable undefined foo)) . over
|
,testBoth "genActual 1" "@,@_sizes" "$" $ over (tcall genActual $ A.ActualExpression (A.Array undefined undefined) (A.ExprVariable undefined $ A.Variable undefined foo))
|
||||||
,testBoth "genActual 2" "@,@_sizes" "@" $ (tcall genActual $ A.ActualVariable A.Abbrev (A.Array undefined undefined) (A.Variable undefined foo)) . over
|
,testBoth "genActual 2" "@,@_sizes" "@" $ over (tcall genActual $ A.ActualVariable A.Abbrev (A.Array undefined undefined) (A.Variable undefined foo))
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
over = (\ops -> ops {genVariable = override1 at, genExpression = override1 dollar})
|
overActual = local (\ops -> ops {genActual = override1 at})
|
||||||
|
over = local (\ops -> ops {genVariable = override1 at, genExpression = override1 dollar})
|
||||||
|
|
||||||
testArraySubscript :: Test
|
testArraySubscript :: Test
|
||||||
testArraySubscript = TestList
|
testArraySubscript = TestList
|
||||||
|
@ -361,7 +379,7 @@ testArraySlice = TestList
|
||||||
testSlice :: Int -> (String,String) -> String -> String -> Integer -> Integer -> [A.Dimension] -> Test
|
testSlice :: Int -> (String,String) -> String -> String -> Integer -> Integer -> [A.Dimension] -> Test
|
||||||
testSlice index eC eCPP nm start count ds
|
testSlice index eC eCPP nm start count ds
|
||||||
= testBothS ("genSlice " ++ show index) (smerge eC) (smerge (eCPP,""))
|
= testBothS ("genSlice " ++ show index) (smerge eC) (smerge (eCPP,""))
|
||||||
(merge . tcall4 genSlice
|
(merge $ tcall4 genSlice
|
||||||
(A.SubscriptedVariable undefined (A.SubscriptFromFor undefined (intLiteral start) (intLiteral count)) (variable nm))
|
(A.SubscriptedVariable undefined (A.SubscriptFromFor undefined (intLiteral start) (intLiteral count)) (variable nm))
|
||||||
(intLiteral start) (intLiteral count) ds)
|
(intLiteral start) (intLiteral count) ds)
|
||||||
(defineName (simpleName nm) $ simpleDefDecl nm (A.Array ds A.Int))
|
(defineName (simpleName nm) $ simpleDefDecl nm (A.Array ds A.Int))
|
||||||
|
@ -390,11 +408,11 @@ testOverArray = TestList $ map testOverArray'
|
||||||
|
|
||||||
testOverArray' :: ((Int -> String),[(String,[Int])] -> String,String, GenOps) -> Test
|
testOverArray' :: ((Int -> String),[(String,[Int])] -> String,String, GenOps) -> Test
|
||||||
testOverArray' (sz,f',suff,ops) = TestCase $
|
testOverArray' (sz,f',suff,ops) = TestCase $
|
||||||
do testRS "testOverArray'" rx1 (tcall3 genOverArray emptyMeta (A.Variable emptyMeta foo) func ops) state1
|
do testRS "testOverArray'" rx1 (flip runReaderT ops $ tcall3 genOverArray emptyMeta (A.Variable emptyMeta foo) func) state1
|
||||||
testRS "testOverArray'" rx3 (tcall3 genOverArray emptyMeta (A.Variable emptyMeta foo) func ops) state3
|
testRS "testOverArray'" rx3 (flip runReaderT ops $ tcall3 genOverArray emptyMeta (A.Variable emptyMeta foo) func) state3
|
||||||
return ()
|
return ()
|
||||||
where
|
where
|
||||||
func f = Just $ call genVariableUnchecked ops (f $ A.Variable emptyMeta foo) >> tell [";"]
|
func f = Just $ call genVariableUnchecked undefined (f $ A.Variable emptyMeta foo) >> tell [";"]
|
||||||
rx1 = "^for\\(int ([[:alnum:]_]+)=0;\\1<foo" ++ sz 0 ++ ";\\1\\+\\+)\\{foo\\[\\1\\]" ++ suff ++ ";\\}$"
|
rx1 = "^for\\(int ([[:alnum:]_]+)=0;\\1<foo" ++ sz 0 ++ ";\\1\\+\\+)\\{foo\\[\\1\\]" ++ suff ++ ";\\}$"
|
||||||
rx3 = "^for\\(int ([[:alnum:]_]+)=0;\\1<foo" ++ sz 0 ++ ";\\1\\+\\+)\\{" ++
|
rx3 = "^for\\(int ([[:alnum:]_]+)=0;\\1<foo" ++ sz 0 ++ ";\\1\\+\\+)\\{" ++
|
||||||
"for\\(int ([[:alnum:]_]+)=0;\\2<foo" ++ sz 1 ++ ";\\2\\+\\+)\\{" ++
|
"for\\(int ([[:alnum:]_]+)=0;\\2<foo" ++ sz 1 ++ ";\\2\\+\\+)\\{" ++
|
||||||
|
@ -472,7 +490,7 @@ testDeclaration = TestList
|
||||||
stateR t = defRecord "REC" "bar" t
|
stateR t = defRecord "REC" "bar" t
|
||||||
|
|
||||||
testDeclareInitFree :: Test
|
testDeclareInitFree :: Test
|
||||||
testDeclareInitFree = TestList
|
testDeclareInitFree = TestLabel "testDeclareInitFree" $ TestList
|
||||||
[
|
[
|
||||||
-- Plain type:
|
-- Plain type:
|
||||||
testAllSame 0 ("","") A.Int
|
testAllSame 0 ("","") A.Int
|
||||||
|
@ -526,16 +544,16 @@ testDeclareInitFree = TestList
|
||||||
testAll' :: Int -> (String,String) -> (String,String) -> A.Type -> State CompState () -> Maybe A.Expression -> Test
|
testAll' :: Int -> (String,String) -> (String,String) -> A.Type -> State CompState () -> Maybe A.Expression -> Test
|
||||||
testAll' n (iC,fC) (iCPP,fCPP) t state init = TestList
|
testAll' n (iC,fC) (iCPP,fCPP) t state init = TestList
|
||||||
[
|
[
|
||||||
testBothS ("testDeclareInitFree/a" ++ show n) ("@" ++ iC) ("@" ++ iCPP) ((tcall introduceSpec $ A.Specification emptyMeta foo (A.Declaration emptyMeta t init)) . over) state
|
testBothS ("testDeclareInitFree/a" ++ show n) ("@" ++ iC) ("@" ++ iCPP) (over (tcall introduceSpec $ A.Specification emptyMeta foo (A.Declaration emptyMeta t init))) state
|
||||||
,testBothS ("testDeclareInitFree/b" ++ show n) iC iCPP ((fromMaybe (return ())) . (tcall4 declareInit emptyMeta t (A.Variable emptyMeta foo) init) . over) state
|
,testBothS ("testDeclareInitFree/b" ++ show n) iC iCPP (over $ ask >>= \ops -> (fromMaybe (return ())) (declareInit ops ops emptyMeta t (A.Variable emptyMeta foo) init)) state
|
||||||
,testBothS ("testDeclareInitFree/c" ++ show n) fC fCPP ((tcall removeSpec $ A.Specification emptyMeta foo (A.Declaration emptyMeta t Nothing)) . over) state
|
,testBothS ("testDeclareInitFree/c" ++ show n) fC fCPP (over (tcall removeSpec $ A.Specification emptyMeta foo (A.Declaration emptyMeta t Nothing))) state
|
||||||
,testBothS ("testDeclareInitFree/d" ++ show n) fC fCPP ((fromMaybe (return ())) . (tcall3 declareFree emptyMeta t (A.Variable emptyMeta foo)) . over) state
|
,testBothS ("testDeclareInitFree/d" ++ show n) fC fCPP (over $ ask >>= \ops -> (fromMaybe (return ())) (declareFree ops ops emptyMeta t (A.Variable emptyMeta foo))) state
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
overArray _ _ v f = case f (\v -> A.SubscriptedVariable emptyMeta (A.Subscript emptyMeta $ intLiteral 0) v) of
|
overArray _ _ v f = case f (\v -> A.SubscriptedVariable emptyMeta (A.Subscript emptyMeta $ intLiteral 0) v) of
|
||||||
Just p -> caret >> p >> caret
|
Just p -> caret >> p >> caret
|
||||||
Nothing -> return ()
|
Nothing -> return ()
|
||||||
over ops = ops {genDeclaration = override3 at, genOverArray = overArray}
|
over = local $ \ops -> ops {genDeclaration = override3 at, genOverArray = overArray}
|
||||||
|
|
||||||
testAllSame :: Int -> (String,String) -> A.Type -> Test
|
testAllSame :: Int -> (String,String) -> A.Type -> Test
|
||||||
testAllSame n e t = testAll n e e t
|
testAllSame n e t = testAll n e e t
|
||||||
|
@ -659,8 +677,8 @@ testSpec = TestList
|
||||||
testAllS :: Int -> (String,String) -> (String,String) -> A.SpecType -> State CompState () -> (GenOps -> GenOps) -> Test
|
testAllS :: Int -> (String,String) -> (String,String) -> A.SpecType -> State CompState () -> (GenOps -> GenOps) -> Test
|
||||||
testAllS n (eCI,eCR) (eCPPI,eCPPR) spec st overFunc = TestList
|
testAllS n (eCI,eCR) (eCPPI,eCPPR) spec st overFunc = TestList
|
||||||
[
|
[
|
||||||
testBothS ("testSpec " ++ show n) eCI eCPPI ((tcall introduceSpec $ A.Specification emptyMeta foo spec) . overFunc) st
|
testBothS ("testSpec " ++ show n) eCI eCPPI (local overFunc (tcall introduceSpec $ A.Specification emptyMeta foo spec)) st
|
||||||
,testBothS ("testSpec " ++ show n) eCR eCPPR ((tcall removeSpec $ A.Specification emptyMeta foo spec) . overFunc) st
|
,testBothS ("testSpec " ++ show n) eCR eCPPR (local overFunc (tcall removeSpec $ A.Specification emptyMeta foo spec)) st
|
||||||
]
|
]
|
||||||
testAllSame n e s = testAll n e e s
|
testAllSame n e s = testAll n e e s
|
||||||
testAllSameS n e s st o = testAllS n e e s st o
|
testAllSameS n e s st o = testAllS n e e s st o
|
||||||
|
@ -699,7 +717,7 @@ testRetypeSizes = TestList
|
||||||
where
|
where
|
||||||
test :: Int -> String -> String -> A.Type -> A.Type -> Test
|
test :: Int -> String -> String -> A.Type -> A.Type -> Test
|
||||||
test n eC eCPP destT srcT = testBoth ("testRetypeSizes " ++ show n) (repAll eC) (repAll eCPP)
|
test n eC eCPP destT srcT = testBoth ("testRetypeSizes " ++ show n) (repAll eC) (repAll eCPP)
|
||||||
((tcall5 genRetypeSizes emptyMeta destT undefined srcT undefined) . over)
|
(over (tcall5 genRetypeSizes emptyMeta destT undefined srcT undefined))
|
||||||
where
|
where
|
||||||
repAll = (rep "#S" ("$(" ++ show srcT ++ " Right)")) .
|
repAll = (rep "#S" ("$(" ++ show srcT ++ " Right)")) .
|
||||||
(rep "#D" ("$(" ++ show destT ++ " Left True)")) .
|
(rep "#D" ("$(" ++ show destT ++ " Left True)")) .
|
||||||
|
@ -710,7 +728,7 @@ testRetypeSizes = TestList
|
||||||
showBytesInParams _ _ t (Right _) = tell ["$(" ++ show t ++ " Right)"]
|
showBytesInParams _ _ t (Right _) = tell ["$(" ++ show t ++ " Right)"]
|
||||||
showBytesInParams _ _ t v = tell ["$(" ++ show t ++ " " ++ show v ++ ")"]
|
showBytesInParams _ _ t v = tell ["$(" ++ show t ++ " " ++ show v ++ ")"]
|
||||||
showArrSize _ _ sz _ = tell ["^("] >> sz >> tell [")"]
|
showArrSize _ _ sz _ = tell ["^("] >> sz >> tell [")"]
|
||||||
over ops = ops {genBytesIn = showBytesInParams, genStop = override2 at, genArraySize = showArrSize}
|
over = local $ \ops -> ops {genBytesIn = showBytesInParams, genStop = override2 at, genArraySize = showArrSize}
|
||||||
|
|
||||||
defRecord :: String -> String -> A.Type -> State CompState ()
|
defRecord :: String -> String -> A.Type -> State CompState ()
|
||||||
defRecord rec mem t = defineName (simpleName rec) $ A.NameDef emptyMeta rec rec A.RecordName (A.RecordType emptyMeta False [(simpleName mem,t)]) A.Original A.Unplaced
|
defRecord rec mem t = defineName (simpleName rec) $ A.NameDef emptyMeta rec rec A.RecordName (A.RecordType emptyMeta False [(simpleName mem,t)]) A.Original A.Unplaced
|
||||||
|
@ -776,13 +794,13 @@ testGenVariable = TestList
|
||||||
test :: Int -> (String,String) -> (String,String) -> (A.Variable -> A.Variable) -> A.AbbrevMode -> A.Type -> Test
|
test :: Int -> (String,String) -> (String,String) -> (A.Variable -> A.Variable) -> A.AbbrevMode -> A.Type -> Test
|
||||||
test n (eC,eUC) (eCPP,eUCPP) sub am t = TestList
|
test n (eC,eUC) (eCPP,eUCPP) sub am t = TestList
|
||||||
[
|
[
|
||||||
testBothS ("testGenVariable/checked" ++ show n) eC eCPP ((tcall genVariable $ sub $ A.Variable emptyMeta foo) . over) state
|
testBothS ("testGenVariable/checked" ++ show n) eC eCPP (over (tcall genVariable $ sub $ A.Variable emptyMeta foo)) state
|
||||||
,testBothS ("testGenVariable/unchecked" ++ show n) eUC eUCPP ((tcall genVariableUnchecked $ sub $ A.Variable emptyMeta foo) . over) state
|
,testBothS ("testGenVariable/unchecked" ++ show n) eUC eUCPP (over (tcall genVariableUnchecked $ sub $ A.Variable emptyMeta foo)) state
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
state = do defineName (simpleName "foo") $ A.NameDef emptyMeta "foo" "foo" A.VariableName (A.Declaration emptyMeta t Nothing) am A.Unplaced
|
state = do defineName (simpleName "foo") $ A.NameDef emptyMeta "foo" "foo" A.VariableName (A.Declaration emptyMeta t Nothing) am A.Unplaced
|
||||||
defRecord "bar" "x" $ A.Array [A.Dimension 7] A.Int
|
defRecord "bar" "x" $ A.Array [A.Dimension 7] A.Int
|
||||||
over ops = ops {genArraySubscript = (\_ b _ subs -> at >> (tell [if b then "C" else "U"]) >> (seqComma $ map (call genExpression ops) subs))
|
over = local $ \ops -> ops {genArraySubscript = (\_ b _ subs -> at >> (tell [if b then "C" else "U"]) >> (seqComma $ map (call genExpression ops) subs))
|
||||||
,genDirectedVariable = (\_ cg _ -> dollar >> cg >> dollar)}
|
,genDirectedVariable = (\_ cg _ -> dollar >> cg >> dollar)}
|
||||||
|
|
||||||
testA :: Int -> (String,String) -> (String,String) -> (A.Variable -> A.Variable) -> A.Type -> Test
|
testA :: Int -> (String,String) -> (String,String) -> (A.Variable -> A.Variable) -> A.Type -> Test
|
||||||
|
@ -808,9 +826,9 @@ testGenVariable = TestList
|
||||||
testAssign :: Test
|
testAssign :: Test
|
||||||
testAssign = TestList
|
testAssign = TestList
|
||||||
[
|
[
|
||||||
testBothSameS "testAssign 0" "@=$;" ((tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])) . over) (state A.Int)
|
testBothSameS "testAssign 0" "@=$;" (over (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e]))) (state A.Int)
|
||||||
,testBothSameS "testAssign 1" "@=$;" ((tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])) . over) (state A.Time)
|
,testBothSameS "testAssign 1" "@=$;" (over (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e]))) (state A.Time)
|
||||||
,testBothSameS "testAssign 2" "@=$;" ((tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])) . over)
|
,testBothSameS "testAssign 2" "@=$;" (over (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])))
|
||||||
(state $ A.Chan A.DirInput (A.ChanAttributes False False) A.Int)
|
(state $ A.Chan A.DirInput (A.ChanAttributes False False) A.Int)
|
||||||
|
|
||||||
-- Fail because genAssign only handles one destination and one source:
|
-- Fail because genAssign only handles one destination and one source:
|
||||||
|
@ -819,31 +837,31 @@ testAssign = TestList
|
||||||
,testBothFail "testAssign 102" (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo,A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e, e]))
|
,testBothFail "testAssign 102" (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo,A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e, e]))
|
||||||
|
|
||||||
-- Fail because assignment can't be done with these types (should have already been transformed away):
|
-- Fail because assignment can't be done with these types (should have already been transformed away):
|
||||||
,testBothFailS "testAssign 200" ((tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])) . over)
|
,testBothFailS "testAssign 200" (over (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])))
|
||||||
(state $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int)
|
(state $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int)
|
||||||
,testBothFailS "testAssign 201" ((tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])) . over)
|
,testBothFailS "testAssign 201" (over (tcall3 genAssign emptyMeta [A.Variable emptyMeta foo] (A.ExpressionList emptyMeta [e])))
|
||||||
(state $ A.Record bar)
|
(state $ A.Record bar)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
--The expression won't be examined so we can use what we like:
|
--The expression won't be examined so we can use what we like:
|
||||||
e = A.True emptyMeta
|
e = A.True emptyMeta
|
||||||
state t = defineName (simpleName "foo") $ simpleDefDecl "foo" t
|
state t = defineName (simpleName "foo") $ simpleDefDecl "foo" t
|
||||||
over ops = ops {genVariable = override1 at, genExpression = override1 dollar}
|
over = local $ \ops -> ops {genVariable = override1 at, genExpression = override1 dollar}
|
||||||
|
|
||||||
testCase :: Test
|
testCase :: Test
|
||||||
testCase = TestList
|
testCase = TestList
|
||||||
[
|
[
|
||||||
testBothSame "testCase 0" "switch($){default:^}" ((tcall3 genCase emptyMeta e (A.Several emptyMeta [])) . over)
|
testBothSame "testCase 0" "switch($){default:^}" (over (tcall3 genCase emptyMeta e (A.Several emptyMeta [])))
|
||||||
,testBothSame "testCase 1" "switch($){default:{@}break;}" ((tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Else emptyMeta p)) . over)
|
,testBothSame "testCase 1" "switch($){default:{@}break;}" (over (tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Else emptyMeta p)))
|
||||||
,testBothSame "testCase 2" "switch($){default:{#@}break;}" ((tcall3 genCase emptyMeta e (spec $ A.Only emptyMeta $ A.Else emptyMeta p)) . over)
|
,testBothSame "testCase 2" "switch($){default:{#@}break;}" (over (tcall3 genCase emptyMeta e (spec $ A.Only emptyMeta $ A.Else emptyMeta p)))
|
||||||
|
|
||||||
,testBothSame "testCase 10" "switch($){case $:{@}break;default:^}" ((tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Option emptyMeta [intLiteral 0] p)) . over)
|
,testBothSame "testCase 10" "switch($){case $:{@}break;default:^}" (over (tcall3 genCase emptyMeta e (A.Only emptyMeta $ A.Option emptyMeta [intLiteral 0] p)))
|
||||||
|
|
||||||
,testBothSame "testCase 20" "switch($){case $:case $:{#@}break;default:{@}break;case $:{@}break;}" ((tcall3 genCase emptyMeta e $ A.Several emptyMeta
|
,testBothSame "testCase 20" "switch($){case $:case $:{#@}break;default:{@}break;case $:{@}break;}" (over (tcall3 genCase emptyMeta e $ A.Several emptyMeta
|
||||||
[spec $ A.Only emptyMeta $ A.Option emptyMeta [e, e] p
|
[spec $ A.Only emptyMeta $ A.Option emptyMeta [e, e] p
|
||||||
,A.Only emptyMeta $ A.Else emptyMeta p
|
,A.Only emptyMeta $ A.Else emptyMeta p
|
||||||
,A.Only emptyMeta $ A.Option emptyMeta [e] p]
|
,A.Only emptyMeta $ A.Option emptyMeta [e] p]
|
||||||
) . over)
|
))
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
--The expression and process won't be used so we can use what we like:
|
--The expression and process won't be used so we can use what we like:
|
||||||
|
@ -851,50 +869,50 @@ testCase = TestList
|
||||||
p = A.Skip emptyMeta
|
p = A.Skip emptyMeta
|
||||||
spec :: Data a => A.Structured a -> A.Structured a
|
spec :: Data a => A.Structured a -> A.Structured a
|
||||||
spec = A.Spec emptyMeta undefined
|
spec = A.Spec emptyMeta undefined
|
||||||
over ops = ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
|
over = local $ \ops -> ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
|
||||||
|
|
||||||
testGetTime :: Test
|
testGetTime :: Test
|
||||||
testGetTime = testBoth "testGetTime 0" "ProcTime(&@);" "csp::CurrentTime(&@);" ((tcall2 genGetTime emptyMeta undefined) . over)
|
testGetTime = testBoth "testGetTime 0" "ProcTime(&@);" "csp::CurrentTime(&@);" (over (tcall2 genGetTime emptyMeta undefined))
|
||||||
where
|
where
|
||||||
over ops = ops {genVariable = override1 at}
|
over = local $ \ops -> ops {genVariable = override1 at}
|
||||||
|
|
||||||
testWait :: Test
|
testWait :: Test
|
||||||
testWait = TestList
|
testWait = TestList
|
||||||
[
|
[
|
||||||
testBoth "testWait 0" "ProcTimeAfter($);" "csp::SleepUntil($);" ((tcall2 genWait A.WaitUntil undefined) . over)
|
testBoth "testWait 0" "ProcTimeAfter($);" "csp::SleepUntil($);" (over (tcall2 genWait A.WaitUntil undefined))
|
||||||
,testBoth "testWait 1" "ProcAfter($);" "csp::SleepFor($);" ((tcall2 genWait A.WaitFor undefined) . over)
|
,testBoth "testWait 1" "ProcAfter($);" "csp::SleepFor($);" (over (tcall2 genWait A.WaitFor undefined))
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
over ops = ops {genExpression = override1 dollar}
|
over = local $ \ops -> ops {genExpression = override1 dollar}
|
||||||
|
|
||||||
testIf :: Test
|
testIf :: Test
|
||||||
testIf = TestList
|
testIf = TestList
|
||||||
[
|
[
|
||||||
testBothR "testIf 0" "/\\*([[:alnum:]_]+)\\*/\\^\\1:;" "class ([[:alnum:]_]+)\\{\\};try\\{\\^\\}catch\\(\\1\\)\\{\\}"
|
testBothR "testIf 0" "/\\*([[:alnum:]_]+)\\*/\\^\\1:;" "class ([[:alnum:]_]+)\\{\\};try\\{\\^\\}catch\\(\\1\\)\\{\\}"
|
||||||
((tcall2 genIf emptyMeta (A.Several emptyMeta [])) . over)
|
(over (tcall2 genIf emptyMeta (A.Several emptyMeta [])))
|
||||||
,testBothR "testIf 1" "/\\*([[:alnum:]_]+)\\*/if\\(\\$\\)\\{@goto \\1;\\}\\^\\1:;"
|
,testBothR "testIf 1" "/\\*([[:alnum:]_]+)\\*/if\\(\\$\\)\\{@goto \\1;\\}\\^\\1:;"
|
||||||
"class ([[:alnum:]_]+)\\{\\};try\\{if\\(\\$\\)\\{@throw \\1\\(\\);\\}\\^\\}catch\\(\\1\\)\\{\\}"
|
"class ([[:alnum:]_]+)\\{\\};try\\{if\\(\\$\\)\\{@throw \\1\\(\\);\\}\\^\\}catch\\(\\1\\)\\{\\}"
|
||||||
((tcall2 genIf emptyMeta (A.Only emptyMeta $ A.Choice emptyMeta e p)) . over)
|
(over (tcall2 genIf emptyMeta (A.Only emptyMeta $ A.Choice emptyMeta e p)))
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
e :: A.Expression
|
e :: A.Expression
|
||||||
e = undefined
|
e = undefined
|
||||||
p :: A.Process
|
p :: A.Process
|
||||||
p = undefined
|
p = undefined
|
||||||
over ops = ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
|
over = local $ \ops -> ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
|
||||||
|
|
||||||
testWhile :: Test
|
testWhile :: Test
|
||||||
testWhile = testBothSame "testWhile 0" "while($){@}" ((tcall2 genWhile undefined undefined) . over)
|
testWhile = testBothSame "testWhile 0" "while($){@}" (over (tcall2 genWhile undefined undefined))
|
||||||
where
|
where
|
||||||
over ops = ops {genExpression = override1 dollar, genProcess = override1 at}
|
over = local $ \ops -> ops {genExpression = override1 dollar, genProcess = override1 at}
|
||||||
|
|
||||||
testInput :: Test
|
testInput :: Test
|
||||||
testInput = TestList
|
testInput = TestList
|
||||||
[
|
[
|
||||||
-- Test that genInput passes on the calls properly:
|
-- Test that genInput passes on the calls properly:
|
||||||
testBothSame "testInput 0" "" ((tcall2 genInput undefined $ A.InputSimple undefined []) . overInputItemCase)
|
testBothSame "testInput 0" "" (overInputItemCase (tcall2 genInput undefined $ A.InputSimple undefined []))
|
||||||
,testBothSame "testInput 1" "^" ((tcall2 genInput undefined $ A.InputSimple undefined [undefined]) . overInputItemCase)
|
,testBothSame "testInput 1" "^" (overInputItemCase (tcall2 genInput undefined $ A.InputSimple undefined [undefined]))
|
||||||
,testBothSame "testInput 2" "^^^" ((tcall2 genInput undefined $ A.InputSimple undefined [undefined, undefined, undefined]) . overInputItemCase)
|
,testBothSame "testInput 2" "^^^" (overInputItemCase (tcall2 genInput undefined $ A.InputSimple undefined [undefined, undefined, undefined]))
|
||||||
|
|
||||||
-- Reading an integer (special case in the C backend):
|
-- Reading an integer (special case in the C backend):
|
||||||
,testInputItem 100 "ChanInInt(#,&x);" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int
|
,testInputItem 100 "ChanInInt(#,&x);" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int
|
||||||
|
@ -950,8 +968,8 @@ testInput = TestList
|
||||||
testInputItem' :: Int -> String -> String -> A.InputItem -> A.Type -> A.Type -> Test
|
testInputItem' :: Int -> String -> String -> A.InputItem -> A.Type -> A.Type -> Test
|
||||||
testInputItem' n eC eCPP ii t ct = TestList
|
testInputItem' n eC eCPP ii t ct = TestList
|
||||||
[
|
[
|
||||||
testBothS ("testInput " ++ show n) (hashIs "(&c)" eC) (hashIs "(&c)->reader()" eCPP) ((tcall2 genInputItem (A.Variable emptyMeta $ simpleName "c") ii) . over) (state A.DirUnknown)
|
testBothS ("testInput " ++ show n) (hashIs "(&c)" eC) (hashIs "(&c)->reader()" eCPP) (over (tcall2 genInputItem (A.Variable emptyMeta $ simpleName "c") ii)) (state A.DirUnknown)
|
||||||
,testBothS ("testInput [in] " ++ show n) (hashIs "c" eC) (hashIs "c" eCPP) ((tcall2 genInputItem (A.Variable emptyMeta $ simpleName "c") ii) . over) (state A.DirInput)
|
,testBothS ("testInput [in] " ++ show n) (hashIs "c" eC) (hashIs "c" eCPP) (over (tcall2 genInputItem (A.Variable emptyMeta $ simpleName "c") ii)) (state A.DirInput)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
hashIs x y = subRegex (mkRegex "#") y x
|
hashIs x y = subRegex (mkRegex "#") y x
|
||||||
|
@ -970,18 +988,18 @@ testInput = TestList
|
||||||
-- state = do defineName chan $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.UserProtocol foo)
|
-- state = do defineName chan $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.UserProtocol foo)
|
||||||
-- defineName chanOut $ simpleDefDecl "cIn" (A.Chan A.DirInput (A.ChanAttributes False False) $ A.UserProtocol foo)
|
-- defineName chanOut $ simpleDefDecl "cIn" (A.Chan A.DirInput (A.ChanAttributes False False) $ A.UserProtocol foo)
|
||||||
|
|
||||||
overInputItemCase ops = ops {genInputItem = override2 caret}
|
overInputItemCase = local $ \ops -> ops {genInputItem = override2 caret}
|
||||||
over ops = ops {genBytesIn = (\_ _ t _ -> tell ["^(",show t,")"]) , genArraySubscript = override3 dollar}
|
over = local $ \ops -> ops {genBytesIn = (\_ _ t _ -> tell ["^(",show t,")"]) , genArraySubscript = override3 dollar}
|
||||||
|
|
||||||
testOutput :: Test
|
testOutput :: Test
|
||||||
testOutput = TestList
|
testOutput = TestList
|
||||||
[
|
[
|
||||||
testBothSame "testOutput 0" "" ((tcall2 genOutput undefined []) . overOutputItem)
|
testBothSame "testOutput 0" "" (overOutputItem (tcall2 genOutput undefined []))
|
||||||
,testBothSame "testOutput 1" "^" ((tcall2 genOutput undefined [undefined]) . overOutputItem)
|
,testBothSame "testOutput 1" "^" (overOutputItem (tcall2 genOutput undefined [undefined]))
|
||||||
,testBothSame "testOutput 2" "^^^" ((tcall2 genOutput undefined [undefined,undefined,undefined]) . overOutputItem)
|
,testBothSame "testOutput 2" "^^^" (overOutputItem (tcall2 genOutput undefined [undefined,undefined,undefined]))
|
||||||
|
|
||||||
,testBothS "testOutput 100" "ChanOutInt((&c),bar_foo);^" "tockSendInt((&c)->writer(),bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chan) bar []) . overOutput) state
|
,testBothS "testOutput 100" "ChanOutInt((&c),bar_foo);^" "tockSendInt((&c)->writer(),bar_foo);^" (overOutput (tcall3 genOutputCase (A.Variable emptyMeta chan) bar [])) state
|
||||||
,testBothS "testOutput 101" "ChanOutInt(cOut,bar_foo);^" "tockSendInt(cOut,bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chanOut) bar []) . overOutput) state
|
,testBothS "testOutput 101" "ChanOutInt(cOut,bar_foo);^" "tockSendInt(cOut,bar_foo);^" (overOutput (tcall3 genOutputCase (A.Variable emptyMeta chanOut) bar [])) state
|
||||||
|
|
||||||
--Integers are a special case in the C backend:
|
--Integers are a special case in the C backend:
|
||||||
,testOutputItem 201 "ChanOutInt(#,x);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
|
,testOutputItem 201 "ChanOutInt(#,x);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
|
||||||
|
@ -1035,8 +1053,8 @@ testOutput = TestList
|
||||||
testOutputItem' :: Int -> String -> String -> A.OutputItem -> A.Type -> A.Type -> Test
|
testOutputItem' :: Int -> String -> String -> A.OutputItem -> A.Type -> A.Type -> Test
|
||||||
testOutputItem' n eC eCPP oi t ct = TestList
|
testOutputItem' n eC eCPP oi t ct = TestList
|
||||||
[
|
[
|
||||||
testBothS ("testOutput " ++ show n) (hashIs "(&c)" eC) (hashIs "(&c)->writer()" eCPP) ((tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi) . over) (state A.DirUnknown)
|
testBothS ("testOutput " ++ show n) (hashIs "(&c)" eC) (hashIs "(&c)->writer()" eCPP) (over (tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi)) (state A.DirUnknown)
|
||||||
,testBothS ("testOutput [out] " ++ show n) (hashIs "c" eC) (hashIs "c" eCPP) ((tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi) . over) (state A.DirOutput)
|
,testBothS ("testOutput [out] " ++ show n) (hashIs "c" eC) (hashIs "c" eCPP) (over (tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi)) (state A.DirOutput)
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
hashIs x y = subRegex (mkRegex "#") y x
|
hashIs x y = subRegex (mkRegex "#") y x
|
||||||
|
@ -1054,9 +1072,9 @@ testOutput = TestList
|
||||||
state :: CSM m => m ()
|
state :: CSM m => m ()
|
||||||
state = do defineName chan $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.UserProtocol foo)
|
state = do defineName chan $ simpleDefDecl "c" (A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.UserProtocol foo)
|
||||||
defineName chanOut $ simpleDefDecl "cOut" (A.Chan A.DirOutput (A.ChanAttributes False False) $ A.UserProtocol foo)
|
defineName chanOut $ simpleDefDecl "cOut" (A.Chan A.DirOutput (A.ChanAttributes False False) $ A.UserProtocol foo)
|
||||||
overOutput ops = ops {genOutput = override2 caret}
|
overOutput = local $ \ops -> ops {genOutput = override2 caret}
|
||||||
overOutputItem ops = ops {genOutputItem = override2 caret}
|
overOutputItem = local $ \ops -> ops {genOutputItem = override2 caret}
|
||||||
over ops = ops {genBytesIn = override3 caret}
|
over = local $ \ops -> ops {genBytesIn = override3 caret}
|
||||||
|
|
||||||
testBytesIn :: Test
|
testBytesIn :: Test
|
||||||
testBytesIn = TestList
|
testBytesIn = TestList
|
||||||
|
@ -1073,7 +1091,7 @@ testBytesIn = TestList
|
||||||
--single unknown dimension, no variable, free dimension allowed:
|
--single unknown dimension, no variable, free dimension allowed:
|
||||||
,testBothSame "testBytesIn 101b" "sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.UnknownDimension] A.Int) (Left True))
|
,testBothSame "testBytesIn 101b" "sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.UnknownDimension] A.Int) (Left True))
|
||||||
--single unknown dimension, with variable:
|
--single unknown dimension, with variable:
|
||||||
,testBothSame "testBytesIn 102" "$(@0)*sizeof(int)" ((tcall3 genBytesIn undefined (A.Array [A.UnknownDimension] A.Int) (Right undefined)) . over)
|
,testBothSame "testBytesIn 102" "$(@0)*sizeof(int)" (over (tcall3 genBytesIn undefined (A.Array [A.UnknownDimension] A.Int) (Right undefined)))
|
||||||
|
|
||||||
--Array with all known dimensions:
|
--Array with all known dimensions:
|
||||||
,testBothSame "testBytesIn 200" "7*6*5*sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6, A.Dimension 7] A.Int) (Left False))
|
,testBothSame "testBytesIn 200" "7*6*5*sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6, A.Dimension 7] A.Int) (Left False))
|
||||||
|
@ -1082,20 +1100,20 @@ testBytesIn = TestList
|
||||||
--single unknown dimension, no variable, free dimension allowed:
|
--single unknown dimension, no variable, free dimension allowed:
|
||||||
,testBothSame "testBytesIn 201b" "6*5*sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6,A.UnknownDimension] A.Int) (Left True))
|
,testBothSame "testBytesIn 201b" "6*5*sizeof(int)" (tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6,A.UnknownDimension] A.Int) (Left True))
|
||||||
--single unknown dimension, with variable:
|
--single unknown dimension, with variable:
|
||||||
,testBothSame "testBytesIn 202" "$(@2)*6*5*sizeof(int)" ((tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6,A.UnknownDimension] A.Int) (Right undefined)) . over)
|
,testBothSame "testBytesIn 202" "$(@2)*6*5*sizeof(int)" (over (tcall3 genBytesIn undefined (A.Array [A.Dimension 5,A.Dimension 6,A.UnknownDimension] A.Int) (Right undefined)))
|
||||||
|
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
over ops = ops {genVariable = override1 dollar, genSizeSuffix = (\_ n -> tell["(@",n,")"])}
|
over = local $ \ops -> ops {genVariable = override1 dollar, genSizeSuffix = (\_ n -> tell["(@",n,")"])}
|
||||||
|
|
||||||
testMobile :: Test
|
testMobile :: Test
|
||||||
testMobile = TestList
|
testMobile = TestList
|
||||||
[
|
[
|
||||||
testBoth "testMobile 0" "malloc(#(Int Left False))" "new Int" ((tcall3 genAllocMobile emptyMeta (A.Mobile A.Int) Nothing) . over)
|
testBoth "testMobile 0" "malloc(#(Int Left False))" "new Int" (local over (tcall3 genAllocMobile emptyMeta (A.Mobile A.Int) Nothing))
|
||||||
,TestCase $ assertGen "testMobile 1/C++" "new Int($)" $ (evalStateT (runErrorT (execWriterT $ call genAllocMobile (over cppgenOps) emptyMeta (A.Mobile A.Int) (Just undefined))) emptyState)
|
,TestCase $ assertGen "testMobile 1/C++" "new Int($)" $ (evalStateT (runErrorT (execWriterT $ flip runReaderT (over cppgenOps) $ call genAllocMobile undefined emptyMeta (A.Mobile A.Int) (Just undefined))) emptyState)
|
||||||
|
|
||||||
,testBoth "testMobile 100" "if(@!=NULL){free(@);@=NULL;}" "if(@!=NULL){delete @;@=NULL;}"
|
,testBoth "testMobile 100" "if(@!=NULL){free(@);@=NULL;}" "if(@!=NULL){delete @;@=NULL;}"
|
||||||
((tcall2 genClearMobile emptyMeta undefined) . over)
|
(local over (tcall2 genClearMobile emptyMeta undefined))
|
||||||
]
|
]
|
||||||
where
|
where
|
||||||
showBytesInParams _ _ t (Right _) = tell ["#(" ++ show t ++ " Right)"]
|
showBytesInParams _ _ t (Right _) = tell ["#(" ++ show t ++ " Right)"]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user