diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/LambdaShorthandToLambda.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/LambdaShorthandToLambda.scala index 209fef12a1..3ff92e6b36 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/LambdaShorthandToLambda.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/LambdaShorthandToLambda.scala @@ -200,14 +200,18 @@ case object LambdaShorthandToLambda extends IRPass { ) val newName = newFn.name (newFn, Some(newName)) - } else (fn, None) + } else { + val newFn = desugarExpression(fn, freshNameSupply) + (newFn, None) + } val processedApp = p.copy( function = updatedFn, arguments = updatedArgs ) - // Wrap the app in lambdas from right to left, lambda / shorthand arg + // Wrap the app in lambdas from right to left, 1 lambda per shorthand + // arg val appResult = actualDefArgs.foldRight(processedApp: IR.Expression)((arg, body) => IR.Function.Lambda(List(arg), body, None) diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/LambdaShorthandToLambdaTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/LambdaShorthandToLambdaTest.scala index c952388d9a..67a0a1eef7 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/LambdaShorthandToLambdaTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/LambdaShorthandToLambdaTest.scala @@ -497,4 +497,68 @@ class LambdaShorthandToLambdaTest extends CompilerTest { arg.defaultValue.get shouldBe an[IR.Function.Lambda] } } + + "Lambda shorthand in nested functions" should { + "correctly translate the section-function in an application" in { + implicit val ctx: InlineContext = mkInlineContext + + val ir = + """(_ + 5) 5 + |""".stripMargin.preprocessExpression.get.desugar + + ir shouldBe an[IR.Application.Prefix] + val app = ir.asInstanceOf[IR.Application.Prefix] + app.function shouldBe an[IR.Function.Lambda] + val lam = app.function.asInstanceOf[IR.Function.Lambda] + lam.arguments.length shouldEqual 1 + val lamArg1Name = lam.arguments.head + .asInstanceOf[IR.DefinitionArgument.Specified] + .name + .name + val lamBody = lam.body.asInstanceOf[IR.Application.Prefix] + lamBody.arguments.length shouldEqual 2 + val appArg1Name = lamBody.arguments.head + .asInstanceOf[IR.CallArgument.Specified] + .value + .asInstanceOf[IR.Name.Literal] + .name + lamArg1Name shouldEqual appArg1Name + } + + "correctly translate the function in an application" in { + implicit val ctx: InlineContext = mkInlineContext + + val ir = + """(f _ _ b) b + |""".stripMargin.preprocessExpression.get.desugar + + ir shouldBe an[IR.Function.Lambda] + val firstLam = ir.asInstanceOf[IR.Function.Lambda] + firstLam.arguments.length shouldEqual 1 + val firstLamArgName = firstLam.arguments.head + .asInstanceOf[IR.DefinitionArgument.Specified] + .name + .name + val secondLam = firstLam.body.asInstanceOf[IR.Function.Lambda] + val secondLamArgName = secondLam.arguments.head + .asInstanceOf[IR.DefinitionArgument.Specified] + .name + .name + val app = secondLam.body.asInstanceOf[IR.Application.Prefix] + app.arguments.length shouldEqual 4 + val appArg1Name = app.arguments.head + .asInstanceOf[IR.CallArgument.Specified] + .value + .asInstanceOf[IR.Name] + .name + val appArg2Name = app + .arguments(1) + .asInstanceOf[IR.CallArgument.Specified] + .value + .asInstanceOf[IR.Name] + .name + firstLamArgName shouldEqual appArg1Name + secondLamArgName shouldEqual appArg2Name + } + } } diff --git a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/LambdaShorthandArgsTest.scala b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/LambdaShorthandArgsTest.scala index cee2e6dac4..3e558f2cc3 100644 --- a/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/LambdaShorthandArgsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/interpreter/test/semantic/LambdaShorthandArgsTest.scala @@ -153,5 +153,16 @@ class LambdaShorthandArgsTest extends InterpreterTest { eval(code) shouldEqual 20 } + + "work properly when used inside the function of an application" in { + val code = + """ + |import Builtins + | + |main = (_ - 5) 0 + |""".stripMargin + + eval(code) shouldEqual -5 + } } }