io.scalaland.chimney.internal.compiletime.Exprs.scala Maven / Gradle / Ivy
package io.scalaland.chimney.internal.compiletime
private[compiletime] trait Exprs { this: Definitions =>
/** Platform-specific expression representation (`c.Expr[A]` in 2, `scala.quoted.Expr[A]` in 3 */
protected type Expr[A]
protected val Expr: ExprModule
protected trait ExprModule { this: Expr.type =>
// Build-in types expressions
val Nothing: Expr[Nothing]
val Null: Expr[Null]
val Unit: Expr[Unit]
def Int(value: Int): Expr[Int]
def String(value: String): Expr[String]
def Tuple2[A: Type, B: Type](a: Expr[A], b: Expr[B]): Expr[(A, B)]
val Function1: Function1Module
trait Function1Module { this: Function1.type =>
def apply[A: Type, B: Type](fn: Expr[A => B])(a: Expr[A]): Expr[B]
def instance[A: Type, B: Type](f: Expr[A] => Expr[B]): Expr[A => B] =
ExprPromise.promise[A](ExprPromise.NameGenerationStrategy.FromType).map[Expr[B]](f).fulfilAsLambda
}
val Function2: Function2Module
trait Function2Module { this: Function2.type =>
def instance[A: Type, B: Type, C: Type](f: (Expr[A], Expr[B]) => Expr[C]): Expr[(A, B) => C] =
ExprPromise
.promise[A](ExprPromise.NameGenerationStrategy.FromType)
.fulfilAsLambda2[B, Expr[B], C](
ExprPromise.promise[B](ExprPromise.NameGenerationStrategy.FromType)
)(f)
def tupled[A: Type, B: Type, C: Type](fn2: Expr[(A, B) => C]): Expr[((A, B)) => C]
}
val Array: ArrayModule
trait ArrayModule { this: Array.type =>
def apply[A: Type](args: Expr[A]*): Expr[Array[A]]
def map[A: Type, B: Type](array: Expr[Array[A]])(fExpr: Expr[A => B]): Expr[Array[B]]
def to[A: Type, C: Type](array: Expr[Array[A]])(
factoryExpr: Expr[scala.collection.compat.Factory[A, C]]
): Expr[C]
def iterator[A: Type](array: Expr[Array[A]]): Expr[Iterator[A]]
}
val Option: OptionModule
trait OptionModule { this: Option.type =>
def apply[A: Type](a: Expr[A]): Expr[Option[A]]
def empty[A: Type]: Expr[Option[A]]
val None: Expr[scala.None.type]
def map[A: Type, B: Type](opt: Expr[Option[A]])(f: Expr[A => B]): Expr[Option[B]]
def fold[A: Type, B: Type](opt: Expr[Option[A]])(onNone: Expr[B])(onSome: Expr[A => B]): Expr[B]
def orElse[A: Type](opt1: Expr[Option[A]], opt2: Expr[Option[A]]): Expr[Option[A]]
def getOrElse[A: Type](opt: Expr[Option[A]])(orElse: Expr[A]): Expr[A]
def get[A: Type](opt: Expr[Option[A]]): Expr[A]
def isDefined[A: Type](opt: Expr[Option[A]]): Expr[Boolean]
}
val Either: EitherModule
trait EitherModule { this: Either.type =>
def fold[L: Type, R: Type, A: Type](either: Expr[Either[L, R]])(left: Expr[L => A])(right: Expr[R => A]): Expr[A]
val Left: LeftModule
trait LeftModule { this: Left.type =>
def apply[L: Type, R: Type](value: Expr[L]): Expr[Left[L, R]]
def value[L: Type, R: Type](left: Expr[Left[L, R]]): Expr[L]
}
val Right: RightModule
trait RightModule { this: Right.type =>
def apply[L: Type, R: Type](value: Expr[R]): Expr[Right[L, R]]
def value[L: Type, R: Type](right: Expr[Right[L, R]]): Expr[R]
}
}
val Iterable: IterableModule
trait IterableModule { this: Iterable.type =>
def map[A: Type, B: Type](iterable: Expr[Iterable[A]])(fExpr: Expr[A => B]): Expr[Iterable[B]]
def to[A: Type, C: Type](iterable: Expr[Iterable[A]])(
factoryExpr: Expr[scala.collection.compat.Factory[A, C]]
): Expr[C]
def iterator[A: Type](iterable: Expr[Iterable[A]]): Expr[Iterator[A]]
}
val Map: MapModule
trait MapModule { this: Map.type =>
def iterator[K: Type, V: Type](map: Expr[scala.collection.Map[K, V]]): Expr[Iterator[(K, V)]]
}
val Iterator: IteratorModule
trait IteratorModule { this: Iterator.type =>
def map[A: Type, B: Type](iterator: Expr[Iterator[A]])(fExpr: Expr[A => B]): Expr[Iterator[B]]
def to[A: Type, C: Type](iterator: Expr[Iterator[A]])(
factoryExpr: Expr[scala.collection.compat.Factory[A, C]]
): Expr[C]
def zipWithIndex[A: Type](it: Expr[Iterator[A]]): Expr[Iterator[(A, Int)]]
}
def ifElse[A: Type](cond: Expr[Boolean])(ifBranch: Expr[A])(elseBranch: Expr[A]): Expr[A]
def block[A: Type](statements: List[Expr[Unit]], expr: Expr[A]): Expr[A]
def summonImplicit[A: Type]: Option[Expr[A]]
def summonImplicitUnsafe[A: Type]: Expr[A] = summonImplicit[A].getOrElse {
assertionFailed(s"Implicit not found: ${Type.prettyPrint[A]}")
}
// Implementations of Expr extension methods
def eq[A: Type, B: Type](a: Expr[A], b: Expr[B]): Expr[Boolean]
def asInstanceOf[A: Type, B: Type](expr: Expr[A]): Expr[B]
def upcast[A: Type, B: Type](expr: Expr[A]): Expr[B]
def suppressUnused[A: Type](expr: Expr[A]): Expr[Unit]
def prettyPrint[A](expr: Expr[A]): String
def typeOf[A](expr: Expr[A]): Type[A]
}
implicit final protected class ExprOps[A: Type](private val expr: Expr[A]) {
def prettyPrint: String = Expr.prettyPrint(expr)
def tpe: Type[A] = Expr.typeOf(expr)
/** Creates '{ $expr == $other } expression, which would compare both expressions in runtime */
def eqExpr[B: Type](other: Expr[B]): Expr[Boolean] = Expr.eq(expr, other)
// Both methods below change Expr[A] to Expr[B], but they differ in checks ans how it affects the underlying code:
// - asInstanceOfExpr[B] should be used when we want to have .asInstanceOf[B] in the generated code, because we need
// to perform the cast in the runtime - WE know what we can perform it but the JVN does not
// - upcastToExprOf[B] should be used when WE know that A <: B, but it is not obvious to Scala compiler - in such
// case Type[A] <:< Type[B] assertion will be checked and the expression upcasted
/** Creates '{ ${ expr }.asInstanceOf[B] } expression in emitted code, moving check to the runtime */
def asInstanceOfExpr[B: Type]: Expr[B] = Expr.asInstanceOf[A, B](expr)
/** Upcasts `Expr[A]` to `Expr[B]` if `A <:< B`, without upcasting the underlying code */
def upcastToExprOf[B: Type]: Expr[B] = Expr.upcast[A, B](expr)
def as_?? : ExistentialExpr = ExistentialExpr(expr)
}
implicit final protected class Function1[A: Type, B: Type](private val function1Expr: Expr[A => B]) {
def apply(a: Expr[A]): Expr[B] = Expr.Function1.apply(function1Expr)(a)
}
implicit final protected class Function2[A: Type, B: Type, C: Type](private val function2Expr: Expr[(A, B) => C]) {
def tupled: Expr[((A, B)) => C] = Expr.Function2.tupled(function2Expr)
}
implicit final protected class ArrayExprOps[A: Type](private val arrayExpr: Expr[Array[A]]) {
def map[B: Type](fExpr: Expr[A => B]): Expr[Array[B]] = Expr.Array.map(arrayExpr)(fExpr)
def to[C: Type](factoryExpr: Expr[scala.collection.compat.Factory[A, C]]): Expr[C] =
Expr.Array.to(arrayExpr)(factoryExpr)
def iterator: Expr[Iterator[A]] = Expr.Array.iterator(arrayExpr)
}
implicit final protected class OptionExprOps[A: Type](private val optionExpr: Expr[Option[A]]) {
def isDefined: Expr[Boolean] = Expr.Option.isDefined(optionExpr)
def map[B: Type](fExpr: Expr[A => B]): Expr[Option[B]] = Expr.Option.map(optionExpr)(fExpr)
def fold[B: Type](noneExpr: Expr[B])(fExpr: Expr[A => B]): Expr[B] =
Expr.Option.fold(optionExpr)(noneExpr)(fExpr)
def getOrElse(noneExpr: Expr[A]): Expr[A] = Expr.Option.getOrElse(optionExpr)(noneExpr)
def get: Expr[A] = Expr.Option.get(optionExpr)
def orElse(other: Expr[Option[A]]): Expr[Option[A]] = Expr.Option.orElse(optionExpr, other)
}
implicit final protected class EitherExprOps[L: Type, R: Type](private val eitherExpr: Expr[Either[L, R]]) {
def fold[B: Type](matchingLeft: Expr[L => B])(matchingRight: Expr[R => B]): Expr[B] =
Expr.Either.fold(eitherExpr)(matchingLeft)(matchingRight)
}
implicit final protected class LeftExprOps[L: Type, R: Type](private val leftExpr: Expr[Left[L, R]]) {
def value: Expr[L] = Expr.Either.Left.value(leftExpr)
}
implicit final protected class RightExprOps[L: Type, R: Type](private val rightExpr: Expr[Right[L, R]]) {
def value: Expr[R] = Expr.Either.Right.value(rightExpr)
}
implicit final protected class IterableExprOps[A: Type](private val iterableExpr: Expr[Iterable[A]]) {
def map[B: Type](fExpr: Expr[A => B]): Expr[Iterable[B]] = Expr.Iterable.map(iterableExpr)(fExpr)
def to[C: Type](factoryExpr: Expr[scala.collection.compat.Factory[A, C]]): Expr[C] =
Expr.Iterable.to(iterableExpr)(factoryExpr)
def iterator: Expr[Iterator[A]] = Expr.Iterable.iterator(iterableExpr)
}
implicit final protected class MapExprOps[K: Type, V: Type](private val mapExpr: Expr[scala.collection.Map[K, V]]) {
def iterator: Expr[Iterator[(K, V)]] = Expr.Map.iterator(mapExpr)
}
implicit final protected class IteratorExprOps[A: Type](private val iteratorExpr: Expr[Iterator[A]]) {
def map[B: Type](fExpr: Expr[A => B]): Expr[Iterator[B]] = Expr.Iterator.map(iteratorExpr)(fExpr)
def to[C: Type](factoryExpr: Expr[scala.collection.compat.Factory[A, C]]): Expr[C] =
Expr.Iterator.to(iteratorExpr)(factoryExpr)
def zipWithIndex: Expr[Iterator[(A, Int)]] = Expr.Iterator.zipWithIndex(iteratorExpr)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy