Skip to content

Commit

Permalink
Close #32 - Add InlinedRefined
Browse files Browse the repository at this point in the history
  • Loading branch information
kevin-lee committed Aug 15, 2023
1 parent 4e69a95 commit 92be58d
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .scalafix-scala3.conf
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ rules = [
OptionMatchToRight

SimplifyForYield
ThrowableToNonFatal
// ThrowableToNonFatal
UnnecessaryCase
UnnecessaryMatch
UnnecessarySort
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package refined4s

import scala.compiletime.*

/** @author Kevin Lee
* @since 2023-08-12
*/
trait InlinedRefined[A] extends RefinedBase[A] {

inline def inlinedInvalidReason(inline a: A): String

inline def inlinedPredicate(inline a: A): Boolean

inline def apply(inline a: A): Type =
inline if inlinedPredicate(a) then a.asInstanceOf[Type] // scalafix:ok DisableSyntax.asInstanceOf
else error("Invalid value: [" + codeOf(a) + "]. " + inlinedInvalidReason(a))

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package refined4s

import hedgehog._
import hedgehog.runner._

/** @author Kevin Lee
* @since 2023-08-14
*/
object InlinedRefinedSpec extends Properties {
override def tests: List[Test] = List(
example("test InlinedRefined with valid value", testInlinedRefined)
)

def testInlinedRefined: Result = {
import InlinedRefinedType.*

Something(1)
Result.success
}

// def testInlinedRefined2: Result = {
// import InlinedRefinedType.*
//
// val a = 1
// // This should not compile.
// Something(a)
// Result.failure
// }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package refined4s

object InlinedRefinedType {
type Something = Something.Type
object Something extends InlinedRefined[Int] {
import scala.compiletime.*
import scala.quoted.*
override inline def inlinedInvalidReason(inline a: Int): String =
"The number is a negative Int. [a: " + codeOf(a) + "]"

private def inlinedPredicate0(a: Expr[Int])(using Quotes): Expr[Boolean] = {
import quotes.reflect.*
a.asTerm match {
case Inlined(_, _, Literal(IntConstant(num))) =>
try {
validate(num)
Expr(true)
} catch {
case _: Throwable => Expr(false)
}
case _ =>
report.error(
"Something must be a Int literal.",
a,
)
Expr(false)
}

}

override inline def inlinedPredicate(inline a: Int): Boolean = ${ inlinedPredicate0('a) }

override def invalidReason(a: Int): String = s"The number is a negative Int. [a: ${a.toString}"

override def predicate(a: Int): Boolean =
try {
validate(a)
true
} catch {
case _: Throwable => false
}
}

def validate(a: Int): Int =
if (a >= 0) a else sys.error("The number should be non-negative number.")

}

0 comments on commit 92be58d

Please sign in to comment.