diff --git a/src/tests/encore/forward/forwardArgInClosure.enc b/src/tests/encore/forward/forwardArgInClosure.enc index a7b55c89c..b01606144 100644 --- a/src/tests/encore/forward/forwardArgInClosure.enc +++ b/src/tests/encore/forward/forwardArgInClosure.enc @@ -6,7 +6,8 @@ end active class Foo def join(ff : Fut[Fut[int]]) : int - forward(ff ~~> (fun (f : Fut[int]) : int => forward(f))) + (ff ~~> (fun (f : Fut[int]) : unit => forward(f))) + 0 -- Will be disregarded since it is used to bypass the typechecker. end def duplicate() : Fut[int] diff --git a/src/tests/encore/forward/forwardClosMaybe.enc b/src/tests/encore/forward/forwardClosMaybe.enc new file mode 100644 index 000000000..562aaf2f4 --- /dev/null +++ b/src/tests/encore/forward/forwardClosMaybe.enc @@ -0,0 +1,22 @@ +active class Crop + var v : Maybe[int] + def init(v : Maybe[int]) : unit + this.v = v + end + def collect() : Maybe[int] + this.v + end +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] + end +end +active class Main + def main() : unit + val arg = (new Crop((Just(42)))) ! collect() + val tem = (new Pepper) ! green(arg) + println("{}", get(tem)) + end +end diff --git a/src/tests/encore/forward/forwardClosMaybe.out b/src/tests/encore/forward/forwardClosMaybe.out new file mode 100644 index 000000000..947d8b4d8 --- /dev/null +++ b/src/tests/encore/forward/forwardClosMaybe.out @@ -0,0 +1 @@ +Just 42 diff --git a/src/tests/encore/forward/forwardClosPassiveObject.enc b/src/tests/encore/forward/forwardClosPassiveObject.enc new file mode 100644 index 000000000..f91bed70f --- /dev/null +++ b/src/tests/encore/forward/forwardClosPassiveObject.enc @@ -0,0 +1,31 @@ +read class Mellon + val v : int + def init(v : int) : unit + this. v = v + end + def grow() : int + this.v + end +end +active class Crop + var v : Mellon + def init(v : Mellon) : unit + this.v = v + end + def collect() : Mellon + this.v + end +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. + end +end +active class Main + def main() : unit + val mellon = new Mellon(42) + val arg = (new Crop(mellon)) ! collect() + println("{}", (get(arg)).grow()) + end +end diff --git a/src/tests/encore/forward/forwardClosPassiveObject.out b/src/tests/encore/forward/forwardClosPassiveObject.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardClosPassiveObject.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardClosString.enc b/src/tests/encore/forward/forwardClosString.enc new file mode 100644 index 000000000..53d57fbfe --- /dev/null +++ b/src/tests/encore/forward/forwardClosString.enc @@ -0,0 +1,23 @@ +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 => forward((new Crop(x)) ! collect())) + "Will be disregarded since it is used to bypass the typechecker." + 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 diff --git a/src/tests/encore/forward/forwardClosString.out b/src/tests/encore/forward/forwardClosString.out new file mode 100644 index 000000000..d81cc0710 --- /dev/null +++ b/src/tests/encore/forward/forwardClosString.out @@ -0,0 +1 @@ +42 diff --git a/src/tests/encore/forward/forwardClosTuple.enc b/src/tests/encore/forward/forwardClosTuple.enc new file mode 100644 index 000000000..134d3a79d --- /dev/null +++ b/src/tests/encore/forward/forwardClosTuple.enc @@ -0,0 +1,24 @@ +typedef Tuple = (int, real) + +active class Crop + var v : Tuple + def init(v : Tuple) : unit + this.v = v + end + def collect() : Tuple + this.v + end +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. + end +end +active class Main + def main() : unit + val arg = (new Crop((42, 42.0))) ! collect() + val tem = (new Pepper) ! green(arg) + println("{}", get(tem)) + end +end diff --git a/src/tests/encore/forward/forwardClosTuple.out b/src/tests/encore/forward/forwardClosTuple.out new file mode 100644 index 000000000..b1b0285e7 --- /dev/null +++ b/src/tests/encore/forward/forwardClosTuple.out @@ -0,0 +1 @@ +(42, 42.000000) diff --git a/src/tests/encore/forward/forwardInClosure.enc b/src/tests/encore/forward/forwardInClosure.enc index 8218eeb03..c1f16eb6c 100644 --- a/src/tests/encore/forward/forwardInClosure.enc +++ b/src/tests/encore/forward/forwardInClosure.enc @@ -1,18 +1,22 @@ active class Main def main() : unit - val fres = (this!foo() ~~> fun (x : int) : int - val tem = this ! inc(x) - await(tem) - forward(tem) - end) - await(fres) - println("{}", get(fres)) + val foo = this ! foo() + await(foo) + val bar = this ! bar(foo) + await(bar) + 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. end - def foo() : int 42 end - def inc(x : int) : int x + 1 end diff --git a/src/tests/encore/forward/forwardInClosurePolyType.enc b/src/tests/encore/forward/forwardInClosurePolyType.enc index 1aa00caee..421ff0963 100644 --- a/src/tests/encore/forward/forwardInClosurePolyType.enc +++ b/src/tests/encore/forward/forwardInClosurePolyType.enc @@ -9,14 +9,15 @@ active class Base[t] end end active class Foo[sharable ty] - def foo(arg : Fut[ty]) : ty - get(arg ~~> fun(x : ty) : ty => forward((new Base[ty](x)) ! base())) + 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. end end - active class Main def main() : unit val arg = (new Base[int](42)) ! base() - println("{}", get((new Foo[int]) ! foo(arg))) + val arg2 = (new Base[int](123456)) ! base() + println("{}", get((new Foo[int]) ! foo(arg, arg2))) end end diff --git a/src/tests/encore/forward/forwardMethodCallInClosureBody.enc b/src/tests/encore/forward/forwardMethodCallInClosureBody.enc index 58b64bc10..b5bb89cc1 100644 --- a/src/tests/encore/forward/forwardMethodCallInClosureBody.enc +++ b/src/tests/encore/forward/forwardMethodCallInClosureBody.enc @@ -3,13 +3,12 @@ active class Base 42 end end - active class Foo def foo(arg : Fut[int]) : int - forward(arg ~~> fun(x : int) : int => forward((new Base) ! base())) + (arg ~~> fun(x : int) : unit => forward((new Base) ! base())) + 0 end end - active class Main def main() : unit val arg = (new Base) ! base() diff --git a/src/types/Typechecker/TypeError.hs b/src/types/Typechecker/TypeError.hs index bc2ec7de9..ba5ba3419 100644 --- a/src/types/Typechecker/TypeError.hs +++ b/src/types/Typechecker/TypeError.hs @@ -726,8 +726,8 @@ instance Show Error where "the result type of the containing method %s") (show retType) (show ty) show (ForwardTypeClosError retType ty) = - printf ("Returned type %s of forward should match with " ++ - "the result type of the closure %s") + printf ("Result type %s of the closure should match with " ++ + "the return type %s of the forward") (show retType) (show ty) show (ForwardInPassiveContext cname) = printf "Forward can not be used in passive class '%s'" diff --git a/src/types/Typechecker/Typechecker.hs b/src/types/Typechecker/Typechecker.hs index 217e1b9c0..88bb6dceb 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 - unlessM (getResultType ty `subtypeOf` mty') $ - pushError eExpr $ ForwardTypeClosError mty' ty - return $ setType (getResultType ty) forward {forwardExpr = eExpr} + unless (isUnitType mty') $ + pushError eExpr $ ForwardTypeClosError mty' unitType + return $ setType (unitType) forward {forwardExpr = eExpr} ClosureContext Nothing -> tcError ClosureForwardError _ -> pushError eExpr ForwardInFunction