-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Replace quoted type variables in signature of HOAS pattern result #16951
Conversation
ea2f748
to
afc2b56
Compare
afc2b56
to
dfae680
Compare
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.
Otherwise LGTM.
} | ||
Closure(meth, bodyFn) | ||
} | ||
val env = summon[Env] |
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.
Looks like the summon[Env]
two lines below could become env
with this addition.
/** Result of matching a part of an expression */ | ||
private type Matching = Option[Tuple] |
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 documentation comment for =?=
still mention that we return a Some(tup: Tuple)
. That should be updated, but I also think that the meaning of None vs Some(Seq()) vs Some(...) should be explained in a documentation comment for type Matching
itself.
|
||
QuoteMatcher.treeMatch(scrutinee, pat1)(using ctx1).map { matchings => | ||
import QuoteMatcher.MatchResult.* | ||
lazy val spliceScope = SpliceScope.getCurrent |
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.
spliceScope
appears to be unused?
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 intended to use pass it to toExpr
. I will change that.
val matchedExprs = matchings.map(_.toExpr(typeHoleMap)) | ||
val matchedTypes = typeHoleApproximations.map(reflect.TypeReprMethods.asType) | ||
val results = matchedTypes ++ matchedExprs | ||
Tuple.fromIArray(results.toArray.asInstanceOf[IArray[Object]]) |
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.
Could this be:
Tuple.fromIArray(results.toArray.asInstanceOf[IArray[Object]]) | |
Tuple.fromIArray(IArray.unsafeFromArray(results.toArray)) |
@@ -452,20 +433,52 @@ object QuoteMatcher { | |||
accumulator.apply(Set.empty, term) | |||
} | |||
|
|||
enum MatchResult: | |||
case ClosedTree(tree: Tree) | |||
case OpenTree(tree: Tree, patternTpe: Type, args: List[Tree], env: Env) |
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.
Woudl be nice to document the expectation on the valid values of the arguments here.
case MatchResult.ClosedTree(tree) => | ||
new ExprImpl(tree, SpliceScope.getCurrent) | ||
case MatchResult.OpenTree(tree, patternTpe, args, env) => | ||
def hoasClosure = { |
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.
Why a def if we then immediately call it?
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.
Accident of refactoring.
case ClosedTree(tree: Tree) | ||
case OpenTree(tree: Tree, patternTpe: Type, args: List[Tree], env: Env) | ||
|
||
def toExpr(mapTypeHoles: TypeMap)(using Context): Expr[Any] = this match |
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.
Documenting what this method generates would also be nice.
val methTpe = MethodType(names)(_ => paramTypes, _ => mapTypeHoles(patternTpe)) | ||
val meth = newAnonFun(ctx.owner, methTpe) | ||
def bodyFn(lambdaArgss: List[List[Tree]]): Tree = { | ||
val argsMap = args.map(_.symbol).zip(lambdaArgss.head).toMap |
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.
Could use a view to avoid intermediate allocations:
val argsMap = args.map(_.symbol).zip(lambdaArgss.head).toMap | |
val argsMap = args.view.map(_.symbol).zip(lambdaArgss.head).toMap |
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 took care of the comments but also rebased on #16953 to take care of the conflicts before they happen.
|
||
QuoteMatcher.treeMatch(scrutinee, pat1)(using ctx1).map { matchings => | ||
import QuoteMatcher.MatchResult.* | ||
lazy val spliceScope = SpliceScope.getCurrent |
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 intended to use pass it to toExpr
. I will change that.
case MatchResult.ClosedTree(tree) => | ||
new ExprImpl(tree, SpliceScope.getCurrent) | ||
case MatchResult.OpenTree(tree, patternTpe, args, env) => | ||
def hoasClosure = { |
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.
Accident of refactoring.
|
||
/** Return the expression that was extracted from a hole. | ||
* | ||
* If the it was a closed expression it return that expression. Otherwise, |
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.
* If the it was a closed expression it return that expression. Otherwise, | |
* If it was a closed expression it returns that expression. Otherwise, |
*/ | ||
def toExpr(mapTypeHoles: TypeMap, spliceScope: Scope)(using Context): Expr[Any] = this match | ||
case MatchResult.ClosedTree(tree) => | ||
new ExprImpl(tree, SpliceScope.getCurrent) |
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.
Why isn't spliceScope
used here?
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 missed it. Now it uses spliceScope
.
To be able to construct the lambda returned by the HOAS pattern we need: first resolve the type variables and then use the result to construct the signature of the lambdas. To simplify this transformation, `QuoteMatcher` returns a `Seq[MatchResult]` instead of an untyped `Tuple` containing `Expr[?]`. The tuple is created once we have accumulated and processed all extracted values. Fixes scala#15165
To be able to construct the lambda returned by the HOAS pattern we need:
first resolve the type variables and then use the result to construct the
signature of the lambdas.
To simplify this transformation,
QuoteMatcher
returns aSeq[MatchResult]
instead of an untyped
Tuple
containingExpr[?]
. The tuple is createdonce we have accumulated and processed all extracted values.
Fixes #15165