Skip to content

Commit d15496b

Browse files
PhucVH888supercooldave
authored and
supercooldave
committed
Extended forward() for using in closure (#805)
* Extend forward() for using in closure * Added forward in closure and test cases * Revised test's expected output * Removed comments * Added more test, removed id-function check * Fixed error on non-primitive type in closure * Fixed forward in closure and added tests * Fixed forward-return case * Fixed deep forward in functions
1 parent 6b0ec36 commit d15496b

36 files changed

+541
-84
lines changed

src/back/CodeGen/CCodeNames.hs

+12-2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ option = Ptr $ Typ "option_t"
107107
par :: CCode Ty
108108
par = Ptr $ Typ "par_t"
109109

110+
futNam :: CCode Name
111+
futNam = Nam "_fut"
112+
110113
capability :: CCode Ty
111114
capability = Ptr $ Typ "capability_t"
112115

@@ -192,6 +195,10 @@ forwardingMethodImplName :: Ty.Type -> ID.Name -> CCode Name
192195
forwardingMethodImplName clazz mname =
193196
Nam $ forwardingMethodImplNameStr clazz mname
194197

198+
forwardingClosureImplName :: ID.Name -> CCode Name
199+
forwardingClosureImplName mname =
200+
Nam $ forwardingClosureImplNameStr mname
201+
195202
callMethodFutureName :: Ty.Type -> ID.Name -> CCode Name
196203
callMethodFutureName clazz mname =
197204
Nam $ callMethodFutureNameStr clazz mname
@@ -217,6 +224,9 @@ forwardingMethodImplNameStr :: Ty.Type -> ID.Name -> String
217224
forwardingMethodImplNameStr clazz mname =
218225
encoreName "method" $ qualifyRefType clazz ++ "_" ++ show mname ++ "_async"
219226

227+
forwardingClosureImplNameStr :: ID.Name -> String
228+
forwardingClosureImplNameStr mname = show mname ++ "_async"
229+
220230
callMethodFutureNameStr :: Ty.Type -> ID.Name -> String
221231
callMethodFutureNameStr clazz mname =
222232
methodImplNameStr clazz mname ++ "_future"
@@ -451,8 +461,8 @@ futureGetActor = Nam "future_get_actor"
451461
futureChainActor :: CCode Name
452462
futureChainActor = Nam "future_chain_actor"
453463

454-
futureChainActorForward :: CCode Name
455-
futureChainActorForward = Nam "future_chain_forward"
464+
futureChainWithFut :: CCode Name
465+
futureChainWithFut = Nam "future_chain_with_fut"
456466

457467
actorSuspend :: CCode Name
458468
actorSuspend = Nam "actor_suspend"

src/back/CodeGen/ClassDecl.hs

+1-1
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ dispatchFunDecl cdecl@(A.Class{A.cname, A.cfields, A.cmethods}) =
188188
unpackFuture =
189189
let
190190
lval = Decl (future, futVar)
191-
rval = (Cast (Ptr $ encMsgT) (Var "_m")) `Arrow` (Nam "_fut")
191+
rval = (Cast (Ptr $ encMsgT) (Var "_m")) `Arrow` futNam
192192
in
193193
Assign lval rval
194194

src/back/CodeGen/Closure.hs

+61-16
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,13 @@ translateClosure closure typeVars table
4343
params = A.eparams closure
4444
body = A.body closure
4545
id = Meta.getMetaId . A.getMeta $ closure
46+
idAsync = id ++ "_async"
4647
funName = closureFunName id
48+
funNameAsync = closureFunName idAsync
49+
nameForwarding = forwardingClosureImplName $ (ID.Name . show) funName
4750
envName = closureEnvName id
4851
traceName = closureTraceName id
52+
traceNameAsync = closureTraceName idAsync
4953
boundVars = map (ID.qName . show . A.pname) params
5054
freeVars = map (first ID.qnlocal) $
5155
filter (ID.isLocalQName . fst) $
@@ -60,21 +64,44 @@ translateClosure closure typeVars table
6064
varSubFromTypeVars fTypeVars
6165
ctx = Ctx.setClsCtx (Ctx.new subst table) closure
6266
((bodyName, bodyStat), _) = runState (translate body) ctx
67+
forwardingCtx = Ctx.setClsCtx(Ctx.newWithForwarding subst table) closure
68+
((forwardingBodyName,forwardingBody),_) =
69+
runState (translate body) forwardingCtx
70+
normalClosureImpl =
71+
Function (Static $ Typ "value_t") funName
72+
[(Ptr (Ptr encoreCtxT), encoreCtxVar),
73+
(Ptr (Ptr ponyTypeT), encoreRuntimeType),
74+
(Typ "value_t", Var "_args[]"),
75+
(Ptr void, envVar)]
76+
(Seq $
77+
dtraceClosureEntry argNames :
78+
extractArguments params ++
79+
extractEnvironment envName freeVars fTypeVars ++
80+
[bodyStat
81+
,dtraceClosureExit
82+
,returnStmnt bodyName resultType]
83+
)
84+
forwardingClosureImpl =
85+
Function (Static $ Typ "value_t") funNameAsync
86+
[(Ptr (Ptr encoreCtxT), encoreCtxVar),
87+
(Ptr (Ptr ponyTypeT), encoreRuntimeType),
88+
(Typ "value_t", Var "_args[]"),
89+
(Ptr void, envVar)]
90+
(Seq $
91+
dtraceClosureEntry argNames :
92+
extractArguments params ++
93+
extractEnvironmentForward envName freeVars fTypeVars ++
94+
[forwardingBody
95+
,dtraceClosureExit
96+
,returnStmnt forwardingBodyName unitType])
6397
in
64-
Concat [buildEnvironment envName freeVars fTypeVars,
65-
tracefunDecl traceName envName freeVars fTypeVars,
66-
Function (Static $ Typ "value_t") funName
67-
[(Ptr (Ptr encoreCtxT), encoreCtxVar),
68-
(Ptr (Ptr ponyTypeT), encoreRuntimeType),
69-
(Typ "value_t", Var "_args[]"),
70-
(Ptr void, envVar)]
71-
(Seq $
72-
dtraceClosureEntry argNames :
73-
extractArguments params ++
74-
extractEnvironment envName freeVars fTypeVars ++
75-
[bodyStat
76-
,dtraceClosureExit
77-
,returnStmnt bodyName resultType])]
98+
Concat $ [buildEnvironmentForward envName freeVars fTypeVars] ++
99+
[tracefunDecl traceName envName freeVars fTypeVars extractEnvironment,
100+
normalClosureImpl] ++
101+
if null $ Util.filter A.isForward body
102+
then []
103+
else [tracefunDecl traceNameAsync envName freeVars fTypeVars extractEnvironmentForward,
104+
forwardingClosureImpl]
78105
| otherwise =
79106
error
80107
"Tried to translate a closure from something that was not a closure"
@@ -92,6 +119,15 @@ translateClosure closure typeVars table
92119
arg = AsLval $ argName pname
93120
getArgument i = fromEncoreArgT ty $ AsExpr $ ArrAcc i (Var "_args")
94121

122+
buildEnvironmentForward name vars typeVars =
123+
StructDecl (Typ $ show name) $
124+
(map translateBinding vars) ++ (map translateTypeVar typeVars) ++ [(future, futVar)]
125+
where
126+
translateBinding (name, ty) =
127+
(translate ty, AsLval $ fieldName name)
128+
translateTypeVar ty =
129+
(Ptr ponyTypeT, AsLval $ typeVarRefName ty)
130+
95131
buildEnvironment name vars typeVars =
96132
StructDecl (Typ $ show name) $
97133
(map translateBinding vars) ++ (map translateTypeVar typeVars)
@@ -101,6 +137,15 @@ translateClosure closure typeVars table
101137
translateTypeVar ty =
102138
(Ptr ponyTypeT, AsLval $ typeVarRefName ty)
103139

140+
extractEnvironmentForward envName vars typeVars =
141+
(extractEnvironment envName vars typeVars) ++ [(assignFut $ ID.Name "_fut")]
142+
where
143+
assignFut name =
144+
let fName = Nam $ show name
145+
in Assign (Decl (future, AsLval fName)) $ getVar fName
146+
getVar name =
147+
(Deref $ Cast (Ptr $ Struct envName) envVar) `Dot` name
148+
104149
extractEnvironment envName vars typeVars =
105150
map assignVar vars ++ map assignTypeVar typeVars
106151
where
@@ -114,15 +159,15 @@ translateClosure closure typeVars table
114159
getVar name =
115160
(Deref $ Cast (Ptr $ Struct envName) envVar) `Dot` name
116161

117-
tracefunDecl traceName envName members fTypeVars =
162+
tracefunDecl traceName envName members fTypeVars extractEnv =
118163
Function (Static void) traceName args body
119164
where
120165
args = [(Ptr encoreCtxT, ctxArg), (Ptr void, Var "p")]
121166
ctxArg = Var "_ctx_arg"
122167
body = Seq $
123168
Assign (Decl (Ptr (Ptr encoreCtxT), encoreCtxVar)) (Amp ctxArg) :
124169
Assign (Decl (Ptr $ Struct envName, envVar)) (Var "p") :
125-
extractEnvironment envName members fTypeVars ++
170+
extractEnv envName members fTypeVars ++
126171
map traceMember members
127172
traceMember (name, ty) = traceVariable ty $ getVar name
128173
getVar name = envVar `Arrow` fieldName name

src/back/CodeGen/Expr.hs

+110-33
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,7 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
221221
let string = head args
222222
rest = tail args
223223
unless (Ty.isStringType $ A.getType string) $
224-
error "Expr.hs: Print expects first argument to be a string literal"
224+
error $ "Expr.hs: Print expects first argument to be a string literal"
225225
targs <- mapM translate rest
226226
let argNames = map (AsExpr . fst) targs
227227
argDecls = map snd targs
@@ -1015,6 +1015,7 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
10151015
then do
10161016
(ntarget, ttarget) <- translate target
10171017
let targetType = A.getType target
1018+
10181019
(initArgs, forwardingCall) <-
10191020
callTheMethodForward [futVar]
10201021
ntarget targetType name args typeArguments Ty.unitType
@@ -1024,25 +1025,37 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
10241025
ntarget targetType name args typeArguments Ty.unitType
10251026

10261027
let nullCheck = targetNullCheck (AsExpr ntarget) target name emeta "."
1028+
result =
1029+
case eCtx of
1030+
Ctx.ClosureContext clos -> []
1031+
_ -> [dtraceExit, Return Skip]
10271032

10281033
return (unit, Seq $
10291034
ttarget : nullCheck :
10301035
[Statement $
10311036
If futVar
10321037
(Seq $ initArgs ++ [Statement forwardingCall])
1033-
(Seq $ initArgs1 ++ [Statement oneWayMsg]),
1034-
dtraceExit,
1035-
Return Skip])
1036-
1038+
(Seq $ initArgs1 ++ [Statement oneWayMsg])] ++
1039+
result
1040+
)
10371041
else do
10381042
(sendn, sendt) <- translate A.MessageSend{A.emeta
10391043
,A.target
10401044
,A.name
10411045
,A.typeArguments
10421046
,A.args}
1047+
tmp <- Ctx.genSym
10431048
let resultType = translate (Ty.getResultType $ A.getType expr)
10441049
theGet = fromEncoreArgT resultType (Call futureGetActor [encoreCtxVar, sendn])
1045-
return (unit, Seq [sendt, dtraceExit, Return theGet])
1050+
result =
1051+
case eCtx of
1052+
Ctx.MethodContext mdecl ->
1053+
(unit, Seq [sendt, dtraceExit, Return theGet])
1054+
Ctx.ClosureContext clos ->
1055+
let ty = (Ty.getResultType $ A.getType clos)
1056+
in (Var tmp, Seq [sendt, Assign (Decl (resultType, Var tmp)) theGet])
1057+
_ -> error "Expr.hs: No context to forward"
1058+
return result
10461059

