Fixed all the tests for sending items in C++, and made the tests pass

This commit is contained in:
Neil Brown 2007-10-06 23:05:03 +00:00
parent 6d29bbd260
commit 9af1ec78bb
3 changed files with 122 additions and 67 deletions

View File

@ -423,26 +423,56 @@ cppgenInputItem ops c (A.InVariable m v)
call genVariable ops v
tell [";\n"]
-- | If we are sending an array, we use the versionToSend function to coerce away any annoying const tags on the array data:
genJustOutputItem :: GenOps -> A.OutputItem -> CGen()
genJustOutputItem ops (A.OutCounted m ce ae)
= do call genExpression ops ae
tell[" .sliceFor("]
call genExpression ops ce
tell[") .versionToSend() "]
genJustOutputItem ops (A.OutExpression m e)
= do t <- typeOfExpression e
call genExpression ops e
case t of
(A.Array _ _) -> tell [" .versionToSend() "]
_ -> return ()
cppgenOutputItem :: GenOps -> A.Variable -> A.OutputItem -> CGen ()
cppgenOutputItem ops chan item
= do genCPPCSPChannelOutput ops chan
tell ["<<"]
genJustOutputItem ops item
tell [";"]
= case item of
(A.OutCounted m (A.ExprVariable _ cv) (A.ExprVariable _ av)) ->
do chan'
tell ["<<tockSendableArrayOfBytes("]
genPoint cv
tell [");"]
chan'
tell ["<<tockSendableArrayOfBytes("]
genPoint av
tell [");"]
(A.OutExpression _ (A.ExprVariable _ sv)) ->
do t <- typeOfVariable chan
tsv <- typeOfVariable sv
case (byteArrayChan t,tsv) of
(True,_) -> do chan'
tell ["<<tockSendableArrayOfBytes("]
genPoint sv
tell [");"]
(False,A.Array {}) -> do tell ["tockSendArray("]
chan'
tell [","]
call genVariable ops sv
tell [");"]
(False,_) -> do chan'
tell ["<<"]
genNonPoint sv
tell [";"]
where
chan' = genCPPCSPChannelOutput ops chan
byteArrayChan :: A.Type -> Bool
byteArrayChan (A.Chan _ _ (A.UserProtocol _)) = True
byteArrayChan (A.Chan _ _ A.Any) = True
byteArrayChan (A.Chan _ _ (A.Counted _ _)) = True
byteArrayChan _ = False
genPoint :: A.Variable -> CGen()
genPoint v = do t <- typeOfVariable v
when (not $ isPoint t) $ tell ["&"]
call genVariable ops v
genNonPoint :: A.Variable -> CGen()
genNonPoint v = do t <- typeOfVariable v
when (isPoint t) $ tell ["*"]
call genVariable ops v
isPoint :: A.Type -> Bool
isPoint (A.Record _) = True
isPoint (A.Array _ _) = True
isPoint _ = False
-- FIXME Should be a generic helper somewhere (along with the others from GenerateC)
-- | Helper function to place a comma between items, but not before or after
@ -1028,6 +1058,12 @@ cppgenType ops (A.Chan dir attr t)
cppTypeInsideChannel ops A.Any = tell ["tockSendableArrayOfBytes"]
cppTypeInsideChannel ops (A.Counted _ _) = tell ["tockSendableArrayOfBytes"]
cppTypeInsideChannel ops (A.UserProtocol _) = tell ["tockSendableArrayOfBytes"]
cppTypeInsideChannel ops (A.Array ds t)
= do tell ["tockSendableArray<"]
call genType ops t
tell [","]
tell $ intersperse "*" [case d of A.Dimension n -> show n | d <- ds]
tell [">/**/"]
cppTypeInsideChannel ops t = call genType ops t
cppgenType ops t
= case call getScalarType ops t of

View File

@ -244,6 +244,13 @@ testGenType = TestList
--Counted:
,testBoth "GenType 1000" "Channel" "csp::One2OneChannel<tockSendableArrayOfBytes>" (tcall genType $ A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.Counted A.Int A.Int)
--Channels of arrays are special in C++:
,testBoth "GenType 1100" "Channel" "csp::One2OneChannel<tockSendableArray<int,6>>"
(tcall genType $ A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.Array [A.Dimension 6] A.Int)
,testBoth "GenType 1101" "Channel" "csp::One2OneChannel<tockSendableArray<int,6*7*8>>"
(tcall genType $ A.Chan A.DirUnknown (A.ChanAttributes False False) $ A.Array [A.Dimension 6,A.Dimension 7,A.Dimension 8] A.Int)
]
testStop :: Test
@ -692,39 +699,54 @@ testOutput = TestList
,testBothSame "testOutput 1" "^" ((tcall2 genOutput undefined [undefined]) . overOutputItem)
,testBothSame "testOutput 2" "^^^" ((tcall2 genOutput undefined [undefined,undefined,undefined]) . overOutputItem)
,testBothS "testOutput 100" "ChanOutInt(@,bar_foo);^" "tockSendInt(@->writer(),bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chan) bar []) . overOutput) state
,testBothS "testOutput 101" "ChanOutInt(@,bar_foo);^" "tockSendInt(@,bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chanOut) bar []) . overOutput) state
,testBothS "testOutput 100" "ChanOutInt((&c),bar_foo);^" "tockSendInt((&c)->writer(),bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chan) bar []) . overOutput) state
,testBothS "testOutput 101" "ChanOutInt(cOut,bar_foo);^" "tockSendInt(cOut,bar_foo);^" ((tcall3 genOutputCase (A.Variable emptyMeta chanOut) bar []) . overOutput) state
--Integers are a special case in the C backend:
,testOutputItem 200 "ChanOutInt(@,$);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ intLiteral 0) A.Int
,testOutputItem 201 "ChanOutInt(@,$);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ exprVariable "x") A.Int
,testOutputItem 201 "ChanOutInt(#,x);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
--A plain type on the channel of the right type:
,testOutputItem 202 "ChanOut(@,&@,^);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ exprVariable "x") A.Int64
--A record type on the channel of the right type (because records are pointed to, so they shouldn't need the address-of operator):
,testOutputItem 202 "ChanOut(@,@,^);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ exprVariable "x") (A.Record foo)
,testOutputItem 202 "ChanOut(#,&x,^);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int64
--A record type on the channel of the right type (because records are always referenced by pointer):
,testOutputItem 203 "ChanOut(#,(&x),^);" "#<<*(&x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Record foo)
--A fixed size array on the channel of the right type:
,testOutputItem 203 "ChanOut(@,@,^);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6] A.Int)
,testOutputItem 204 "ChanOut(@,@,^);" ("@->writer()<<$;", "@<<$;") (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6, A.Dimension 7, A.Dimension 8] A.Int)
,testOutputItem 204 "ChanOut(#,x,^);" "tockSendArray(#,x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6] A.Int)
,testOutputItem 205 "ChanOut(#,x,^);" "tockSendArray(#,x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6, A.Dimension 7, A.Dimension 8] A.Int)
--A counted array:
,testOutputItem 205 "ChanOutInt(@,$);ChanOut(@,@,$*^);" ("tockSendInt(@->writer(),$);@->writer()<<$;", "tockSendInt(@,$);@<<$;")
,testOutputItem 206 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int A.Int)
,testOutputItem 206 "ChanOutInt(@,$);ChanOut(@,@,$*^);" ("tockSendInt(@->writer(),$);@->writer()<<$;", "tockSendInt(@,$);@<<$;")
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int (A.Array [A.Dimension 8] A.Int))
--TODO add a pass that makes sure all outputs are either of type Int or are variables. Including count for counted items
--TODO add a pass that makes sure all outputs are variables. Including count for counted items
--Test sending things that are part of protocols (this will require different code in the C++ backend)
,testOutputItemProt 301 "ChanOutInt(#,x);" "#<<tockSendableArrayOfBytes(&x);" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
,testOutputItemProt 302 "ChanOut(#,&x,^);" "#<<tockSendableArrayOfBytes(&x);" (A.OutExpression emptyMeta $ exprVariable "x") A.Int64
,testOutputItemProt 303 "ChanOut(#,(&x),^);" "#<<tockSendableArrayOfBytes((&x));" (A.OutExpression emptyMeta $ exprVariable "x") (A.Record foo)
,testOutputItemProt 304 "ChanOut(#,x,^);" "#<<tockSendableArrayOfBytes(x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6] A.Int)
,testOutputItemProt 305 "ChanOut(#,x,^);" "#<<tockSendableArrayOfBytes(x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6, A.Dimension 7, A.Dimension 8] A.Int)
,testOutputItemProt 306 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int A.Int)
--TODO test sending things that are part of protocols (this will require different code in the C++ backend)
]
where
testOutputItem :: Int -> String -> (String,String) -> A.OutputItem -> A.Type -> Test
testOutputItem n eC (eCPP,eCPP_Out) oi t = TestList
testOutputItem :: Int -> String -> String -> A.OutputItem -> A.Type -> Test
testOutputItem n eC eCPP oi t = testOutputItem' n eC eCPP oi t t
-- Tests sending things over channels of protocol or ANY
testOutputItemProt :: Int -> String -> String -> A.OutputItem -> A.Type -> Test
testOutputItemProt n eC eCPP oi t = TestList [testOutputItem' n eC eCPP oi t (A.UserProtocol foo),testOutputItem' n eC eCPP oi t A.Any]
testOutputItem' :: Int -> String -> String -> A.OutputItem -> A.Type -> A.Type -> Test
testOutputItem' n eC eCPP oi t ct = TestList
[
testBothS ("testOutput " ++ show n) eC eCPP ((tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi) . over) (state A.DirUnknown)
,testBothS ("testOutput [out] " ++ show n) eC eCPP_Out ((tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi) . over) (state A.DirOutput)
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 [out] " ++ show n) (hashIs "c" eC) (hashIs "c" eCPP) ((tcall2 genOutputItem (A.Variable emptyMeta $ simpleName "c") oi) . over) (state A.DirOutput)
]
where
state dir = do defineName (simpleName "c") $ simpleDefDecl "c" (A.Chan dir (A.ChanAttributes False False) t)
hashIs x y = subRegex (mkRegex "#") y x
state dir = do defineName (simpleName "c") $ simpleDefDecl "c" (A.Chan dir (A.ChanAttributes False False) ct)
case t of
A.Counted t t' -> do defineName (simpleName "x") $ simpleDefDecl "x" t
defineName (simpleName "xs") $ simpleDefDecl "xs" (A.Array [A.Dimension 6] t')
@ -734,9 +756,9 @@ testOutput = TestList
chanOut = simpleName "cOut"
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)
overOutput ops = ops {genVariable = override1 at, genOutput = override2 caret}
overOutput ops = ops {genOutput = override2 caret}
overOutputItem ops = ops {genOutputItem = override2 caret}
over ops = ops {genVariable = override1 at, genExpression = override1 dollar, genBytesIn = override2 caret}
over ops = ops {genBytesIn = override2 caret}
---Returns the list of tests:
tests :: Test

