Skip to content

Instantly share code, notes, and snippets.

View xeno-by's full-sized avatar

Eugene Burmako xeno-by

View GitHub Profile

Keybase proof

I hereby claim:

  • I am xeno-by on github.
  • I am xeno_by (https://keybase.io/xeno_by) on keybase.
  • I have a public key whose fingerprint is FE5A 8474 50B9 0939 A0A5 6C10 E512 F2A2 36EE 59D9

To claim this, I am signing this object:

@xeno-by
xeno-by / gist:8b64ca6a73775147941e
Last active December 4, 2018 03:29
Towards perfect compile-time proxies in Scala
// PROBLEM STATEMENT
// Let's build Proxy[T], an object that can capture calls to methods of an underlying object.
// We want the proxy to be type-safe, i.e. we need to verify that the names of the calls
// and the arguments that are passed to those calls are well-typed wrt the type of the proxee.
object Test extends App {
trait Foo { /* ... */ }
val proxy: Proxy[Foo] = ???
proxy.bar()
import scala.reflect.macros.whitebox._
import scala.language.experimental.macros
object Macros {
def impl(c: Context)(fn: c.Tree) = {
import c.universe._
val Typed(Block(List(ClassDef(_, _, _, Template(_, _, stats))), _), _) = fn
val List(_, DefDef(_, TermName("applyOrElse"), _, _, _, Match(_, clauses :+ _)), _) = stats
val pfs = clauses.map(clause => {
object betterUntypecheck extends Transformer {
object Test extends App {
trait Term
class If extends Term
trait AllowedTransformation[I, O]
implicit object term2Term extends AllowedTransformation[Term, Term]
class Foo[T] {
def filter[U <: T : scala.reflect.ClassTag](f: PartialFunction[U, Boolean]): Foo[U] = {
println(scala.reflect.classTag[U])
14:58 ~/Projects/211x/sandbox (2.11.x)$ cat Macros.scala
import scala.reflect.macros.whitebox._
import scala.language.experimental.macros
object Macros {
def macroImpl[T: c.WeakTypeTag](c: Context) = {
import c.universe._
val tpe = weakTypeTag[T].tpe
implicit class RichType(tpe: Type) {
def pre: Type = tpe match {
[INFO] --- scala-maven-plugin:3.1.7-SNAPSHOT:compile (scala-compile-first) @ scala ---
[WARNING] Zinc server is not available at port 3030 - reverting to normal incremental compile
[INFO] Using incremental compilation
[WARNING] extra args for zinc are ignored in non-server mode
[INFO] 'compiler-interface' not yet compiled for Scala 2.11.2. Compiling...
/var/folders/bq/rz89jq0x4f13cm4sk6ss08l80000gn/T/sbt_3f3e9cfe/CompilerInterface.scala:246: error: recursive method rootLoader needs result type
override def rootLoader = if(resident) newPackageLoaderCompat(rootLoader)(compiler.classPath) else super.rootLoader
^
/var/folders/bq/rz89jq0x4f13cm4sk6ss08l80000gn/T/sbt_3f3e9cfe/CompilerInterface.scala:246: error: value rootLoader is not a member of scala.tools.nsc.backend.JavaPlatform
override def rootLoader = if(resident) newPackageLoaderCompat(rootLoader)(compiler.classPath) else super.rootLoader
11:42 ~/Projects/211x/sandbox (2.11.x)$ cat Test.scala
import scala.reflect.runtime.universe._
import scala.reflect.runtime.{currentMirror => cm}
import scala.tools.reflect.ToolBox
import scala.tools.reflect.Eval
object Test extends App {
val tb = cm.mkToolBox(options = "-Ydump-classes .")
println(tb.eval(q"123"))
}
@clean
def foo = bar
// expands into
def foo = WartRemover.clean(bar)
class ReflectTypechecker { self =>
type UnaffiliatedMacroContext <: scala.reflect.moved.macros.contexts.Context
type MacroContext = UnaffiliatedMacroContext { val universe: self.global.type }
def newContext(): MacroContext = new ReflectMacroContext().asInstanceOf[MacroContext]
}
class CompilerTypechecker extends ReflectTypechecker {
override type UnaffiliatedMacroContext = scala.reflect.macros.contexts.Context
override def newContext(): MacroContext = new CompilerMacroContext().asInstanceOf[MacroContext]
}
class ReflectCompilationUnit {
type Icode
def icodes: List[Icode] = Nil
}
class CompilerCompilationUnit extends ReflectCompilationUnit {
type Icode = compiler.Icode
override val icodes: List[Icode] = ...
}