Convert the C backend to the new CIF API (mostly).

Most of this is mechanical: changing function names, and carrying the "wptr"
argument around. I've made the code for computing Expressions from Structureds
a bit more generic too.

The only complex bit is the handling of PAR processes, which I'm not very happy
with at the moment; they used to use the normal C calling convention, but now
you need to pack the arguments into the workspace. I'm handling this at the
moment by generating wrapper functions that do the unpacking, but it would be
better in the future to make the wrapper PROCs that we already generate have
the right interface.

This won't work for programs that use any of the top-level channels yet, since
there are no handlers for them.
This commit is contained in:
Adam Sampson 2008-03-07 17:50:10 +00:00
parent 87a1c39411
commit 2f7539bcdb
5 changed files with 197 additions and 172 deletions

View File

@ -160,16 +160,20 @@ cgenTopLevel s
cs <- get
(tlpName, chans) <- tlpInterface
tell ["extern int " ++ nameString n ++ "_stack_size;\n"
| n <- tlpName : (Set.toList $ csParProcs cs)]
sequence_ $ map (call genForwardDeclaration)
(listify (const True :: A.Specification -> Bool) s)
tell ["/* ", show $ csParProcs cs, " */\n"]
sequence_ [do tell ["extern int " ++ nameString n ++ "_wrapper_stack_size;\n"]
cgenProcWrapper n
| n <- tlpName : (Set.toList $ csParProcs cs)]
sequence_ $ map (call genForwardDeclaration) (listify (const True :: A.Specification -> Bool) s)
call genStructured s (\m _ -> tell ["\n#error Invalid top-level item: ", show m])
tell ["void tock_main (Workspace wptr) {\n\
\ Workspace tlp = ProcAlloc (wptr, ", show $ length chans, ", "]
genName tlpName
tell ["_stack_size);\n"]
tell ["_wrapper_stack_size);\n"]
sequence_ [do tell [" ProcParam (wptr, tlp, " ++ show i ++ ", "]
call genTLPChannel c
tell [");\n"]
@ -180,7 +184,7 @@ cgenTopLevel s
\ LightProcBarrierInit (wptr, &bar, 1);\n\
\ LightProcStart (wptr, &bar, tlp, (Process) "]
genName tlpName
tell [");\n\
tell ["_wrapper);\n\
\ LightProcBarrierWait (wptr, &bar);\n\
\ Shutdown (wptr);\n\
\}\n\
@ -280,7 +284,7 @@ cgetScalarType A.Int32 = Just "int32_t"
cgetScalarType A.Int64 = Just "int64_t"
cgetScalarType A.Real32 = Just "float"
cgetScalarType A.Real64 = Just "double"
cgetScalarType A.Timer = Just "Time"
cgetScalarType A.Timer = Just "Time" -- Not used in the C backend.
cgetScalarType A.Time = Just "Time"
cgetScalarType _ = Nothing
@ -888,7 +892,7 @@ cgenInputItem :: A.Variable -> A.InputItem -> CGen ()
cgenInputItem c (A.InCounted m cv av)
= do call genInputItem c (A.InVariable m cv)
t <- typeOfVariable av
tell ["ChanIn("]
tell ["ChanIn(wptr,"]
call genVariable c
tell [","]
fst $ abbrevVariable A.Abbrev t av
@ -903,13 +907,13 @@ cgenInputItem c (A.InVariable m v)
let rhs = fst $ abbrevVariable A.Abbrev t v
case t of
A.Int ->
do tell ["ChanInInt("]
do tell ["ChanInInt(wptr,"]
call genVariable c
tell [","]
rhs
tell [");"]
_ ->
do tell ["ChanIn("]
do tell ["ChanIn(wptr,"]
call genVariable c
tell [","]
rhs
@ -923,7 +927,7 @@ cgenOutputItem c (A.OutCounted m ce ae)
t <- typeOfExpression ae
case ae of
A.ExprVariable m v ->
do tell ["ChanOut("]
do tell ["ChanOut(wptr,"]
call genVariable c
tell [","]
fst $ abbrevVariable A.Abbrev t v
@ -937,13 +941,13 @@ cgenOutputItem c (A.OutExpression m e)
= do t <- typeOfExpression e
case (t, e) of
(A.Int, _) ->
do tell ["ChanOutInt("]
do tell ["ChanOutInt(wptr,"]
call genVariable c
tell [","]
call genExpression e
tell [");"]
(_, A.ExprVariable _ v) ->
do tell ["ChanOut("]
do tell ["ChanOut(wptr,"]
call genVariable c
tell [","]
fst $ abbrevVariable A.Abbrev t v
@ -1166,6 +1170,7 @@ cgenDeclaration (A.Array ds t) n True
tell ["int "]
genName n
tell ["_sizes[",show $ length ds,"];"]
cgenDeclaration A.Timer _ _ = return ()
cgenDeclaration t n _
= do call genType t
tell [" "]
@ -1201,7 +1206,7 @@ cgenArraySizesLiteral n (A.Array ds _)
-- | Initialise an item being declared.
cdeclareInit :: Meta -> A.Type -> A.Variable -> Maybe A.Expression -> Maybe (CGen ())
cdeclareInit _ (A.Chan A.DirUnknown _ _) var _
= Just $ do tell ["ChanInit("]
= Just $ do tell ["ChanInit(wptr,"]
call genVariableUnchecked var
tell [");"]
cdeclareInit m t@(A.Array ds t') var _
@ -1327,7 +1332,7 @@ cintroduceSpec (A.Specification _ n (A.Proc _ sm fs p))
= do call genSpecMode sm
tell ["void "]
genName n
tell [" (Process *me"]
tell [" (Workspace wptr"]
call genFormals fs
tell [") {\n"]
call genProcess p
@ -1365,13 +1370,12 @@ cgenRecordTypeSpec n b fs
genName n
tell [";"]
cgenForwardDeclaration :: A.Specification -> CGen ()
cgenForwardDeclaration (A.Specification _ n (A.Proc _ sm fs _))
= do call genSpecMode sm
tell ["void "]
genName n
tell [" (Process *me"]
tell [" (Workspace wptr"]
call genFormals fs
tell [");"]
cgenForwardDeclaration (A.Specification _ n (A.RecordType _ b fs))
@ -1401,43 +1405,88 @@ cgenActuals :: [A.Actual] -> CGen ()
cgenActuals as = prefixComma (map (call genActual) as)
cgenActual :: A.Actual -> CGen ()
cgenActual actual
= case actual of
A.ActualExpression t e ->
case (t, e) of
(A.Array _ _, A.ExprVariable _ v) ->
do call genVariable v
tell [","]
call genVariable v
tell ["_sizes"]
_ -> call genExpression e
A.ActualVariable am t v ->
case t of
A.Array _ _ ->
do call genVariable v
tell [","]
call genVariable v
tell ["_sizes"]
_ -> fst $ abbrevVariable am t v
numCArgs :: [A.Actual] -> Int
numCArgs [] = 0
numCArgs (A.ActualVariable _ (A.Array _ _) _:fs) = 2 + numCArgs fs
numCArgs (A.ActualExpression (A.Array _ _) _:fs) = 2 + numCArgs fs
numCArgs (_:fs) = 1 + numCArgs fs
cgenActual actual = seqComma $ realActuals actual
cgenFormals :: [A.Formal] -> CGen ()
cgenFormals fs = prefixComma (map (call genFormal) fs)
cgenFormal :: A.Formal -> CGen ()
cgenFormal (A.Formal am t n)
cgenFormal f = seqComma [t >> tell [" "] >> n | (t, n) <- realFormals f]
-- | Return generators for all the real actuals corresponding to a single
-- actual.
realActuals :: A.Actual -> [CGen ()]
realActuals (A.ActualExpression t e)
= case (t, e) of
(A.Array _ _, A.ExprVariable _ v) ->
[call genVariable v,
call genVariable v >> tell ["_sizes"]]
_ -> [call genExpression e]
realActuals (A.ActualVariable am t v)
= case t of
A.Array _ _ ->
[call genVariable v,
call genVariable v >> tell ["_sizes"]]
_ -> [fst $ abbrevVariable am t v]
-- | Return (type, name) generator pairs for all the real formals corresponding
-- to a single formal.
realFormals :: A.Formal -> [(CGen (), CGen ())]
realFormals (A.Formal am t n)
= case t of
A.Array _ t' ->
do call genDecl am t n
tell [", const int *"]
genName n
tell ["_sizes"]
_ -> call genDecl am t n
[(mainType, mainName),
(tell ["const int *"], genName n >> tell ["_sizes"])]
_ -> [(mainType, mainName)]
where
mainType = cgenDeclType am t
mainName = genName n
-- | Generate a wrapper function for a PAR subprocess.
cgenProcWrapper :: A.Name -> CGen ()
cgenProcWrapper n
= do st <- specTypeOfName n
let fs = case st of A.Proc _ _ fs _ -> fs
let rfs = concatMap realFormals fs
tell ["static void "]
genName n
tell ["_wrapper (Workspace wptr) {\n"]
sequence_ [unpackParam num rf | (num, rf) <- zip [0..] rfs]
genName n
tell [" (wptr"]
prefixComma [n | (_, n) <- rfs]
tell [");\n"]
tell ["}\n"]
where
unpackParam :: Int -> (CGen (), CGen ()) -> CGen ()
unpackParam num (t, n)
= do t
tell [" "]
n
tell [" = ProcGetParam (wptr, " ++ show num ++ ", "]
t
tell [");\n"]
-- | Generate a ProcAlloc for a PAR subprocess, returning a nonce for the
-- workspace pointer and the name of the function to call.
cgenProcAlloc :: A.Name -> [A.Actual] -> CGen (String, CGen ())
cgenProcAlloc n as
= do let ras = concatMap realActuals as
ws <- makeNonce "workspace"
tell ["Workspace ", ws, " = ProcAlloc (wptr, ", show $ length ras, ", "]
genName n
tell ["_wrapper_stack_size);\n"]
sequence_ [do tell ["ProcParam (wptr, ", ws, ", ", show num, ", "]
ra
tell [");\n"]
| (num, ra) <- zip [(0 :: Int)..] ras]
return (ws, genName n >> tell ["_wrapper"])
--}}}
--{{{ processes
@ -1447,7 +1496,7 @@ cgenProcess p = case p of
A.Input m c im -> call genInput c im
A.Output m c ois -> call genOutput c ois
A.OutputCase m c t ois -> call genOutputCase c t ois
A.GetTime m v -> call genGetTime m v
A.GetTime m v -> call genGetTime v
A.Wait m wm e -> call genWait wm e
A.Skip m -> tell ["/* skip */\n"]
A.Stop m -> call genStop m "STOP process"
@ -1494,31 +1543,23 @@ cgenInput c im
_ -> call genMissing $ "genInput " ++ show im
cgenTimerRead :: A.Variable -> A.Variable -> CGen ()
cgenTimerRead c v
= do tell ["ProcTime (&"]
call genVariable c
tell [");\n"]
call genVariable v
tell [" = "]
call genVariable c
tell [";\n"]
cgenTimerRead _ v = cgenGetTime v
cgenTimerWait :: A.Expression -> CGen ()
cgenTimerWait e
= do tell ["ProcTimeAfter("]
= do tell ["TimerWait(wptr,"]
call genExpression e
tell [");"]
cgenGetTime :: Meta -> A.Variable -> CGen ()
cgenGetTime m v
= do tell ["ProcTime(&"]
call genVariable v
tell [");"]
cgenGetTime :: A.Variable -> CGen ()
cgenGetTime v
= do call genVariable v
tell [" = TimerRead(wptr);"]
cgenWait :: A.WaitMode -> A.Expression -> CGen ()
cgenWait A.WaitUntil e = call genTimerWait e
cgenWait A.WaitFor e
= do tell ["ProcAfter("]
= do tell ["TimerDelay(wptr,"]
call genExpression e
tell [");"]
@ -1531,7 +1572,7 @@ cgenOutputCase :: A.Variable -> A.Name -> [A.OutputItem] -> CGen ()
cgenOutputCase c tag ois
= do t <- typeOfVariable c
let proto = case t of A.Chan _ _ (A.UserProtocol n) -> n
tell ["ChanOutInt("]
tell ["ChanOutInt(wptr,"]
call genVariable c
tell [","]
genName tag
@ -1545,7 +1586,7 @@ cgenStop :: Meta -> String -> CGen ()
cgenStop m s
= do tell ["occam_stop("]
genMeta m
tell [",\"", s, "\");"]
tell [",1,\"", s, "\");"]
--}}}
--{{{ seq
cgenSeq :: A.Structured A.Process -> CGen ()
@ -1616,66 +1657,46 @@ cgenWhile e p
tell ["}"]
--}}}
--{{{ par
-- FIXME: The ParMode is now ignored (as it is in occ21), so PRI PAR behaves
-- the same as PAR.
cgenPar :: A.ParMode -> A.Structured A.Process -> CGen ()
cgenPar pm s
= do (size, _, _) <- constantFold $ addOne (sizeOfStructured s)
pids <- makeNonce "pids"
pris <- makeNonce "priorities"
index <- makeNonce "i"
when (pm == A.PriPar) $
do tell ["int ", pris, "["]
call genExpression size
tell ["];\n"]
tell ["Process *", pids, "["]
call genExpression size
tell ["];\n"]
tell ["int ", index, " = 0;\n"]
call genStructured s (createP pids pris index)
tell [pids, "[", index, "] = NULL;\n"]
tell ["if(",pids,"[0] != NULL){"] -- CIF seems to deadlock when you give ProcParList a list
-- beginning with NULL (i.e. with no processes)
case pm of
A.PriPar -> tell ["ProcPriParList (", pids, ", ", pris, ");\n"]
_ -> tell ["ProcParList (", pids, ");\n"]
tell ["}"]
tell [index, " = 0;\n"]
call genStructured s (freeP pids index)
where
createP pids pris index _ p
= do when (pm == A.PriPar) $
tell [pris, "[", index, "] = ", index, ";\n"]
tell [pids, "[", index, "++] = "]
genProcAlloc p
tell [";\n"]
freeP pids index _ _
= do tell ["ProcAllocClean (", pids, "[", index, "++]);\n"]
= do (count, _, _) <- constantFold $ countStructured s
genProcAlloc :: A.Process -> CGen ()
genProcAlloc (A.ProcCall m n as)
= do tell ["ProcAlloc ("]
genName n
let stackSize = nameString n ++ "_stack_size"
tell [", ", stackSize, ", ", show $ numCArgs as]
call genActuals as
tell [")"]
genProcAlloc p = call genMissing $ "genProcAlloc " ++ show p
bar <- makeNonce "par_barrier"
tell ["LightProcBarrier ", bar, ";\n"]
tell ["LightProcBarrierInit (wptr, &", bar, ", "]
call genExpression count
tell [");\n"]
call genStructured s (startP bar)
tell ["LightProcBarrierWait (wptr, &", bar, ");\n"]
where
startP :: String -> Meta -> A.Process -> CGen ()
startP bar _ (A.ProcCall _ n as)
= do (ws, func) <- cgenProcAlloc n as
tell ["LightProcStart (wptr, &", bar, ", ", ws, ", "]
func
tell [");\n"]
--}}}
--{{{ alt
cgenAlt :: Bool -> A.Structured A.Alternative -> CGen ()
cgenAlt isPri s
= do tell ["AltStart ();\n"]
= do tell ["Alt (wptr);\n"]
tell ["{\n"]
genAltEnable s
tell ["}\n"]
-- Like occ21, this is always a PRI ALT, so we can use it for both.
tell ["AltWait ();\n"]
tell ["AltWait (wptr);\n"]
id <- makeNonce "alt_id"
tell ["int ", id, " = 0;\n"]
tell ["{\n"]
genAltDisable id s
tell ["}\n"]
fired <- makeNonce "alt_fired"
tell ["int ", fired, " = AltEnd ();\n"]
tell ["int ", fired, " = AltEnd (wptr);\n"]
tell [id, " = 0;\n"]
label <- makeNonce "alt_end"
tell ["{\n"]
@ -1690,10 +1711,10 @@ cgenAlt isPri s
= case alt of
A.Alternative _ c im _ -> doIn c im
A.AlternativeCond _ e c im _ -> withIf e $ doIn c im
A.AlternativeSkip _ e _ -> withIf e $ tell ["AltEnableSkip ();\n"]
A.AlternativeSkip _ e _ -> withIf e $ tell ["AltEnableSkip (wptr);\n"]
--transformWaitFor should have removed all A.WaitFor guards (transforming them into A.WaitUntil):
A.AlternativeWait _ A.WaitUntil e _ ->
do tell ["AltEnableTimer ( "]
do tell ["AltEnableTimer (wptr,"]
call genExpression e
tell [" );\n"]
@ -1701,11 +1722,11 @@ cgenAlt isPri s
= do case im of
A.InputTimerRead _ _ -> call genMissing "timer read in ALT"
A.InputTimerAfter _ time ->
do tell ["AltEnableTimer ("]
do tell ["AltEnableTimer (wptr,"]
call genExpression time
tell [");\n"]
_ ->
do tell ["AltEnableChannel ("]
do tell ["AltEnableChannel (wptr,"]
call genVariable c
tell [");\n"]
@ -1716,20 +1737,20 @@ cgenAlt isPri s
= case alt of
A.Alternative _ c im _ -> doIn c im
A.AlternativeCond _ e c im _ -> withIf e $ doIn c im
A.AlternativeSkip _ e _ -> withIf e $ tell ["AltDisableSkip (", id, "++);\n"]
A.AlternativeSkip _ e _ -> withIf e $ tell ["AltDisableSkip (wptr,", id, "++);\n"]
A.AlternativeWait _ A.WaitUntil e _ ->
do tell ["AltDisableTimer (", id, "++, "]
do tell ["AltDisableTimer (wptr,", id, "++, "]
call genExpression e
tell [");\n"]
doIn c im
= do case im of
A.InputTimerRead _ _ -> call genMissing "timer read in ALT"
A.InputTimerAfter _ time ->
do tell ["AltDisableTimer (", id, "++, "]
do tell ["AltDisableTimer (wptr,", id, "++, "]
call genExpression time
tell [");\n"]
_ ->
do tell ["AltDisableChannel (", id, "++, "]
do tell ["AltDisableChannel (wptr,", id, "++, "]
call genVariable c
tell [");\n"]
@ -1767,7 +1788,7 @@ withIf cond body
cgenProcCall :: A.Name -> [A.Actual] -> CGen ()
cgenProcCall n as
= do genName n
tell [" (me"]
tell [" (wptr"]
call genActuals as
tell [");\n"]
--}}}

