Skip to content

Commit 98574b1

Browse files
authored
Fix: dot notation using block params (#918)
Fixes #709 by changing `resolveOverloadedFunction` to also check `BlockParam`s in scope. Notably, we only look up the first matching symbol, as we do not (yet?) support overloading on block parameters.
1 parent ed31425 commit 98574b1

File tree

6 files changed

+23
-12
lines changed

6 files changed

+23
-12
lines changed

effekt/shared/src/main/scala/effekt/Namer.scala

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -903,7 +903,10 @@ trait NamerOps extends ContextOps { Context: Context =>
903903

904904
val syms2 = if (syms.isEmpty) scope.lookupOperation(id.path, id.name) else syms
905905

906-
if (syms2.nonEmpty) { assignSymbol(id, CallTarget(syms2.asInstanceOf)); true } else { false }
906+
// lookup first block param and do not collect multiple since we do not (yet?) permit overloading on block parameters
907+
val syms3 = if (syms2.isEmpty) List(scope.lookupFirstBlockParam(id.path, id.name)) else syms2
908+
909+
if (syms3.nonEmpty) { assignSymbol(id, CallTarget(syms3.asInstanceOf)); true } else { false }
907910
}
908911

909912
/**

effekt/shared/src/main/scala/effekt/source/Tree.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ object Named {
646646
// CallLike
647647
case Do => symbols.Operation
648648
case Select => symbols.Field
649-
case MethodCall => symbols.Operation | symbols.CallTarget
649+
case MethodCall => symbols.Operation | symbols.CallTarget | symbols.BlockParam
650650
case IdTarget => symbols.TermSymbol
651651

652652
// Others

effekt/shared/src/main/scala/effekt/symbols/Scope.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,13 @@ object scopes {
192192
namespace.terms.getOrElse(name, Set.empty).collect { case c: Callable if !c.isInstanceOf[Operation] => c }
193193
}.filter { namespace => namespace.nonEmpty }
194194

195+
def lookupFirstBlockParam(path: List[String], name: String)(using ErrorReporter): Set[BlockParam] =
196+
first(path, scope) { namespace =>
197+
namespace.terms.get(name).map(set =>
198+
set.collect { case bp: BlockParam => bp }
199+
)
200+
}.getOrElse(Set.empty)
201+
195202
// can be a term OR a type symbol
196203
def lookupFirst(path: List[String], name: String)(using E: ErrorReporter): Symbol =
197204
lookupFirstOption(path, name) getOrElse { E.abort(s"Could not resolve ${name}") }

effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -87,20 +87,14 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] {
8787
val vargsTransformed = vargs.map(rewriteAsExpr)
8888
val bargsTransformed = bargs.map(rewriteAsBlock)
8989

90-
val syms = m.definition match {
90+
val hasMethods = m.definition match {
9191
// an overloaded call target
92-
case symbols.CallTarget(syms) => syms.flatten
93-
case s => C.panic(s"Not a valid method or function: ${id.name}")
94-
}
95-
96-
val (funs, methods) = syms.partitionMap {
97-
case t: symbols.Operation => Right(t)
98-
case t: symbols.Callable => Left(t)
99-
case t => C.abort(pp"Not a valid method or function: ${t}")
92+
case symbols.CallTarget(syms) => syms.flatten.exists(b => b.isInstanceOf[symbols.Operation])
93+
case s => false
10094
}
10195

10296
// we prefer methods over uniform call syntax
103-
if (methods.nonEmpty) {
97+
if (hasMethods) {
10498
MethodCall(rewriteAsBlock(receiver), id, targs, vargsTransformed, bargsTransformed)
10599
} else {
106100
Call(IdTarget(id).inheritPosition(id), targs, rewriteAsExpr(receiver) :: vargsTransformed, bargsTransformed)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
true
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
def refl[A](a: A) { eq: (A, A) => Bool }: Bool =
2+
a.eq(a) && eq(a, a)
3+
4+
def main() = {
5+
println(refl(42) { (x, y) => x == y })
6+
}

0 commit comments

Comments
 (0)