10471060
translate A.Forward{A.emeta, A.forwardExpr = fchain@A.FutureChain{A.future, A.chain}} = do
10481061
(nfuture,tfuture) <- translate future
@@ -1051,17 +1064,26 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
10511064
isAsyncForward <- gets Ctx.isAsyncForward
10521065
let ty = getRuntimeType chain
10531066
dtraceExit = getDtraceExit eCtx
1067+
result = case eCtx of
1068+
Ctx.ClosureContext clos -> []
1069+
_ -> [dtraceExit, Return Skip]
1070+
futureChain =
1071+
if Util.isForwardInExpr chain
1072+
then Call futureChainActor
1073+
[AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain]
1074+
else Call futureChainWithFut
1075+
[AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain
1076+
,AsExpr futVar, AsExpr $ AsLval $ Nam "false"]
1077+
when (A.isVarAccess chain) $
1078+
unless (A.isIdClosure chain) $
1079+
error $ "Expr.hs: The closure that contains forward must be defined in chain."
10541080
if isAsyncForward
10551081
then do
10561082
return (unit, Seq $
10571083
[tfuture,
10581084
tchain,
1059-
(Statement $
1060-
Call futureChainActorForward
1061-
[AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain, AsExpr futVar]
1062-
)] ++
1063-
[dtraceExit,
1064-
Return Skip])
1085+
Statement futureChain] ++
1086+
result)
10651087
else do
10661088
tmp <- Ctx.genSym
10671089
result <- Ctx.genSym
@@ -1094,17 +1116,40 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
10941116
translate ret@(A.Return{A.val}) =
10951117
do (nval, tval) <- translate val
10961118
eCtx <- gets Ctx.getExecCtx
1119+
isAsyncForward <- gets Ctx.isAsyncForward
10971120
let theReturn =
1098-
case eCtx of
1099-
Ctx.FunctionContext fun ->
1100-
[dtraceFunctionExit (A.functionName fun), Return nval]
1101-
Ctx.MethodContext mdecl ->
1102-
[dtraceMethodExit thisVar (A.methodName mdecl), Return nval]
1103-
Ctx.ClosureContext clos ->
1104-
let ty = (Ty.getResultType $ A.getType clos)
1105-
in [dtraceClosureExit,
1106-
Return $ asEncoreArgT (translate ty) nval]
1107-
_ -> error "Expr.hs: No context to return from"
1121+
if isAsyncForward then
1122+
case eCtx of
1123+
Ctx.FunctionContext fun ->
1124+
let ty = A.getType fun
1125+
in [dtraceFunctionExit (A.functionName fun)
1126+
,Statement $ Call futureFulfil [AsExpr encoreCtxVar, AsExpr futVar
1127+
,asEncoreArgT (translate ty) nval]
1128+
,Return Skip]
1129+
Ctx.MethodContext mdecl ->
1130+
let ty = A.getType mdecl
1131+
in [dtraceMethodExit thisVar (A.methodName mdecl)
1132+
,Statement $ Call futureFulfil [AsExpr encoreCtxVar, AsExpr futVar
1133+
,asEncoreArgT (translate ty) nval]
1134+
,Return Skip]
1135+
Ctx.ClosureContext clos ->
1136+
let ty = (Ty.getResultType $ A.getType clos)
1137+
in [dtraceClosureExit
1138+
,Statement $ Call futureFulfil [AsExpr encoreCtxVar, AsExpr futVar
1139+
,asEncoreArgT (translate ty) nval]
1140+
,Return Skip]
1141+
_ -> error "Expr.hs: No context to return from"
1142+
else
1143+
case eCtx of
1144+
Ctx.FunctionContext fun ->
1145+
[dtraceFunctionExit (A.functionName fun), Return nval]
1146+
Ctx.MethodContext mdecl ->
1147+
[dtraceMethodExit thisVar (A.methodName mdecl), Return nval]
1148+
Ctx.ClosureContext clos ->
1149+
let ty = (Ty.getResultType $ A.getType clos)
1150+
in [dtraceClosureExit,
1151+
Return $ asEncoreArgT (translate ty) nval]
1152+
_ -> error "Expr.hs: No context to return from"
11081153
return (unit, Seq $ tval:theReturn)
11091154

11101155
translate iseos@(A.IsEos{A.target}) =
@@ -1129,30 +1174,62 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where
11291174
translate futureChain@(A.FutureChain{A.future, A.chain}) = do
11301175
(nfuture,tfuture) <- translate future
11311176
(nchain, tchain) <- translate chain
1132-
let ty = getRuntimeType chain
11331177
result <- Ctx.genSym
1178+
isAsyncForward <- gets Ctx.isAsyncForward
1179+
let ty = getRuntimeType chain
11341180
return $ (Var result,
1135-
Seq [tfuture,
1136-
tchain,
1137-
(Assign (Decl (C.future, Var result))
1138-
(Call futureChainActor
1139-
[AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain]
1140-
))])
1181+
Seq $ [tfuture,
1182+
tchain,
1183+
if (Util.isForwardInExpr chain && isAsyncForward)
1184+
then Statement $
1185+
(Call futureChainWithFut
1186+
[AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain,
1187+
AsExpr ((Deref envName) `Dot` futNam), AsExpr $ AsLval $ Nam "true"])
1188+
else Assign (Decl (C.future, Var result))
1189+
(Call futureChainActor [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain])
1190+
] ++
1191+
if (Util.isForwardInExpr chain && isAsyncForward)
1192+
then [assignVar futNam (Decl (C.future, Var result))]
1193+
else [])
1194+
where
1195+
metaId = Meta.getMetaId . A.getMeta $ chain
1196+
envName = closureEnvName metaId
1197+
assignVar lhs rhs = Assign rhs ((Deref envName) `Dot` lhs)
11411198

11421199
translate clos@(A.Closure{A.eparams, A.body}) = do
11431200
tmp <- Ctx.genSym
1201+
futClos <- Ctx.genNamedSym "fut_closure"
11441202
globalFunctionNames <- gets Ctx.getGlobalFunctionNames
1203+
isAsyncForward <- gets Ctx.isAsyncForward
11451204
let bound = map (ID.qLocal . A.pname) eparams
11461205
freeVars = filter (ID.isLocalQName . fst) $
11471206
Util.freeVariables bound body
1207+
ty = runtimeType . A.getType $ body
11481208
fillEnv <- insertAllVars freeVars fTypeVars
11491209
return
11501210
(Var tmp,
1151-
Seq $
1152-
mkEnv envName : fillEnv ++
1153-
[Assign (Decl (closure, Var tmp))
1154-
(Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])])
1211+
Seq $
1212+
mkEnv envName : fillEnv ++
1213+
if isAsyncForward then
1214+
if forwardInBody
1215+
then [Assign (Decl (future, Var futClos))
1216+
(Call futureMkFn [AsExpr encoreCtxVar, ty])
1217+
,assignVar futNam (Var futClos)
1218+
,Assign (Decl (closure, Var tmp))
1219+
(Call closureMkFn [encoreCtxName, funNameAsync, envName, traceNameAsync, nullName])]
1220+
else [Assign (Decl (closure, Var tmp))
1221+
(Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])]
1222+
else
1223+
[Assign (Decl (closure, Var tmp))
1224+
(Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])])
11551225
where
1226+
forwardInBody = Util.isForwardInExpr body
1227+
metaIdAsync = metaId ++ "_async"
1228+
idClos = A.isIdClosure body
1229+
funNameAsync = if idClos || not forwardInBody then funName
1230+
else closureFunName metaIdAsync
1231+
traceNameAsync = if idClos || not forwardInBody then traceName
1232+
else closureTraceName metaIdAsync
11561233
metaId = Meta.getMetaId . A.getMeta $ clos
11571234
funName = closureFunName metaId
11581235
envName = closureEnvName metaId

0 commit comments

Comments
 (0)