View File

@ -122,7 +122,7 @@ data GenOps = GenOps {
genFuncDyadic :: Meta -> String -> A.Expression -> A.Expression -> CGen (),
genFuncMonadic :: Meta -> String -> A.Expression -> CGen (),
-- | Gets the current time into the given variable
genGetTime :: Meta -> A.Variable -> CGen (),
genGetTime :: A.Variable -> CGen (),
-- | Generates an IF statement (which can have replicators, specifications and such things inside it).
genIf :: Meta -> A.Structured A.Choice -> CGen (),
genInput :: A.Variable -> A.InputMode -> CGen (),

View File

@ -248,8 +248,8 @@ cppgenTimerRead c v
call genVariable c
tell ["),4294967296.0);\n"]
cppgenGetTime :: Meta -> A.Variable -> CGen ()
cppgenGetTime m v
cppgenGetTime :: A.Variable -> CGen ()
cppgenGetTime v
= do tell ["csp::CurrentTime(&"]
call genVariable v
tell [");"]

View File

@ -285,7 +285,7 @@ testGenType = TestList
testStop :: Test
testStop =
testBoth "Stop" "occam_stop(\"foo:4:9\",\"bar\");" "throw StopException(\"foo:4:9\" \"bar\");" (tcall2 genStop (Meta (Just "foo") 4 9) "bar")
testBoth "Stop" "occam_stop(\"foo:4:9\",1,\"bar\");" "throw StopException(\"foo:4:9\" \"bar\");" (tcall2 genStop (Meta (Just "foo") 4 9) "bar")
testArraySizes :: Test
testArraySizes = TestList
@ -487,16 +487,16 @@ testDeclareInitFree = TestLabel "testDeclareInitFree" $ TestList
,testAllSameInit 10 ("foo=3;","") A.Int (intLiteral 3)
-- Channel types:
,testAll 1 ("ChanInit((&foo));","") ("","") $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int
,testAll 1 ("ChanInit(wptr,(&foo));","") ("","") $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int
,testAllSame 2 ("","") $ A.Chan A.DirInput (A.ChanAttributes False False) A.Int
-- Plain arrays:
,testAllSame 3 ("","") $ A.Array [A.Dimension 4] A.Int
-- Channel arrays:
,testAll 4 ("tock_init_chan_array(foo_storage,foo,4);^ChanInit(foo[0]);^","") ("tockInitChanArray(foo_storage,foo_actual,4);","") $ A.Array [A.Dimension 4] $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int
,testAll 4 ("tock_init_chan_array(foo_storage,foo,4);^ChanInit(wptr,foo[0]);^","") ("tockInitChanArray(foo_storage,foo_actual,4);","") $ A.Array [A.Dimension 4] $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int
-- The subscripting on this test is incomplete; it should probably be fixed at some point:
,testAll 5 ("tock_init_chan_array(foo_storage,foo,4*5*6);^ChanInit(foo[0*foo_sizes[1]*foo_sizes[2]]);^","") ("tockInitChanArray(foo_storage,foo_actual,4*5*6);","") $
,testAll 5 ("tock_init_chan_array(foo_storage,foo,4*5*6);^ChanInit(wptr,foo[0*foo_sizes[1]*foo_sizes[2]]);^","") ("tockInitChanArray(foo_storage,foo_actual,4*5*6);","") $
A.Array [A.Dimension 4,A.Dimension 5,A.Dimension 6] $ A.Chan A.DirUnknown (A.ChanAttributes False False) A.Int
,testAllSame 6 ("","") $ A.Array [A.Dimension 4] $ A.Chan A.DirInput (A.ChanAttributes False False) A.Int
@ -889,7 +889,7 @@ testCase = TestList
over = local $ \ops -> ops {genExpression = override1 dollar, genProcess = override1 at, genStop = override2 caret, genSpec = override2 hash}
testGetTime :: Test
testGetTime = testBoth "testGetTime 0" "ProcTime(&@);" "csp::CurrentTime(&@);" (over (tcall2 genGetTime emptyMeta undefined))
testGetTime = testBoth "testGetTime 0" "@ = TimerRead(wptr);" "csp::CurrentTime(&@);" (over (tcall genGetTime undefined))
where
over :: Override
over = local $ \ops -> ops {genVariable = override1 at}
@ -897,8 +897,8 @@ testGetTime = testBoth "testGetTime 0" "ProcTime(&@);" "csp::CurrentTime(&@);" (
testWait :: Test
testWait = TestList
[
testBoth "testWait 0" "ProcTimeAfter($);" "csp::SleepUntil($);" (over (tcall2 genWait A.WaitUntil undefined))
,testBoth "testWait 1" "ProcAfter($);" "csp::SleepFor($);" (over (tcall2 genWait A.WaitFor undefined))
testBoth "testWait 0" "TimerWait(wptr,$);" "csp::SleepUntil($);" (over (tcall2 genWait A.WaitUntil undefined))
,testBoth "testWait 1" "TimerDelay(wptr,$);" "csp::SleepFor($);" (over (tcall2 genWait A.WaitFor undefined))
]
where
over :: Override
@ -936,43 +936,43 @@ testInput = TestList
,testBothSame "testInput 2" "^^^" (overInputItemCase (tcall2 genInput undefined $ A.InputSimple undefined [undefined, undefined, undefined]))
-- Reading an integer (special case in the C backend):
,testInputItem 100 "ChanInInt(#,&x);" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int
,testInputItem 100 "ChanInInt(wptr,#,&x);" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int
-- Reading a other plain types:
,testInputItem 101 "ChanIn(#,&x,^(Int8));" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int8
,testInputItem 102 ("ChanIn(#,(&x),^(" ++ show (A.Record foo) ++ "));") "#>>*(&x);" (A.InVariable emptyMeta $ variable "x") (A.Record foo)
,testInputItem 101 "ChanIn(wptr,#,&x,^(Int8));" "#>>x;" (A.InVariable emptyMeta $ variable "x") A.Int8
,testInputItem 102 ("ChanIn(wptr,#,(&x),^(" ++ show (A.Record foo) ++ "));") "#>>*(&x);" (A.InVariable emptyMeta $ variable "x") (A.Record foo)
-- Reading into a fixed size array:
,testInputItem 103 "ChanIn(#,x,^(Array [Dimension 8] Int));" "tockRecvArray(#,x);" (A.InVariable emptyMeta $ variable "x") $ A.Array [A.Dimension 8] A.Int
,testInputItem 103 "ChanIn(wptr,#,x,^(Array [Dimension 8] Int));" "tockRecvArray(#,x);" (A.InVariable emptyMeta $ variable "x") $ A.Array [A.Dimension 8] A.Int
-- Reading into subscripted variables:
,testInputItem 110 "ChanInInt(#,&xs$);" "#>>xs$;" (A.InVariable emptyMeta $ sub0 $ variable "xs") A.Int
,testInputItem 110 "ChanInInt(wptr,#,&xs$);" "#>>xs$;" (A.InVariable emptyMeta $ sub0 $ variable "xs") A.Int
-- Reading a other plain types:
,testInputItem 111 "ChanIn(#,&xs$,^(Int8));" "#>>xs$;" (A.InVariable emptyMeta $ sub0 $ variable "xs") A.Int8
,testInputItem 112 ("ChanIn(#,(&xs$),^(" ++ show (A.Record foo) ++ "));") "#>>*(&xs$);" (A.InVariable emptyMeta $ sub0 $ variable "xs") (A.Record foo)
,testInputItem 111 "ChanIn(wptr,#,&xs$,^(Int8));" "#>>xs$;" (A.InVariable emptyMeta $ sub0 $ variable "xs") A.Int8
,testInputItem 112 ("ChanIn(wptr,#,(&xs$),^(" ++ show (A.Record foo) ++ "));") "#>>*(&xs$);" (A.InVariable emptyMeta $ sub0 $ variable "xs") (A.Record foo)
-- A counted array of Int:
,testInputItem 200 "ChanInInt(#,&x);ChanIn(#,xs,x*^(Int));"
,testInputItem 200 "ChanInInt(wptr,#,&x);ChanIn(wptr,#,xs,x*^(Int));"
"tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int),&x));tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(x*^(Int),xs));"
(A.InCounted emptyMeta (variable "x") (variable "xs")) (A.Counted A.Int A.Int)
-- A counted array, counted by Int8:
,testInputItem 201 "ChanIn(#,&x,^(Int8));ChanIn(#,xs,x*^(Int));"
,testInputItem 201 "ChanIn(wptr,#,&x,^(Int8));ChanIn(wptr,#,xs,x*^(Int));"
"tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int8),&x));tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(x*^(Int),xs));"
(A.InCounted emptyMeta (variable "x") (variable "xs")) (A.Counted A.Int8 A.Int)
-- TODO reading in a counted/fixed-size array into an array of arrays (or will that have already been sliced?)
-- inputs as part of protocols/any:
,testInputItemProt 300 "ChanInInt(#,&x);" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int),&x));"
,testInputItemProt 300 "ChanInInt(wptr,#,&x);" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int),&x));"
(A.InVariable emptyMeta $ variable "x") A.Int
,testInputItemProt 301 "ChanIn(#,&x,^(Int8));" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int8),&x));"
,testInputItemProt 301 "ChanIn(wptr,#,&x,^(Int8));" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int8),&x));"
(A.InVariable emptyMeta $ variable "x") A.Int8
,testInputItemProt 302 ("ChanIn(#,(&x),^(" ++ show (A.Record foo) ++ "));") ("tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(" ++ show (A.Record foo) ++ "),(&x)));")
,testInputItemProt 302 ("ChanIn(wptr,#,(&x),^(" ++ show (A.Record foo) ++ "));") ("tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(" ++ show (A.Record foo) ++ "),(&x)));")
(A.InVariable emptyMeta $ variable "x") (A.Record foo)
,testInputItemProt 303 "ChanIn(#,x,^(Array [Dimension 8] Int));" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Array [Dimension 8] Int),x));"
,testInputItemProt 303 "ChanIn(wptr,#,x,^(Array [Dimension 8] Int));" "tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Array [Dimension 8] Int),x));"
(A.InVariable emptyMeta $ variable "x") $ A.Array [A.Dimension 8] A.Int
,testInputItemProt 400 "ChanInInt(#,&x);ChanIn(#,xs,x*^(Int));"
,testInputItemProt 400 "ChanInInt(wptr,#,&x);ChanIn(wptr,#,xs,x*^(Int));"
"tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int),&x));tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(x*^(Int),xs));"
(A.InCounted emptyMeta (variable "x") (variable "xs")) (A.Counted A.Int A.Int)
,testInputItemProt 401 "ChanIn(#,&x,^(Int8));ChanIn(#,xs,x*^(Int8));"
,testInputItemProt 401 "ChanIn(wptr,#,&x,^(Int8));ChanIn(wptr,#,xs,x*^(Int8));"
"tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(^(Int8),&x));tockRecvArrayOfBytes(#,tockSendableArrayOfBytes(x*^(Int8),xs));"
(A.InCounted emptyMeta (variable "x") (variable "xs")) (A.Counted A.Int8 A.Int8)
@ -1020,46 +1020,46 @@ testOutput = TestList
,testBothSame "testOutput 1" "^" (overOutputItem (tcall2 genOutput undefined [undefined]))
,testBothSame "testOutput 2" "^^^" (overOutputItem (tcall2 genOutput undefined [undefined,undefined,undefined]))
,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);^" (overOutput (tcall3 genOutputCase (A.Variable emptyMeta chanOut) bar [])) state
,testBothS "testOutput 100" "ChanOutInt(wptr,(&c),bar_foo);^" "tockSendInt((&c)->writer(),bar_foo);^" (overOutput (tcall3 genOutputCase (A.Variable emptyMeta chan) bar [])) state
,testBothS "testOutput 101" "ChanOutInt(wptr,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:
,testOutputItem 201 "ChanOutInt(#,x);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
,testOutputItem 201 "ChanOutInt(wptr,#,x);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
--A plain type on the channel of the right type:
,testOutputItem 202 "ChanOut(#,&x,^);" "#<<x;" (A.OutExpression emptyMeta $ exprVariable "x") A.Int64
,testOutputItem 202 "ChanOut(wptr,#,&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)
,testOutputItem 203 "ChanOut(wptr,#,(&x),^);" "#<<*(&x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Record foo)
--A fixed size array on the channel of the right type:
,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)
,testOutputItem 204 "ChanOut(wptr,#,x,^);" "tockSendArray(#,x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6] A.Int)
,testOutputItem 205 "ChanOut(wptr,#,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 206 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItem 206 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int A.Int)
--A counted array of arrays:
,testOutputItem 207 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItem 207 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int (A.Array [A.Dimension 5] A.Int))
,testOutputItem 208 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItem 208 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int (A.Array [A.Dimension 4,A.Dimension 5] A.Int))
-- Test counted arrays that do not have Int as the count type:
,testOutputItem 209 "ChanOut(#,&x,^);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItem 209 "ChanOut(wptr,#,&x,^);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int8 A.Int8)
--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);"
,testOutputItemProt 301 "ChanOutInt(wptr,#,x);" "#<<tockSendableArrayOfBytes(&x);" (A.OutExpression emptyMeta $ exprVariable "x") A.Int
,testOutputItemProt 302 "ChanOut(wptr,#,&x,^);" "#<<tockSendableArrayOfBytes(&x);" (A.OutExpression emptyMeta $ exprVariable "x") A.Int64
,testOutputItemProt 303 "ChanOut(wptr,#,(&x),^);" "#<<tockSendableArrayOfBytes((&x));" (A.OutExpression emptyMeta $ exprVariable "x") (A.Record foo)
,testOutputItemProt 304 "ChanOut(wptr,#,x,^);" "#<<tockSendableArrayOfBytes(x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6] A.Int)
,testOutputItemProt 305 "ChanOut(wptr,#,x,^);" "#<<tockSendableArrayOfBytes(x);" (A.OutExpression emptyMeta $ exprVariable "x") (A.Array [A.Dimension 6, A.Dimension 7, A.Dimension 8] A.Int)
,testOutputItemProt 306 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int A.Int)
,testOutputItemProt 307 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItemProt 307 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int (A.Array [A.Dimension 5] A.Int))
,testOutputItemProt 308 "ChanOutInt(#,x);ChanOut(#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
,testOutputItemProt 308 "ChanOutInt(wptr,#,x);ChanOut(wptr,#,xs,x*^);" "#<<tockSendableArrayOfBytes(&x);#<<tockSendableArrayOfBytes(xs);"
(A.OutCounted emptyMeta (exprVariable "x") (exprVariable "xs")) (A.Counted A.Int (A.Array [A.Dimension 4,A.Dimension 5] A.Int))

View File

@ -22,7 +22,7 @@ module Types
specTypeOfName, typeOfSpec, abbrevModeOfName, typeOfName, typeOfExpression, typeOfVariable, underlyingType, stripArrayType, abbrevModeOfVariable, abbrevModeOfSpec
, isRealType, isIntegerType, isCaseableType, resolveUserType, isSafeConversion, isPreciseConversion, isImplicitConversionRain
, returnTypesOfFunction
, BytesInResult(..), bytesInType, sizeOfReplicator, sizeOfStructured
, BytesInResult(..), bytesInType, countReplicator, countStructured, computeStructured
, makeAbbrevAM, makeConstant, addOne
, addDimensions, removeFixedDimensions, trivialSubscriptType, subscriptType, unsubscriptType
@ -261,7 +261,7 @@ typeOfExpression e
else typeOfArrayList [A.UnknownDimension] bt
A.ExprConstr m (A.RepConstr _ rep e) ->
do t <- typeOfExpression e
count <- evalIntExpression $ sizeOfReplicator rep
count <- evalIntExpression $ countReplicator rep
typeOfArrayList [A.Dimension count] t
A.AllocMobile _ t _ -> return t
--}}}
@ -577,20 +577,24 @@ bytesInType _ = return $ BIUnknown
--}}}
-- | Get the number of items a replicator produces.
sizeOfReplicator :: A.Replicator -> A.Expression
sizeOfReplicator (A.For _ _ _ count) = count
countReplicator :: A.Replicator -> A.Expression
countReplicator (A.For _ _ _ count) = count
-- | Get the number of items in a Structured as an expression.
sizeOfStructured :: Data a => A.Structured a -> A.Expression
sizeOfStructured (A.Rep m rep s)
= A.Dyadic m A.Times (sizeOfReplicator rep) (sizeOfStructured s)
sizeOfStructured (A.Spec _ _ s) = sizeOfStructured s
sizeOfStructured (A.ProcThen _ _ s) = sizeOfStructured s
sizeOfStructured (A.Several m ss)
countStructured :: Data a => A.Structured a -> A.Expression
countStructured = computeStructured (\m _ -> makeConstant m 1)
-- | Compute an expression over a Structured.
computeStructured :: Data a => (Meta -> a -> A.Expression) -> A.Structured a -> A.Expression
computeStructured f (A.Rep m rep s)
= A.Dyadic m A.Times (countReplicator rep) (computeStructured f s)
computeStructured f (A.Spec _ _ s) = computeStructured f s
computeStructured f (A.ProcThen _ _ s) = computeStructured f s
computeStructured f (A.Only m x) = f m x
computeStructured f (A.Several m ss)
= case ss of
[] -> makeConstant m 0
_ -> foldl1 (A.Dyadic m A.Plus) (map sizeOfStructured ss)
sizeOfStructured s = makeConstant (findMeta s) 1
_ -> foldl1 (A.Dyadic m A.Plus) (map (computeStructured f) ss)
-- | Add one to an expression.
addOne :: A.Expression -> A.Expression