-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Transform/nullarify #122
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Transform/nullarify #122
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
e5ae4a7
Fixing prefix of implicit members
odersky f39b624
Members of stable methods
odersky 103beef
InfoTransformers as specific DenotTransformers
odersky b4b688d
ByNameTypeTree is a TypTree.
odersky 2a681ec
Fix to Select(Tree, Symbol)
odersky 0aa3f4c
New phase: Nullarify
odersky d3adfd7
Fix Nullarify treating all 'apply' methods as Function0
DarkDimius File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package dotty.tools.dotc | ||
package transform | ||
|
||
import TreeTransforms._ | ||
import core.DenotTransformers._ | ||
import core.Symbols._ | ||
import core.Contexts._ | ||
import core.Types._ | ||
import core.Flags._ | ||
import core.Decorators._ | ||
import core.StdNames.nme | ||
import ast.Trees._ | ||
|
||
/** This phase eliminates ExprTypes `=> T` and PolyTypes over value types `[X]T`. | ||
* They are expressed in terms of nullary method or function types. More precisely: | ||
* | ||
* For types: | ||
* | ||
* => T ==> () => T if T is the type of a parameter | ||
* ==> ()T otherwise | ||
* [X]T ==> [X]()T | ||
* | ||
* For definitions: | ||
* | ||
* def f: R ==> def f(): R | ||
* def f[X]: R ==> def f[X](): R | ||
* (x: => T) ==> (x: () => T) | ||
* | ||
* For terms: | ||
* | ||
* f ==> f() if f had type => T and is not a parameter | ||
* x ==> x.apply() if x is a parameter that had type => T | ||
* e.apply() ==> e if e.apply() is an argument to a call-by-name parameter | ||
* expr ==> () => expr if other expr is an argument to a call-by-name parameter | ||
* | ||
*/ | ||
class Nullarify extends TreeTransform with InfoTransformer { | ||
import ast.tpd._ | ||
|
||
override def name: String = "nullarify" | ||
|
||
override def runsAfterGroupsOf: Set[String] = Set("splitter") | ||
// assumes idents and selects have symbols; interferes with splitter distribution | ||
// that's why it's "after group". | ||
|
||
override def transformApply(tree: Apply)(implicit ctx: Context, info: TransformerInfo): Tree = | ||
ctx.traceIndented(s"transforming ${tree.show} at phase ${ctx.phase}", show = true) { | ||
|
||
def transformArg(arg: Tree, formal: Type): Tree = formal match { | ||
case _: ExprType => | ||
arg match { | ||
case Apply(Select(qual, nme.apply), Nil) if qual.tpe <:< defn.FunctionClass(0).typeRef => qual | ||
case _ => | ||
val meth = ctx.newSymbol(ctx.owner, nme.ANON_FUN, Synthetic, | ||
MethodType(Nil, Nil, arg.tpe.widen)) | ||
Closure(meth, _ => arg) | ||
} | ||
case _ => | ||
arg | ||
} | ||
|
||
// Compute the method type tree had before this phase is run. | ||
// This is needed to find out which parameters are by-name. | ||
val funType = tree.fun.symbol.info match { | ||
case info: PolyType => info.resultType | ||
case info => info | ||
} | ||
def methType(info: Type, tree: Tree): Type = tree match { | ||
case Apply(fn, args) => methType(info.resultType, fn) | ||
case _ => info | ||
} | ||
val MethodType(_, formals) = methType(funType, tree.fun) | ||
|
||
val args1 = tree.args.zipWithConserve(formals)(transformArg) | ||
cpy.Apply(tree, tree.fun, args1) withType nullarify(tree.tpe) | ||
} | ||
|
||
/** Insert () or .apply() if the term refers to something that was converted to a | ||
* nullary method. Also, transform its type. | ||
*/ | ||
def insertParens(tree: Tree)(implicit ctx: Context): Tree = { | ||
val tp1 = transformInfo(tree.tpe, tree.symbol) | ||
val tree1 = tree.withType(tp1) | ||
val origType = tree.tpe.widenSingleton | ||
def result(implicit ctx: Context) = { | ||
tp1.widen match { | ||
case MethodType(Nil, _) if origType.widenExpr.isInstanceOf[ValueType] => | ||
Apply(tree1, Nil) | ||
case _ => | ||
origType match { | ||
case _: ExprType => // it's a by-name parameter | ||
Apply(Select(tree1, defn.Function0_apply), Nil) | ||
case _ => | ||
tree1 | ||
} | ||
} | ||
} | ||
result(ctx.withPhase(ctx.phase.next)) | ||
} | ||
|
||
override def transformIdent(tree: Ident)(implicit ctx: Context, info: TransformerInfo): Tree = | ||
insertParens(tree) | ||
|
||
override def transformSelect(tree: Select)(implicit ctx: Context, info: TransformerInfo): Tree = | ||
insertParens(tree) | ||
|
||
override def transformTypeApply(tree: TypeApply)(implicit ctx: Context, info: TransformerInfo): Tree = | ||
insertParens(tree) | ||
|
||
override def transformDefDef(tree: DefDef)(implicit ctx: Context, info: TransformerInfo): Tree = { | ||
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = tree | ||
val vparamss1 = | ||
if (vparamss.isEmpty) Nil :: Nil | ||
else vparamss nestedMap { vparam => | ||
val tp = vparam.tpt.tpe | ||
val tp1 = nullarifyParam(tp) | ||
if (tp eq tp1) vparam | ||
else cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt.withType(tp1), vparam.rhs) | ||
} | ||
cpy.DefDef(tree, mods, name, tparams, vparamss1, tpt, rhs) | ||
} | ||
|
||
def nullarify(tp: Type)(implicit ctx: Context): Type = tp match { | ||
case ExprType(rt) => | ||
MethodType(Nil, Nil, rt) | ||
case pt: PolyType => | ||
val rt = pt.resultType match { | ||
case mt: MethodType => nullarify(mt) | ||
case rt => MethodType(Nil, Nil, rt) | ||
} | ||
pt.derivedPolyType(pt.paramNames, pt.paramBounds, rt) | ||
case mt: MethodType => | ||
mt.derivedMethodType(mt.paramNames, mt.paramTypes mapConserve nullarifyParam, | ||
nullarify(mt.resultType)) | ||
case _ => | ||
tp | ||
} | ||
|
||
def nullarifyParam(tp: Type)(implicit ctx: Context) = tp match { | ||
case ExprType(rt) => defn.FunctionType(Nil, rt) | ||
case _ => tp | ||
} | ||
|
||
def transformInfo(tp: Type, sym: Symbol)(implicit ctx: Context): Type = | ||
if (defn.typeTestsOrCasts contains sym) tp | ||
else if (sym is Param) nullarifyParam(tp) | ||
else nullarify(tp) | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was a reason to create one more group?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's explained in class Nullarify: