diff --git a/src/back/CodeGen/Closure.hs b/src/back/CodeGen/Closure.hs index 8df03d46c..ff13e36c0 100644 --- a/src/back/CodeGen/Closure.hs +++ b/src/back/CodeGen/Closure.hs @@ -43,10 +43,13 @@ translateClosure closure typeVars table params = A.eparams closure body = A.body closure id = Meta.getMetaId . A.getMeta $ closure + idAsync = id ++ "_async" funName = closureFunName id + funNameAsync = closureFunName idAsync nameForwarding = forwardingClosureImplName $ (ID.Name . show) funName envName = closureEnvName id traceName = closureTraceName id + traceNameAsync = closureTraceName idAsync boundVars = map (ID.qName . show . A.pname) params freeVars = map (first ID.qnlocal) $ filter (ID.isLocalQName . fst) $ @@ -79,7 +82,7 @@ translateClosure closure typeVars table ,returnStmnt bodyName resultType] ) forwardingClosureImpl = - Function (Static $ Typ "value_t") funName + Function (Static $ Typ "value_t") funNameAsync [(Ptr (Ptr encoreCtxT), encoreCtxVar), (Ptr (Ptr ponyTypeT), encoreRuntimeType), (Typ "value_t", Var "_args[]"), @@ -92,12 +95,13 @@ translateClosure closure typeVars table ,dtraceClosureExit ,returnStmnt forwardingBodyName unitType]) in - Concat $ [buildEnvironmentForward envName freeVars fTypeVars] ++ + Concat $ [buildEnvironmentForward envName freeVars fTypeVars] ++ + [tracefunDecl traceName envName freeVars fTypeVars extractEnvironment, + normalClosureImpl] ++ if null $ Util.filter A.isForward body - then [tracefunDecl traceName envName freeVars fTypeVars extractEnvironment, - normalClosureImpl] - else [tracefunDecl traceName envName freeVars fTypeVars extractEnvironmentForward, - forwardingClosureImpl] + then [] + else [tracefunDecl traceNameAsync envName freeVars fTypeVars extractEnvironmentForward, + forwardingClosureImpl] | otherwise = error "Tried to translate a closure from something that was not a closure" diff --git a/src/back/CodeGen/Expr.hs b/src/back/CodeGen/Expr.hs index 63cc0a532..b793aa6eb 100644 --- a/src/back/CodeGen/Expr.hs +++ b/src/back/CodeGen/Expr.hs @@ -221,7 +221,7 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where let string = head args rest = tail args unless (Ty.isStringType $ A.getType string) $ - error "Expr.hs: Print expects first argument to be a string literal" + error $ "Expr.hs: Print expects first argument to be a string literal" targs <- mapM translate rest let argNames = map (AsExpr . fst) targs argDecls = map snd targs @@ -1032,7 +1032,8 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where If futVar (Seq [Statement forwardingCall]) (Seq [Statement oneWayMsg])] ++ - result) + result + ) else do (sendn, sendt) <- translate A.MessageSend{A.emeta ,A.target @@ -1059,25 +1060,26 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where isAsyncForward <- gets Ctx.isAsyncForward let ty = getRuntimeType chain dtraceExit = getDtraceExit eCtx - result = - case eCtx of - Ctx.ClosureContext clos -> [] - _ -> [dtraceExit, Return Skip] + result = case eCtx of + Ctx.ClosureContext clos -> [] + _ -> [dtraceExit, Return Skip] futureChain = if Util.isForwardInExpr chain - then - Call futureChainActor - [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain] - else - Call futureChainWithFut - [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain, AsExpr futVar] + then Call futureChainActor + [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain] + else Call futureChainWithFut + [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain + ,AsExpr futVar, AsExpr $ AsLval $ Nam "false"] + when (A.isVarAccess chain) $ + unless (A.isIdClosure chain) $ + error $ "Expr.hs: The closure that contains forward must be defined in chain." if isAsyncForward then do return (unit, Seq $ [tfuture, tchain, Statement futureChain] ++ - result) + closResult) else do tmp <- Ctx.genSym result <- Ctx.genSym @@ -1146,53 +1148,84 @@ instance Translatable A.Expr (State Ctx.Context (CCode Lval, CCode Stat)) where (nfuture,tfuture) <- translate future (nchain, tchain) <- translate chain result <- Ctx.genSym + isAsyncForward <- gets Ctx.isAsyncForward let ty = getRuntimeType chain + fwdInClos = case eCtx of + Ctx.ClosureContext _ -> True + _ -> False + when (A.isVarAccess chain && isAsyncForward) $ + if (fwdInClos) + then error $ "Expr.hs: The closure that contains forward must be defined in chain." + else return () return $ (Var result, Seq $ [tfuture, tchain, - (Assign (Decl (C.future, Var result)) - (Call futureChainActor - [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain] - ))] ++ - if (Util.isForwardInExpr chain) then [assignVar futNam (Nam result)] + if (Util.isForwardInExpr chain && isAsyncForward) + then Statement $ + (Call futureChainWithFut + [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain, + AsExpr ((Deref envName) `Dot` futNam), AsExpr $ AsLval $ Nam "true"]) + else Assign (Decl (C.future, Var result)) + (Call futureChainActor [AsExpr encoreCtxVar, AsExpr nfuture, ty, AsExpr nchain]) + ] ++ + if (Util.isForwardInExpr chain && isAsyncForward) + then [assignVar futNam (Decl (C.future, Var result))] else []) where metaId = Meta.getMetaId . A.getMeta $ chain envName = closureEnvName metaId - assignVar lhs rhs = Assign rhs ((Deref envName) `Dot` lhs) + assignVar lhs rhs = Assign (Decl (C.future, lhs)) ((Deref envName) `Dot` rhs) translate clos@(A.Closure{A.eparams, A.body}) = do tmp <- Ctx.genSym - fut <- Ctx.genNamedSym "fut" + futClos <- Ctx.genNamedSym "fut_closure" globalFunctionNames <- gets Ctx.getGlobalFunctionNames isAsyncForward <- gets Ctx.isAsyncForward let bound = map (ID.qLocal . A.pname) eparams freeVars = filter (ID.isLocalQName . fst) $ Util.freeVariables bound body ty = runtimeType . A.getType $ body - futArg = if isAsyncForward - then futVar - else (Var fut) fillEnv <- insertAllVars freeVars fTypeVars return (Var tmp, - Seq $ - mkEnv envName : fillEnv ++ - (if isAsyncForward || (not $ Util.isForwardInExpr body) - then [] - else [Assign (Decl (future, Var fut)) - (Call futureMkFn [AsExpr encoreCtxVar, ty])]) ++ - (if Util.isForwardInExpr body - then [assignVar futNam futArg] - else []) ++ - [Assign (Decl (closure, Var tmp)) - (Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])]) + Seq $ + mkEnv envName : fillEnv ++ + if isAsyncForward then + if forwardInBody + then [Assign (Decl (future, Var futClos)) + (Call futureMkFn [AsExpr encoreCtxVar, ty]) + ,assignVar futNam (Var futClos) + ,Assign (Decl (closure, Var tmp)) + (Call closureMkFn [encoreCtxName, funNameAsync, envName, traceNameAsync, nullName])] + else [Assign (Decl (closure, Var tmp)) + (Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])] + else + [Assign (Decl (closure, Var tmp)) + (Call closureMkFn [encoreCtxName, funName, envName, traceName, nullName])]) where + forwardInBody = Util.isForwardInExpr body + metaIdAsync = metaId ++ "_async" + idClos = A.isIdClosure body + funNameAsync = if idClos || not forwardInBody then funName + else closureFunName metaIdAsync + traceNameAsync = if idClos || not forwardInBody then traceName + else closureTraceName metaIdAsync metaId = Meta.getMetaId . A.getMeta $ clos funName = closureFunName metaId envName = closureEnvName metaId traceName = closureTraceName metaId + metaIdAsync = metaId ++ "_async" + idClos = A.isIdClos body + fwdInBody = Util.isForwardInExpr body + funNameAsync = if idClos || not fwdInBody + then funName + else closureFunName metaIdAsync + traceNameAsync = if idClos || not fwdInBody + then traceName + else closureTraceName metaIdAsync fTypeVars = Util.freeTypeVars body + futureMake f ty = Assign (Decl (future, Var f)) + (Call futureMkFn [AsExpr encoreCtxVar, ty]) mkEnv name = Assign (Decl (Ptr $ Struct name, AsLval name)) (Call encoreAllocName [AsExpr (Deref encoreCtxVar), Sizeof $ Struct name]) diff --git a/src/back/CodeGen/MethodDecl.hs b/src/back/CodeGen/MethodDecl.hs index 48f594bdb..a5d37d1d0 100644 --- a/src/back/CodeGen/MethodDecl.hs +++ b/src/back/CodeGen/MethodDecl.hs @@ -73,12 +73,14 @@ translateGeneral mdecl@(A.Method {A.mbody, A.mlocals}) ,returnStatement mType bodyn]) forwardingMethodImpl = Function void nameForwarding (args ++ [(future, futVar)]) - (Seq [dtraceMethodEntry thisVar mName argNames + (Seq $[dtraceMethodEntry thisVar mName argNames ,parametricMethodTypeVars ,extractTypeVars ,forwardingBody ,dtraceMethodExit thisVar mName - ,Return Skip]) + ,Statement $ returnForForwardingMethod returnType + ,Return Skip] + ) in code ++ return (Concat $ locals ++ closures ++ [normalMethodImpl] ++ @@ -87,6 +89,13 @@ translateGeneral mdecl@(A.Method {A.mbody, A.mlocals}) then [] else [forwardingMethodImpl]) where + returnForForwardingMethod returnType = + let fulfilArgs = [AsExpr encoreCtxVar + ,AsExpr $ futVar + ,asEncoreArgT returnType + (Cast returnType forwardingBodyName)] + in + If futVar (Statement $ Call futureFulfil fulfilArgs) Skip mName = A.methodName mdecl localNames = map (ID.qLocal . A.functionName) mlocals localized = map (localize cname (A.methodName mdecl)) mlocals @@ -133,6 +142,14 @@ translateGeneral mdecl@(A.Method {A.mbody, A.mlocals}) show oldName in A.setFunctionName newName fun + returnForForwardingMethod returnType = + let fulfilArgs = [AsExpr encoreCtxVar + ,AsExpr $ futVar + ,asEncoreArgT returnType + (Cast returnType forwardingBodyName)] + in + If futVar (Statement $ Call futureFulfil fulfilArgs) Skip + callMethodWithFuture m cdecl@(A.Class {A.cname}) code | A.isActive cdecl || A.isShared cdecl = diff --git a/src/ir/AST/AST.hs b/src/ir/AST/AST.hs index 2f4487613..18344b1c1 100644 --- a/src/ir/AST/AST.hs +++ b/src/ir/AST/AST.hs @@ -676,7 +676,7 @@ data Expr = Skip {emeta :: Meta Expr} val :: Expr} | Suspend {emeta :: Meta Expr} | FutureChain {emeta :: Meta Expr, - future :: Expr, + future :: Expr, chain :: Expr} | FieldAccess {emeta :: Meta Expr, target :: Expr, @@ -765,14 +765,26 @@ isThisAccess :: Expr -> Bool isThisAccess VarAccess {qname = QName{qnlocal}} = qnlocal == Name "this" isThisAccess _ = False +isIdClos :: Expr -> Bool +isIdClos VarAccess{qname = QName{qnlocal}} = qnlocal == Name "_id_fun_tmp" +isIdClos _ = False + isClosure :: Expr -> Bool isClosure Closure {} = True isClosure _ = False +isIdClosure :: Expr -> Bool +isIdClosure VarAccess{qname = QName{qnlocal}} = qnlocal == Name "_id_fun_tmp" +isIdClosure _ = False + isForward :: Expr -> Bool isForward Forward {} = True isForward _ = False +isVarAccess :: Expr -> Bool +isVarAccess VarAccess{} = True +isVarAccess _ = False + isNull :: Expr -> Bool isNull Null{} = True isNull _ = False diff --git a/src/runtime/future/future.c b/src/runtime/future/future.c index ff080917f..46c1b14ba 100644 --- a/src/runtime/future/future.c +++ b/src/runtime/future/future.c @@ -102,7 +102,7 @@ static void future_finalizer(future_t *fut); static inline void future_gc_send_value(pony_ctx_t *ctx, future_t *fut); static inline void future_gc_recv_value(pony_ctx_t *ctx, future_t *fut); static void future_chain(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, - closure_t *c, future_t *r); + closure_t *c, future_t *r, bool withForward); pony_type_t future_type = { .id = ID_FUTURE, @@ -197,6 +197,12 @@ static inline encore_arg_t run_closure(pony_ctx_t **ctx, closure_t *c, encore_ar return closure_call(ctx, c, (value_t[1]) { value }); } +static inline void run_closure_fwd(pony_ctx_t **ctx, closure_t *c, encore_arg_t value) +{ + closure_call(ctx, c, (value_t[1]) { value }); + return; +} + bool future_fulfilled(future_t *fut) { perr("future_fulfilled"); @@ -305,21 +311,21 @@ future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, { ENC_DTRACE3(FUTURE_CHAINING, (uintptr_t) *ctx, (uintptr_t) fut, (uintptr_t) type); future_t *r = future_mk(ctx, type); - future_chain(ctx, fut, type, c, r); + future_chain(ctx, fut, type, c, r, false); return r; } void future_chain_with_fut(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, - closure_t *c, future_t *r) + closure_t *c, future_t *r, bool keepFwd) { ENC_DTRACE3(FUTURE_CHAINING, (uintptr_t) *ctx, (uintptr_t) fut, (uintptr_t) type); (void)type; - future_chain(ctx, fut, type, c, r); + future_chain(ctx, fut, type, c, r, keepFwd); return; } static void future_chain(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, - closure_t *c, future_t *r) + closure_t *c, future_t *r, bool withForward) { (void)type; perr("future_chain_actor"); @@ -327,8 +333,13 @@ static void future_chain(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, if (fut->fulfilled) { acquire_future_value(ctx, fut); - value_t result = run_closure(ctx, c, fut->value); - future_fulfil(ctx, r, result); + if (withForward) { + run_closure_fwd(ctx, c, fut->value); + } + else { + value_t result = run_closure(ctx, c, fut->value); + future_fulfil(ctx, r, result); + } UNBLOCK; return; } diff --git a/src/runtime/future/future.h b/src/runtime/future/future.h index 3b706c952..e6e5f8967 100644 --- a/src/runtime/future/future.h +++ b/src/runtime/future/future.h @@ -55,7 +55,7 @@ future_t *future_chain_actor(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, closure_t *c); void future_chain_with_fut(pony_ctx_t **ctx, future_t *fut, pony_type_t *type, - closure_t *c, future_t *r); + closure_t *c, future_t *r, bool keepFwd); /** Registers a callback and returns void * diff --git a/src/tests/encore/forward/failedPolyTypeStreamWithObject.enc b/src/tests/encore/forward/failedPolyTypeStreamWithObject.enc new file mode 100644 index 000000000..510b6a1de --- /dev/null +++ b/src/tests/encore/forward/failedPolyTypeStreamWithObject.enc @@ -0,0 +1,58 @@ +-- Error related to unknown _enc_type_t in method produce() +-- read class Bar +-- val v : int +-- def init(v : int) : unit +-- this.v = v +-- end +-- def getter() : int +-- this.v +-- end +-- end +active class Foo[t] + stream produce(var n : int, v : t) : t + while n>0 do + yield(v) + n -= 1 + end + end +end +active class Main + def main() : unit + val foo = new Foo[int] + val s = foo!produce(10, 42) + end +end + +-- With the concrete type of stream, it works properly. +{- +read class Bar + val v : int + def init(v : int) : unit + this.v = v + end + def getter() : int + this.v + end +end +active class Foo + stream produce(var n : int) : Bar + while n>0 do + yield(new Bar(n)) + n -= 1 + end + end +end +active class Main + def printStream(var s : Stream[Bar]) : unit + while not(eos(s)) do + println("{}", (get(s)).getter()) + s = getNext(s) + end + end + def main() : unit + val foo = new Foo + val s = foo!produce(10) + this.printStream(s) + end +end +-} diff --git a/src/tests/encore/forward/forwardArgInClosure.enc b/src/tests/encore/forward/forwardArgInClosure.enc index b01606144..26cc6b9a0 100644 --- a/src/tests/encore/forward/forwardArgInClosure.enc +++ b/src/tests/encore/forward/forwardArgInClosure.enc @@ -6,8 +6,7 @@ end active class Foo def join(ff : Fut[Fut[int]]) : int - (ff ~~> (fun (f : Fut[int]) : unit => forward(f))) - 0 -- Will be disregarded since it is used to bypass the typechecker. + get(ff ~~> (fun (f : Fut[int]) : int => forward(f))) end def duplicate() : Fut[int] diff --git a/src/tests/encore/forward/forwardClosMaybe.enc b/src/tests/encore/forward/forwardClosMaybe.enc index 562aaf2f4..17b71a778 100644 --- a/src/tests/encore/forward/forwardClosMaybe.enc +++ b/src/tests/encore/forward/forwardClosMaybe.enc @@ -9,8 +9,7 @@ active class Crop end active class Pepper def green(arg : Fut[Maybe[int]]) : Maybe[int] - get(arg ~~> fun(x : Maybe[int]) : unit => forward((new Crop(x)) ! collect())) - Nothing : Maybe[int] + get(arg ~~> fun(x : Maybe[int]) : Maybe[int] => forward((new Crop(x)) ! collect())) end end active class Main diff --git a/src/tests/encore/forward/forwardClosPassiveObject.enc b/src/tests/encore/forward/forwardClosPassiveObject.enc index f91bed70f..787262cca 100644 --- a/src/tests/encore/forward/forwardClosPassiveObject.enc +++ b/src/tests/encore/forward/forwardClosPassiveObject.enc @@ -18,8 +18,7 @@ active class Crop end active class Pepper def green(arg : Fut[Mellon]) : Mellon - (arg ~~> fun(x : Mellon) : unit => forward((new Crop(x)) ! collect())) - new Mellon(42000000) -- Will be disregarded since it is used to bypass the typechecker. + get(arg ~~> fun(x : Mellon) : Mellon => forward((new Crop(x)) ! collect())) end end active class Main diff --git a/src/tests/encore/forward/forwardClosString.enc b/src/tests/encore/forward/forwardClosString.enc index 53d57fbfe..0c49fdd04 100644 --- a/src/tests/encore/forward/forwardClosString.enc +++ b/src/tests/encore/forward/forwardClosString.enc @@ -9,8 +9,7 @@ active class Crop end active class Pepper def green(arg : Fut[String]) : String - (arg ~~> fun(x : String) : unit => forward((new Crop(x)) ! collect())) - "Will be disregarded since it is used to bypass the typechecker." + get(arg ~~> fun(x : String) : String => forward((new Crop(x)) ! collect())) end end diff --git a/src/tests/encore/forward/forwardClosTuple.enc b/src/tests/encore/forward/forwardClosTuple.enc index 134d3a79d..fc20f2df2 100644 --- a/src/tests/encore/forward/forwardClosTuple.enc +++ b/src/tests/encore/forward/forwardClosTuple.enc @@ -11,8 +11,7 @@ active class Crop end active class Pepper def green(arg : Fut[Tuple]) : Tuple - (arg ~~> fun(x : Tuple) : unit => forward((new Crop(x)) ! collect())) - (0, 0.0) -- Will be disregarded since it is used to bypass the typechecker. + get(arg ~~> fun(x : Tuple) : Tuple => forward((new Crop(x)) ! collect())) end end active class Main diff --git a/src/tests/encore/forward/forwardCoverage.enc b/src/tests/encore/forward/forwardCoverage.enc index dcd7bfbe7..a08035a1a 100644 --- a/src/tests/encore/forward/forwardCoverage.enc +++ b/src/tests/encore/forward/forwardCoverage.enc @@ -6,17 +6,20 @@ active class Foo def multiChainWithExistingFuture(arg: Fut[int]) : int val f = fun (x: int) => x + 1 - forward(arg ~~> f ~~> f ~~> f ~~> f ~~> f) + val temp = arg ~~> f ~~> f ~~> f ~~> f ~~> f + forward(temp) end def multiChainWithId(arg: Fut[int]) : int val f = fun (x: int) => x + 1 - forward(id(arg ~~> f) ~~> f ~~> f ~~> f ~~> f) + val temp = id(arg ~~> f) ~~> f ~~> f ~~> f ~~> f + forward(temp) end def multiChainWithMethodCall() : int val f = fun (x: int) => x + 1 - forward(((new Foo) ! foo()) ~~> f ~~> f ~~> f ~~> f ~~> f) + val temp = ((new Foo) ! foo()) ~~> f ~~> f ~~> f ~~> f ~~> f + forward(temp) end def foo() : int diff --git a/src/tests/encore/forward/forwardInClosure.enc b/src/tests/encore/forward/forwardInClosure.enc index c1f16eb6c..13dd1d07e 100644 --- a/src/tests/encore/forward/forwardInClosure.enc +++ b/src/tests/encore/forward/forwardInClosure.enc @@ -7,12 +7,11 @@ active class Main println("{}", get(bar)) end def bar(foo : Fut[int]) : int - (foo ~~> fun (x : int) : unit - val inc = this ! inc(x) - await(inc) - forward(inc) - end) - 0 -- Will be disregarded since it is used to bypass the typechecker. + get(foo ~~> fun (x : int) : int + val inc = this ! inc(x) + await(inc) + forward(inc) + end) end def foo() : int 42 diff --git a/src/tests/encore/forward/forwardInClosurePolyType.enc b/src/tests/encore/forward/forwardInClosurePolyType.enc index 421ff0963..58b24bcf1 100644 --- a/src/tests/encore/forward/forwardInClosurePolyType.enc +++ b/src/tests/encore/forward/forwardInClosurePolyType.enc @@ -10,8 +10,7 @@ active class Base[t] end active class Foo[sharable ty] def foo(arg : Fut[ty], arg2 : Fut[ty]) : ty - (arg ~~> fun(x : ty) : unit => forward((new Base[ty](x)) ! base())) - get(arg2) -- Will be disregarded since it is used to bypass the typechecker. + get(arg ~~> fun(x : ty) : ty => forward((new Base[ty](x)) ! base())) end end active class Main diff --git a/src/tests/encore/forward/forwardMethodCallInClosureBody.enc b/src/tests/encore/forward/forwardMethodCallInClosureBody.enc index b5bb89cc1..73c79905d 100644 --- a/src/tests/encore/forward/forwardMethodCallInClosureBody.enc +++ b/src/tests/encore/forward/forwardMethodCallInClosureBody.enc @@ -5,8 +5,7 @@ active class Base end active class Foo def foo(arg : Fut[int]) : int - (arg ~~> fun(x : int) : unit => forward((new Base) ! base())) - 0 + get(arg ~~> fun(x : int) : int => forward((new Base) ! base())) end end active class Main diff --git a/src/tests/encore/forward/forwardReturn.enc b/src/tests/encore/forward/forwardReturn.enc new file mode 100644 index 000000000..13f52cef0 --- /dev/null +++ b/src/tests/encore/forward/forwardReturn.enc @@ -0,0 +1,12 @@ +active class Main + def foo(b : bool) : int + if b then + forward (this ! foo(b)) + else + return this.foo(b) + end + end + def main() : unit + this.foo(false) + end +end diff --git a/src/tests/encore/forward/test0613.enc b/src/tests/encore/forward/test0613.enc new file mode 100644 index 000000000..c33ee5fb2 --- /dev/null +++ b/src/tests/encore/forward/test0613.enc @@ -0,0 +1,71 @@ +active class Crop + var v : String + def init(v : String) : unit + this.v = v + end + def collect() : String + this.v + end +end +active class Pepper + def green(arg : Fut[String]) : String + (arg ~~> fun(x : String) : unit + "jdfdf" + forward((new Crop(x)) ! collect()) + end) + -- forward((new Crop("Never mind")) ! collect()) + "This message should never be appeared when calling method green()" + end +end +-- active class Pepper +-- def green(arg : Fut[String]) : String +-- get(arg ~~> fun(x : String) : String => fo((new Crop(x)) ! collect())) +-- end +-- end +active class Main + def main() : unit + val arg = (new Crop("42")) ! collect() + val tem = (new Pepper) ! green(arg) + println("{}", get(tem)) + end +end +-- local class Rock[sharable t] +-- def roll(b : bool, v : t, r : t) : Fut[t] +-- ((new Lazy[t]) ! lazyWork(b, v, r)) +-- end +-- end +-- +-- active class Worker[t] +-- val v : t +-- def init(v : t) : unit +-- this.v = v +-- end +-- def work() : t +-- this.v +-- end +-- end +-- +-- active class Lazy[sharable t] +-- def lazyWork(b : bool, v : t, r : t) : t +-- if b then +-- forward((new Worker[t](v)) ! work()) +-- else +-- r +-- end +-- println("This should never run!") +-- r +-- end +-- end +-- +-- active class Main +-- def main() : unit +-- val b = false +-- println(get((new Lazy[String]) ! lazyWork(b, "42.0", "100.0"))) +-- println(get((new Lazy[real]) ! lazyWork(b, 42.0, 100.0))) +-- println(get((new Lazy[int]) ! lazyWork(b, 42, 100))) +-- println(get((new Lazy[bool]) ! lazyWork(b, true, false))) +-- println(get((new Lazy[Maybe[int]]) ! lazyWork(b, Just(42), Just(100)))) +-- -- Tested with passive class +-- println(get((new Rock[int]).roll(b, 42, 100))) +-- end +-- end diff --git a/src/types/Typechecker/Typechecker.hs b/src/types/Typechecker/Typechecker.hs index 88bb6dceb..040762d62 100644 --- a/src/types/Typechecker/Typechecker.hs +++ b/src/types/Typechecker/Typechecker.hs @@ -1268,9 +1268,9 @@ instance Checkable Expr where return $ setType (getResultType ty) forward {forwardExpr = eExpr} ClosureContext (Just mty) -> do mty' <- resolveType mty - unless (isUnitType mty') $ - pushError eExpr $ ForwardTypeClosError mty' unitType - return $ setType (unitType) forward {forwardExpr = eExpr} + unlessM (getResultType ty `subtypeOf` mty') $ + pushError eExpr $ ForwardTypeClosError mty' ty + return $ setType (getResultType ty) forward {forwardExpr = eExpr} ClosureContext Nothing -> tcError ClosureForwardError _ -> pushError eExpr ForwardInFunction @@ -2294,8 +2294,5 @@ typecheckParametricFun argTypes eSeqFunc | otherwise = error $ "Function that is callable but distinct from" ++ " 'VarAccess' or 'FunctionAsValue' AST node used." where - isVarAccess VarAccess{} = True - isVarAccess _ = False - isFunctionAsValue FunctionAsValue{} = True isFunctionAsValue _ = False