Skip to content

Commit

Permalink
implemented scope injection via import
Browse files Browse the repository at this point in the history
  • Loading branch information
pweisenburger committed May 19, 2015
1 parent ae2df6b commit 39e9656
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 25 deletions.
6 changes: 3 additions & 3 deletions plugin/src/main/scala/dslparadise/package.scala
@@ -1,7 +1,7 @@
package object dslparadise {
type `implicit =>`[-T, +R] = T => R

// type `import._ =>`[-T, +R] = T => R
//
// type `import._`[+T, +I] = T
type `import._ =>`[-T, +R] = T => R

type `import._`[+T, I] = T
}
71 changes: 49 additions & 22 deletions plugin/src/main/scala/dslparadise/typechecker/Typers.scala
Expand Up @@ -3,45 +3,72 @@ package typechecker

import scala.reflect.NameTransformer
import scala.reflect.internal.Mode
import dslparadise._

trait Typers {
self: Analyzer =>

import global._

trait ParadiseTyper extends Typer with TyperContextErrors {
override def typedArg(arg: Tree, mode: Mode, newmode: Mode, pt: Type): Tree = {
// val pre = typeOf[dslparadise.`package`.type]
// rewriting rules for the DSL Paradise types
val rewritings = Map(
"dslparadise.implicit =>" -> { (arg: Tree, pt: Type) =>
q"{ implicit $$bang => $arg }"
},

pt match {
// case TypeRef(`pre`, sym, _) if sym.name.decodedName.toString == "implicit =>" =>
case TypeRef(_, sym, _)
if NameTransformer.decode(sym.fullName) == "dslparadise.implicit =>" =>
"dslparadise.import._ =>" -> { (arg: Tree, pt: Type) =>
q"{ $$bang => import $$bang._; $arg }"
},

val convertArg = context inSilentMode {
super.typedArg(arg.duplicate, mode, newmode, pt)
context.reporter.hasErrors
}
"dslparadise.import._" -> { (arg: Tree, pt: Type) =>
q"{ import ${pt.typeArgs(1).typeSymbol.companionSymbol}._; $arg }"
}
)

val newarg = if (convertArg) {
val newarg = q"{ implicit! => $arg }"
override def typedArg(arg: Tree, mode: Mode, newmode: Mode, pt: Type): Tree = {
val newarg = pt match {
case TypeRef(_, sym, _) =>
// find rewriting rule for the expected type
rewritings get (NameTransformer decode sym.fullName) map { rewrite =>

val keepArg = context inSilentMode {
super.typedArg(newarg.duplicate, mode, newmode, pt)
context.reporter.errors exists { _.errPos == NoPosition }
// only rewrite argument if it does not compile in its current form
val rewriteArg = context inSilentMode {
super.typedArg(arg.duplicate, mode, newmode, pt)
context.reporter.hasErrors
}

if (keepArg) arg else newarg
}
else
arg
if (rewriteArg) {
// apply rewriting rule
val newarg = rewrite(arg, pt)

super.typedArg(newarg, mode, newmode, pt)
// to improve compiler-issued error messages, keep the original
// (non-rewritten) argument if the new (rewritten) argument
// produces compile errors
// - that have no corresponding position in the source file
// (i.e. the position is within the code that was introduced
// by the rewriting) or
// - whose message is "missing parameter type", which could be
// misleading if the rewriting introduced a function and the
// original code already had function type
val keepArg = context inSilentMode {
super.typedArg(newarg.duplicate, mode, newmode, pt)
context.reporter.errors exists { e =>
e.errPos == NoPosition || e.errMsg == "missing parameter type"
}
}

if (keepArg) arg else newarg
}
else
arg

} getOrElse arg

case _ =>
super.typedArg(arg, mode, newmode, pt)
arg
}

super.typedArg(newarg, mode, newmode, pt)
}
}
}

0 comments on commit 39e9656

Please sign in to comment.