Changed the behaviour of assignment for records
Previously, assignments of records were directly flattened into assignment of each of the fields. Now, we instead generate a copy_<recordname> inline procedure for each record definition, and compile code that uses that (for C++, we could even make this an operator= implementation later on). This allows us to re-use the proc later in the C/C++ backends if needed.
This commit is contained in:
parent
f5022228ba
commit
08d02bfb17
|
@ -89,7 +89,7 @@ removeParAssign = doGeneric `extM` doProcess
|
|||
|
||||
-- | Turn assignment of arrays and records into multiple assignments.
|
||||
flattenAssign :: Data t => t -> PassM t
|
||||
flattenAssign = doGeneric `extM` doProcess
|
||||
flattenAssign = doGeneric `extM` doProcess `ext1M` doStructured
|
||||
where
|
||||
doGeneric :: Data t => t -> PassM t
|
||||
doGeneric = makeGeneric flattenAssign
|
||||
|
@ -99,6 +99,13 @@ flattenAssign = doGeneric `extM` doProcess
|
|||
= do t <- typeOfVariable v
|
||||
assign m t v m' e
|
||||
doProcess p = doGeneric p
|
||||
|
||||
doStructured :: Data a => A.Structured a -> PassM (A.Structured a)
|
||||
doStructured (A.Spec m (A.Specification m' n t@(A.RecordType _ _ fs)) s)
|
||||
= do procSpec <- recordCopyProc n m fs
|
||||
s' <- doStructured s
|
||||
return $ A.Spec m (A.Specification m' n t) (procSpec s')
|
||||
doStructured s = doGeneric s
|
||||
|
||||
assign :: Meta -> A.Type -> A.Variable -> Meta -> A.Expression -> PassM A.Process
|
||||
assign m t@(A.Array _ _) v m' e = complexAssign m t v m' e
|
||||
|
@ -133,19 +140,30 @@ flattenAssign = doGeneric `extM` doProcess
|
|||
(A.ExprVariable m'
|
||||
(A.SubscriptedVariable m' sub srcV))
|
||||
return $ A.Rep m rep $ A.Only m inner
|
||||
A.Record _ ->
|
||||
-- Record assignments become a sequence of
|
||||
-- assignments, one for each field.
|
||||
do
|
||||
fs <- recordFields m t
|
||||
assigns <-
|
||||
sequence [do let sub = A.SubscriptField m fName
|
||||
assign m fType
|
||||
(A.SubscriptedVariable m sub destV) m'
|
||||
(A.ExprVariable m'
|
||||
(A.SubscriptedVariable m' sub srcV))
|
||||
| (fName, fType) <- fs]
|
||||
return $ A.Several m $ map (A.Only m) assigns
|
||||
A.Record n ->
|
||||
return $ A.Only m $ A.ProcCall m (n {A.nameName = "copy_" ++ A.nameName n})
|
||||
[A.ActualVariable A.Abbrev t destV, A.ActualVariable A.ValAbbrev t srcV]
|
||||
|
||||
return $ A.Seq m $ A.Spec m src $ A.Spec m dest body
|
||||
|
||||
-- TODO could make this a separate pass if we wanted (to be run first)
|
||||
recordCopyProc :: Data a => A.Name -> Meta -> [(A.Name, A.Type)] -> PassM (A.Structured a -> A.Structured a)
|
||||
recordCopyProc n m fs
|
||||
-- Record assignments become a sequence of
|
||||
-- assignments, one for each field.
|
||||
= do let t = A.Record n
|
||||
(A.Specification _ nonceLHS _) <- makeNonceVariable "record_copy_arg" m t A.VariableName A.Abbrev
|
||||
let destV = A.Variable m nonceLHS
|
||||
(A.Specification _ nonceRHS _) <- makeNonceVariable "record_copy_arg" m t A.VariableName A.Abbrev
|
||||
let srcV = A.Variable m nonceRHS
|
||||
assigns <-
|
||||
sequence [do let sub = A.SubscriptField m fName
|
||||
assign m fType
|
||||
(A.SubscriptedVariable m sub destV) m
|
||||
(A.ExprVariable m
|
||||
(A.SubscriptedVariable m sub srcV))
|
||||
| (fName, fType) <- fs]
|
||||
let code = A.Seq m $ A.Several m $ map (A.Only m) assigns
|
||||
|
||||
return (A.Spec m (A.Specification m (n {A.nameName = "copy_" ++ A.nameName n})
|
||||
(A.Proc m A.InlineSpec [A.Formal A.Abbrev t nonceLHS, A.Formal A.ValAbbrev t nonceRHS] code)))
|
||||
|
|
Loading…
Reference in New Issue
Block a user