Skip to content

Port of gestalt Optional as a test #5385

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 5, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/main/scala/gestalt/macros/Optional.scala
// using only `inline`

final class Optional[+A >: Null](val value: A) extends AnyVal {
def get: A = value
def isEmpty = value == null

inline def getOrElse[B >: A](alt: => B): B =
if (isEmpty) alt else value

// f is by name to beta-reduce it
inline def map[B >: Null](f: => A => B): Optional[B] = {
if (isEmpty) new Optional(null)
else new Optional(f(value))
}

override def toString = if (isEmpty) "<empty>" else s"$value"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/test/scala/gestalt/macros/OptionalTest.scala

object Test {

class C

def main(args: Array[String]): Unit = {
getOrElseTest()
mapTest()
simpleGetOrElseTest()
`don't duplicate side-effects of the prefix test`()
hygieneTest()
`owner chain corruptionTest`()
`typed/untyped mixup test`()
`the final thingTest`()
}

def getOrElseTest(): Unit = {
val opt = new Optional[String]("hello")
assert(opt.getOrElse("world") == "hello")

val opt2 = new Optional[String](null)
assert(opt2.getOrElse("hello") == "hello")
}

def mapTest(): Unit = {
val opt = new Optional[String]("hello")
assert(opt.map(_ + " world") == new Optional("hello world"))

val opt2 = new Optional[String](null)
assert(opt2.map(_ + " world") == new Optional(null))
}

def simpleGetOrElseTest(): Unit = {
val c1 = new C
val c2 = new C
val c3 = new C
var sideEffect = 0

val x = new Optional(c1)
val x1 = x.getOrElse(c2)
assert(x1 == c1)
assert(sideEffect == 0)

val y = new Optional(null)
val y1 = y.getOrElse({ sideEffect += 1; c3 })
assert(y1 == c3)
assert(sideEffect == 1)
}

def `don't duplicate side-effects of the prefix test`(): Unit = {
val c1 = new C
val c2 = new C
var sideEffect = 0

def x = { sideEffect += 1; new Optional(c1) }
val x1 = x.getOrElse(c2)
assert(sideEffect == 1)
}

def hygieneTest(): Unit = {
val temp = 100
new Optional(if (temp < 100) new C else null).getOrElse(new C)
}

def `owner chain corruptionTest`(): Unit = {
def foo(x: => Optional[C]) = x
foo({ val y = new Optional(null); y }).getOrElse(new C)
}

def `typed/untyped mixup test`(): Unit = {
val x1 = new Optional(new C)
val x2 = x1.map(_.toString)
}

def `the final thingTest`(): Unit = {
def foo(f: => C): C = f
val x1 = new Optional(new C)
val x2 = x1.map(x => foo({ val y = x; y }))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/main/scala/gestalt/macros/Optional.scala
// using staging macros (only quotes and splices)

import scala.quoted._

final class Optional[+A >: Null](val value: A) extends AnyVal {
def get: A = value
def isEmpty = value == null

inline def getOrElse[B >: A](alt: => B): B = ~Optional.getOrElseImpl('(this), '(alt))

inline def map[B >: Null](f: A => B): Optional[B] = ~Optional.mapImpl('(this), '(f))

override def toString = if (isEmpty) "<empty>" else s"$value"
}

object Optional {

// FIXME fix issue #5097 and enable private
/*private*/ def getOrElseImpl[T >: Null](opt: Expr[Optional[T]], alt: Expr[T]): Expr[T] = '{
if ((~opt).isEmpty) ~alt else (~opt).value
}

// FIXME fix issue #5097 and enable private
/*private*/ def mapImpl[A >: Null, B >: Null : Type](opt: Expr[Optional[A]], f: Expr[A => B]): Expr[Optional[B]] = '{
if ((~opt).isEmpty) new Optional(null)
else new Optional(~f('((~opt).value)))
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Port of https://github.com/liufengyun/gestalt/blob/master/macros/src/test/scala/gestalt/macros/OptionalTest.scala

object Test {

class C

def main(args: Array[String]): Unit = {
getOrElseTest()
mapTest()
simpleGetOrElseTest()
`don't duplicate side-effects of the prefix test`()
hygieneTest()
`owner chain corruptionTest`()
`typed/untyped mixup test`()
`the final thingTest`()
}

def getOrElseTest(): Unit = {
val opt = new Optional[String]("hello")
assert(opt.getOrElse("world") == "hello")

val opt2 = new Optional[String](null)
assert(opt2.getOrElse("hello") == "hello")
}

def mapTest(): Unit = {
val opt = new Optional[String]("hello")
assert(opt.map(_ + " world") == new Optional("hello world"))

val opt2 = new Optional[String](null)
assert(opt2.map(_ + " world") == new Optional(null))
}

def simpleGetOrElseTest(): Unit = {
val c1 = new C
val c2 = new C
val c3 = new C
var sideEffect = 0

val x = new Optional(c1)
val x1 = x.getOrElse(c2)
assert(x1 == c1)
assert(sideEffect == 0)

val y = new Optional(null)
val y1 = y.getOrElse({ sideEffect += 1; c3 })
assert(y1 == c3)
assert(sideEffect == 1)
}

def `don't duplicate side-effects of the prefix test`(): Unit = {
val c1 = new C
val c2 = new C
var sideEffect = 0

def x = { sideEffect += 1; new Optional(c1) }
val x1 = x.getOrElse(c2)
assert(sideEffect == 1)
}

def hygieneTest(): Unit = {
val temp = 100
new Optional(if (temp < 100) new C else null).getOrElse(new C)
}

def `owner chain corruptionTest`(): Unit = {
def foo(x: => Optional[C]) = x
foo({ val y = new Optional(null); y }).getOrElse(new C)
}

def `typed/untyped mixup test`(): Unit = {
val x1 = new Optional(new C)
val x2 = x1.map(_.toString)
}

def `the final thingTest`(): Unit = {
def foo(f: => C): C = f
val x1 = new Optional(new C)
val x2 = x1.map(x => foo({ val y = x; y }))
}
}