scala.reflect.macros.whitebox.Context Scala Examples

The following examples show how to use scala.reflect.macros.whitebox.Context. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example.
Example 1
Source File: Macro.scala    From zio-macros   with Apache License 2.0 5 votes vote down vote up
package zio.macros.accessible

import com.github.ghik.silencer.silent
import zio.macros.core.ModulePattern

import scala.reflect.macros.whitebox.Context

private[macros] class Macro(val c: Context) extends ModulePattern {
  import c.universe._

  case class Config(name: Option[String])

  def apply(annottees: c.Tree*): c.Tree = {

    @silent("pattern var [^\\s]+ in method unapply is never used")
    val config: Config = c.prefix.tree match {
      case Apply(_, args) =>
        val name = args.collectFirst { case q"$cfg" => c.eval(c.Expr[String](cfg)) }.map { ident =>
          util.Try(c.typecheck(c.parse(s"object $ident {}"))) match {
            case util.Failure(_) =>
              c.abort(c.enclosingPosition, s"""Invalid identifier "$ident". Cannot generate accessors object.""")
            case util.Success(_) => ident
          }
        }

        Config(name)
      case other => c.abort(c.enclosingPosition, s"Invalid accessible macro call ${showRaw(other)}")
    }

    val trees            = extractTrees(annottees)
    val module           = extractModule(trees.module)
    val companion        = extractCompanion(trees.companion)
    val service          = extractService(companion.body)
    val capabilites      = extractCapabilities(service)
    val accessors        = generateCapabilityAccessors(module.name, module.serviceName, capabilites)
    val updatedCompanion = generateUpdatedCompanion(config, module, companion, accessors)

    q"""
       ${trees.module}
       $updatedCompanion
     """
  }

  private def generateCapabilityAccessors(
    moduleType: TypeName,
    serviceName: TermName,
    capabilities: List[Capability]
  ): List[Tree] =
    capabilities.map { capability =>
      val (name, e, a) = (capability.name, capability.error, capability.value)
      val mods =
        if (capability.impl == EmptyTree) Modifiers()
        else Modifiers(Flag.OVERRIDE)

      val returnType = tq"_root_.zio.ZIO[$moduleType, $e, $a]"
      val returnValue =
        capability.argLists match {
          case Some(argLists) if argLists.flatten.nonEmpty =>
            val argNames = argLists.map(_.map(_.name))
            q"_root_.zio.ZIO.accessM(_.$serviceName.$name(...$argNames))"
          case _ =>
            q"_root_.zio.ZIO.accessM(_.$serviceName.$name)"
        }

      capability.argLists match {
        case None            => q"$mods val $name: $returnType = $returnValue"
        case Some(Nil)       => q"$mods def $name: $returnType = $returnValue"
        case Some(List(Nil)) => q"$mods def $name(): $returnType = $returnValue"
        case Some(argLists)  => q"$mods def $name(...$argLists): $returnType = $returnValue"
      }
    }

  private def generateUpdatedCompanion(
    config: Config,
    module: ModuleSummary,
    companion: CompanionSummary,
    capabilityAccessors: List[Tree]
  ): Tree = {

    val accessor: Tree = config.name match {
      case Some(name) => c.parse(s"object $name extends Accessors")
      case None       => EmptyTree
    }

    q"""
      object ${companion.name} {

        ..${companion.body}

       trait Accessors extends Service[${module.name}] {
         ..$capabilityAccessors
       }

       $accessor
     }
    """
  }
} 
Example 2
Source File: package.scala    From logging   with Apache License 2.0 5 votes vote down vote up
package com.persist

