diff --git a/effekt/jvm/src/test/scala/effekt/RecursiveDescentTests.scala b/effekt/jvm/src/test/scala/effekt/RecursiveDescentTests.scala index 496b975b5..9971dff3e 100644 --- a/effekt/jvm/src/test/scala/effekt/RecursiveDescentTests.scala +++ b/effekt/jvm/src/test/scala/effekt/RecursiveDescentTests.scala @@ -311,6 +311,14 @@ class RecursiveDescentTests extends munit.FunSuite { intercept[Throwable] { parseExpr("[,1]") } } + test("ufcs") { + parseExpr("{ l }.foo { x => x + 1}.bar { x => x * 2}") + parseExpr("{ 42 }.bar") + parseExpr("{ 42 }.bar()") + parseExpr("{ x => x }.foo(42)") + parseExpr("l.bar { fn }") + } + test("Boxing") { parseExpr("box f") parseExpr("unbox f") diff --git a/effekt/shared/src/main/scala/effekt/RecursiveDescent.scala b/effekt/shared/src/main/scala/effekt/RecursiveDescent.scala index c2138bc1a..92de99b6b 100644 --- a/effekt/shared/src/main/scala/effekt/RecursiveDescent.scala +++ b/effekt/shared/src/main/scala/effekt/RecursiveDescent.scala @@ -959,40 +959,43 @@ class RecursiveDescent(positions: Positions, tokens: Seq[Token], source: Source) * This way expressions like `foo.bar.baz()(x).bam.boo()` are * parsed with the correct left-associativity. */ - def callExpr(): Term = nonterminal { - var e = primExpr() + def callExpr(): Term = + nonterminal: + var e = peek.kind match { + case `{` => blockArg() + case _ => primExpr() + } - while (peek(`.`) || isArguments) - peek.kind match { - // member selection (or method call) - // . - // | .( ... ) - case `.` => - consume(`.`) - val member = idRef() - // method call - if (isArguments) { - val (targs, vargs, bargs) = arguments() - e = Term.MethodCall(e, member, targs, vargs, bargs) - } else { - e = Term.MethodCall(e, member, Nil, Nil, Nil) - } + while (peek(`.`) || isArguments) + peek.kind match { + // member selection (or method call) + // . + // | .( ... ) + case `.` => + consume(`.`) + val member = idRef() + // method call + if (isArguments) { + val (targs, vargs, bargs) = arguments() + e = Term.MethodCall(e, member, targs, vargs, bargs) + } else { + e = Term.MethodCall(e, member, Nil, Nil, Nil) + } - // function call - case _ if isArguments => - val callee = e match { - case Term.Var(id) => IdTarget(id) - case other => ExprTarget(other) - } - val (targs, vargs, bargs) = arguments() - e = Term.Call(callee, targs, vargs, bargs) + // function call + case _ if isArguments => + val callee = e match { + case Term.Var(id) => IdTarget(id) + case other => ExprTarget(other) + } + val (targs, vargs, bargs) = arguments() + e = Term.Call(callee, targs, vargs, bargs) - // nothing to do - case _ => () - } + // nothing to do + case _ => () + } + e - e - } // argument lists cannot follow a linebreak: // foo == foo; diff --git a/effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala b/effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala index 6492eb591..ddfee7476 100644 --- a/effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala +++ b/effekt/shared/src/main/scala/effekt/typer/BoxUnboxInference.scala @@ -97,7 +97,11 @@ object BoxUnboxInference extends Phase[NameResolved, NameResolved] { if (hasMethods) { MethodCall(rewriteAsBlock(receiver), id, targs, vargsTransformed, bargsTransformed) } else { - Call(IdTarget(id).inheritPosition(id), targs, rewriteAsExpr(receiver) :: vargsTransformed, bargsTransformed) + receiver match + case _: BlockLiteral => + Call(IdTarget(id).inheritPosition(id), targs, vargsTransformed, rewriteAsBlock(receiver) :: bargsTransformed) + case _ => + Call(IdTarget(id).inheritPosition(id), targs, rewriteAsExpr(receiver) :: vargsTransformed, bargsTransformed) } case TryHandle(prog, handlers) =>