Skip to content

Commit

Permalink
make reactive state variables lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
cornerman committed Dec 5, 2022
1 parent 5bffba8 commit 893dc8a
Show file tree
Hide file tree
Showing 14 changed files with 349 additions and 476 deletions.
15 changes: 15 additions & 0 deletions reactive/src/main/scala-2/colibri/reactive/LiveOwnerPlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package colibri.reactive

import colibri.{Observable, Cancelable}

trait LiveOwnerPlatform {
@annotation.compileTimeOnly(
"No implicit LiveOwner is available here! Wrap inside `Rx { <code> }`, or provide an implicit `LiveOwner`.",
)
implicit object compileTimeMock extends LiveOwner {
def cancelable: Cancelable = ???
def unsafeNow[A](rx: Rx[A]): A = ???
def unsafeLive[A](rx: Rx[A]): A = ???
def liveObservable: Observable[Any] = ???
}
}

This file was deleted.

27 changes: 0 additions & 27 deletions reactive/src/main/scala-2/colibri/reactive/OwnerPlatform.scala

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package colibri.reactive
import colibri.reactive.internal.MacroUtils

trait RxPlatform {
def apply[R](f: R)(implicit owner: Owner): Rx[R] = macro MacroUtils.rxImpl[R]
def apply[R](f: R): Rx[R] = macro MacroUtils.rxImpl[R]
}
Original file line number Diff line number Diff line change
@@ -1,30 +1,25 @@
package colibri.reactive.internal

import colibri.reactive.{Rx, Owner, LiveOwner}
import colibri.effect.SyncEmbed
import colibri.SubscriptionOwner
import colibri.reactive.{Rx, LiveOwner}
import scala.reflect.macros._

// Inspired by scala.rx
object MacroUtils {

private val ownerName = "colibriOwner"
private val liveOwnerName = "colibriLiveOwner"

def injectOwner[T](c: blackbox.Context)(src: c.Tree, newOwner: c.universe.TermName, exceptOwner: c.Type): c.Tree = {
def injectOwner[T](c: blackbox.Context)(src: c.Tree, newOwner: c.universe.TermName): c.Tree = {
import c.universe._

val implicitOwnerAtCaller = c.inferImplicitValue(typeOf[Owner], silent = false)
val implicitLiveOwnerAtCaller = c.inferImplicitValue(typeOf[LiveOwner], silent = false)

object transformer extends c.universe.Transformer {
override def transform(tree: c.Tree): c.Tree = {
val shouldReplaceOwner = tree != null &&
tree.isTerm &&
(tree.tpe =:= implicitOwnerAtCaller.tpe || tree.tpe =:= implicitLiveOwnerAtCaller.tpe) &&
tree.tpe <:< typeOf[Owner] &&
!(tree.tpe =:= typeOf[Nothing]) &&
!(tree.tpe <:< exceptOwner)
tree.tpe =:= implicitLiveOwnerAtCaller.tpe &&
tree.tpe <:< typeOf[LiveOwner] &&
!(tree.tpe =:= typeOf[Nothing])

if (shouldReplaceOwner) q"$newOwner"
else super.transform(tree)
Expand All @@ -33,37 +28,17 @@ object MacroUtils {
transformer.transform(src)
}

def ownedImpl[R](
c: blackbox.Context,
)(f: c.Expr[R])(subscriptionOwner: c.Expr[SubscriptionOwner[R]], syncEmbed: c.Expr[SyncEmbed[R]]): c.Expr[R] = {
import c.universe._

val newOwner = c.freshName(TermName(ownerName))

val newTree = c.untypecheck(injectOwner(c)(f.tree, newOwner, typeOf[LiveOwner]))

val tree = q"""
_root_.colibri.reactive.Owned.function { ($newOwner: _root_.colibri.reactive.Owner) =>
$newTree
}($subscriptionOwner, $syncEmbed)
"""

// println(tree)

c.Expr(tree)
}

def rxImpl[R](c: blackbox.Context)(f: c.Expr[R])(owner: c.Expr[Owner]): c.Expr[Rx[R]] = {
def rxImpl[R](c: blackbox.Context)(f: c.Expr[R]): c.Expr[Rx[R]] = {
import c.universe._

val newOwner = c.freshName(TermName(liveOwnerName))

val newTree = c.untypecheck(injectOwner(c)(f.tree, newOwner, typeOf[Nothing]))
val newTree = c.untypecheck(injectOwner(c)(f.tree, newOwner))

val tree = q"""
_root_.colibri.reactive.Rx.function { ($newOwner: _root_.colibri.reactive.LiveOwner) =>
$newTree
}($owner)
}
"""

// println(tree)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
package colibri.reactive

trait OwnerPlatform

trait LiveOwnerPlatform

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package colibri.reactive

trait RxPlatform {
def apply[R](f: LiveOwner ?=> R)(implicit owner: Owner): Rx[R] = Rx.function(implicit owner => f)
def apply[R](f: LiveOwner ?=> R): Rx[R] = Rx.function(implicit owner => f)
}
36 changes: 36 additions & 0 deletions reactive/src/main/scala/colibri/reactive/LiveOwner.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package colibri.reactive

import colibri._

@annotation.implicitNotFound(
"No implicit LiveOwner is available here! Wrap inside `Rx { <code> }`, or provide an implicit `LiveOwner`.",
)
trait LiveOwner {
def liveObservable: Observable[Any]

def unsafeLive[A](rx: Rx[A]): A
def unsafeNow[A](rx: Rx[A]): A

def cancelable: Cancelable
}
object LiveOwner extends LiveOwnerPlatform {
def create(): LiveOwner = new LiveOwner {
private val ref = Cancelable.builder()

private val subject = Subject.publish[Any]()

val cancelable: Cancelable = ref

val liveObservable: Observable[Any] = subject

def unsafeNow[A](rx: Rx[A]): A = {
ref.unsafeAdd(() => rx.observable.unsafeSubscribe())
rx.nowGet()
}

def unsafeLive[A](rx: Rx[A]): A = {
ref.unsafeAdd(() => rx.observable.to(subject).unsafeSubscribe())
rx.nowGet()
}
}
}
12 changes: 0 additions & 12 deletions reactive/src/main/scala/colibri/reactive/Owned.scala

This file was deleted.

69 changes: 0 additions & 69 deletions reactive/src/main/scala/colibri/reactive/Owner.scala

This file was deleted.

Loading

0 comments on commit 893dc8a

Please sign in to comment.