import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context
import com.persist.JsonOps._


  def richToString(m: RichMsg): String = {
    m match {
      case s: String => s
      case x => Compact(x, safe = true)
    }
  }

  implicit def sourceLocation: () => SourceLocation = macro sourceLocationMacro

  def sourceLocationMacro(c: Context): c.Expr[() => SourceLocation] = {
    import c.universe._

    val p = c.macroApplication.pos
    val file = p.source.file.name
    val line = p.line

    def allOwners(s: c.Symbol): Seq[c.Symbol] = {
      if (s == `NoSymbol`) {
        Seq()
      } else {
        s +: allOwners(s.owner)
      }
    }
    val owners = allOwners(c.internal.enclosingOwner)

    val className = owners
      .filter(s => s.toString.startsWith("class") || s.toString.startsWith("object"))
      .map(s => s.asClass.name.toString())
      .reverse
      .mkString("$")
    val packageName = owners
      .filter(_.isPackage)
      .map(_.name.toString())
      .filter(_ != "<root>")
      .reverse
      .mkString(".")

    c.Expr[() => SourceLocation](q"() => SourceLocation($file,$packageName,$className,$line)")
  }
} 
Example 3
Source File: singletons.scala    From iota   with Apache License 2.0 5 votes vote down vote up
package iota  //#=cats
package iotaz //#=scalaz
package test

import scala.language.dynamics
import scala.reflect.macros.whitebox.Context

import scala.Predef.augmentString

trait Literal {
  type T
}

object Literal {
  type Bound[A] = Literal { type T <: A }
}

object LiteralInt extends Dynamic {
  def selectDynamic(selector: String): Literal.Bound[Int] =
    macro MacrosLiterally.literalIntSelectDynamic
}

object LiteralString extends Dynamic {
  def selectDynamic(selector: String): Literal.Bound[String] =
    macro MacrosLiterally.literalStringSelectDynamic
}

final class MacrosLiterally(val c: Context) {
  import c.universe.{ Literal => ASTLiteral, _ }
  import internal.decorators._

  private[this] final val iotaPackage: Tree =
    q"_root_.iota"  //#=cats
    q"_root_.iotaz" //#=scalaz

  def literalIntSelectDynamic(selector: Tree): Tree = {
    val q"${value: String}" = selector
    val tpe = c.internal.constantType(Constant(value.toInt))
    val tree = tq"$iotaPackage.test.Literal { type T = $tpe }"
    ASTLiteral(Constant(())).setType(c.typecheck(tree, mode = c.TYPEmode).tpe)
  }

  def literalStringSelectDynamic(selector: Tree): Tree = {
    val q"${value: String}" = selector
    val tpe = c.internal.constantType(Constant(value))
    val tree = tq"$iotaPackage.test.Literal { type T = $tpe }"
    ASTLiteral(Constant(())).setType(c.typecheck(tree, mode = c.TYPEmode).tpe)
  }
} 
Example 4
Source File: typeclass.scala    From typeclassic   with Apache License 2.0 5 votes vote down vote up
package typeclassic

import scala.annotation.{ compileTimeOnly, StaticAnnotation }
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context

import macrocompat._

@compileTimeOnly("typeclass annotation should have been automatically removed but was not")
class typeclass(excludeParents: List[String] = Nil, generateAllOps: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro TypeClassMacros.generateTypeClass
}


@bundle
class TypeClassMacros(val c: Context) {
  import c.universe._

  def generateTypeClass(annottees: c.Expr[Any]*): c.Expr[Any] = {
    annottees.map(_.tree) match {
      case (typeClass: ClassDef) :: Nil => modify(typeClass, None)
      case (typeClass: ClassDef) :: (companion: ModuleDef) :: Nil => modify(typeClass, Some(companion))
      case other :: Nil =>
        c.abort(c.enclosingPosition, "@typeclass can only be applied to traits or abstract classes that take 1 type parameter which is either a proper type or a type constructor")
    }
  }

  private def modify(typeClass: ClassDef, companion: Option[ModuleDef]) = {
    val (tparam, proper) = typeClass.tparams match {
      case hd :: Nil =>
        hd.tparams.size match {
          case 0 => (hd, true)
          case 1 => (hd, false)
          case n => c.abort(c.enclosingPosition, "@typeclass may only be applied to types that take a single proper type or type constructor")
        }
      case other => c.abort(c.enclosingPosition, "@typeclass may only be applied to types that take a single type parameter")
    }

    val modifiedTypeClass = typeClass // TODO

    val modifiedCompanion = generateCompanion(typeClass, tparam, proper, companion match {
      case Some(c) => c
      case None => q"object ${typeClass.name.toTermName} {}"
    })

    val result = c.Expr(q"""
      $modifiedTypeClass
      $modifiedCompanion
    """)

    trace(s"Generated type class ${typeClass.name}:\n" + showCode(result.tree))

    result
  }

  private def generateCompanion(typeClass: ClassDef, tparam0: TypeDef, proper: Boolean, comp: Tree): Tree = {
    val tparam = eliminateVariance(tparam0)

    val q"$mods object $name extends ..$bases { ..$body }" = comp

    q"""
      $mods object $name extends ..$bases {
        import scala.language.experimental.macros
        ..$body
        ${generateInstanceSummoner(typeClass, tparam)}
      }
    """
  }

  private def generateInstanceSummoner(typeClass: ClassDef, tparam: TypeDef): Tree = {
    q"""
      @_root_.typeclassic.op("$$y {$$x}")
      def apply[$tparam](implicit x1: ${typeClass.name}[${tparam.name}]): ${typeClass.name}[${tparam.name}] =
        macro _root_.typeclassic.OpsMacros.op10
    """
  }

  // This method is from simulacrum, contributed by paulp, and is licensed under 3-Clause BSD
  private def eliminateVariance(tparam: TypeDef): TypeDef = {
    // If there's another way to do this I'm afraid I don't know it.
    val u        = c.universe.asInstanceOf[c.universe.type with scala.reflect.internal.SymbolTable]
    val tparam0  = tparam.asInstanceOf[u.TypeDef]
    val badFlags = (Flag.COVARIANT | Flag.CONTRAVARIANT).asInstanceOf[Long]
    val fixedMods = tparam0.mods & ~badFlags
    TypeDef(fixedMods.asInstanceOf[c.universe.Modifiers], tparam.name, tparam.tparams, tparam.rhs)
  }

  private def trace(s: => String) = {
    // Macro paradise seems to always output info statements, even without -verbose
    if (sys.props.get("typeclassic.trace").isDefined) c.info(c.enclosingPosition, s, false)
  }
} 
Example 5
Source File: AnnotationMacros.scala    From scalajs-angulate   with MIT License 5 votes vote down vote up
// -   Project: scalajs-angulate (https://github.com/jokade/scalajs-angulate)
// Description: Macro implementations for AnnotatedFunction
//
// Distributed under the MIT License (see included file LICENSE)
package biz.enef.angulate.impl

import scala.reflect.macros.whitebox.Context

protected[angulate] class AnnotationMacros(val c: Context) extends MacroBase {
  import c.universe._

  // print generated code to console during compilation
  private lazy val logCode = c.settings.exists( _ == "biz.enef.angulate.AnnotationMacros.debug" )

  def functionDIArray(f: c.Tree) = {
    val diArray = createFunctionDIArray(f)

    val tree =
    q"""{import scalajs.js
         import biz.enef.angulate.AnnotatedFunction
         new AnnotatedFunction($diArray)
         }"""

    if(logCode) printCode( tree )
    tree
  }

} 
Example 6
Source File: QuotationDsl.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.dsl

import scala.language.experimental.macros
import scala.language.implicitConversions
import scala.reflect.macros.whitebox.Context

import io.getquill.ast.Ast
import io.getquill.quotation.NonQuotedException
import io.getquill.quotation.Quotation
import scala.annotation.compileTimeOnly

private[dsl] trait QuotationDsl {
  this: CoreDsl =>

  trait Quoted[+T] {
    def ast: Ast
    override def toString = ast.toString
  }

  def quote[T](body: Quoted[T]): Quoted[T] = macro QuotationMacro.doubleQuote[T]
  def quote[T1, R](func: T1 => Quoted[R]): Quoted[T1 => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, R](func: (T1, T2) => Quoted[R]): Quoted[(T1, T2) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, R](func: (T1, T2, T3) => Quoted[R]): Quoted[(T1, T2, T3) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, R](func: (T1, T2, T3, T4) => Quoted[R]): Quoted[(T1, T2, T3, T4) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, R](func: (T1, T2, T3, T4, T5) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, T6, R](func: (T1, T2, T3, T4, T5, T6) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5, T6) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, T6, T7, R](func: (T1, T2, T3, T4, T5, T6, T7) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5, T6, T7) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, T6, T7, T8, R](func: (T1, T2, T3, T4, T5, T6, T7, T8) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5, T6, T7, T8) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, T6, T7, T8, T9, R](func: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5, T6, T7, T8, T9) => R] = macro QuotationMacro.quotedFunctionBody
  def quote[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R](func: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => Quoted[R]): Quoted[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R] = macro QuotationMacro.quotedFunctionBody

  implicit def quote[T](body: T): Quoted[T] = macro QuotationMacro.quote[T]

  @compileTimeOnly(NonQuotedException.message)
  implicit def unquote[T](quoted: Quoted[T]): T = NonQuotedException()
}

private[dsl] class QuotationMacro(val c: Context) extends Quotation 
Example 7
Source File: LoadNaming.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.idiom

import scala.reflect.macros.whitebox.Context
import scala.util.Try

import io.getquill.NamingStrategy
import io.getquill.util.CollectTry
import io.getquill.util.LoadObject
import io.getquill.CompositeNamingStrategy

object LoadNaming {

  def static(c: Context)(tpe: c.Type): Try[NamingStrategy] =
    CollectTry {
      strategies(c)(tpe).map(LoadObject[NamingStrategy](c)(_))
    }.map(NamingStrategy(_))

  private def strategies(c: Context)(tpe: c.Type) =
    tpe <:< c.typeOf[CompositeNamingStrategy] match {
      case true =>
        tpe.typeArgs
          .filterNot(_ =:= c.weakTypeOf[NamingStrategy])
          .filterNot(_ =:= c.weakTypeOf[scala.Nothing])
      case false =>
        List(tpe)
    }
} 
Example 8
Source File: Rebind.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.quotation

import scala.reflect.macros.whitebox.Context
import io.getquill.ast.Ast
import io.getquill.ast.Function
import io.getquill.ast.FunctionApply
import io.getquill.ast.Ident
import io.getquill.ast.QuotedReference

object Rebind {

  def apply(c: Context)(tree: c.Tree, ast: Ast, astParser: c.Tree => Ast): Option[Ast] = {
    import c.universe.{ Function => _, Ident => _, _ }

    def toIdent(s: Symbol) =
      Ident(s.name.decodedName.toString)

    def paramIdents(method: MethodSymbol) =
      method.paramLists.flatten.map(toIdent)

    def placeholder(t: Tree): Tree =
      q"null.asInstanceOf[${t.tpe}]"

    tree match {
      case q"$conv($orig).$m[..$t](...$params)" =>
        val convMethod = conv.symbol.asMethod
        val origIdent = paramIdents(convMethod).head
        val paramsIdents = paramIdents(convMethod.returnType.member(m).asMethod)
        val paramsAsts = params.flatten.map(astParser)
        val reifiedTree = q"$conv(${placeholder(orig)}).$m[..$t](...${params.map(_.map(placeholder(_)))})"
        val function = QuotedReference(reifiedTree, Function(origIdent :: paramsIdents, ast))
        val apply = FunctionApply(function, astParser(orig) :: paramsAsts)
        Some(apply)
      case _ =>
        None
    }
  }
} 
Example 9
Source File: Bindings.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.quotation

import scala.reflect.macros.whitebox.Context

object Bindings {
  def apply(c: Context)(quoted: c.Tree, tpe: c.Type): Map[c.Symbol, c.Tree] = {
    import c.universe._
    tpe
      .member(TermName("bindings"))
      .typeSignature.decls.collect {
        case m: MethodSymbol if (m.isGetter) =>
          m ->
            q"""
              {
                import _root_.scala.language.reflectiveCalls
                $quoted.bindings.$m
              }
            """
      }.toMap
  }
} 
Example 10
Source File: Quotation.scala    From quill   with Apache License 2.0 5 votes vote down vote up
package io.getquill.quotation

import scala.annotation.StaticAnnotation
import scala.reflect.ClassTag
import scala.reflect.macros.whitebox.Context

import io.getquill.ast._
import io.getquill.util.MacroContextExt._
import io.getquill.norm.BetaReduction
import io.getquill.util.EnableReflectiveCalls

case class QuotedAst(ast: Ast) extends StaticAnnotation

trait Quotation extends Liftables with Unliftables with Parsing with ReifyLiftings {
  val c: Context
  import c.universe._

  private val quoted = TermName("quoted")

  def quote[T](body: Tree)(implicit t: WeakTypeTag[T]) = {

    val ast = BetaReduction(astParser(body))

    val id = TermName(s"id${ast.hashCode.abs}")

    val (reifiedAst, liftings) = reifyLiftings(ast)

    val quotation =
      c.untypecheck {
        q"""
          new ${c.prefix}.Quoted[$t] {

            ..${EnableReflectiveCalls(c)}

            @${c.weakTypeOf[QuotedAst]}($reifiedAst)
            def $quoted = ast

            override def ast = $reifiedAst

            def $id() = ()

            $liftings
          }
        """
      }

    if (IsDynamic(ast)) {
      q"$quotation: ${c.prefix}.Quoted[$t]"
    } else {
      quotation
    }
  }

  def doubleQuote[T: WeakTypeTag](body: Expr[Any]) =
    body.tree match {
      case q"null" => c.fail("Can't quote null")
      case tree    => q"${c.prefix}.unquote($tree)"
    }

  def quotedFunctionBody(func: Expr[Any]) =
    func.tree match {
      case q"(..$p) => $b" => q"${c.prefix}.quote((..$p) => ${c.prefix}.unquote($b))"
    }

  protected def unquote[T](tree: Tree)(implicit ct: ClassTag[T]) =
    astTree(tree).flatMap(astUnliftable.unapply).map {
      case ast: T => ast
    }

  private def astTree(tree: Tree) =
    for {
      method <- tree.tpe.decls.find(_.name == quoted)
      annotation <- method.annotations.headOption
      astTree <- annotation.tree.children.lastOption
    } yield astTree
} 
Example 11
Source File: ByTreeTyper.scala    From coroutines   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package org.coroutines.common



import scala.collection._
import scala.language.experimental.macros
import scala.reflect.macros.whitebox.Context



private[coroutines] class ByTreeTyper[C <: Context](val c: C)(val treeValue: Any) {
  import c.universe._
  private val tree = treeValue.asInstanceOf[Tree]
  private val treeMapping = mutable.Map[Tree, Tree]()
  private val traverser = new TraverserUtil[c.type](c)
  val untypedTree = c.untypecheck(tree)
  traverser.traverseByShape(untypedTree, tree)((t, pt) => treeMapping(t) = pt)

  object typeOf {
    private val augmentedTypes = mutable.Map[Tree, Type]()
    def apply(t: Tree) = {
      if (augmentedTypes.contains(t)) augmentedTypes(t)
      else if (treeMapping.contains(t)) treeMapping(t).tpe
      else t.tpe
    }
    def update(t: Tree, tpe: Type) = augmentedTypes(t) = tpe
  }
} 
Example 12
Source File: macro_impl.scala    From lms-clean   with BSD 3-Clause "New" or "Revised" License 5 votes vote down vote up
package lms.experimental

//import language.experimental.macros
import scala.annotation.StaticAnnotation
import scala.reflect.macros.whitebox.Context

import scala.util.matching.Regex

import scala.collection.mutable




object ir_impl {
  def impl(c: Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._

    println("YOUPI")
    println(c.prefix)
    val List(a) = annottees
    println(a)
    a.tree match {
      case q"def $name[..$t](..$args): $tpe" =>
        val args1 = args map { case ValDef(_,x,_,_) => q"ref($x)" }
        return c.Expr(q"def $name[..$t](..$args): $tpe = reflect[$tpe](${name.toString},..$args1)")
      case q"def $name[..$t](..$args): $tpe = $body" =>
        // TODO: strip by-name type
        val args0 = args map { case ValDef(_,x,_,_) => q"$x" }
        val args1 = args map { case ValDef(_,x,_,_) => q"ref($x)" }
        val name_next = TermName(name.toString + "_next")
        // TODO: what if we have type parameters? just disallow?
        return c.Expr(q"""
          lower((..$args) => 
            Rewrite[$tpe]($name(..$args0), $name_next(..$args0)))
          def $name[..$t](..$args): $tpe = reflect[$tpe](${name.toString},..$args1)
          def $name_next[..$t](..$args): $tpe = $body
        """)
     // TODO class def
      //case t@ClassDef(_,_,_,_) =>
    }
  }
}