scala.reflect.macros.whitebox Scala Examples

The following examples show how to use scala.reflect.macros.whitebox. 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: delegate.scala    From macro-compat   with Apache License 2.0 5 votes vote down vote up
package delegate

import scala.language.experimental.macros

import scala.reflect.macros.whitebox

import macrocompat.bundle

class Delegate {
  def delegate: Unit = macro DelegateMacro.delegate
}

@bundle
class DelegateMacro(val c: whitebox.Context) { outer =>
  import c.universe._

  class D(override val c: outer.c.type) extends Delegatee(c)
  def delegate: Tree = (new D(c)).delegate
}

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

  def delegate: Tree = {
    q"()"
  }
} 
Example 2
Source File: autoSemigroupalK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoSemigroupalK")
class autoSemigroupalK extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoSemigroupalKMacros.semigroupalKInst
}

private[tagless] class autoSemigroupalKMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateSemigroupalKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("semigroupalKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.SemigroupalK[$algebraType]",
      q"_root_.cats.tagless.Derive.semigroupalK[$algebraType]"
    )

  def semigroupalKInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList) { algebra =>
      algebra.forVaryingEffectType(generateSemigroupalKFor(algebra.name)) :: Nil
    }
} 
Example 3
Source File: autoFlatMap.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFlatMap")
class autoFlatMap extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFlatMapMacros.flatMapInst
}


private[tagless] class autoFlatMapMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateFlatMapFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("flatMapFor" + algebraName),
      typeParams,
      tq"_root_.cats.FlatMap[$algebraType]",
      q"_root_.cats.tagless.Derive.flatMap[$algebraType]"
    )

  def flatMapInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateFlatMapFor(algebra.name)) :: Nil
    }
} 
Example 4
Source File: autoContravariantK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctorK")
class autoContravariantK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoContravariantKMacros.contravariantKInst
}

private [tagless] class autoContravariantKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateContravariantKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("contravariantKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.ContravariantK[$algebraType]",
      q"_root_.cats.tagless.Derive.contravariantK[$algebraType]"
    )

  def contravariantKInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList) { algebra =>
      algebra.forVaryingEffectType(generateContravariantKFor(algebra.name)) :: Nil
    }
} 
Example 5
Source File: autoFunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctor")
class autoFunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFunctorMacros.functorInst
}


private[tagless] class autoFunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateFunctorFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("functorFor" + algebraName),
      typeParams,
      tq"_root_.cats.Functor[$algebraType]",
      q"_root_.cats.tagless.Derive.functor[$algebraType]"
    )

  def functorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateFunctorFor(algebra.name)) :: Nil
    }
} 
Example 6
Source File: autoInvariant.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInvariant")
class autoInvariant extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInvariantMacros.invariantInst
}

private[tagless] class autoInvariantMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateInvariantFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("invariantFor" + algebraName),
      typeParams,
      tq"_root_.cats.Invariant[$algebraType]",
      q"_root_.cats.tagless.Derive.invariant[$algebraType]"
    )

  def invariantInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateInvariantFor(algebra.name)) :: Nil
    }
} 
Example 7
Source File: autoProfunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoProfunctor")
class autoProfunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoProfunctorMacros.profunctorInst
}

private[tagless] class autoProfunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateProfunctorFor(
    algebraName: String
  )(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("profunctorFor" + algebraName),
      typeParams,
      tq"_root_.cats.arrow.Profunctor[$algebraType]",
      q"_root_.cats.tagless.Derive.profunctor[$algebraType]"
    )

  def profunctorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.TwoLastRegularTypeParams) {
      algebra =>
        algebra.forVaryingEffectType(generateProfunctorFor(algebra.name)) :: Nil
    }
} 
Example 8
Source File: autoBifunctor.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoBifunctor")
class autoBifunctor extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoBifunctorMacros.bifunctorInst
}

private[tagless] class autoBifunctorMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateBifunctorFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("bifunctorFor" + algebraName),
      typeParams,
      tq"_root_.cats.Bifunctor[$algebraType]",
      q"_root_.cats.tagless.Derive.bifunctor[$algebraType]"
    )

  def bifunctorInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.TwoLastRegularTypeParams) {
      algebra =>
        algebra.forVaryingEffectType(generateBifunctorFor(algebra.name)) :: Nil
    }
} 
Example 9
Source File: autoInstrument.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInstrument")
class autoInstrument extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInstrumentMacros.instrumentInst
}

private[tagless] class autoInstrumentMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateInstrumentFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("instrumentFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.diagnosis.Instrument[$algebraType]",
      q"_root_.cats.tagless.Derive.instrument[$algebraType]"
    )

  def instrumentInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.FirstHigherKindedTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateInstrumentFor(algebra.name)) :: Nil
    }
} 
Example 10
Source File: ExportedMagnolia.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.module.magnolia

import magnolia.Magnolia
import pureconfig.Exported

import scala.language.higherKinds
import scala.reflect.macros.whitebox

// Wrap the output of Magnolia in an Exported to force it to a lower priority.
// This seems to work, despite magnolia hardcode checks for `macroApplication` symbol
// and relying on getting an diverging implicit expansion error for auto-mode.
// Thankfully at least it doesn't check the output type of its `macroApplication`
object ExportedMagnolia {
  def exportedMagnolia[TC[_], A: c.WeakTypeTag](c: whitebox.Context): c.Expr[Exported[TC[A]]] = {
    val magnoliaTree = c.Expr[TC[A]](Magnolia.gen[A](c))
    c.universe.reify(Exported(magnoliaTree.splice))
  }
} 
Example 11
Source File: MacroCompat.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.derivation

import scala.reflect.macros.{ TypecheckException, whitebox }

import pureconfig.Derivation


trait MacroCompat {
  val c: whitebox.Context

  import c.universe._

  // since we are inside a whitebox implicit macro, error messages from `c.abort` as not printed. A trick must be used
  // to make the compiler print our custom message. That's done by setting a @implicitNotFound annotation on our
  // `Derivation` class (idea taken from shapeless `Lazy`).
  def setImplicitNotFound(msg: String): Unit = {
    import c.internal.decorators._
    val infTree = c.typecheck(q"""new _root_.scala.annotation.implicitNotFound($msg)""", silent = false)
    typeOf[Derivation[_]].typeSymbol.setAnnotations(Annotation(infTree))
  }

  // This should be simply defined as `c.inferImplicitValue(c.weakTypeOf[A])`, but divergent implicits are wrongly
  // reported up to Scala 2.12.2. See https://github.com/scala/bug/issues/10398 for more information.
  def inferImplicitValueCompat(typ: Type): Tree = {
    val cc = c.asInstanceOf[scala.reflect.macros.contexts.Context]
    val enclosingTree =
      cc.openImplicits.headOption.map(_.tree)
        .orElse(cc.enclosingMacros.lastOption.map(_.macroApplication))
        .getOrElse(EmptyTree).asInstanceOf[cc.universe.analyzer.global.Tree]

    val res: cc.Tree = cc.universe.analyzer.inferImplicit(
      enclosingTree, typ.asInstanceOf[cc.Type], false, cc.callsiteTyper.context, true, false, cc.enclosingPosition,
      (pos, msg) => throw TypecheckException(pos, msg))

    res.asInstanceOf[c.Tree]
  }
} 
Example 12
Source File: LazyContextParser.scala    From pureconfig   with Mozilla Public License 2.0 5 votes vote down vote up
package pureconfig.derivation

import scala.reflect.macros.whitebox


    def unapply(tree: Tree): Option[LazyContext] = tree match {
      case q"""{
              val $outer = {
                final class $anonClass extends ${ _ } with ${ _ } { ..$lazyDefs }
                new $anonClassRef().$entrypoint
              }
              shapeless.Lazy.apply[${ _ }]($outerRef)
            }""" if isRefTo(outerRef, outer) && isRefTo(anonClassRef, anonClass) =>

        val lazyDefMap: Map[TermName, Tree] = lazyDefs.collect {
          case q"lazy val $valName = $valBody" => valName -> valBody
        }.toMap

        val entrypointDef = lazyDefMap(entrypoint)
        Some(LazyContext(anonClass, lazyDefMap - entrypoint, entrypointDef))

      case _ => None
    }

    private[this] def isRefTo(tree: Tree, name: Name): Boolean = tree match {
      case Ident(otherName) => name == otherName
      case _ => false
    }
  }
} 
Example 13
Source File: Sanitiser.scala    From sansible   with MIT License 5 votes vote down vote up
package ansible

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

class Sanitiser(c: whitebox.Context) {
  private def reSugar(sym: c.universe.Symbol): String =
    Seq(
      "\\$eq" -> "=",
      "\\$hash" -> "#",
      "\\$bang" -> "!",
      "\\$asInstanceOf" -> "asInstanceOf",
      "\\$isInstanceOf" -> "isInstanceOf"
    ).foldLeft(sym.name.toString) { case (s, (a, b)) => s.replaceAll(a, b) }

  private val objType = c.weakTypeOf[Object]
  private val prodType = c.weakTypeOf[Product]
  private val keywords = c.universe.asInstanceOf[scala.reflect.internal.SymbolTable].nme.keywords.map(_.decoded)
  private val reservedWords = keywords ++ objType.decls.map(reSugar) ++ prodType.decls.map(reSugar)

  def safeName(name: String) =
    if (reservedWords(name)) s"_$name" else name
} 
Example 14
Source File: Expand.scala    From sansible   with MIT License 5 votes vote down vote up
package ansible

import ansible.AnsibleModule._
import argonaut.Argonaut._
import better.files._

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

@compileTimeOnly("enable macro paradise to expand macro annotations")
class expand extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Expander.expand_impl
}

object Expander {
  val tmpDir = System.getProperty("java.io.tmpdir")

  def expand_impl(c: whitebox.Context)(annottees: c.Expr[Any]*): c.Expr[Any] = {
    import c.universe._
    val gen = new CodeGen(c)

    val files = (tmpDir / "parsed_modules").listRecursively.filter(_.extension.contains(".json")).toList
    val ansibleModules = files.map { f =>
      f.contentAsString.decodeValidation[AnsibleModule].fold(err =>
        throw new Exception(s"Failed reading the json representation of the Ansible module: ${f.path}, error: $err"),
        identity
      )
    }

    def generateModule(m: AnsibleModule): (ModuleDef, ClassDef) = {
      val moduleTypeName = TypeName(camelize(m.name))
      val moduleTermName = TermName(camelize(m.name))
      val sortedOptions  = m.options.sortBy(_.required)(Ordering[Boolean].reverse)

      val (enumTypes, enumValues, fields) =
        sortedOptions.foldLeft((List.empty[ClassDef], List.empty[ModuleDef], Vector.empty[ValDef])) { case ((enumTypes, enumValues, fields), option) =>
          option match {
            case o: BooleanOption =>
              (enumTypes, enumValues, fields :+ gen.boolVal(o).asInstanceOf[ValDef])
            case o: StringOption =>
              (enumTypes, enumValues, fields :+ gen.stringVal(o).asInstanceOf[ValDef])
            case o: EnumOption =>
              (gen.enumClassDef(o).asInstanceOf[ClassDef] :: enumTypes,
                gen.enumObjectDef(o).asInstanceOf[ModuleDef] :: enumValues,
                fields :+ gen.enumVal(o, m.name).asInstanceOf[ValDef])
          }
        }

      val jsonEncoderVal = gen.moduleObjectJsonEncoder(m).asInstanceOf[ValDef]

      val enumSetters = m.enumOptions.map(gen.enumSetterDef(m.name)).asInstanceOf[List[DefDef]]

      val objectDef = q"""
         object $moduleTermName {
           $jsonEncoderVal
           ..$enumTypes
           ..$enumValues
         }
      """.asInstanceOf[ModuleDef]


      val classDef = q"""
        case class $moduleTypeName(..$fields) extends ansible.Module {
          override def call = ModuleCall(this.asJson)
          ..$enumSetters
        }
       """.asInstanceOf[ClassDef]

      (objectDef, classDef)
    }

    annottees.map(_.tree) match {
      case List(q"trait $_") =>
        val (objectDefs, classDefs) = ansibleModules.map(m => generateModule(m)).unzip
        c.Expr[Any](
          q"""
             import argonaut._
             import Argonaut._

             ..$objectDefs
             ..$classDefs
          """)
      case _ =>
        c.abort(c.enclosingPosition, "@expand should annotate a trait")
    }
  }

  private def camelize(str: String): String =
    str.split('_').map { s =>
      if (s.isEmpty)
        ""
      else
        s.head.toUpper.toString + s.tail.toLowerCase
    }.mkString
} 
Example 15
Source File: ShowRenderMacros.scala    From Vegas   with MIT License 5 votes vote down vote up
package vegas.macros

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

class ShowRenderMacros(val c: whitebox.Context) {
  import c.universe.{Try => _, _}

  private def html(tree: Tree) = Try(c.typecheck(tree)).flatMap {
    checked => Try(c.typecheck(q"vegas.render.ShowHTML($checked)"))
  }

  def materializeDefault: Tree = {
    val possibilities: Try[Tree] =
      html(q"""(str: String) => { println(org.apache.zeppelin.spark.utils.DisplayUtils.html(str)) }""") orElse
      html(q"""(str: String) => { publish.html(str) }""") orElse
      html(q"""(str: String) => { display.html(str) }""") orElse
      html(q"""(str: String) => { kernel.display.content("text/html", str) }""") orElse
      Try(c.typecheck(q"""vegas.render.ShowRender.using(_.window.show)"""))

    possibilities.getOrElse(c.abort(c.enclosingPosition, "No default Vegas renderer could be materialized"))
  }
} 
Example 16
Source File: ConfigurableDeriver.scala    From circe-generic-extras   with Apache License 2.0 5 votes vote down vote up
package io.circe.generic.extras

import io.circe.generic.extras.codec.{ ConfiguredAsObjectCodec, ReprAsObjectCodec }
import io.circe.generic.extras.decoding.{ ConfiguredDecoder, ReprDecoder }
import io.circe.generic.extras.encoding.{ ConfiguredAsObjectEncoder, ReprAsObjectEncoder }
import io.circe.generic.util.macros.DerivationMacros
import scala.reflect.macros.whitebox

class ConfigurableDeriver(val c: whitebox.Context)
    extends DerivationMacros[
      ReprDecoder,
      ReprAsObjectEncoder,
      ReprAsObjectCodec,
      ConfiguredDecoder,
      ConfiguredAsObjectEncoder,
      ConfiguredAsObjectCodec
    ] {
  import c.universe._

  def deriveConfiguredDecoder[R: c.WeakTypeTag]: c.Expr[ReprDecoder[R]] =
    c.Expr[ReprDecoder[R]](constructDecoder[R])
  def deriveConfiguredEncoder[R: c.WeakTypeTag]: c.Expr[ReprAsObjectEncoder[R]] =
    c.Expr[ReprAsObjectEncoder[R]](constructEncoder[R])
  def deriveConfiguredCodec[R: c.WeakTypeTag]: c.Expr[ReprAsObjectCodec[R]] =
    c.Expr[ReprAsObjectCodec[R]](constructCodec[R])

  protected[this] val RD: TypeTag[ReprDecoder[_]] = c.typeTag
  protected[this] val RE: TypeTag[ReprAsObjectEncoder[_]] = c.typeTag
  protected[this] val RC: TypeTag[ReprAsObjectCodec[_]] = c.typeTag
  protected[this] val DD: TypeTag[ConfiguredDecoder[_]] = c.typeTag
  protected[this] val DE: TypeTag[ConfiguredAsObjectEncoder[_]] = c.typeTag
  protected[this] val DC: TypeTag[ConfiguredAsObjectCodec[_]] = c.typeTag

  protected[this] val hnilReprDecoder: Tree = q"_root_.io.circe.generic.extras.decoding.ReprDecoder.hnilReprDecoder"
  protected[this] val hnilReprCodec: Tree = q"_root_.io.circe.generic.extras.codec.ReprAsObjectCodec.hnilReprCodec"

  protected[this] val decodeMethodName: TermName = TermName("configuredDecode")
  protected[this] val decodeAccumulatingMethodName: TermName = TermName("configuredDecodeAccumulating")

  protected[this] override def decodeMethodArgs: List[Tree] = List(
    q"transformMemberNames: (_root_.java.lang.String => _root_.java.lang.String)",
    q"transformConstructorNames: (_root_.java.lang.String => _root_.java.lang.String)",
    q"defaults: _root_.scala.collection.immutable.Map[_root_.java.lang.String, _root_.scala.Any]",
    q"discriminator: _root_.scala.Option[_root_.java.lang.String]"
  )

  protected[this] def encodeMethodName: TermName = TermName("configuredEncodeObject")
  protected[this] override def encodeMethodArgs: List[Tree] = List(
    q"transformMemberNames: (_root_.java.lang.String => _root_.java.lang.String)",
    q"transformConstructorNames: (_root_.java.lang.String => _root_.java.lang.String)",
    q"discriminator: _root_.scala.Option[_root_.java.lang.String]"
  )

  protected[this] def decodeField(name: String, decode: TermName): Tree = q"""
    orDefault(
      c.downField(transformMemberNames($name)),
      $decode,
      $name,
      defaults
    )
  """

  protected[this] def decodeFieldAccumulating(name: String, decode: TermName): Tree = q"""
    orDefaultAccumulating(
      c.downField(transformMemberNames($name)),
      $decode,
      $name,
      defaults
    )
  """

  protected[this] def decodeSubtype(name: String, decode: TermName): Tree = q"""
    withDiscriminator(
      $decode,
      c,
      transformConstructorNames($name),
      discriminator
    )
  """

  protected[this] def decodeSubtypeAccumulating(name: String, decode: TermName): Tree = q"""
    withDiscriminatorAccumulating(
      $decode,
      c,
      transformConstructorNames($name),
      discriminator
    )
  """

  protected[this] def encodeField(name: String, encode: TermName, value: TermName): Tree =
    q"(transformMemberNames($name), $encode($value))"

  protected[this] def encodeSubtype(name: String, encode: TermName, value: TermName): Tree =
    q"addDiscriminator($encode, $value, transformConstructorNames($name), discriminator)"
} 
Example 17
Source File: autoContravariant.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoContravariant")
class autoContravariant extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoContravariantMacros.contravariantInst
}

private[tagless] class autoContravariantMacros(override val c: whitebox.Context) extends MacroUtils  {
  import c.universe._

  private def generateContravariantFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("contravariantFor" + algebraName),
      typeParams,
      tq"_root_.cats.Contravariant[$algebraType]",
      q"_root_.cats.tagless.Derive.contravariant[$algebraType]"
    )

  def contravariantInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateContravariantFor(algebra.name)) :: Nil
    }
} 
Example 18
Source File: reporter.scala    From macro-compat   with Apache License 2.0 5 votes vote down vote up
package reporters

import scala.reflect.macros.whitebox

@macrocompat.bundle
class ErrorReporterMacro(val c: whitebox.Context) {
  import c.universe._
  def testReporterImplicit(t: Tree): Tree = {
    val casted = c.asInstanceOf[reflect.macros.runtime.Context]
    val typer = casted.callsiteTyper
    val ctx = typer.context
    val r = ctx.reporter
    r.errors.map(_.errMsg)
    t
  }
} 
Example 19
Source File: LocationMacros.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.env.macros

import polynote.env.ops.Location

import scala.annotation.tailrec
import scala.reflect.macros.whitebox

class LocationMacros(val c: whitebox.Context) {
  import c.universe._

  def materialize: Expr[Location] = {
    val enclosingPosition = c.enclosingPosition
    val owner = c.internal.enclosingOwner
    val name = expr(enclosingPosition.source.file.name)
    val line = expr(enclosingPosition.line)
    val method = expr(enclosingMethod(owner).map(_.name.decodedName.toString).getOrElse("<unknown>"))
    val cls = expr(enclosingClass(owner).map(_.fullName).getOrElse("<unknown>"))

    reify {
      Location(name.splice, line.splice, method.splice, cls.splice)
    }
  }

  private def expr[T](const: T): Expr[T] = c.Expr[T](Literal(Constant(const)))

  @tailrec private def enclosingMethod(sym: Symbol): Option[MethodSymbol] = sym match {
    case null | NoSymbol => None
    case m if m.isMethod => Some(m.asMethod)
    case m => enclosingMethod(sym.owner)
  }

  @tailrec private def enclosingClass(sym: Symbol): Option[ClassSymbol] = sym match {
    case null | NoSymbol => None
    case m if m.isClass => Some(m.asClass)
    case m => enclosingClass(sym.owner)
  }

} 
Example 20
Source File: ZEnvMacros.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.env.macros

import zio.ZIO
import polynote.env.ops.Enrich

import scala.reflect.macros.whitebox

class ZEnvMacros(val c: whitebox.Context) extends RefinementMacros {
  import c.universe._
  private def zio(R: Type, E: Type, A: Type): Type =
    appliedType(
      weakTypeOf[ZIO[_, _, _]].typeConstructor, R, E, A)

  private def delegate(sym: Symbol, in: Type, to: Tree) =
    q"final val ${sym.name.toTermName}: ${sym.infoIn(in).resultType} = $to"

  def createDelegate[A : WeakTypeTag, B : WeakTypeTag](a: Tree, b: Tree): Tree = {
    val A = weakTypeOf[A].dealias
    val B = weakTypeOf[B].dealias
    val Result = weakTypeOf[A with B]
    for {
      aParts <- refinementParts(A).right
      bParts <- refinementParts(B).right
    } yield {
      val clsName = TypeName(c.freshName("Env"))
      val aDecls = A.members.collect {
        case sym if sym.isMethod && sym.asMethod.paramLists == Nil && sym.isAbstract && !B.members.exists(_.name.toString == sym.name.toString) => delegate(sym, A, q"$a.$sym")
        case sym if sym.isMethod && sym.asMethod.paramLists == List(Nil) && sym.isAbstract && !B.members.exists(_.name.toString == sym.name.toString) => delegate(sym, A, q"$a.$sym()")
      }.toList

      val bDecls = B.members.collect {
        case sym if sym.isMethod && sym.asMethod.paramLists == Nil && sym.isAbstract => delegate(sym, B, q"$b.$sym")
        case sym if sym.isMethod && sym.asMethod.paramLists == List(Nil) && sym.isAbstract => delegate(sym, B, q"$b.$sym()")
      }.toList

      val classDef = ClassDef(Modifiers(), clsName, Nil, Template(
        TypeTree(weakTypeOf[AnyRef]) :: ((aParts ::: bParts).distinct).map(TypeTree(_)),
        noSelfType,
        DefDef(Modifiers(), termNames.CONSTRUCTOR, Nil, Nil :: Nil, TypeTree(), Block(List(Apply(Select(Super(This(typeNames.EMPTY), typeNames.EMPTY), termNames.CONSTRUCTOR), Nil)), Literal(Constant(())))) ::
          aDecls ::: bDecls
      ))


      Block(List(classDef), q"new $clsName: $Result")
    }
  }.fold(fail[A, B], identity)

  def mkEnrich[A : WeakTypeTag, B : WeakTypeTag]: Tree = {
    val A = weakTypeOf[A].dealias
    val B = weakTypeOf[B].dealias
    val ResultType = weakTypeOf[Enrich[A, B]]
    val result = q"""
       new $ResultType {
         def apply(a: $A, b: $B): $A with $B = ${createDelegate[A, B](q"a", q"b")}
       }
     """

    try {
      c.typecheck(result)
    } catch {
      case err: Throwable =>
        val e = err
        throw(e)
    }
  }

  def fail[A : WeakTypeTag, B : WeakTypeTag](err: Failure): Nothing = {
    val str = failureString(err, weakTypeOf[A], weakTypeOf[B])
    c.abort(c.enclosingPosition, str)
  }
} 
Example 21
Source File: RefinementMacros.scala    From polynote   with Apache License 2.0 5 votes vote down vote up
package polynote.env.macros

import scala.reflect.macros.whitebox

trait RefinementMacros {
  val c: whitebox.Context

  import c.universe._

  sealed trait Failure
  case object NotRefinement extends Failure
  case object NoMember extends Failure
  case class AmbiguousMember(members: List[(Type, Symbol)]) extends Failure

  def refinementParts(typ: Type): Either[Failure, List[Type]] = typ.dealias match {
    case RefinedType(parts, _) => parts.foldLeft[Either[Failure, List[Type]]](Right(Nil)) {
      case (l@Left(_), _) => l
      case (Right(parts), part) => refinementParts(part).right.map {
        partParts => partParts ::: parts
      }
    }
    case other if other =:= typeOf[Any] => Right(List(typeOf[Any]))
    case other => Right(List(other))
  }

  def definingPart(parts: List[Type], member: Type): Either[Failure, (Type, Symbol)] = parts.flatMap {
    part =>
      part.decls.collect {
        case sym if member <:< sym.infoIn(part).resultType => part -> sym
      }
  } match {
    case one :: Nil => Right(one)
    case Nil => Left(NoMember)
    case many => Left(AmbiguousMember(many))
  }

  def intersection(parts: List[Type]): Type = parts match {
    case Nil        => weakTypeOf[Any]
    case one :: Nil => one
    case many       => c.internal.refinedType(many, NoSymbol)
  }

  def formatMembers(members: List[(Type, Symbol)]): String = members.map {
    case (typ, sym) => s"${sym.name} in ${typ.typeSymbol.name}"
  }.mkString(", ")

  def failureString(failure: Failure, in: Type, member: Type): String = failure match {
    case NotRefinement            => s"Type $in is not an intersection type"
    case NoMember                 => s"Type $in does not contain a member of type $member"
    case AmbiguousMember(members) => s"Ambiguous member; $in declares multiple members of type $member: ${formatMembers(members)}"
  }
} 
Example 22
Source File: DummyImplicit.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
package loci
package transmitter

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

object DummyImplicit {
  class Resolvable private[DummyImplicit]

  object Resolvable {
    implicit def dummy: Resolvable = new Resolvable
    implicit def noDummy: Resolvable = macro NoDummyImplicit.skip
  }

  class Unresolvable private[DummyImplicit]

  object Unresolvable {
    implicit def noDummy: Unresolvable = macro NoDummyImplicit.skip
  }
}

object NoDummyImplicit {
  def skip(c: whitebox.Context): c.Tree =
    c.abort(c.enclosingPosition, "Skipping dummy macro")
} 
Example 23
Source File: Serializable.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
package loci
package transmitter

import scala.annotation.{compileTimeOnly, implicitNotFound}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.util.Try

@implicitNotFound("${T} is not serializable")
trait Serializable[T] {
  def serialize(value: T): MessageBuffer
  def deserialize(value: MessageBuffer): Try[T]
}

object Serializable {
  @inline def apply[T](implicit serializable: Serializable[T]): Serializable[T] =
    serializable

  @compileTimeOnly("Value is not serializable")
  final implicit def resolutionFailure[T](implicit ev: DummyImplicit.Resolvable): Serializable[T] =
    macro SerializableResolutionFailure[T]

  @compileTimeOnly("Value is not serializable")
  final def dummy[T]: Serializable[T] = throw new NotImplementedError
}

object SerializableResolutionFailure {
  def apply[T: c.WeakTypeTag](c: whitebox.Context)(ev: c.Tree): c.Tree = {
    import c.universe._

    // the current macro expansion always appears twice
    // see: http://stackoverflow.com/a/20466423
    val recursionCount = c.openMacros.count { other =>
      c.enclosingPosition == other.enclosingPosition &&
        c.macroApplication.toString == other.macroApplication.toString
    }
    if (recursionCount > 2)
      c.abort(c.enclosingPosition, "Skipping serializable resolution failure macro for recursive invocation")

    val serializableType = weakTypeOf[Serializable[T]]

    if ((c inferImplicitValue serializableType).nonEmpty)
      c.abort(c.enclosingPosition, "Skipping serializable resolution failure macro to prioritize other implicit")

    val tpe = weakTypeOf[T]
    val message = s"$tpe is not serializable"

    q"""{
      @${termNames.ROOTPKG}.scala.annotation.compileTimeOnly($message) def resolutionFailure() = ()
      resolutionFailure()
      ${termNames.ROOTPKG}.loci.transmitter.Serializable.dummy[$tpe]
    }"""
  }
} 
Example 24
Source File: TransmittableDummy.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
package loci
package transmitter

import scala.annotation.compileTimeOnly
import scala.concurrent.Future
import scala.language.experimental.macros
import scala.reflect.macros.whitebox

trait TransmittableDummy {
  this: Transmittable.type =>

  @compileTimeOnly("Value is not transmittable")
  final implicit def resolutionFailure[T](implicit ev: DummyImplicit.Resolvable): Transmittable[T, T, T] {
    type Proxy = Future[T]
    type Transmittables = Transmittables.None
  } = macro TransmittableResolutionFailure[T]

  @compileTimeOnly("Value is not transmittable")
  final def dummy[T]: Transmittable[T, T, T] {
    type Proxy = Future[T]
    type Transmittables = Transmittables.None
  } = IdenticallyTransmittable()
}

object TransmittableResolutionFailure {
  def apply[T: c.WeakTypeTag](c: whitebox.Context)(ev: c.Tree): c.Tree = {
    import c.universe._

    // the current macro expansion always appears twice
    // see: http://stackoverflow.com/a/20466423
    val recursionCount = c.openMacros.count { other =>
      c.enclosingPosition == other.enclosingPosition &&
      c.macroApplication.toString == other.macroApplication.toString
    }
    if (recursionCount > 2)
      c.abort(c.enclosingPosition, "Skipping transmittable resolution failure macro for recursive invocation")

    val resolutionType = weakTypeOf[Transmittable.Aux.Resolution[T, _, _, _, _]]

    if ((c inferImplicitValue resolutionType).nonEmpty)
      c.abort(c.enclosingPosition, "Skipping transmittable resolution failure macro to prioritize other implicit")

    val tpe = weakTypeOf[T]
    val message = s"$tpe is not transmittable"

    q"""{
      @${termNames.ROOTPKG}.scala.annotation.compileTimeOnly($message) def resolutionFailure() = ()
      resolutionFailure()
      ${termNames.ROOTPKG}.loci.transmitter.Transmittable.dummy[$tpe]
    }"""
  }
} 
Example 25
Source File: TracingExecutionContext.scala    From scala-loci   with Apache License 2.0 5 votes vote down vote up
package loci
package logging

import scribe.{LoggingExecutionContext, Position}

import scala.concurrent.{ExecutionContext, ExecutionContextExecutor}
import scala.reflect.macros.whitebox

class TracingExecutionContext(context: ExecutionContext, stack: List[Position]) extends
    LoggingExecutionContext(context, stack) with
    ExecutionContextExecutor {
  override def execute(runnable: Runnable) = super.execute(new Runnable {
    override def run() = tracing run { runnable.run() }
  })
}

object ImplicitTracingExecutionContext {
  def resolve(c: whitebox.Context): c.Tree = {
    import c.universe._

    if (c.hasErrors)
      c.abort(c.enclosingPosition, "Skipping tracing execution context macro due to compilation errors")

    // the current macro expansion always appears twice
    // see: http://stackoverflow.com/a/20466423
    val recursionCount = c.openMacros.count { other =>
      c.enclosingPosition == other.enclosingPosition &&
        c.macroApplication.toString == other.macroApplication.toString
    }
    if (recursionCount > 2)
      c.abort(c.enclosingPosition, "Skipping tracing execution context macro for recursive invocation")

    val tree = c.inferImplicitValue(typeOf[ExecutionContext])
    if (tree.isEmpty)
      c.abort(c.enclosingPosition, "Skipping tracing execution context macro due to unresolved execution context")

    // flag symbol of inferred tree as synthetic if it is private or a local variable
    // to prevent "value is never used" warnings
    val symbol = tree.symbol.asTerm
    if (!symbol.isGetter && !symbol.isParamAccessor || symbol.isGetter && symbol.isPrivate)
      c.internal.setFlag(tree.symbol, Flag.SYNTHETIC)

    ExplicitTracingExecutionContext.instrument(c)(tree)
  }
}

object ExplicitTracingExecutionContext {
  def instrument(c: whitebox.Context)(context: c.Tree): c.Tree = {
    import c.universe._

    val stack = c.typecheck(q"${termNames.ROOTPKG}.scribe.Execution.custom(null)", silent = true) match {
      case q"new $_($_, $stack)" =>
        Right(stack)
      case q"new $_($_, $stack): $_" =>
        Right(stack)
      case tree =>
        Left(tree)
    }

    val tracingContext = tq"${termNames.ROOTPKG}.loci.logging.TracingExecutionContext"

    stack match {
      case Right(stack) =>
        q"new $tracingContext($context, $stack)"

      case Left(tree) =>
        val message = s"scribe logging framework custom execution context macro generated unexpected code: $tree"
        q"""{
          @${termNames.ROOTPKG}.scala.annotation.compileTimeOnly($message) def unexpectedTree() = ()
          unexpectedTree()
          new $tracingContext(null, null)
        }"""
    }
  }
} 
Example 26
Source File: ToStringObfuscate.scala    From firebase4s   with MIT License 5 votes vote down vote up
package firebase4s.macros

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.annotation.compileTimeOnly

@compileTimeOnly("enable macro paradise to expand macro annotations")
class ToStringObfuscate(fieldsToObfuscate: String*) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ToStringObfuscateImpl.impl
}

object ToStringObfuscateImpl {

  def obfuscateValue(value: String) = "*" * value.length

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

    def extractAnnotationParameters(tree: Tree): List[c.universe.Tree] = tree match {
      case q"new $name( ..$params )" => params
      case _                         => throw new Exception("ToStringObfuscate annotation must be have at least one parameter.")
    }

    def extractCaseClassesParts(classDecl: ClassDef) = classDecl match {
      case q"case class $className(..$fields) extends ..$parents { ..$body }" =>
        (className, fields, parents, body)
    }

    def replaceCaseClassSensitiveValues(tree: Tree) = tree match {
      case Literal(Constant(field: String)) =>
        q"""
            ${TermName(field)} = firebase4s.macros.ToStringObfuscateImpl.obfuscateValue(this.${TermName(field)})
          """
      case _ => c.abort(c.enclosingPosition, s"[replaceCaseClassSensitiveValues] Match error with $tree")
    }

    val sensitiveFields = extractAnnotationParameters(c.prefix.tree)
    
    val fieldReplacements = sensitiveFields.map(replaceCaseClassSensitiveValues(_))

    def extractNewToString(sensitiveFields: List[Tree]) = q"""
         override def toString: ${typeOf[String]} = {
          scala.runtime.ScalaRunTime._toString(this.copy(..$fieldReplacements))
         }
      """

    def modifiedDeclaration(classDecl: ClassDef) = {
      val (className, fields, parents, body) = extractCaseClassesParts(classDecl)
      val newToString = extractNewToString(sensitiveFields)

      val params = fields.asInstanceOf[List[ValDef]].map { p =>
        p.duplicate
      }

      c.Expr[Any](
        q"""
        case class $className ( ..$params ) extends ..$parents {
          $newToString
          ..$body
        }
      """
      )
    }

    annottees.map(_.tree) toList match {
      case (classDecl: ClassDef) :: Nil => modifiedDeclaration(classDecl)
      case _                            => c.abort(c.enclosingPosition, "Invalid annottee")
    }
  }
} 
Example 27
Source File: SymbolMacros.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.macros
import shapeless.ReprTypes

import scala.reflect.macros.{blackbox, whitebox}

trait SymbolMacros extends ReprTypes {
  val c: blackbox.Context

  import c.universe._
  import c.internal.{constantType, refinedType}

  def taggedType = typeOf[shapeless.tag.Tagged[_]].typeConstructor

  object KeyName {
    def apply(name: String): Type =
      NamedSymbol(appliedType(taggedType, constantType(Constant(name))))

    def unapply(tpe: Type): Option[String] = tpe match {
      case NamedSymbol(ConstantType(Constant(name: String))) => Some(name)
      case ConstantType(Constant(name: String))              => Some(name)
      case _                                                 => None
    }
  }

  object NamedSymbol {
    def apply(tpe: Type): Type = refinedType(List(symbolTpe, tpe), NoSymbol)

    def unapply(tpe: Type): Option[Type] = tpe.dealias match {
      case RefinedType(List(sym, tag, _*), _) if sym == symbolTpe => tag.typeArgs.headOption
      case _                                                      => None
    }
  }

  def freshIdent(name: String): Ident   = Ident(freshName(name))
  def freshName(name: String): TermName = TermName(c.freshName(name))

} 
Example 28
Source File: ParamMaker.scala    From typed-schema   with Apache License 2.0 5 votes vote down vote up
package ru.tinkoff.tschema.macros
import ru.tinkoff.tschema.macros.ParamMaker.Applyer
import ru.tinkoff.tschema.typeDSL
import ru.tinkoff.tschema.typeDSL.{Capture, DSLAtom, FormField, Header, QueryParam}

import scala.language.{dynamics, higherKinds}
import scala.language.experimental.macros
import shapeless.Witness

import scala.reflect.macros.whitebox

class ParamMaker[T[_, _]] extends Dynamic {
  def params[A]: Applyer = macro ParamMakerMacro.paramsImpl[A, T[_, _]]
}

object ParamMaker {
  type Applyer = { def apply[A](x: => A): DSLAtom }
  def apply[T[_, _]]: ParamMaker[T] = new ParamMaker[T]

  object query   extends ParamMaker[QueryParam]
  object path    extends ParamMaker[Capture]
  object headers extends ParamMaker[Header]
  object form    extends ParamMaker[FormField]
}

class ParamMakerMacro(val c: whitebox.Context) extends SymbolMacros {
  import c.universe._

  val consTpe = typeOf[typeDSL.:>[_, _]].typeConstructor

  def paramsImpl[A: WeakTypeTag, T: WeakTypeTag] = {
    val const = weakTypeTag[T].tpe.typeConstructor

    val result = extractNamesTypes(weakTypeOf[A]).map { case (name, tpe) => appliedType(const, KeyName(name), tpe) }
      .reduce((a, b) => appliedType(consTpe, a, b))

    q"""
    new {
      import ru.tinkoff.tschema.typeDSL.{:>}
      def apply[A](x: => A): :>[$result, A] = new :>
    }"""
  }

  def extractNamesTypes(ref: Type): List[(String, Type)] = ref match {
    case RefinedType(tpes, scope) =>
      info(tpes)
      scope.collect {
        case m: MethodSymbol =>
          info(m)
          m.name.decodedName.toString -> m.returnType
      }.toList
    case _                        => List.empty
  }

  def info[A](mess: A) = c.info(c.enclosingPosition, mess.toString, force = false)
} 
Example 29
Source File: TypeName.scala    From zio-config   with Apache License 2.0 5 votes vote down vote up
package zio.config.shapeless

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

trait TypeName[T] {
  def apply(): String
}

object TypeName {
  implicit def materializeTypeName[T]: TypeName[T] = macro typeNameImpl[T]

  def typeNameImpl[T: c.WeakTypeTag](c: whitebox.Context): c.Tree = {
    import c.universe._

    val T    = c.weakTypeOf[T]
    val name = T.typeSymbol.name.toString
    q" new _root_.zio.config.shapeless.TypeName[$T]{ def apply(): String = $name } "
  }
} 
Example 30
Source File: Macros.scala    From libisabelle   with Apache License 2.0 5 votes vote down vote up
package info.hupel.isabelle.internal

import scala.reflect.macros.whitebox

import cats.instances.list._
import cats.syntax.traverse._

import info.hupel.isabelle._
import info.hupel.isabelle.pure._

object Macros {

  def fuse(terms: List[Program[Term]], parts: List[String]): Program[String] = {
    val tps: Program[List[String]] =
      terms.sequence.map { ts =>
        ts zip parts.tail map { case (t, p) =>
          val s = Codec[Term].encode(t).compact
          s"XML\\<open>$s\\<close>$p"
        }
      }

    tps.map(_.mkString("")).map(parts.head + _)
  }

}

class Macros(val c: whitebox.Context) {

  import c.universe.{Expr => _, _}

  private val q"""${_}(${_}(..$parts)).term""" = c.prefix.tree

  private def embed(arg: Tree): Tree = {
    if (arg.tpe <:< typeOf[Term])
      q"""_root_.info.hupel.isabelle.Program.pure($arg)"""
    else if (arg.tpe <:< typeOf[Expr[_]])
      q"""_root_.info.hupel.isabelle.Program.pure($arg.term)"""
    else {
      val embeddable = c.inferImplicitValue(appliedType(typeOf[Embeddable[_]], arg.tpe))
      if (embeddable == EmptyTree)
        c.error(c.enclosingPosition, s"Could not find implicit `Embeddable` for type ${arg.tpe}")
      q"""$embeddable.embed($arg)"""
    }
  }

  def term(args: Tree*): c.Expr[Program[String]] = {
    val terms = args.map(embed)
    val termList = c.Expr[List[Program[Term]]](q"""_root_.scala.List(..$terms)""")
    val partList = c.Expr[List[String]](q"""_root_.scala.List(..$parts)""")
    reify {
      Macros.fuse(termList.splice, partList.splice)
    }
  }

} 
Example 31
Source File: TransformerIntoWhiteboxMacros.scala    From chimney   with Apache License 2.0 5 votes vote down vote up
package io.scalaland.chimney.internal.macros

import io.scalaland.chimney.internal.utils.MacroUtils

import scala.reflect.macros.whitebox

class TransformerIntoWhiteboxMacros(val c: whitebox.Context) extends MacroUtils {

  import c.universe._

  def withFieldConstImpl(selector: Tree, value: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldConst($selector, ${trees("value")})",
      "value" -> value
    )
  }

  def withFieldConstFImpl[F[+_]](
      selector: Tree,
      value: Tree
  )(
      implicit F: WeakTypeTag[F[_]]
  ): Tree = {
    q"${c.prefix.tree}.lift[$F].withFieldConstF($selector, $value)"
  }

  def withFieldComputedImpl(selector: Tree, map: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldComputed($selector, ${trees("map")})",
      "map" -> map
    )
  }

  def withFieldComputedFImpl[F[+_]](
      selector: Tree,
      map: Tree
  )(
      implicit F: WeakTypeTag[F[_]]
  ): Tree = {
    q"${c.prefix.tree}.lift[$F].withFieldComputedF($selector, $map)"
  }

  def withFieldRenamedImpl(selectorFrom: Tree, selectorTo: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition(q"_.withFieldRenamed($selectorFrom, $selectorTo)")
  }

  def withCoproductInstanceImpl(f: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withCoproductInstance(${trees("f")})",
      "f" -> f
    )
  }

  def withCoproductInstanceFImpl[F[+_]](f: Tree)(implicit F: WeakTypeTag[F[_]]): Tree = {
    q"${c.prefix.tree}.lift[$F].withCoproductInstanceF($f)"
  }
} 
Example 32
Source File: TransformerFIntoWhiteboxMacros.scala    From chimney   with Apache License 2.0 5 votes vote down vote up
package io.scalaland.chimney.internal.macros

import io.scalaland.chimney.internal.utils.MacroUtils

import scala.reflect.macros.whitebox

class TransformerFIntoWhiteboxMacros(val c: whitebox.Context) extends MacroUtils {

  import c.universe._

  def withFieldConstImpl(selector: Tree, value: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldConst($selector, ${trees("value")})",
      "value" -> value
    )
  }

  def withFieldConstFImpl(selector: Tree, value: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldConstF($selector, ${trees("value")})",
      "value" -> value
    )
  }

  def withFieldComputedImpl(selector: Tree, map: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldComputed($selector, ${trees("map")})",
      "map" -> map
    )
  }

  def withFieldComputedFImpl(selector: Tree, map: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withFieldComputedF($selector, ${trees("map")})",
      "map" -> map
    )
  }

  def withFieldRenamedImpl(selectorFrom: Tree, selectorTo: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition(q"_.withFieldRenamed($selectorFrom, $selectorTo)")
  }

  def withCoproductInstanceImpl(f: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withCoproductInstance(${trees("f")})",
      "f" -> f
    )
  }

  def withCoproductInstanceFImpl(f: Tree): Tree = {
    c.prefix.tree.refineTransformerDefinition_Hack(
      trees => q"_.withCoproductInstanceF(${trees("f")})",
      "f" -> f
    )
  }

} 
Example 33
Source File: ServiceMacros.scala    From scalajs-angulate   with MIT License 5 votes vote down vote up
// -   Project: scalajs-angulate (https://github.com/jokade/scalajs-angulate)
// Description:
//
// Distributed under the MIT License (see included file LICENSE)
package biz.enef.angulate.impl

import acyclic.file
import scala.reflect.macros.whitebox

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

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

  def serviceOf[T: c.WeakTypeTag] = {
    val serviceType = weakTypeOf[T]
    val name = serviceType.toString.split('.').last
    createService(serviceType, q"${name.head.toLower+name.tail}")
  }

  def serviceOfWithName[T: c.WeakTypeTag](name: c.Tree) = {
    val serviceType = weakTypeOf[T]
    createService(serviceType, q"${name}")
  }

  private def createService(ct: c.Type, name: c.Tree) = {
    val module = Select(c.prefix.tree, TermName("self"))

    val constr = ct.members.filter( _.isConstructor ).map( _.asMethod ).head

    val (params,args) = makeArgsList(constr)
    val deps = getDINames(constr)

    // AngularJS service construction array
    val carray =
     q"""js.Array[Any](..$deps, ((..$params) =>
          new $ct(..$args)):js.Function)
      """

    val tree = q"""{import scala.scalajs.js
                    import js.Dynamic.{global,literal}
                    $module.self.factory($name,$carray)
                   }"""

    if (logCode) printCode(tree, "\nserviceOf macro:")
    tree
  }
} 
Example 34
Source File: CoproductMacros.scala    From featherbed   with Apache License 2.0 5 votes vote down vote up
package featherbed.littlemacros

import scala.reflect.macros.whitebox

import shapeless.{:+:, CNil}

class CoproductMacros(val c: whitebox.Context) {
  import c.universe._

  
  def callAcceptCoproduct(types: Tree*): Tree = {
    val lhs = c.prefix.tree
    val accepts = types map {
      case Literal(const @ Constant(str: String)) => c.internal.constantType(const)
      case other => c.abort(c.enclosingPosition, s"$other is not a string constant")
    }

    val cnil = weakTypeOf[CNil]
    val ccons = weakTypeOf[:+:[_, _]].typeConstructor

    val coproductType =
      accepts.foldRight(cnil) { case (elemTpe, acc) =>
        appliedType(ccons, List(elemTpe, acc))
      }

    q"$lhs.accept[$coproductType]"
  }
} 
Example 35
Source File: GogglesMacros.scala    From goggles   with MIT License 5 votes vote down vote up
package goggles.macros

import goggles.macros.interpret.dsl.{GetModeDslImpl, SetModeDslImpl, LensModeDslImpl}
import scala.reflect.macros.whitebox


object GogglesMacros {

  def getImpl(ctx: whitebox.Context)(args: ctx.Expr[Any]*): ctx.Tree = {
    val interpreter = new GetModeDslImpl { override val c: ctx.type = ctx; }
    interpreter.handleMacroResultOf(_.get(args: _*))
  }

  def setImpl(ctx: whitebox.Context)(args: ctx.Expr[Any]*): ctx.Tree = {
    val interpreter = new SetModeDslImpl { override val c: ctx.type = ctx; }
    interpreter.handleMacroResultOf(_.set(args: _*))
  }

  def lensImpl(ctx: whitebox.Context)(args: ctx.Expr[Any]*): ctx.Tree = {
    val interpreter = new LensModeDslImpl { override val c: ctx.type = ctx; }
    interpreter.handleMacroResultOf(_.lens(args: _*))
  }
} 
Example 36
Source File: WindowedStreamMacros.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.lang.internal

import com.amazon.milan.Id
import com.amazon.milan.lang.Stream
import com.amazon.milan.program.WindowApply
import com.amazon.milan.program.internal.{ConvertExpressionHost, MappedStreamHost}
import com.amazon.milan.typeutil.TypeDescriptor

import scala.reflect.macros.whitebox


class WindowedStreamMacros(val c: whitebox.Context)
  extends ConvertExpressionHost
    with MappedStreamHost {

  import c.universe._

  def apply[T: c.WeakTypeTag, TOut: c.WeakTypeTag](f: c.Expr[Iterable[T] => TOut]): c.Expr[Stream[TOut]] = {
    val applyFunction = getMilanFunction(f.tree)

    val streamType = getStreamTypeExpr[TOut](applyFunction)
    val outputNodeId = Id.newId()

    val sourceExpressionVal = TermName(c.freshName("sourceExpr"))
    val exprVal = TermName(c.freshName("expr"))

    val tree =
      q"""
          val $sourceExpressionVal = ${c.prefix}.expr
          val $exprVal = new ${typeOf[WindowApply]}($sourceExpressionVal, $applyFunction, $outputNodeId, $outputNodeId, $streamType)
          new ${weakTypeOf[Stream[TOut]]}($exprVal, $exprVal.recordType.asInstanceOf[${weakTypeOf[TypeDescriptor[TOut]]}])
       """
    c.Expr[Stream[TOut]](tree)
  }
} 
Example 37
Source File: JoinedStreamMacros.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.lang.internal

import com.amazon.milan.Id
import com.amazon.milan.lang.{JoinType, JoinedStream, JoinedStreamWithCondition, Stream}
import com.amazon.milan.program.internal.ConvertExpressionHost
import com.amazon.milan.program.{FullJoin, FunctionDef, LeftInnerJoin, LeftJoin}
import com.amazon.milan.typeutil.{JoinedStreamsTypeDescriptor, TypeDescriptor}

import scala.reflect.macros.whitebox



  def select[TLeft: c.WeakTypeTag, TRight: c.WeakTypeTag, TOut: c.WeakTypeTag](f: c.Expr[(TLeft, TRight) => TOut]): c.Expr[Stream[TOut]] = {
    this.warnIfNoRecordId[TOut]()

    val exprTree = createMappedToRecordStream2[TLeft, TRight, TOut](f)
    val exprVal = TermName(c.freshName("expr"))
    val tree =
      q"""
          val $exprVal = $exprTree
          new ${weakTypeOf[Stream[TOut]]}($exprVal, $exprVal.recordType.asInstanceOf[${weakTypeOf[TypeDescriptor[TOut]]}])
       """
    c.Expr[Stream[TOut]](tree)
  }
}


object JoinedStreamUtil {
  def where[TLeft, TRight](inputStream: JoinedStream[TLeft, TRight], conditionExpr: FunctionDef): JoinedStreamWithCondition[TLeft, TRight] = {
    ProgramValidation.validateFunction(conditionExpr, 2)

    val joinNodeId = Id.newId()
    val joinedStreamType = new JoinedStreamsTypeDescriptor(inputStream.leftInput.recordType, inputStream.rightInput.recordType)

    val joinExpr = inputStream.joinType match {
      case JoinType.LeftEnrichmentJoin => new LeftJoin(inputStream.leftInput, inputStream.rightInput, conditionExpr, joinNodeId, joinNodeId, joinedStreamType)
      case JoinType.FullEnrichmentJoin => new FullJoin(inputStream.leftInput, inputStream.rightInput, conditionExpr, joinNodeId, joinNodeId, joinedStreamType)
      case JoinType.LeftInnerJoin => new LeftInnerJoin(inputStream.leftInput, inputStream.rightInput, conditionExpr, joinNodeId, joinNodeId, joinedStreamType)
    }

    new JoinedStreamWithCondition[TLeft, TRight](joinExpr)
  }
} 
Example 38
Source File: JoinedWindowedStreamMacros.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.lang.internal

import com.amazon.milan.Id
import com.amazon.milan.lang.{LeftJoinedWindowedStream, Stream}
import com.amazon.milan.program.internal.ConvertExpressionHost
import com.amazon.milan.program.{FlatMap, FunctionDef, LeftWindowedJoin}
import com.amazon.milan.typeutil.{DataStreamTypeDescriptor, TypeDescriptor}

import scala.reflect.macros.whitebox


class JoinedWindowedStreamMacros(val c: whitebox.Context)
  extends StreamMacroHost
    with ConvertExpressionHost {

  import c.universe._

  def leftApply[TLeft: c.WeakTypeTag, TRight: c.WeakTypeTag, TOut: c.WeakTypeTag](applyFunction: c.Expr[(TLeft, Iterable[TRight]) => TOut]): c.Expr[Stream[TOut]] = {
    this.warnIfNoRecordId[TOut]()

    val applyFunctionExpr = getMilanFunction(applyFunction.tree)

    val inputStreamVal = TermName(c.freshName("inputStream"))
    val outputTypeInfo = getTypeDescriptor[TOut]

    val tree =
      q"""
          _root_.com.amazon.milan.lang.internal.ProgramValidation.validateFunction($applyFunctionExpr, 2)

          val $inputStreamVal = ${c.prefix}
          _root_.com.amazon.milan.lang.internal.JoinedWindowedStreamUtil.leftApply[${weakTypeOf[TLeft]}, ${weakTypeOf[TRight]}, ${weakTypeOf[TOut]}]($inputStreamVal, $applyFunctionExpr, $outputTypeInfo)
       """
    c.Expr[Stream[TOut]](tree)
  }
}


object JoinedWindowedStreamUtil {
  def leftApply[TLeft, TRight, TOut](inputStream: LeftJoinedWindowedStream[TLeft, TRight],
                                     applyFunction: FunctionDef,
                                     outputRecordType: TypeDescriptor[TOut]): Stream[TOut] = {
    val outNodeId = Id.newId()

    val leftInputExpr = inputStream.leftInput.expr
    val rightInputExpr = inputStream.rightInput.expr

    val joinExpr = LeftWindowedJoin(leftInputExpr, rightInputExpr)
    val outputStreamType = new DataStreamTypeDescriptor(outputRecordType)
    val mapExpr = new FlatMap(joinExpr, applyFunction, outNodeId, outNodeId, outputStreamType)

    new Stream[TOut](mapExpr, outputRecordType)
  }
} 
Example 39
Source File: ProgramTypeNamesHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.program.internal

import scala.reflect.macros.whitebox



trait ProgramTypeNamesHost {
  val c: whitebox.Context

  import c.universe._

  val FieldTypeName: Tree = q"_root_.com.amazon.milan.program.Field"
  val FieldComputationExpressionTypeName: Tree = q"_root_.com.amazon.milan.program.FieldComputationExpression"
  val FilteredStreamTypeName: Tree = q"_root_.com.amazon.milan.program.FilteredStream"
  val MappedStreamTypeName: Tree = q"_root_.com.amazon.milan.program.MappedStream"
  val MapToFieldsTypeName: Tree = q"_root_.com.amazon.milan.program.MapToFields"
  val MapToRecordTypeName: Tree = q"_root_.com.amazon.milan.program.MapToRecord"
  val ProgramValidationTypeName: Tree = q"_root_.com.amazon.milan.program.ProgramValidation"
  val FunctionReferenceTypeName: Tree = q"_root_.com.amazon.milan.program.FunctionReference"
  val TypeDescriptorTypeName: Tree = q"_root_.com.amazon.milan.typeutil.TypeDescriptor[Any]"
  val FieldDescriptorTypeName: Tree = q"_root_.com.amazon.milan.typeutil.FieldDescriptor[Any]"
} 
Example 40
Source File: FilteredStreamHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.program.internal

import com.amazon.milan.Id
import com.amazon.milan.program.Filter

import scala.reflect.macros.whitebox


  def createdFilteredStream[T: c.WeakTypeTag](predicate: c.Expr[T => Boolean]): c.Expr[Filter] = {
    val outputNodeId = Id.newId()
    val predicateExpression = getMilanFunction(predicate.tree)
    val inputExprVal = TermName(c.freshName("inputExpr"))

    val tree =
      q"""
          val $inputExprVal = ${c.prefix}.expr
          new ${typeOf[Filter]}($inputExprVal, $predicateExpression, $outputNodeId, $outputNodeId, $inputExprVal.tpe)
       """
    c.Expr[Filter](tree)
  }
} 
Example 41
Source File: FunctionReferenceHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.program.internal

import com.amazon.milan.program.FunctionReference

import scala.reflect.macros.whitebox



  private def getFunctionReferenceFromSelect(objectRef: c.universe.Tree,
                                             functionName: c.universe.Name): FunctionReference = {
    if (!functionName.isTermName) {
      abort(s"$functionName is not a method name.")
    }

    val typeName = this.getTypeName(objectRef)
    val aggregationTypePrefix = "com.amazon.milan.lang.aggregation."
    val methodName = functionName.toTermName.toString

    if (methodName == "apply" && typeName.startsWith(aggregationTypePrefix)) {
      val actualMethodName = "aggregation." + typeName.substring(aggregationTypePrefix.length)
      FunctionReference("builtin", actualMethodName)
    }
    else {
      FunctionReference(typeName, methodName)
    }
  }
} 
Example 42
Source File: RecordTypeHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.program.internal

import com.amazon.milan.program.{FunctionDef, NamedFields}
import com.amazon.milan.typeutil.{DataStreamTypeDescriptor, FieldDescriptor, GroupedStreamTypeDescriptor, StreamTypeDescriptor, TupleTypeDescriptor, TypeDescriptor, TypeDescriptorMacroHost}

import scala.reflect.macros.whitebox

trait RecordTypeHost extends TypeDescriptorMacroHost {
  val c: whitebox.Context

  import c.universe._

  def getStreamTypeExpr[T: c.WeakTypeTag](producingFunction: c.Expr[FunctionDef]): c.Expr[StreamTypeDescriptor] = {
    val recordType = getTypeDescriptor[T]
    val tree = q"new ${typeOf[DataStreamTypeDescriptor]}(com.amazon.milan.program.internal.RecordTypeUtil.addFieldNames($recordType, $producingFunction))"
    c.Expr[StreamTypeDescriptor](tree)
  }

  def getGroupedStreamTypeExpr[T: c.WeakTypeTag, TKey: c.WeakTypeTag](producingFunction: c.Expr[FunctionDef]): c.Expr[GroupedStreamTypeDescriptor] = {
    val recordType = getTypeDescriptor[T]
    val keyType = getTypeDescriptor[TKey]
    val tree = q"new ${typeOf[GroupedStreamTypeDescriptor]}($keyType, com.amazon.milan.program.internal.RecordTypeUtil.addFieldNames($recordType, $producingFunction))"
    c.Expr[GroupedStreamTypeDescriptor](tree)
  }

  def getRecordTypeExpr[T: c.WeakTypeTag](producingFunction: c.Expr[FunctionDef]): c.Expr[TypeDescriptor[T]] = {
    this.getRecordTypeExpr[T](getTypeDescriptor[T], producingFunction)
  }

  def getRecordTypeExpr[T](recordType: TypeDescriptor[T],
                           producingFunction: c.Expr[FunctionDef]): c.Expr[TypeDescriptor[T]] = {
    val tree = q"com.amazon.milan.program.internal.RecordTypeUtil.addFieldNames($recordType, $producingFunction)"
    c.Expr[TypeDescriptor[T]](tree)
  }
}


object RecordTypeUtil {
  def addFieldNames[T](recordType: TypeDescriptor[T], producingFunction: FunctionDef): TypeDescriptor[T] = {
    if (recordType.fields.nonEmpty || recordType.genericArguments.isEmpty) {
      recordType
    }
    else {
      producingFunction.body match {
        case NamedFields(fields) if fields.length == recordType.genericArguments.length =>
          val fieldDescriptors = fields.zip(recordType.genericArguments).map {
            case (field, ty) => FieldDescriptor(field.fieldName, ty)
          }

          new TupleTypeDescriptor[T](fieldDescriptors)

        case _ =>
          recordType
      }
    }
  }
} 
Example 43
Source File: MappedStreamHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.program.internal

import com.amazon.milan.Id
import com.amazon.milan.program._

import scala.reflect.macros.whitebox


  def createStreamMap[TOut: c.WeakTypeTag](mapFunction: c.Expr[FunctionDef],
                                           validationExpression: c.universe.Tree): c.Expr[StreamMap] = {
    val streamType = getStreamTypeExpr[TOut](mapFunction)
    val outputNodeId = Id.newId()

    val sourceExpressionVal = TermName(c.freshName("sourceExpr"))

    val tree =
      q"""
          $validationExpression

          val $sourceExpressionVal = ${c.prefix}.expr
          new ${typeOf[StreamMap]}($sourceExpressionVal, $mapFunction, $outputNodeId, $outputNodeId, $streamType)
       """
    c.Expr[StreamMap](tree)
  }

  def createAggregate[TOut: c.WeakTypeTag](aggregateFunction: c.Expr[FunctionDef],
                                           validationExpression: c.universe.Tree): c.Expr[Aggregate] = {
    val streamType = getStreamTypeExpr[TOut](aggregateFunction)
    val outputNodeId = Id.newId()

    val sourceExpressionVal = TermName(c.freshName("sourceExpr"))

    val tree =
      q"""
          $validationExpression

          val $sourceExpressionVal = ${c.prefix}.expr
          new ${typeOf[Aggregate]}($sourceExpressionVal, $aggregateFunction, $outputNodeId, $outputNodeId, $streamType)
       """
    c.Expr[Aggregate](tree)
  }
} 
Example 44
Source File: LiftTypeDescriptorHost.scala    From milan   with Apache License 2.0 5 votes vote down vote up
package com.amazon.milan.typeutil

import scala.reflect.macros.whitebox


trait LiftTypeDescriptorHost {
  val c: whitebox.Context

  import c.universe._

  implicit def liftNumericTypeDescriptor[T: c.WeakTypeTag]: Liftable[NumericTypeDescriptor[T]] = { t =>
    q"new ${weakTypeOf[NumericTypeDescriptor[T]]}(${t.typeName})"
  }

  implicit def liftBasicTypeDescriptor[T: c.WeakTypeTag]: Liftable[BasicTypeDescriptor[T]] = { tree =>
    tree match {
      case t: NumericTypeDescriptor[T] => liftNumericTypeDescriptor[T](c.weakTypeTag[T])(t)
      case t: BasicTypeDescriptor[T] => q"new ${weakTypeOf[BasicTypeDescriptor[T]]}(${t.typeName})"
    }
  }

  implicit def liftTupleTypeDescriptor[T: c.WeakTypeTag]: Liftable[TupleTypeDescriptor[T]] = { t =>
    q"new ${weakTypeOf[TupleTypeDescriptor[T]]}(${t.typeName}, ${t.genericArguments}, ${t.fields})"
  }

  implicit def liftObjectTypeDescriptor[T: c.WeakTypeTag]: Liftable[ObjectTypeDescriptor[T]] = { t =>
    q"new ${weakTypeOf[ObjectTypeDescriptor[T]]}(${t.typeName}, ${t.genericArguments}, ${t.fields})"
  }

  implicit def liftGeneratedTypeDescriptor[T: c.WeakTypeTag]: Liftable[GeneratedTypeDescriptor[T]] = { t =>
    q"new ${weakTypeOf[GeneratedTypeDescriptor[T]]}(${t.typeName}, ${t.genericArguments}, ${t.fields})"
  }

  implicit def liftCollectionTypeDescriptor[T: c.WeakTypeTag]: Liftable[CollectionTypeDescriptor[T]] = { t =>
    q"new ${weakTypeOf[CollectionTypeDescriptor[T]]}(${t.typeName}, ${t.genericArguments})"
  }

  implicit val liftDataStreamTypeDescriptor: Liftable[DataStreamTypeDescriptor] = { t =>
    q"new ${typeOf[DataStreamTypeDescriptor]}(${t.recordType})"
  }

  implicit val liftJoinedStreamsTypeDescriptor: Liftable[JoinedStreamsTypeDescriptor] = { t =>
    q"new ${typeOf[JoinedStreamsTypeDescriptor]}(${t.leftRecordType}, ${t.rightRecordType})"
  }

  implicit val liftGroupedStreamTypeDescriptor: Liftable[GroupedStreamTypeDescriptor] = { t =>
    q"new ${typeOf[GroupedStreamTypeDescriptor]}(${t.keyType}, ${t.recordType})"
  }

  implicit def liftStreamTypeDescriptor: Liftable[StreamTypeDescriptor] = { tree =>
    tree match {
      case t: DataStreamTypeDescriptor => liftDataStreamTypeDescriptor(t)
      case t: JoinedStreamsTypeDescriptor => liftJoinedStreamsTypeDescriptor(t)
      case t: GroupedStreamTypeDescriptor => liftGroupedStreamTypeDescriptor(t)
    }
  }

  implicit def liftTypeDescriptor[T: c.WeakTypeTag]: Liftable[TypeDescriptor[T]] = { tree =>
    tree match {
      case t: BasicTypeDescriptor[T] => liftBasicTypeDescriptor[T](c.weakTypeTag[T])(t)
      case t: TupleTypeDescriptor[T] => liftTupleTypeDescriptor(c.weakTypeTag[T])(t)
      case t: ObjectTypeDescriptor[T] => liftObjectTypeDescriptor(c.weakTypeTag[T])(t)
      case t: GeneratedTypeDescriptor[T] => liftGeneratedTypeDescriptor(c.weakTypeTag[T])(t)
      case t: CollectionTypeDescriptor[T] => liftCollectionTypeDescriptor(c.weakTypeTag[T])(t)
      case t: StreamTypeDescriptor => liftStreamTypeDescriptor(t)
    }
  }

  implicit val liftTypeDescriptorAny: Liftable[TypeDescriptor[Any]] = { t =>
    liftTypeDescriptor[Any](c.weakTypeTag[Any])(t)
  }

  implicit val liftTypeDescriptorWildcard: Liftable[TypeDescriptor[_]] = { t =>
    liftTypeDescriptor[Any](c.weakTypeTag[Any])(t.asInstanceOf[TypeDescriptor[Any]])
  }

  implicit def liftFieldDescriptor[T: c.WeakTypeTag]: Liftable[FieldDescriptor[T]] = { t =>
    q"new ${weakTypeOf[FieldDescriptor[T]]}(${t.name}, ${t.fieldType})"
  }

  implicit val liftFieldDescriptorWildcard: Liftable[FieldDescriptor[_]] = { t =>
    q"new ${weakTypeOf[FieldDescriptor[Any]]}(${t.name}, ${t.fieldType.asInstanceOf[TypeDescriptor[Any]]})"
  }
} 
Example 45
Source File: unions.scala    From perf_tester   with Apache License 2.0 5 votes vote down vote up
package shapeless

import scala.language.dynamics
import scala.language.experimental.macros

import scala.reflect.macros.whitebox

object union {
  import syntax.UnionOps

  implicit def unionOps[C <: Coproduct](u : C) : UnionOps[C] = new UnionOps(u)

  
  object Union extends Dynamic {
    def applyDynamicNamed[U <: Coproduct](method: String)(elems: Any*): U = macro UnionMacros.mkUnionNamedImpl[U]

    def selectDynamic(tpeSelector: String): Any = macro LabelledMacros.unionTypeImpl
  }
}

@macrocompat.bundle
class UnionMacros(val c: whitebox.Context) {
  import c.universe._
  import internal.constantType
  import labelled.FieldType

  val fieldTypeTpe = typeOf[FieldType[_, _]].typeConstructor
  val SymTpe = typeOf[scala.Symbol]
  val atatTpe = typeOf[tag.@@[_,_]].typeConstructor

  def mkUnionNamedImpl[U <: Coproduct : WeakTypeTag](method: Tree)(elems: Tree*): Tree = {
    def mkSingletonSymbolType(c: Constant): Type =
      appliedType(atatTpe, List(SymTpe, constantType(c)))

    def mkFieldTpe(keyTpe: Type, valueTpe: Type): Type =
      appliedType(fieldTypeTpe, List(keyTpe, valueTpe.widen))

    def mkElem(keyTpe: Type, value: Tree): Tree =
      q"$value.asInstanceOf[${mkFieldTpe(keyTpe, value.tpe)}]"

    def promoteElem(elem: Tree): Tree = elem match {
      case q""" $prefix(${Literal(k: Constant)}, $v) """ => mkElem(mkSingletonSymbolType(k), v)
      case _ =>
        c.abort(c.enclosingPosition, s"$elem has the wrong shape for a record field")
    }

    val q"${methodString: String}" = method
    if(methodString != "apply")
      c.abort(c.enclosingPosition, s"this method must be called as 'apply' not '$methodString'")

    val elem =
      elems match {
        case Seq(e) => e
        case _ =>
          c.abort(c.enclosingPosition, s"only one branch of a union may be inhabited")
      }

    q""" _root_.shapeless.Coproduct[${weakTypeOf[U]}](${promoteElem(elem)}) """
  }
} 
Example 46
Source File: typechecking.scala    From perf_tester   with Apache License 2.0 5 votes vote down vote up
package shapeless.test

import scala.language.experimental.macros

import java.util.regex.Pattern

import scala.reflect.macros.{ whitebox, ParseException, TypecheckException }


object illTyped {
  def apply(code: String): Unit = macro IllTypedMacros.applyImplNoExp
  def apply(code: String, expected: String): Unit = macro IllTypedMacros.applyImpl
}

@macrocompat.bundle
class IllTypedMacros(val c: whitebox.Context) {
  import c.universe._

  def applyImplNoExp(code: Tree): Tree = applyImpl(code, null)

  def applyImpl(code: Tree, expected: Tree): Tree = {
    val Literal(Constant(codeStr: String)) = code
    val (expPat, expMsg) = expected match {
      case null => (null, "Expected some error.")
      case Literal(Constant(s: String)) =>
        (Pattern.compile(s, Pattern.CASE_INSENSITIVE | Pattern.DOTALL), "Expected error matching: "+s)
    }

    try {
      val dummy0 = TermName(c.freshName)
      val dummy1 = TermName(c.freshName)
      c.typecheck(c.parse(s"object $dummy0 { val $dummy1 = { $codeStr } }"))
      c.error(c.enclosingPosition, "Type-checking succeeded unexpectedly.\n"+expMsg)
    } catch {
      case e: TypecheckException =>
        val msg = e.getMessage
        if((expected ne null) && !(expPat.matcher(msg)).matches)
          c.error(c.enclosingPosition, "Type-checking failed in an unexpected way.\n"+expMsg+"\nActual error: "+msg)
      case e: ParseException =>
        c.error(c.enclosingPosition, s"Parsing failed.\n${e.getMessage}")
    }

    q"()"
  }
} 
Example 47
Source File: lazyref.scala    From perf_tester   with Apache License 2.0 5 votes vote down vote up
package shapeless

import scala.reflect.macros.whitebox


class LazyMacrosRef(val c: whitebox.Context) {
  import c.universe._

  def mkLazyImpl[I: WeakTypeTag]: Tree = {
    val i = new LazyMacros(c)
    i.mkLazyImpl[I].asInstanceOf[Tree]
  }

  def mkStrictImpl[I: WeakTypeTag]: Tree = {
    val i = new LazyMacros(c)
    i.mkStrictImpl[I].asInstanceOf[Tree]
  }
} 
Example 48
Source File: nat.scala    From perf_tester   with Apache License 2.0 5 votes vote down vote up
package shapeless

import scala.language.experimental.macros

import scala.annotation.tailrec
import scala.reflect.macros.whitebox


  type _0 = shapeless._0
  val _0: _0 = new _0

  def toInt[N <: Nat](implicit toIntN : ToInt[N]) = toIntN()

  def toInt(n : Nat)(implicit toIntN : ToInt[n.N]) = toIntN()

  implicit def natOps[N <: Nat](n : N) : NatOps[N] = new NatOps(n)
}

@macrocompat.bundle
class NatMacros(val c: whitebox.Context) extends NatMacroDefns {
  import c.universe._

  def materializeWidened(i: Tree): Tree =
    i match {
      case NatLiteral(n) => mkNatValue(n)
      case _ =>
        c.abort(c.enclosingPosition, s"Expression $i does not evaluate to a non-negative Int literal")
    }
}

@macrocompat.bundle
trait NatMacroDefns {
  val c: whitebox.Context
  import c.universe._

  object NatLiteral {
    def unapply(i: Tree): Option[Int] =
      i match {
        case Literal(Constant(n: Int)) if n >= 0 => Some(n)
        case _ => None
      }
  }

  def mkNatTpt(i: Int): Tree = {
    val succSym = typeOf[Succ[_]].typeConstructor.typeSymbol
    val _0Sym = typeOf[_0].typeSymbol

    @tailrec
    def loop(i: Int, acc: Tree): Tree = {
      if(i == 0) acc
      else loop(i-1, AppliedTypeTree(Ident(succSym), List(acc)))
    }

    loop(i, Ident(_0Sym))
  }

  def mkNatTpe(i: Int): Type = {
    val succTpe = typeOf[Succ[_]].typeConstructor
    val _0Tpe = typeOf[_0]

    @tailrec
    def loop(i: Int, acc: Type): Type = {
      if(i == 0) acc
      else loop(i-1, appliedType(succTpe, acc))
    }

    loop(i, _0Tpe)
  }

  def mkNatValue(i: Int): Tree =
    q""" new ${mkNatTpt(i)} """
} 
Example 49
Source File: CaseClassSkipper.scala    From singleton-ops   with Apache License 2.0 5 votes vote down vote up
package singleton.twoface.impl

import singleton.ops.impl.HasOut
import singleton.twoface.TwoFace

import scala.reflect.macros.whitebox

sealed trait CaseClassSkipper[T <: HasOut] extends HasOut {
  type Out
  def apply(value : T => Any, fallBack : => Boolean) : Out
}
object CaseClassSkipper {
  type Aux[T <: HasOut, Out0] = CaseClassSkipper[T]{type Out = Out0}
  type TAux[T <: HasOut, Out0] = T {type Out = Out0}
  //Normal value retrieval
  implicit def evNormal[T <: HasOut](implicit t : T) : Aux[T, TwoFace.Boolean[t.Out]] = new CaseClassSkipper[T] {
    type Out = TwoFace.Boolean[t.Out]
    def apply(value: T => Any, fallBack: => Boolean): Out = value(t).asInstanceOf[Out]
  }
  //Fallback value retrieval
  case class Fail[T <: HasOut]() extends CaseClassSkipper[T] {
    type Out = Boolean
    def apply(value: T => Any, fallBack: => Boolean): Boolean = fallBack
  }
  implicit def evCC[T <: HasOut](implicit n : shapeless.Refute[T]) : Aux[T, Boolean] = macro evCCMacro[T]
  def evCCMacro[T <: HasOut](c: whitebox.Context)(n : c.Tree)(implicit wt : c.WeakTypeTag[T]) : c.Tree = {
    import c.universe._
    val t = weakTypeOf[T]
    if (c.internal.enclosingOwner.owner.asClass.isCaseClass)
      q"_root_.singleton.twoface.impl.CaseClassSkipper.Fail[$t]()"
    else
      c.abort(c.enclosingPosition, "Could not find implicit for...")
  }
} 
Example 50
Source File: Injectable.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angular2 @Injectable annotation.

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Injectable")
object InjectableFacade extends js.Object {
  def apply() : js.Object = js.native
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Injectable.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Injectable extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Injectable.Macro.impl
}


object Injectable {

  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._
    override val annotationName: String = "Injectable"

    override val annotationParamNames: Seq[String] = Seq()

    override def mainAnnotationObject = q"angulate2.core.InjectableFacade"
  }
} 
Example 51
Source File: NgModule.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2
// Description: Angular2 @NgModule macro annotation

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","NgModule")
object NgModuleFacade extends js.Object {
  def apply() : js.Object = js.native
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Component.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class NgModule(providers: js.Array[js.Any] = null,
               declarations: js.Array[js.Any] = null,
               imports: js.Array[js.Any] = null,
               exports: js.Array[js.Any] = null,
               entryComponents: js.Array[js.Any] = null,
               bootstrap: js.Array[js.Any] = null,
               schemas: js.Array[js.Any] = null,
               id: String = null) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro NgModule.Macro.impl
}

object NgModule {
  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._

    val annotationParamNames = Seq(
      "providers",
      "declarations",
      "imports",
      "exports",
      "entryComponents",
      "bootstrap",
      "schemas",
      "id"
    )

    override val annotationName: String = "NgModule"

    override def mainAnnotationObject = q"angulate2.core.NgModuleFacade"
  }

} 
Example 52
Source File: Pipe.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description:

// Copyright (c) 2017 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.ClassDecorator
import de.surfice.smacrotools.createJS

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Pipe")
object PipeFacade extends js.Object {
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Directive.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Pipe(name: String, pure: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Pipe.Macro.impl
}

object Pipe {

  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._
    val annotationParamNames = Seq(
      "name",
      "pure"
    )

    override val annotationName: String = "Pipe"

    override def mainAnnotationObject = q"angulate2.core.PipeFacade"
  }
}

@createJS
trait PipeTransform0[T,R] {
  def transform(value: T): R
}

@createJS
trait PipeTransform1[T,A1,R] {
  def transform(value: T, arg1: A1): R
}

@createJS
trait PipeTransform2[T,A1,A2,R] {
  def transform(value: T, arg1: A1, arg2: A2): R
}

@createJS
trait PipeTransform3[T,A1,A2,A3,R] {
  def transform(value: T, arg1: A1, arg2: A2, arg3: A3): R
} 
Example 53
Source File: Directive.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angular2 @Directive macro annotation

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.core

import angulate2.internal.{ClassDecorator, FieldDecorator}

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import scala.scalajs.js
import scala.scalajs.js.annotation.JSImport

@js.native
@JSImport("@angular/core","Directive")
object DirectiveFacade extends js.Object {
  def apply(options: js.Object) : js.Object = js.native
}

// NOTE: keep the constructor parameter list and Directive.Macro.annotationParamNames in sync!
@compileTimeOnly("enable macro paradise to expand macro annotations")
class Directive(selector: String = null,
                inputs: js.Array[String] = null,
                outputs: js.Array[String] = null,
                host: js.Dictionary[String] = null,
                template: String = null,
                providers: js.Array[js.Any] = null,
                exportAs: String = null,
                queries: js.Any = null) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro Directive.Macro.impl
}


object Directive {

  private[angulate2] abstract class BaseMacro extends ClassDecorator with FieldDecorator

  private[angulate2] class Macro(val c: whitebox.Context) extends BaseMacro {
    import c.universe._

    override def annotationName = "Directive"

    override def mainAnnotationObject: c.universe.Tree = q"angulate2.core.DirectiveFacade"

    override def annotationParamNames: Seq[String] = Seq(
      "selector",
      "inputs",
      "outputs",
      "host",
      "template",
      "providers",
      "exportAs",
      "queries"
    )
  }
} 
Example 54
Source File: Routes.scala    From angulate2   with MIT License 5 votes vote down vote up
//     Project: angulate2 (https://github.com/jokade/angulate2)
// Description: Angulate2 extension for simplified creation of routing modules

// Copyright (c) 2016 Johannes.Kastner <[email protected]>
//               Distributed under the MIT License (see included LICENSE file)
package angulate2.ext

import angulate2.internal.ClassDecorator
import angulate2.router.Route

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

@compileTimeOnly("enable macro paradise to expand macro annotations")
class Routes(root: Boolean, routes: Route*) extends StaticAnnotation {
  def this(providers: js.Array[js.Any])(root: Boolean, routes: Route*) = this(root,routes:_*)
  def macroTransform(annottees: Any*): Any = macro Routes.Macro.impl
}

object Routes {
  private[angulate2] class Macro(val c: whitebox.Context) extends ClassDecorator {
    import c.universe._

    val annotationParamNames = Seq(
      "root",
      "routes*"
    )

    override val firstArglistParamNames = Seq(
      "providers"
    )

    override val annotationName: String = "Routes"

    override def mainAnnotationObject = q"angulate2.core.NgModuleFacade"

    private val routerModule = q"angulate2.ops.@@[angulate2.router.RouterModule]"

    override def analyze: Analysis = super.analyze andThen {
      case (cls: ClassParts, data) =>
        val cdd = ClassDecoratorData(data)
        val routes = q"scalajs.js.Array(..${cdd.annotParams("routes")})"
        val remainingParams = cdd.annotParams - "root" - "routes"

        val imports = cdd.annotParams("root") match {
          case Literal(Constant(true)) => q"scalajs.js.Array(angulate2.router.RouterModule.forRoot($routes))"
          case Literal(Constant(false)) => q"scalajs.js.Array(angulate2.router.RouterModule.forChild($routes))"
        }
        (cls, ClassDecoratorData.update(data,cdd.copy(annotParams = remainingParams ++ Map("imports" -> imports, "exports" -> routerModule))))
      case default => default
    }

  }
} 
Example 55
Source File: DefaultReaderMacro.scala    From grafter   with MIT License 5 votes vote down vote up
package org.zalando.grafter.macros

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import ReaderMacros._

object DefaultReaderMacro {

  val annotationName = "defaultReader"

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

    val (classTree, companionTree): (Tree, Option[Tree]) =
      annotationInputs(c)(annotationName)(annottees)

    classTree match {
      case ClassDef(_, className, typeParams, _) =>
        val genericTypeName = internal.reificationSupport.freshTypeName("A")
        val typeParam = typeParameter(annotationName)(c)

        typeParams match {
          case _ :: Nil =>
            outputs(c)(classTree, className, companionTree) {
              q"""
         implicit def reader[$genericTypeName, F[_]](implicit defaultReader: cats.data.Reader[$genericTypeName, $typeParam[F]]): cats.data.Reader[$genericTypeName, $className[F]] =
           org.zalando.grafter.GenericReader.widenReader(defaultReader)
      """
            }

          case Nil =>
            outputs(c)(classTree, className, companionTree) {
              q"""
         implicit def reader[$genericTypeName](implicit defaultReader: cats.data.Reader[$genericTypeName, $typeParam]): cats.data.Reader[$genericTypeName, $className] =
           org.zalando.grafter.GenericReader.widenReader(defaultReader)
      """
            }

          case other =>
            c.abort(c.macroApplication.pos, s"the @$annotationName annotation must specify a type containing at most one type parameter, found $other")

        }

      case other =>
        c.abort(c.macroApplication.pos, s"the @$annotationName annotation must annotate a trait, found $other")
    }
  }

}

class defaultReader[A] extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro DefaultReaderMacro.impl
} 
Example 56
Source File: ReaderMacros.scala    From grafter   with MIT License 5 votes vote down vote up
package org.zalando.grafter.macros

import scala.collection.mutable.ListBuffer
import scala.reflect.macros.whitebox

object ReaderMacros {

  
  def typeParameter(name: String)(c: whitebox.Context) = {
    import c.universe._
    val traverser = new Traverser {
      val types: ListBuffer[c.universe.TypeName] = new ListBuffer[TypeName]()

      override def traverse(tree: Tree): Unit = tree match {
        case New(AppliedTypeTree(Ident(TypeName(_)), typeIds)) =>
          types.appendAll(typeIds.collect {  case Ident(typeName: TypeName) => typeName })

        case _ =>
          super.traverse(tree)
      }
    }

    traverser.traverse(c.macroApplication)
    traverser.types.headOption match {
      case Some(t) => t
      case None    => c.abort(c.enclosingPosition, s"the @$name annotation requires a type parameter")
    }
  }

} 
Example 57
Source File: ReaderOfMacro.scala    From grafter   with MIT License 5 votes vote down vote up
package org.zalando.grafter.macros

import scala.annotation.StaticAnnotation
import scala.language.experimental.macros
import scala.reflect.macros.whitebox
import ReaderMacros._


object ReaderOfMacro {

  val annotationName = "readerOf"

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

    def name(t: Name) = t.decodedName.toString.trim

    val (classTree, companionTree): (Tree, Option[Tree]) =
      annotationInputs(c)(annotationName)(annottees)

    classTree match {

      case ClassDef(_, className, _, Template(_, _, fields)) =>
        val typeParam  = typeParameter(annotationName)(c)
        def params     = fieldsNamesAndTypes(c)(fields)
        val paramNames = params.map(_._1).distinct
        val implicits  = params.map { case (p, _type) => q"""private val ${TermName("_"+name(p))}: cats.data.Reader[$typeParam, ${_type}] = implicitly[cats.data.Reader[$typeParam, ${_type}]];""" }
        val readValues = paramNames.map { p => q"""val ${TermName("_"+name(p)+"Value")} = ${TermName("_"+name(p))}.apply(r);""" }
        val values     = paramNames.map { p => q"""${TermName("_"+name(p)+"Value")}""" }
        val klassName  = name(className)

        val reader =
          c.Expr[Any](
            q"""
             implicit val reader: cats.data.Reader[$typeParam, ${TypeName(klassName)}] = {
               cats.data.Reader { r =>
                 ..$readValues
                 new ${TypeName(klassName)}(...${List(values)})
               }
             }
             """)

        outputs(c)(classTree, className, companionTree) {
          q"""
         ..$implicits

         ..$reader
      """
        }

      case other =>
        c.abort(c.macroApplication.pos, s"the @$annotationName annotation must annotate a class, found $other")
    }

  }

}

class readerOf[A] extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro ReaderOfMacro.impl
} 
Example 58
Source File: Facades.scala    From scalapy   with MIT License 5 votes vote down vote up
package me.shadaj.scalapy.py

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

import scala.annotation.StaticAnnotation
class native extends StaticAnnotation

object FacadeImpl {
  def creator[T <: Any](c: whitebox.Context)(implicit tag: c.WeakTypeTag[T]): c.Tree = {
    import c.universe._

    if (!tag.tpe.typeSymbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "Cannot derive a creator for a trait that is not annotated as @py.native")
    }
    
    q"""new _root_.me.shadaj.scalapy.py.FacadeCreator[${tag.tpe}] {
      def create(value: _root_.me.shadaj.scalapy.py.PyValue) = new _root_.me.shadaj.scalapy.py.FacadeValueProvider(value) with ${tag.tpe} {}
    }"""
  }

  def native_impl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[T] = {
    import c.universe._

    if (!c.enclosingClass.symbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "py.native implemented functions can only be declared inside traits annotated as @py.native")
    }

    val method = c.internal.enclosingOwner.asMethod
    val methodName = method.name.toString
    val returnType = method.returnType
    val paramss = method.paramLists

    paramss.headOption match {
      case Some(params) =>
        val paramExprs = params.map(_.name)
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].applyDynamic($methodName)(..$paramExprs).as[$returnType]")
      case scala.None =>
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].selectDynamic($methodName).as[$returnType]")
    }
  }

  def native_named_impl[T: c.WeakTypeTag](c: whitebox.Context): c.Expr[T] = {
    import c.universe._

    if (!c.enclosingClass.symbol.annotations.exists(_.tpe =:= typeOf[native])) {
      c.error(c.enclosingPosition, "py.native implemented functions can only be declared inside traits annotated as @py.native")
    }

    val method = c.internal.enclosingOwner.asMethod
    val methodName = method.name.toString
    val returnType = method.returnType
    val paramss = method.paramLists

    paramss.headOption match {
      case Some(params) =>
        val paramExprs = params.map { p =>
          val paramName = q"${p.asTerm}".toString
          s"""("${p.name}", $paramName)"""
        }

        c.Expr[T](c.parse(s"""as[_root_.me.shadaj.scalapy.py.Dynamic].applyDynamicNamed("$methodName")(${paramExprs.mkString(",")}).as[$returnType]"""))

      case scala.None =>
        c.Expr[T](q"as[_root_.me.shadaj.scalapy.py.Dynamic].selectDynamic($methodName).as[$returnType]")
    }
  }
} 
Example 59
Source File: autoApplyK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoApplyK")
class autoApplyK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoApplyKMacros.newDef
}

private [tagless] class autoApplyKMacros(override val c: whitebox.Context) extends MacroUtils with CovariantKMethodsGenerator {
  import c.universe._

  private def generateApplyKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("applyKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.ApplyK[$algebraType]",
      q"_root_.cats.tagless.Derive.applyK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateApplyKFor(algebra.name))

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(algebra => instanceDef(algebra) :: companionMapKDef(algebra) :: autoDerivationDef(algebra) :: Nil)
} 
Example 60
Source File: autoApply.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoApply")
class autoApply extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoApplyMacros.applyInst
}


private[tagless] class autoApplyMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateApplyFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("applyFor" + algebraName),
      typeParams,
      tq"_root_.cats.Apply[$algebraType]",
      q"_root_.cats.tagless.Derive.apply[$algebraType]"
    )

  def applyInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateApplyFor(algebra.name)) :: Nil
    }
} 
Example 61
Source File: autoProductNK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless
import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoProductK")
class autoProductNK extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoProductNKMacros.productKInst
}

private [tagless] class autoProductNKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  def productMethod(typedef: TypeDefinition)(arity: Int): Tree = {
    def af(n: Int) = TermName("af" + n)

    val name = typedef.ident
    val range = 1 to arity

    // tparam"F1[_], F2[_], F3[_]"
    val effectTypeParams: List[TypeDef] =
      range.map(n => createTypeParam("F" + n, 1)).toList
    val effectTypeParamsNames = tArgs(effectTypeParams)

    //Tuple3K
    val productTypeName = tq"_root_.cats.tagless.${TypeName("Tuple" + arity + "K")}"

    val methods = typedef.impl.body.map {
      case q"def $method[..$typeParams](...$paramLists): ${_}[$resultType]" =>
        val returnItems = range.map(n => q"${af(n)}.$method(...${argumentLists(paramLists)})")
        q"""def $method[..$typeParams](...$paramLists): $productTypeName[..$effectTypeParamsNames]#λ[$resultType] =
           (..$returnItems)
        """

      case statement =>
        abort(s"autoProductK does not support algebra with such statement: $statement")
    }

    //af1: A[F1], af2: A[F2], af3: A[F3]
    val inboundInterpreters: Seq[ValDef] =
      (range zip effectTypeParamsNames).map {
        case (idx, fx) =>
          ValDef(
            Modifiers(Flag.PARAM),
            af(idx),
            typedef.applied(fx),
            EmptyTree
          )
      }

    q"""
        def ${TermName("product" + arity + "K")}[..$effectTypeParams](..$inboundInterpreters): $name[$productTypeName[..$effectTypeParamsNames]#λ] =
          new $name[$productTypeName[..$effectTypeParamsNames]#λ] {
            ..$methods
          }
      """

  }

  def productKInst(annottees: c.Tree*): c.Tree =
    enrich(annottees.toList) { td =>
      val productMethods = (3 to 9).map(productMethod(td))
      Seq(td.defn, addStats(td.companion, productMethods))
    }
} 
Example 62
Source File: autoInvariantK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoInvariantK")
class autoInvariantK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoInvariantKMacros.newDef
}

private [tagless] class autoInvariantKMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateInvariantKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("invariantKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.InvariantK[$algebraType]",
      q"_root_.cats.tagless.Derive.invariantK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateInvariantKFor(algebra.name))

  def instanceDefFullyRefined(algDefn: AlgDefn.UnaryAlg): Tree = {
    algDefn.forVaryingEffectTypeFullyRefined {
      (algebraType, tparams) =>
        val impl = Seq(
          generateInvariantKFor("FullyRefined" + algDefn.name)(
            algebraType,
            tparams
          ),
          generateAutoDerive(algDefn.fullyRefinedTypeSig)(
            algebraType,
            tparams
          )
        )
        q"object fullyRefined { ..$impl }"
    }
  }

  def companionIMapKDef(algDefn: AlgDefn.UnaryAlg) = {
    val from = TermName("af")
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = algDefn.newTypeSig(F)
    val fullyRefinedAlgebraG = algDefn.dependentRefinedTypeSig(G, from)

    algDefn.forVaryingEffectType((algebraType, tparams) => q"""
      def imapK[$F, $G, ..$tparams]($from: $algebraF)(fk: _root_.cats.~>[..${tArgs(F, G)}])(gk: _root_.cats.~>[..${tArgs(G, F)}]): $fullyRefinedAlgebraG =
        _root_.cats.tagless.InvariantK[$algebraType].imapK($from)(fk)(gk).asInstanceOf[$fullyRefinedAlgebraG]
    """)
  }

  def generateAutoDerive(newTypeSig: TypeDef => TypTree)(algebraType: Tree, tparams: Seq[TypeDef]) = {
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = newTypeSig(F)
    val algebraG = newTypeSig(G)

    q"""
      object autoDerive {
        @SuppressWarnings(Array("org.wartremover.warts.ImplicitParameter"))
        implicit def fromFunctorK[$F, $G, ..$tparams](
          implicit af: $algebraF,
          IK: _root_.cats.tagless.InvariantK[$algebraType],
          fk: _root_.cats.~>[..${tArgs(F, G)}],
          gk: _root_.cats.~>[..${tArgs(G, F)}])
          : $algebraG = IK.imapK(af)(fk)(gk)
      }"""
  }

  def autoDerivationDef(algDefn: AlgDefn.UnaryAlg) =
    if(autoDerive) algDefn.forVaryingEffectType(generateAutoDerive(algDefn.newTypeSig)) else EmptyTree

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(algebra => instanceDef(algebra) :: companionIMapKDef(algebra) :: instanceDefFullyRefined(algebra) :: autoDerivationDef(algebra) :: Nil)
} 
Example 63
Source File: autoSemigroupal.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoSemigroupal")
class autoSemigroupal extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoSemigroupalMacros.semigroupalInst
}


private[tagless] class autoSemigroupalMacros(override val c: whitebox.Context) extends MacroUtils {
  import c.universe._

  private def generateSemigroupalFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("semigroupalFor" + algebraName),
      typeParams,
      tq"_root_.cats.Semigroupal[$algebraType]",
      q"_root_.cats.tagless.Derive.semigroupal[$algebraType]"
    )

  def semigroupalInst(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList, AlgebraResolver.LastRegularTypeParam) { algebra =>
      algebra.forVaryingEffectType(generateSemigroupalFor(algebra.name)) :: Nil
    }
} 
Example 64
Source File: autoFunctorK.scala    From cats-tagless   with Apache License 2.0 5 votes vote down vote up
package cats.tagless

import scala.annotation.{StaticAnnotation, compileTimeOnly}
import scala.collection.immutable.Seq
import scala.reflect.macros.whitebox


@compileTimeOnly("Cannot expand @autoFunctorK")
class autoFunctorK(autoDerivation: Boolean = true) extends StaticAnnotation {
  def macroTransform(annottees: Any*): Any = macro autoFunctorKMacros.newDef
}

private [tagless] class autoFunctorKMacros(override val c: whitebox.Context) extends MacroUtils with CovariantKMethodsGenerator {
  import c.universe._

  private def generateFunctorKFor(algebraName: String)(algebraType: Tree, typeParams: Seq[TypeDef]) =
    typeClassInstance(
      TermName("functorKFor" + algebraName),
      typeParams,
      tq"_root_.cats.tagless.FunctorK[$algebraType]",
      q"_root_.cats.tagless.Derive.functorK[$algebraType]"
    )

  def instanceDef(algebra: AlgDefn.UnaryAlg): Tree =
    algebra.forVaryingEffectType(generateFunctorKFor(algebra.name))

  def instanceDefFullyRefined(algDefn: AlgDefn.UnaryAlg): Tree = {
    algDefn.forVaryingEffectTypeFullyRefined {
      (algebraType, tparams) =>
        val impl = Seq(
          generateFunctorKFor("FullyRefined" + algDefn.name)(
            algebraType,
            tparams
          ),
          generateAutoDerive(algDefn.fullyRefinedTypeSig)(
            algebraType,
            tparams
          )
        )
        q"object fullyRefined { ..$impl }"
    }
  }

  def newDef(annottees: c.Tree*): c.Tree =
    enrichAlgebra(annottees.toList)(
      algebra => instanceDef(algebra) :: companionMapKDef(algebra) :: instanceDefFullyRefined(algebra) :: autoDerivationDef(algebra) :: Nil)
}

private [tagless] trait CovariantKMethodsGenerator { self: MacroUtils =>
  import c.universe._

  def companionMapKDef(algDefn: AlgDefn.UnaryAlg) = {
    val from = TermName("af")
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = algDefn.newTypeSig(F)
    val fullyRefinedAlgebraG = algDefn.dependentRefinedTypeSig(G, from)

    algDefn.forVaryingEffectType((algebraType, tparams) => q"""
      def mapK[$F, $G, ..$tparams]($from: $algebraF)(fk: _root_.cats.~>[..${tArgs(F, G)}]): $fullyRefinedAlgebraG =
        _root_.cats.tagless.FunctorK[$algebraType].mapK($from)(fk).asInstanceOf[$fullyRefinedAlgebraG]
    """)
  }

  def generateAutoDerive(newTypeSig: TypeDef => TypTree)(algebraType: Tree, tparams: Seq[TypeDef]) = {
    val F = createFreshTypeParam("F", 1)
    val G = createFreshTypeParam("G", 1)
    val algebraF = newTypeSig(F)
    val algebraG = newTypeSig(G)

    q"""
      object autoDerive {
        @SuppressWarnings(Array("org.wartremover.warts.ImplicitParameter"))
        implicit def fromFunctorK[$F, $G, ..$tparams](
          implicit fk: _root_.cats.~>[..${tArgs(F, G)}],
          FK: _root_.cats.tagless.FunctorK[$algebraType],
          af: $algebraF)
          : $algebraG = FK.mapK(af)(fk)
      }"""
  }

  def autoDerivationDef(algDefn: AlgDefn.UnaryAlg) =
    if(autoDerive) algDefn.forVaryingEffectType(generateAutoDerive(algDefn.newTypeSig)) else EmptyTree

}