Skip to content

Instantly share code, notes, and snippets.

@deanwampler
Last active May 22, 2022 14:07
Show Gist options
  • Save deanwampler/56418ab335ad1d8c5fdb80534c8ce019 to your computer and use it in GitHub Desktop.
Save deanwampler/56418ab335ad1d8c5fdb80534c8ce019 to your computer and use it in GitHub Desktop.
// Adapted from "Programming Scala, Third Edition" (http://programming-scala.com)
// https://github.com/deanwampler/programming-scala-book-code-examples/blob/master/src/main/scala/progscala3/meta/Invariant.scala
import scala.quoted.*
object invariantMinInline:
val ignore = false
inline def apply[T]( // Use of "minimal" inlining. Does it still work?
predicate: => Boolean, // Now we need by-name parameters!
message: => String = "")(
block: => T): T =
if !ignore then
if !predicate then fail(predicate, message, block, "before")
val result = block
if !predicate then fail(predicate, message, block, "after")
result
else
block
inline private def fail[T](
predicate: => Boolean,
message: => String,
block: => T,
beforeAfter: String): Unit =
${ failImpl('predicate, 'message, 'block, 'beforeAfter) }
case class InvariantFailure(msg: String) extends RuntimeException(msg)
private def failImpl[T](
predicate: Expr[Boolean], message: Expr[String],
block: Expr[T], beforeAfter: Expr[String])(
using Quotes): Expr[String] =
'{ throw InvariantFailure(
s"""FAILURE! predicate "${${showExpr(predicate)}}" """
+ s"""failed ${$beforeAfter} evaluation of block:"""
+ s""" "${${showExpr(block)}}". Message = "${$message}". """)
}
private def showExpr[T](expr: Expr[T])(using Quotes): Expr[String] =
val code: String = expr.show
Expr(code)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment