-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Refactor pickled quotes logic #9948
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
nicolasstucki
merged 2 commits into
scala:master
from
dotty-staging:refector-pickled-quotes-logic
Oct 22, 2020
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
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
28 changes: 0 additions & 28 deletions
28
library/src-bootstrapped/scala/internal/quoted/Unpickler.scala
This file was deleted.
Oops, something went wrong.
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,45 @@ | ||
package scala.internal.quoted | ||
|
||
import scala.quoted._ | ||
import scala.internal.tasty.CompilerInterface.quoteContextWithCompilerInterface | ||
|
||
/** Pickled representation of a quoted expression or type */ | ||
trait PickledQuote: | ||
|
||
/** Bytes of the TASTy containing the quoted expression or type */ | ||
def bytes(): Array[Byte] | ||
|
||
/** Expression that will fill the hole `Hole(<idx> | <args>*)` */ | ||
def exprSplice(idx: Int)(args: Seq[Any /* Expr[Any] | Type[?] */])(qctx: QuoteContext): Expr[Any] | ||
|
||
/** Type that will fill the hole `Hole(<idx> | <args>*)` */ | ||
def typeSplice(idx: Int)(args: Seq[Any /* Expr[Any] | Type[?] */]): Type[?] | ||
|
||
object PickledQuote: | ||
|
||
def unpickleExpr[T](pickledQuote: PickledQuote): QuoteContext ?=> Expr[T] = | ||
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext]) | ||
val tree = qctx.reflect.unpickleTerm(pickledQuote) | ||
new scala.internal.quoted.Expr(tree, qctx.hashCode).asInstanceOf[Expr[T]] | ||
|
||
def unpickleType[T](pickledQuote: PickledQuote): QuoteContext ?=> Type[T] = | ||
val qctx = quoteContextWithCompilerInterface(summon[QuoteContext]) | ||
val tree = qctx.reflect.unpickleTypeTree(pickledQuote) | ||
new scala.internal.quoted.Type(tree, qctx.hashCode).asInstanceOf[Type[T]] | ||
|
||
/** Create an instance of PickledExpr from encoded tasty and sequence of labmdas to fill holes | ||
* | ||
* @param pickled: Bytes of tasty encoded using TastyString.pickle | ||
* @param seq: Sequence containing all the functions needed to fill the holes of the quote | ||
*/ | ||
def make(pickled: List[String], seq: Seq[Seq[Any /* Expr[Any] | Type[?] */] => Any]): PickledQuote = | ||
// TODO: generate a more efficient representation | ||
// - avoid creation of lambdas | ||
// - use swich on id | ||
new PickledQuote: | ||
def bytes(): Array[Byte] = | ||
TastyString.unpickle(pickled) | ||
def exprSplice(idx: Int)(args: Seq[Any])(qctx: QuoteContext): Expr[Any] = | ||
seq(idx)(args).asInstanceOf[QuoteContext => Expr[Any]](qctx) | ||
def typeSplice(idx: Int)(args: Seq[Any]): Type[?] = | ||
seq(idx)(args).asInstanceOf[Type[?]] |
10 changes: 4 additions & 6 deletions
10
...y/tools/dotc/core/tasty/TastyString.scala → ...c/scala/internal/quoted/TastyString.scala
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
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.
In the original design, the interface defines abstract methods such as
unpickle()
. Will it be more flexible to keep the original design without committing to a concrete representation in the interface?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.
We have the same flexibility with both designs. In this one we just need to add can add a
PickledQuote.unpickleV2
if we need to change the unpickling logic without breaking the old one. Thoughmake
is the one that will most likely evolve as it contains the byte representation logic and the hole logic.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.
The old
PickledExpr
interface was guided by an attempt to have a user-facing interface for pickled quotes. But we could provide the same abstraction and internally usePickledQuote
to achieve the same.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.
As we put the protocol methods in a single trait. What will happen if we put the methods in
CompilerInterface
similar to the original design before this PR? Will that have the same benefit?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.
How would one create a
PickledQuote
in that design? We need to create it with some concrete class that exists in the library, but that design seems to indicate that it is not known in the library.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.
Just repeat the message in the email, it seems I miss something about the following point:
I think
qctx.reflect.pickTasty(...)
will remove the need to put concrete implementation in stdlib.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.
Indeed, it could all be implemented on the compiler. But that means that each improvement will be painfully complex in the compiler (i.e. the reason why we have not been able to improve it so far) and would have to add a new method on the interface on each change. I don't see how that would scale. The version I propose has the option of adding new static helper method if it is simpler or lets the code be generated without the CompilerInterface which is more flexible.
If we do it your way we also need to add the static helper methods as we do not have access to
pickTasty
method directly because we don't have access to theqctx
where the transformation happens.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.
This seems to be an implementation detail, as a QuoteContext must be available in scope. Currently, in the implementation, it seems each quoted tree is associated with a
QuoteContext
, thus it's possible to get that in later compiler phases. It seems to me that polluting the API design with accidental implementation details is not a good idea.But there might be other aspects that I'm not aware of in the design. Therefore, feel free to choose whatever you think makes more sense technically.
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.
This design also generated reduces the code size of each quote by putting common code in those static methods. We do not want to generate the following code (or equivalent) at each place a quote is load.
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.
I would use this design as I can see some clear benefits for the optimization I have in mind. We can always evolve the API the way you said later if we need to do a major change.