All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.github.zeal18.zio.mongodb.bson.codecs.EasierValDef.scala Maven / Gradle / Ivy

There is a newer version: 0.11.0
Show newest version
package io.github.zeal18.zio.mongodb.bson.codecs

import scala.quoted.*

object EasierValDef {

  def untypedValDef(using
    q: Quotes,
  )(name: String, tpe: q.reflect.TypeRepr, flags: q.reflect.Flags = q.reflect.Flags.EmptyFlags)(
    rhs: q.reflect.Term,
  ): UntypedValDef.WithQuotes[q.type] =
    import quotes.reflect.*
    val sym = Symbol.newVal(Symbol.spliceOwner, name, tpe, flags, Symbol.noSymbol)
    val vd  = ValDef(sym, Some(rhs))
    Ref(sym) match
      case ref: Ident => UntypedValDef(using q)(sym, vd, ref)

  object UntypedValDef:
    type WithQuotes[Q <: Quotes] = UntypedValDef { val q: Q }

    def apply(using q: Quotes)(
      symbol: q.reflect.Symbol,
      valDef: q.reflect.ValDef,
      ref: q.reflect.Ident,
    ): WithQuotes[q.type] =
      new UntypedValDef(using q)(symbol, valDef, ref).asInstanceOf[WithQuotes[q.type]] // TODO: S3

  final class UntypedValDef(using val q: Quotes)(
    val symbol: q.reflect.Symbol,
    val valDef: q.reflect.ValDef,
    val ref: q.reflect.Ident,
  ):
    import q.reflect.*

    def substQ(using qq: Quotes) =
      this.asInstanceOf[UntypedValDef.WithQuotes[qq.type]]

    def as[A: Type]: TypedValDef.WithQuotes[A, q.type] =
      import quotes.reflect.*
      TypedValDef(symbol, valDef, ref.asExprOf[A])

    def assign(rhs: Term): Assign =
      Assign(ref, rhs)

    def modify(f: Ident => Term): Assign =
      assign(f(ref))

  // ===================================================================================================================

  def typedValDef[A: Type](using
    q: Quotes,
  )(name: String, flags: q.reflect.Flags = q.reflect.Flags.EmptyFlags)(
    rhs: Expr[A],
  ): TypedValDef.WithQuotes[A, q.type] =
    import quotes.reflect.*
    val u = untypedValDef(using q)(name, TypeRepr.of[A], flags)(rhs.asTerm)
    u.as[A]

  object TypedValDef:
    type WithQuotes[A, Q <: Quotes] = TypedValDef[A] { val q: Q }

    def apply[A](using
      q: Quotes,
    )(symbol: q.reflect.Symbol, valDef: q.reflect.ValDef, ref: Expr[A]): WithQuotes[A, q.type] =
      new TypedValDef(using q)(symbol, valDef, ref).asInstanceOf[WithQuotes[A, q.type]] // TODO: S3

  final class TypedValDef[A](using val q: Quotes)(
    val symbol: q.reflect.Symbol,
    val valDef: q.reflect.ValDef,
    val ref: Expr[A],
  ) { self =>
    import q.reflect.*

    lazy val untyped: UntypedValDef.WithQuotes[q.type] =
      ref.asTerm match
        case i: Ident => (new UntypedValDef(using q)(symbol, valDef, i)).substQ

    def subst[B] =
      this.asInstanceOf[TypedValDef.WithQuotes[B, self.q.type]]

    def substQ(using qq: Quotes) =
      this.asInstanceOf[TypedValDef.WithQuotes[A, qq.type]]

    def use[B: Type](f: Expr[A] => Expr[B]): Expr[B] =
      Block(valDef :: Nil, f(ref).asTerm).asExprOf[B]

    def assignTerm(rhs: Expr[A]): Assign =
      untyped.assign(rhs.asTerm)

    def assign(rhs: Expr[A]): Expr[Unit] =
      assignTerm(rhs).asExprOf[Unit]

    def modify(f: Expr[A] => Expr[A]): Expr[Unit] =
      assign(f(ref))
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy