|
Scala example source code file (Exprs.scala)
The Exprs.scala Scala example source code/* NSC -- new Scala compiler * Copyright 2005-2013 LAMP/EPFL * @author Martin Odersky */ package scala package reflect package api import scala.reflect.runtime.{universe => ru} import scala.annotation.compileTimeOnly /** * <span class="badge badge-red" style="float: right;">EXPERIMENTAL</span> * * A trait that defines strongly-typed tree wrappers and operations on them for use in Scala Reflection. * * `Expr` wraps an abstract syntax tree ([[scala.reflect.api.Trees#Tree]]) and tags it with its type ([[scala.reflect.api.Types#Type]]). * * Usually `Expr`s are created via [[scala.reflect.api.Universe#reify]], in which case a compiler * produces a [[scala.reflect.api.TreeCreator]] for the provided expression and also * creates a complementary [[scala.reflect.api.TypeTags#WeakTypeTag]] that corresponds to the type of that expression. * * `Expr`s can also be created manually via the `Expr` companion object, but then the burden of providing a `TreeCreator` lies on the programmer. * Compile-time reflection via macros, as described in [[scala.reflect.macros.Aliases]], provides an easier way to instantiate exprs manually. * Manual creation, however, is very rarely needed when working with runtime reflection. * * `Expr` can be migrated from one mirror to another by using the `in` method. Migration means that all symbolic references * to classes/objects/packages in the expression are re-resolved within the new mirror * (typically using that mirror's classloader). The default universe of an `Expr` is typically * [[scala.reflect.runtime#universe]], the default mirror is typically [[scala.reflect.runtime#currentMirror]]. * * @group ReflectionAPI */ trait Exprs { self: Universe => /** Expr wraps an abstract syntax tree and tags it with its type. * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page. * @group Expressions */ trait Expr[+T] extends Equals with Serializable { /** * Underlying mirror of this expr. */ val mirror: Mirror /** * Migrates the expression into another mirror, jumping into a different universe if necessary. */ def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # Expr[T] /** * The Scala abstract syntax tree representing the wrapped expression. */ def tree: Tree /** * Type of the wrapped expression tree as provided during creation. * * When exprs are created by the compiler, `staticType` represents * a statically known type of the tree as calculated at that point by the compiler. */ def staticType: Type /** * Type of the wrapped expression tree as found in the underlying tree. */ def actualType: Type /** * A dummy method to mark expression splicing in reification. * * It should only be used within a `reify` call, which eliminates the `splice` call and embeds * the wrapped tree into the reified surrounding expression. * If used alone `splice` throws an exception when called at runtime. * * If you want to use an Expr in reification of some Scala code, you need to splice it in. * For an expr of type `Expr[T]`, where `T` has a method `foo`, the following code * {{{ * reify{ expr.splice.foo } * }}} * uses splice to turn an expr of type Expr[T] into a value of type T in the context of `reify`. * * It is equivalent to * {{{ * Select( expr.tree, newTermName("foo") ) * }}} * * The following example code however does not compile * {{{ * reify{ expr.foo } * }}} * because expr of type Expr[T] itself does not have a method foo. */ @compileTimeOnly("splice must be enclosed within a reify {} block") def splice: T /** * A dummy value to denote cross-stage path-dependent type dependencies. * * For example for the following macro definition: * {{{ * class X { type T } * object Macros { def foo(x: X): x.T = macro Impls.foo_impl } * }}} * * The corresponding macro implementation should have the following signature (note how the return type denotes path-dependency on x): * {{{ * object Impls { def foo_impl(c: Context)(x: c.Expr[X]): c.Expr[x.value.T] = ... } * }}} */ @compileTimeOnly("cannot use value except for signatures of macro implementations") val value: T override def canEqual(x: Any) = x.isInstanceOf[Expr[_]] override def equals(x: Any) = x.isInstanceOf[Expr[_]] && this.mirror == x.asInstanceOf[Expr[_]].mirror && this.tree == x.asInstanceOf[Expr[_]].tree override def hashCode = mirror.hashCode * 31 + tree.hashCode override def toString = "Expr["+staticType+"]("+tree+")" } /** * Constructor/Extractor for Expr. * * Can be useful, when having a tree and wanting to splice it in reify call, * in which case the tree first needs to be wrapped in an expr. * The main source of information about exprs is the [[scala.reflect.api.Exprs]] page. * @group Expressions */ object Expr { def apply[T: WeakTypeTag](mirror: scala.reflect.api.Mirror[self.type], treec: TreeCreator): Expr[T] = new ExprImpl[T](mirror.asInstanceOf[Mirror], treec) def unapply[T](expr: Expr[T]): Option[Tree] = Some(expr.tree) } private class ExprImpl[+T: WeakTypeTag](val mirror: Mirror, val treec: TreeCreator) extends Expr[T] { def in[U <: Universe with Singleton](otherMirror: scala.reflect.api.Mirror[U]): U # Expr[T] = { val otherMirror1 = otherMirror.asInstanceOf[scala.reflect.api.Mirror[otherMirror.universe.type]] val tag1 = (implicitly[WeakTypeTag[T]] in otherMirror).asInstanceOf[otherMirror.universe.WeakTypeTag[T]] otherMirror.universe.Expr[T](otherMirror1, treec)(tag1) } lazy val tree: Tree = treec(mirror) lazy val staticType: Type = implicitly[WeakTypeTag[T]].tpe def actualType: Type = tree.tpe def splice: T = throw new UnsupportedOperationException(""" |the function you're calling has not been spliced by the compiler. |this means there is a cross-stage evaluation involved, and it needs to be invoked explicitly. |if you're sure this is not an oversight, add scala-compiler.jar to the classpath, |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) lazy val value: T = throw new UnsupportedOperationException(""" |the value you're calling is only meant to be used in cross-stage path-dependent types. |if you want to splice the underlying expression, use `<your expr>.splice`. |if you want to get a value of the underlying expression, add scala-compiler.jar to the classpath, |import `scala.tools.reflect.Eval` and call `<your expr>.eval` instead.""".trim.stripMargin) private def writeReplace(): AnyRef = new SerializedExpr(treec, implicitly[WeakTypeTag[T]].in(ru.rootMirror)) } } private[scala] class SerializedExpr(var treec: TreeCreator, var tag: ru.WeakTypeTag[_]) extends Serializable { private def writeObject(out: java.io.ObjectOutputStream): Unit = { out.writeObject(treec) out.writeObject(tag) } private def readObject(in: java.io.ObjectInputStream): Unit = { treec = in.readObject().asInstanceOf[TreeCreator] tag = in.readObject().asInstanceOf[ru.WeakTypeTag[_]] } private def readResolve(): AnyRef = { import ru._ Expr(rootMirror, treec)(tag) } } Other Scala source code examplesHere is a short list of links related to this Scala Exprs.scala source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.