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

japgolly.microlibs.compiletime.Init.scala Maven / Gradle / Ivy

There is a newer version: 4.2.1
Show newest version
package japgolly.microlibs.compiletime

import scala.quoted.*
import MacroEnv.*

object Init:
  def apply(using qq   : Quotes)
           (freshNameFn: Int => String    = "i" + _,
            flags      : qq.reflect.Flags = qq.reflect.Flags.EmptyFlags): Init { val q: qq.type } =
    new Init(using qq)(freshNameFn, flags)
      .asInstanceOf[Init { val q: qq.type }] // TODO: S3 bug

class Init(using val q: Quotes)
          (freshNameFn: Int => String,
           flags      : q.reflect.Flags
          ) {
  import q.reflect.*

  var seen = ExprMap.empty[Any, TypedValDef[Any]]
  var stmts = Vector.empty[Statement]

  private var vars = 0
  def newName(): String =
    vars += 1
    freshNameFn(vars)

  def +=(t: Statement): Unit =
    stmts :+= t

  def ++=(ts: IterableOnce[Statement]): Unit =
    ts.iterator.foreach(this.+=)

  def valDef[A: Type](expr      : Expr[A],
                      name      : String  = newName(),
                      reuse     : Boolean = true,
                      extraFlags: Flags   = Flags.EmptyFlags,
                      onInit    : Boolean = true,
                     ): TypedValDef.WithQuotes[A, q.type] =
    val allFlags    = flags | extraFlags
    val allowReuse  = reuse && !allFlags.is(Flags.Mutable)
    val alreadySeen = if allowReuse then seen.get(expr) else None
    alreadySeen match
      case None =>
        val vd = typedValDef(name, allFlags)(expr)
        if onInit then this += vd.valDef
        seen += ((expr, vd.subst[Any]))
        vd
      case Some(vd) =>
        vd.subst[A].substQ

  def wrapTerm(term: Term): Block =
    Block(stmts.toList, term)

  def wrapExpr[A: Type](expr: Expr[A]): Expr[A] =
    wrapTerm(expr.asTerm).asExprOf[A]
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy