Skip to content

Commit

Permalink
fixed bug with incorrect classification of function which return Not…
Browse files Browse the repository at this point in the history
…hing as unshiftable
  • Loading branch information
rssh committed Oct 1, 2023
1 parent af03404 commit 189ed01
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 20 deletions.
13 changes: 5 additions & 8 deletions docs/BasicUsage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ This minimal example is for |Future|_ monad and depends on library |dotty-cps-as
.. code-block:: scala
// https://mvnrepository.com/artifact/com.github.rssh/dotty-cps-async
libraryDependencies += "com.github.rssh" %% "dotty-cps-async" % "0.9.18"
libraryDependencies += "com.github.rssh" %% "dotty-cps-async" % "0.9.19"
**Note**: The :ref:`Integrations` section lists further library dependencies needed for integration with well-known monadic frameworks such as |Cats Effect|_, |Monix|_, |ScalaZ IO|_ or |ZIO|_ and streaming frameworks like |Akka Streams|_ and |fs2|_.
Expand Down Expand Up @@ -320,14 +320,11 @@ Yet one pair of names 'lift/unlift', used for example in the |monadless|_ librar
.. ###########################################################################
.. ## Hyperlink definitions with text formating (e.g. verbatim, bold)
.. |0.9.18| replace:: ``0.9.18``
.. _0.9.18: https://repo1.maven.org/maven2/com/github/rssh/dotty-cps-async_3/0.9.18/
.. |0.9.19| replace:: ``0.9.19``
.. _0.9.19: https://repo1.maven.org/maven2/com/github/rssh/dotty-cps-async_3/0.9.19/

.. /*to update*/
.. |3.0.2| replace:: ``3.0.2``
.. _3.0.2: https://github.com/lampepfl/dotty/releases/tag/3.0.2

.. |3.1.0| replace:: ``3.1.0``
.. _3.1.0: https://github.com/lampepfl/dotty/releases/tag/3.1.0

Expand All @@ -337,8 +334,8 @@ Yet one pair of names 'lift/unlift', used for example in the |monadless|_ librar
.. |3.2.0| replace:: ``3.2.0``
.. _3.2.0: https://github.com/lampepfl/dotty/releases/tag/3.2.0

.. |3.3.0| replace:: ``3.3.0``
.. _3.3.0: https://github.com/lampepfl/dotty/releases/tag/3.3.0
.. |3.3.1| replace:: ``3.3.0``
.. _3.3.1: https://github.com/lampepfl/dotty/releases/tag/3.3.1


.. |Akka Streams| replace:: **Akka Streams**
Expand Down
10 changes: 5 additions & 5 deletions docs/HighOrderFunctions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,14 @@ So, we can write something like
Loom-based runtime await.
-------------------------

JDK-19 includes a set of interfaces (project Loom) that allows execution of code in virtual threads,
JDK-21 includes a set of interfaces (project Loom) that allows execution of code in virtual threads,
where runtime blocking wait is not blocking from OS view: real thread can execute tasks from other virtual threads during the wait.
In this case, we don't need to substitute a high-order function but change instead the function argument to the original form.
Target monad should implement one of the
`CpsRuntimeAwait` or
`CpsRuntimeAwaitProvider` typeclasses
(see
`sources <https://github.com/rssh/dotty-cps-async/blob/master/shared/src/main/scala/cps/CpsRuntimeAwait.scala>`_ )
`CpsRuntimeAwait` or
`CpsRuntimeAwaitProvider` typeclasses
(see
`sources <https://github.com/rssh/dotty-cps-async/blob/master/shared/src/main/scala/cps/CpsRuntimeAwait.scala>`_ )

For enabling this future, add `dotty-cps-async-loom` artifact to the dependencies of your project.

