diff --git a/shared/src/main/scala/cps/Async.scala b/shared/src/main/scala/cps/Async.scala index 076ba6e92..51923646d 100644 --- a/shared/src/main/scala/cps/Async.scala +++ b/shared/src/main/scala/cps/Async.scala @@ -12,11 +12,14 @@ import scala.compiletime._ import cps.plugin.annotation.CpsNotChange -/** - * Pseudofunction, which can be used inside async block, to 'await' (i.e. receive value of `t:T` from `ft:F[T]`). - **/ -@compileTimeOnly("await should be inside async block") -def await[F[_],T,G[_]](f: F[T])(using ctx: CpsMonadContext[G], conversion: CpsMonadConversion[F,G]): T = ??? + +extension [F[_], T, G[_]](f: F[T])(using ctx: CpsMonadContext[G], conversion: CpsMonadConversion[F,G]) + /** + * Pseudofunction, which can be used inside async block, to 'await' (i.e. receive value of `t:T` from `ft:F[T]`). + **/ + @compileTimeOnly("await should be inside async block") + def await: T = ??? + /** * Pseudofunction, which can be used inside async block or in function with CpsDirect[F] context parameter, to 'asynchronize computation' (i.e. receive value of `F[T]` from `t:FT`). @@ -54,11 +57,12 @@ transparent inline def async[F[_]](using am: CpsMonad[F]) = transparent inline def reify[F[_]](using am: CpsMonad[F]) = macros.Async.InferAsyncArg(using am) -/** - * Synonym for `await` - **/ -transparent inline def reflect[F[_],T,G[_]](f: F[T])(using inline ctx: CpsMonadContext[G], inline conv: CpsMonadConversion[F,G]): T = - await[F,T,G](f) + +extension [F[_], T, G[_]](f: F[T])(using ctx: CpsMonadContext[G], conversion: CpsMonadConversion[F, G]) + /** + * Synonym for `await` + * */ + transparent inline def reflect: T = await(f) @experimental diff --git a/shared/src/main/scala/cps/syntax/monadless/package.scala b/shared/src/main/scala/cps/syntax/monadless/package.scala index fb6fa2dfd..00ebd4dac 100644 --- a/shared/src/main/scala/cps/syntax/monadless/package.scala +++ b/shared/src/main/scala/cps/syntax/monadless/package.scala @@ -14,9 +14,9 @@ transparent inline def lift[F[_]](using am: CpsMonad[F]) = macros.Async.InferAsyncArg(using am) -/** - * Synomym for `await` - **/ -transparent inline def unlift[F[_],T,G[_]](f: F[T])(using ctx: CpsMonadContext[G], conversion: CpsMonadConversion[F,G]): T = - cps.await[F,T,G](f)(using ctx, conversion) +extension [F[_], T, G[_]](f: F[T])(using ctx: CpsMonadContext[G], conversion: CpsMonadConversion[F, G]) + /** + * Synonym for `await` + * */ + transparent inline def unlift: T = await(f) diff --git a/shared/src/test/scala/cpstest/TestExtensionSyntax.scala b/shared/src/test/scala/cpstest/TestExtensionSyntax.scala new file mode 100644 index 000000000..0555a9b86 --- /dev/null +++ b/shared/src/test/scala/cpstest/TestExtensionSyntax.scala @@ -0,0 +1,37 @@ +package cpstest + + + +import cps.* +import org.junit.Test + +import scala.util.Success + +class TestExtensionSyntax { + + @Test + def testCBExtensionSyntax() = { + + val c = async[ComputationBound] { + val a = T1.cbi(1) + val b = T1.cbi(2) + a.await + b.await + } + assert(c.run() == Success(3)) + + } + + @Test + def testCBReflectExtensionSyntax() = { + + val c = reify[ComputationBound] { + val a = T1.cbi(1) + val b = T1.cbi(2) + a.reflect + b.reflect + } + assert(c.run() == Success(3)) + + } + + +} diff --git a/shared/src/test/scala/cpstest/TestMonadlessSyntax.scala b/shared/src/test/scala/cpstest/TestMonadlessSyntax.scala index b3cf1368d..195c6c876 100644 --- a/shared/src/test/scala/cpstest/TestMonadlessSyntax.scala +++ b/shared/src/test/scala/cpstest/TestMonadlessSyntax.scala @@ -32,6 +32,20 @@ class TestMonadlessSyntax { case Failure(ex) => throw ex } + @Test + def testUnliftExtension() = { + val c = lift[ComputationBound] { + val x = T1.cbi(1).unlift + T1.cbi(2).unlift + x + } + val r = c.run() + assert(r.isSuccess) + r match + case Success(v) => assert(v == 3) + case Failure(ex) => throw ex + } + + @Test def testInferenceForFutureMonad() = {