View File

@ -313,35 +313,6 @@ public:
return tockArrayView<const T,DIMS>((const T*)realArray,std::make_pair(dims,totalSubDim));
}
inline tockArrayView<typename boost::remove_const<T>::type,DIMS> versionToSend()
{
return tockArrayView<typename boost::remove_const<T>::type,DIMS>(const_cast<typename boost::remove_const<T>::type*>(realArray),std::make_pair(dims,totalSubDim));
}
inline const tockArrayView<typename boost::remove_const<T>::type,DIMS> versionToSend() const
{
return tockArrayView<typename boost::remove_const<T>::type,DIMS>(const_cast<typename boost::remove_const<T>::type*>(realArray),std::make_pair(dims,totalSubDim));
}
inline tockArrayView& operator=(const tockArrayView& tav)
{
//TODO investigate speeding up when T is primitive (maybe there's a boost class for that?)
unsigned n = tav.size();
for (unsigned i = 0;i < n;i++)
{
realArray[i] = tav.realArray[i];
}
dims = tav.dims;
totalSubDim = tav.totalSubDim;
return *this;
}
inline tockArrayView& operator=(const tockAny&)
{
//TODO later on
}
};
template <typename T>
@ -405,3 +376,29 @@ void tockRecvInt(const csp::Chanin<tockSendableArrayOfBytes>& c, unsigned int* p
tockSendableArrayOfBytes d(sizeof(unsigned int),p);
c >> d;
}
template <typename T, unsigned N>
class tockSendableArray
{
private:
tockSendableArrayOfBytes aob;
public:
template <unsigned D>
inline explicit tockSendableArray(const tockArrayView<T,D>& arr)
: aob(N*sizeof(T),arr.data())
{
}
};
template <typename T, unsigned N, unsigned D>
void tockSendArray(const csp::Chanout< tockSendableArray<T,N> >& out,const tockArrayView<T,D>& arr)
{
out << tockSendableArray<T,N>(arr);
}
template <typename T, unsigned N, unsigned D>
void tockRecvArray(const csp::Chanin< tockSendableArray<T,N> >& in,const tockArrayView<T,D>& arr)
{
tockSendableArray<T,N> tsa(arr);
in >> tsa;
}