Expand Down
22 changes: 20 additions & 2 deletions jvm-loom-addon/src/test/scala/cpsloomtest/TestPE.scala
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ object PoorManEffect {

case class Thunk[T](th: (RunAPI => PoorManEffect[T])) extends PoorManEffect[T]

object CpsPMEAsyncEffectMonad extends CpsTryMonad[PoorManEffect] with CpsTryMonadInstanceContext[PoorManEffect] {
object CpsPMEMonad extends CpsTryMonad[PoorManEffect] with CpsTryMonadInstanceContext[PoorManEffect] {

def pure[T](t: T): PoorManEffect[T] = Pure(t)

Expand All @@ -56,7 +56,7 @@ object PoorManEffect {

}

given CpsTryMonad[PoorManEffect] = CpsPMEAsyncEffectMonad
given CpsPMEMonad.type = CpsPMEMonad


private class Runner[A] extends RunAPI {
Expand Down Expand Up @@ -313,5 +313,23 @@ class TestPE {
assert(r == 124*4)
}

@Test
def testPMECatchExceptionFromAwait(): Int = {
val c = async[PoorManEffect] {
val list0 = MyList.create(1, 2, 3, 4, 5)
try {
val list1 = list0.map[Int](x => await(PoorManEffect.Error(new RuntimeException("test"))))
assert(false)
1
} catch {
case ex: RuntimeException =>
assert(ex.getMessage() == "test")
2
}
}
val r = PoorManEffect.run(c)
assert(r==2)
}


}
4 changes: 4 additions & 0 deletions shared/src/main/scala/cps/CpsMonadContextInclusion.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
package cps

/**
* Typeclass for inclusion of one monad context into another.
* If this inclusion exists, that we can call direct context encoding method over G[_] in F[_].
*/
trait CpsMonadContextInclusion[F[_],G[_]] {

def apply[T](fctx: CpsTryMonadContext[F])(fun: CpsTryMonadContext[G] => G[T]):F[T]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ trait TreeTransformScope[F[_]:Type,CT:Type, CC<:CpsMonadContext[F]:Type]
def isInMonad(tpe: qctx.reflect.TypeRepr): Boolean =
given Type[F] = fType
tpe.widen.asType match
case '[Nothing] => false
case '[F[r]] =>
// bug in dotty-3.2.1
// see #63
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,12 +293,16 @@ trait ApplyArgRecordScope[F[_], CT, CC<:CpsMonadContext[F]]:
case None =>
if (existsLambdaUnshift) then
body.tpe.widen.asType match
case '[Nothing] =>
throw MacroError(s"Can't unshift lambda with Nothing type: ${body.tpe.widen.show}", posExpr(term))
case '[F[r]] if body.tpe.widen <:< TypeRepr.of[F[r]] =>
val nBody = '{ ${cpsCtx.monad}.flatMap(
${cpsBody.transformed.asExprOf[F[F[r]]]})((x:F[r])=>x) }.asTerm
val mt = MethodType(paramNames)(_ => paramTypes, _ => body.tpe.widen)
Lambda(owner, mt,
(owner,args) => changeArgs(params,args,nBody,owner).changeOwner(owner))
val nBody = '{ ${ cpsCtx.monad }.flatMap(
${
cpsBody.transformed.asExprOf[F[F[r]]]
})((x: F[r]) => x) }.asTerm
val mt = MethodType(paramNames)(_ => paramTypes, _ => body.tpe.widen)
Lambda(owner, mt,
(owner, args) => changeArgs(params, args, nBody, owner).changeOwner(owner))
case _ =>
throw MacroError(s"F[?] expected, we have ${body.tpe.widen.show}",term.asExpr)
else
Expand Down
33 changes: 33 additions & 0 deletions shared/src/test/scala/cpstest/TestRunFailInsideAwait.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cpstest;

import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import org.junit.Test

import cps.*
import cps.monads.{*,given}

import cps.testconfig.given
import cps.util.FutureCompleter


class TestRunFailInsideAwait {

@Test
def testFailInsideAwait() = {
val c = async[Future] {
val list0 = List(1, 2, 3, 4, 5)
try {
val list1 = list0.map[Int](x => await(Future.failed(new RuntimeException("test"))))
assert(false)
1
} catch {
case ex: RuntimeException =>
assert(ex.getMessage() == "test")
2
}
}
FutureCompleter(c.map(x => assert(x == 2)))
}

}

0 comments on commit 189ed01

Please sign in to comment.