From 3d23c6a8d0741c37af736df0c3e002cc4b58edd9 Mon Sep 17 00:00:00 2001 From: Jaroslav Tulach Date: Tue, 31 Oct 2023 06:20:29 +0100 Subject: [PATCH] Removal of useless ApplicationSaturation phase (#8181) --- .../main/scala/org/enso/compiler/Passes.scala | 4 +- .../compiler/pass/desugar/ComplexType.scala | 6 +- .../desugar/LambdaShorthandToLambda.scala | 6 +- .../pass/optimise/ApplicationSaturation.scala | 278 --------------- .../interpreter/runtime/IrToTruffle.scala | 18 +- .../compiler/test/pass/PassManagerTest.scala | 6 +- .../pass/analyse/DataflowAnalysisTest.scala | 4 +- .../test/pass/analyse/TailCallTest.scala | 4 +- .../test/pass/lint/UnusedBindingsTest.scala | 4 +- .../optimise/ApplicationSaturationTest.scala | 327 ------------------ .../test/pass/resolve/PatternsTest.scala | 4 +- 11 files changed, 13 insertions(+), 648 deletions(-) delete mode 100644 engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/ApplicationSaturation.scala delete mode 100644 engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/ApplicationSaturationTest.scala diff --git a/engine/runtime/src/main/scala/org/enso/compiler/Passes.scala b/engine/runtime/src/main/scala/org/enso/compiler/Passes.scala index fd6ff0e0dc..b12de383fd 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/Passes.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/Passes.scala @@ -11,7 +11,6 @@ import org.enso.compiler.pass.lint.{ UnusedBindings } import org.enso.compiler.pass.optimise.{ - ApplicationSaturation, LambdaConsolidate, UnreachableMatchBranches } @@ -114,8 +113,7 @@ class Passes( /** Configuration for the passes. */ private val passConfig: PassConfiguration = PassConfiguration( - ApplicationSaturation -->> ApplicationSaturation.Configuration(), - AliasAnalysis -->> AliasAnalysis.Configuration() + AliasAnalysis -->> AliasAnalysis.Configuration() ) /** The pass manager for running compiler passes. */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala index 382ab31094..15ad1135a5 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/ComplexType.scala @@ -26,10 +26,7 @@ import org.enso.compiler.pass.analyse.{ TailCall } import org.enso.compiler.pass.lint.UnusedBindings -import org.enso.compiler.pass.optimise.{ - ApplicationSaturation, - LambdaConsolidate -} +import org.enso.compiler.pass.optimise.{LambdaConsolidate} import org.enso.compiler.pass.resolve.{ DocumentationComments, IgnoredBindings, @@ -58,7 +55,6 @@ case object ComplexType extends IRPass { override lazy val invalidatedPasses: Seq[IRPass] = List( AliasAnalysis, - ApplicationSaturation, DataflowAnalysis, DemandAnalysis, FunctionBinding, 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 041c3fd59f..86bf4a9f76 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 @@ -21,10 +21,7 @@ import org.enso.compiler.pass.analyse.{ TailCall } import org.enso.compiler.pass.lint.UnusedBindings -import org.enso.compiler.pass.optimise.{ - ApplicationSaturation, - LambdaConsolidate -} +import org.enso.compiler.pass.optimise.{LambdaConsolidate} import org.enso.compiler.pass.resolve.{ DocumentationComments, IgnoredBindings, @@ -53,7 +50,6 @@ case object LambdaShorthandToLambda extends IRPass { ) override lazy val invalidatedPasses: Seq[IRPass] = List( AliasAnalysis, - ApplicationSaturation, DataflowAnalysis, DemandAnalysis, IgnoredBindings, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/ApplicationSaturation.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/ApplicationSaturation.scala deleted file mode 100644 index 29d03adcbd..0000000000 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/ApplicationSaturation.scala +++ /dev/null @@ -1,278 +0,0 @@ -package org.enso.compiler.pass.optimise - -import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.Implicits.AsMetadata -import org.enso.compiler.core.ir.{Expression, Module, Name} -import org.enso.compiler.core.ir.MetadataStorage._ -import org.enso.compiler.core.CompilerError -import org.enso.compiler.core.ir.expression.Application -import org.enso.compiler.pass.IRPass -import org.enso.compiler.pass.analyse.AliasAnalysis -import org.enso.compiler.pass.desugar._ -import org.enso.interpreter.node.{ExpressionNode => RuntimeExpression} -import org.enso.interpreter.runtime.callable.argument.CallArgument -import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope} - -/** This optimisation pass recognises fully-saturated applications of known - * functions and writes analysis data that allows optimisation of them to - * specific nodes at codegen time. - * - * This pass requires the context to provide: - * - * - A [[org.enso.compiler.pass.PassConfiguration]] containing an instance of - * [[ApplicationSaturation.Configuration]]. - */ -case object ApplicationSaturation extends IRPass { - - /** Information on the saturation state of a function. */ - override type Metadata = CallSaturation - override type Config = Configuration - - override lazy val precursorPasses: Seq[IRPass] = List( - AliasAnalysis, - ComplexType, - FunctionBinding, - GenerateMethodBodies, - LambdaConsolidate, - LambdaShorthandToLambda, - NestedPatternMatch, - OperatorToFunction, - SectionsToBinOp - ) - override lazy val invalidatedPasses: Seq[IRPass] = List() - - /** Executes the analysis pass, marking functions with information about their - * argument saturation. - * - * @param ir the Enso IR to process - * @param moduleContext a context object that contains the information needed - * to process a module - * @return `ir`, possibly having made transformations or annotations to that - * IR. - */ - override def runModule( - ir: Module, - moduleContext: ModuleContext - ): Module = { - val passConfig = moduleContext.passConfiguration - ir.mapExpressions( - runExpression( - _, - new InlineContext( - moduleContext, - passConfiguration = passConfig, - compilerConfig = moduleContext.compilerConfig - ) - ) - ) - } - - /** Executes the analysis pass, marking functions with information about their - * argument saturation. - * - * @param ir the Enso IR to process - * @return `ir`, possibly having made transformations or annotations to that - * IR. - */ - //noinspection DuplicatedCode - override def runExpression( - ir: Expression, - inlineContext: InlineContext - ): Expression = { - val knownFunctions = - inlineContext.passConfiguration - .flatMap(configs => configs.get(this)) - .getOrElse( - throw new CompilerError("Pass configuration is missing.") - ) - .knownFunctions - - ir.transformExpressions { - case func @ Application.Prefix(fn, args, _, _, _, _) => - fn match { - case name: Name => - val aliasInfo = - name - .unsafeGetMetadata( - AliasAnalysis, - "Name occurrence with missing alias information." - ) - .unsafeAs[AliasAnalysis.Info.Occurrence] - - if (!aliasInfo.graph.linkedToShadowingBinding(aliasInfo.id)) { - knownFunctions.get(name.name) match { - case Some(FunctionSpec(arity, codegenHelper)) => - if (args.length == arity) { - val argsArePositional = args.forall(arg => arg.name.isEmpty) - - // TODO [AA] In future this should work regardless of the - // application style. Needs interpreter changes. - val saturationInfo = if (argsArePositional) { - CallSaturation.Exact(codegenHelper) - } else { - CallSaturation.ExactButByName() - } - - func - .copy( - arguments = args.map( - _.mapExpressions((ir: Expression) => - runExpression(ir, inlineContext) - ) - ) - ) - .updateMetadata(this -->> saturationInfo) - - } else if (args.length > arity) { - func - .copy( - arguments = args.map( - _.mapExpressions((ir: Expression) => - runExpression(ir, inlineContext) - ) - ) - ) - .updateMetadata( - this -->> CallSaturation.Over(args.length - arity) - ) - } else { - func - .copy( - arguments = args.map( - _.mapExpressions((ir: Expression) => - runExpression(ir, inlineContext) - ) - ) - ) - .updateMetadata( - this -->> CallSaturation.Partial(arity - args.length) - ) - } - case None => - func - .copy( - arguments = args.map( - _.mapExpressions((ir: Expression) => - runExpression(ir, inlineContext) - ) - ) - ) - .updateMetadata(this -->> CallSaturation.Unknown()) - } - } else { - func - .copy( - function = runExpression(fn, inlineContext), - arguments = - args.map(_.mapExpressions(runExpression(_, inlineContext))) - ) - .updateMetadata(this -->> CallSaturation.Unknown()) - } - case _ => - func - .copy( - function = runExpression(fn, inlineContext), - arguments = - args.map(_.mapExpressions(runExpression(_, inlineContext))) - ) - .updateMetadata(this -->> CallSaturation.Unknown()) - } - } - } - - /** Configuration for this pass - * - * @param knownFunctions the mapping of known functions - */ - sealed case class Configuration( - knownFunctions: KnownFunctionsMapping = Map() - ) extends IRPass.Configuration { - override var shouldWriteToContext: Boolean = false - } - - /** A function for constructing the optimised node for a function. */ - type CodegenHelper = - ModuleScope => LocalScope => List[CallArgument] => RuntimeExpression - - /** The configuration for this pass. - * - * The [[String]] is the name of the known function, while the - * [[FunctionSpec]] describes said function. - */ - type KnownFunctionsMapping = Map[String, FunctionSpec] - - /** Describes the saturation state of a function application. */ - sealed trait CallSaturation extends IRPass.IRMetadata { - override def duplicate(): Option[IRPass.IRMetadata] = Some(this) - } - object CallSaturation { - sealed case class Over(additionalArgCount: Int) extends CallSaturation { - override val metadataName: String = - "ApplicationSaturation.CallSaturation.Over" - - /** @inheritdoc */ - override def prepareForSerialization(compiler: Compiler): Over = this - - /** @inheritdoc */ - override def restoreFromSerialization(compiler: Compiler): Option[Over] = - Some(this) - } - sealed case class Exact(helper: CodegenHelper) extends CallSaturation { - override val metadataName: String = - "ApplicationSaturation.CallSaturation.Exact" - - /** @inheritdoc */ - override def prepareForSerialization(compiler: Compiler): Exact = this - - /** @inheritdoc */ - override def restoreFromSerialization( - compiler: Compiler - ): Option[Exact] = Some(this) - } - sealed case class ExactButByName() extends CallSaturation { - override val metadataName: String = - "ApplicationSaturation.CallSaturation.ExactButByName" - - /** @inheritdoc */ - override def prepareForSerialization(compiler: Compiler): ExactButByName = - this - - /** @inheritdoc */ - override def restoreFromSerialization( - compiler: Compiler - ): Option[ExactButByName] = Some(this) - } - sealed case class Partial(unappliedArgCount: Int) extends CallSaturation { - override val metadataName: String = - "ApplicationSaturation.CallSaturation.Partial" - - /** @inheritdoc */ - override def prepareForSerialization(compiler: Compiler): Partial = this - - /** @inheritdoc */ - override def restoreFromSerialization( - compiler: Compiler - ): Option[Partial] = Some(this) - } - sealed case class Unknown() extends CallSaturation { - override val metadataName: String = - "ApplicationSaturation.CallSaturation.Unknown" - - /** @inheritdoc */ - override def prepareForSerialization(compiler: Compiler): Unknown = this - - /** @inheritdoc */ - override def restoreFromSerialization( - compiler: Compiler - ): Option[Unknown] = Some(this) - } - } - - /** A description of a known function - * - * @param arity the number of arguments the function expects - * @param codegenHelper a function that can construct the optimised node to - * represent the function at codegen time. - */ - sealed case class FunctionSpec(arity: Int, codegenHelper: CodegenHelper) -} diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala index ba3642a375..b7c3a2f9fe 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala @@ -51,7 +51,6 @@ import org.enso.compiler.pass.analyse.{ DataflowAnalysis, TailCall } -import org.enso.compiler.pass.optimise.ApplicationSaturation import org.enso.compiler.pass.resolve.{ ExpressionAnnotations, GenericAnnotations, @@ -2072,18 +2071,11 @@ class IrToTruffle( InvokeCallableNode.DefaultsExecutionMode.EXECUTE } - val appNode = application.getMetadata(ApplicationSaturation) match { - case Some( - ApplicationSaturation.CallSaturation.Exact(createOptimised) - ) => - createOptimised(moduleScope)(scope)(callArgs.toList) - case _ => - ApplicationNode.build( - this.run(fn, subjectToInstrumentation), - callArgs.toArray, - defaultsExecutionMode - ) - } + val appNode = ApplicationNode.build( + this.run(fn, subjectToInstrumentation), + callArgs.toArray, + defaultsExecutionMode + ) setLocation(appNode, loc) } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassManagerTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassManagerTest.scala index 2ce81187fd..e957029de4 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassManagerTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassManagerTest.scala @@ -16,10 +16,7 @@ import org.enso.compiler.pass.analyse.{ } import org.enso.compiler.pass.desugar._ import org.enso.compiler.pass.lint.UnusedBindings -import org.enso.compiler.pass.optimise.{ - ApplicationSaturation, - LambdaConsolidate -} +import org.enso.compiler.pass.optimise.{LambdaConsolidate} import org.enso.compiler.pass.resolve.{IgnoredBindings, OverloadsResolution} import org.enso.compiler.test.CompilerTest @@ -39,7 +36,6 @@ class PassManagerTest extends CompilerTest { LambdaConsolidate, OverloadsResolution, DemandAnalysis, - ApplicationSaturation, TailCall, AliasAnalysis, DataflowAnalysis, diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DataflowAnalysisTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DataflowAnalysisTest.scala index 995407bc93..8ebc0a5240 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DataflowAnalysisTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DataflowAnalysisTest.scala @@ -24,7 +24,6 @@ import org.enso.compiler.pass.analyse.DataflowAnalysis.{ DependencyMapping } import org.enso.compiler.pass.analyse.{AliasAnalysis, DataflowAnalysis} -import org.enso.compiler.pass.optimise.ApplicationSaturation import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest import org.enso.interpreter.runtime.scope.LocalScope @@ -44,8 +43,7 @@ class DataflowAnalysisTest extends CompilerTest { passes.getPrecursors(DataflowAnalysis).get val passConfig: PassConfiguration = PassConfiguration( - AliasAnalysis -->> AliasAnalysis.Configuration(), - ApplicationSaturation -->> ApplicationSaturation.Configuration() + AliasAnalysis -->> AliasAnalysis.Configuration() ) implicit val passManager: PassManager = diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/TailCallTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/TailCallTest.scala index fa24361c2d..00c970cbd3 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/TailCallTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/TailCallTest.scala @@ -16,7 +16,6 @@ import org.enso.compiler.core.ir.expression.Case import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse.TailCall.TailPosition import org.enso.compiler.pass.analyse.{AliasAnalysis, TailCall} -import org.enso.compiler.pass.optimise.ApplicationSaturation import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest import org.enso.interpreter.runtime.scope.LocalScope @@ -49,8 +48,7 @@ class TailCallTest extends CompilerTest { val precursorPasses: PassGroup = passes.getPrecursors(TailCall).get val passConfiguration: PassConfiguration = PassConfiguration( - AliasAnalysis -->> AliasAnalysis.Configuration(), - ApplicationSaturation -->> ApplicationSaturation.Configuration() + AliasAnalysis -->> AliasAnalysis.Configuration() ) implicit val passManager: PassManager = diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/UnusedBindingsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/UnusedBindingsTest.scala index 0ab17344a1..f582de5d90 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/UnusedBindingsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/UnusedBindingsTest.scala @@ -8,7 +8,6 @@ import org.enso.compiler.core.ir.expression.{warnings, Case} import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse._ import org.enso.compiler.pass.lint.UnusedBindings -import org.enso.compiler.pass.optimise.ApplicationSaturation import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest import org.enso.interpreter.runtime.scope.LocalScope @@ -23,8 +22,7 @@ class UnusedBindingsTest extends CompilerTest with Inside { val precursorPasses: PassGroup = passes.getPrecursors(UnusedBindings).get val passConfiguration: PassConfiguration = PassConfiguration( - ApplicationSaturation -->> ApplicationSaturation.Configuration(), - AliasAnalysis -->> AliasAnalysis.Configuration() + AliasAnalysis -->> AliasAnalysis.Configuration() ) implicit val passManager: PassManager = diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/ApplicationSaturationTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/ApplicationSaturationTest.scala deleted file mode 100644 index 8c7775e71f..0000000000 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/ApplicationSaturationTest.scala +++ /dev/null @@ -1,327 +0,0 @@ -package org.enso.compiler.test.pass.optimise - -import org.enso.compiler.Passes -import org.enso.compiler.context.FreshNameSupply -import org.enso.compiler.core.Implicits.AsMetadata -import org.enso.compiler.core.ir.{CallArgument, Empty, Expression, Name} -import org.enso.compiler.core.ir.expression.Application -import org.enso.compiler.pass.PassConfiguration._ -import org.enso.compiler.pass.analyse.{AliasAnalysis, TailCall} -import org.enso.compiler.pass.optimise.ApplicationSaturation -import org.enso.compiler.pass.optimise.ApplicationSaturation.{ - CallSaturation, - FunctionSpec, - Metadata -} -import org.enso.compiler.pass.{PassConfiguration, PassManager} -import org.enso.compiler.test.CompilerTest -import org.enso.interpreter.node.ExpressionNode -import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope} -import org.enso.interpreter.runtime.callable - -import scala.annotation.unused - -class ApplicationSaturationTest extends CompilerTest { - - // === Utilities ============================================================ - - /** Generates n arguments that _do not_ contain function applications - * themselves. - * - * @param n the number of arguments to generate - * @param positional whether or not the arguments should be generated by name - * or positionally - * @return a list containing `n` arguments - */ - def genNArgs(n: Int, positional: Boolean = true): List[CallArgument] = { - val name = if (positional) { - None - } else { - Some(Name.Literal("a", isMethod = false, None)) - } - - List.fill(n)(CallArgument.Specified(name, Empty(None), None)) - } - - // === Test Setup =========================================================== - - // The functions are unused, so left undefined for ease of testing - def dummyFn(@unused mod: ModuleScope)(@unused loc: LocalScope)( - @unused args: List[callable.argument.CallArgument] - ): ExpressionNode = ??? - - val knownFunctions: ApplicationSaturation.Configuration = - ApplicationSaturation.Configuration( - Map( - "+" -> FunctionSpec(2, dummyFn), - "baz" -> FunctionSpec(3, dummyFn), - "foo" -> FunctionSpec(4, dummyFn) - ) - ) - - val passes: Passes = new Passes(defaultConfig) - - val precursorPasses = passes.getPrecursors(TailCall).get - - val knownPassConfig: PassConfiguration = PassConfiguration( - ApplicationSaturation -->> knownFunctions, - AliasAnalysis -->> AliasAnalysis.Configuration() - ) - val passManagerKnown = new PassManager(List(precursorPasses), knownPassConfig) - - val localScope: Option[LocalScope] = Some(LocalScope.root) - - val knownCtx = buildInlineContext( - localScope = localScope, - freshNameSupply = Some(new FreshNameSupply), - passConfiguration = Some(knownPassConfig) - ) - - val moduleCtx = buildModuleContext( - passConfiguration = Some(knownPassConfig), - freshNameSupply = Some(new FreshNameSupply) - ) - - // === The Tests ============================================================ - - "Known applications" should { - val plusFn = Application - .Prefix( - Name.Literal("+", isMethod = true, None), - genNArgs(2), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - val bazFn = Application - .Prefix( - Name.Literal("baz", isMethod = false, None), - genNArgs(2), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - val fooFn = Application - .Prefix( - Name.Literal("foo", isMethod = false, None), - genNArgs(5), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - val fooFnByName = Application - .Prefix( - Name.Literal("foo", isMethod = false, None), - genNArgs(4, positional = false), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - "be tagged with full saturation where possible" in { - val resultIR = - ApplicationSaturation.runExpression(plusFn, knownCtx) - - resultIR.getMetadata(ApplicationSaturation).foreach { - case _: CallSaturation.Exact => succeed - case _ => fail() - } - } - - "be tagged with partial saturation where possible" in { - val resultIR = - ApplicationSaturation.runExpression(bazFn, knownCtx) - val expected = Some(CallSaturation.Partial(1)) - - resultIR.getMetadata(ApplicationSaturation) shouldEqual expected - } - - "be tagged with over saturation where possible" in { - val resultIR = - ApplicationSaturation.runExpression(fooFn, knownCtx) - val expected = Some(CallSaturation.Over(1)) - - resultIR.getMetadata(ApplicationSaturation) shouldEqual expected - } - - "be tagged with by name if applied by name" in { - val resultIR = - ApplicationSaturation.runExpression(fooFnByName, knownCtx) - val expected = Some(CallSaturation.ExactButByName()) - - resultIR.getMetadata(ApplicationSaturation) shouldEqual expected - } - } - - "Unknown applications" should { - val unknownFn = Application - .Prefix( - Name.Literal("unknown", isMethod = false, None), - genNArgs(10), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - "be tagged with unknown saturation" in { - val resultIR = - ApplicationSaturation.runExpression(unknownFn, knownCtx) - val expected = Some(CallSaturation.Unknown()) - - resultIR.getMetadata(ApplicationSaturation) shouldEqual expected - } - } - - "Known applications containing known applications" should { - val empty = Empty(None) - val knownPlus = Application - .Prefix( - Name.Literal("+", isMethod = true, None), - genNArgs(2), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - val undersaturatedPlus = Application - .Prefix( - Name.Literal("+", isMethod = true, None), - genNArgs(1), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - val oversaturatedPlus = Application - .Prefix( - Name.Literal("+", isMethod = true, None), - genNArgs(3), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - - implicit class InnerMeta(ir: Expression) { - def getInnerMetadata: Option[Metadata] = { - ir.asInstanceOf[Application.Prefix] - .arguments - .head - .asInstanceOf[CallArgument.Specified] - .value - .getMetadata(ApplicationSaturation) - } - } - - def outerPlus(argExpr: Expression): Application.Prefix = { - Application - .Prefix( - Name.Literal("+", isMethod = true, None), - List( - CallArgument.Specified(None, argExpr, None), - CallArgument.Specified(None, empty, None) - ), - hasDefaultsSuspended = false, - None - ) - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Application.Prefix] - } - - "have fully saturated applications tagged correctly" in { - val result = - ApplicationSaturation.runExpression(outerPlus(knownPlus), knownCtx) - - // The outer should be reported as fully saturated - result.getMetadata(ApplicationSaturation).foreach { - case _: CallSaturation.Exact => succeed - case _ => fail() - } - - // The inner should be reported as fully saturated - result.getInnerMetadata.foreach { - case _: CallSaturation.Exact => succeed - case _ => fail() - } - } - - "have non-fully saturated applications tagged correctly" in { - val result = - ApplicationSaturation.runExpression( - outerPlus(undersaturatedPlus), - knownCtx - ) - val expectedInnerMeta = CallSaturation.Partial(1) - - // The outer should be reported as fully saturated - result.getMetadata(ApplicationSaturation).foreach { - case _: CallSaturation.Exact => succeed - case _ => fail() - } - - // The inner should be reported as under saturateD - result.getInnerMetadata - .foreach(t => t shouldEqual expectedInnerMeta) - } - - "have a mixture of application saturations tagged correctly" in { - val result = - ApplicationSaturation.runExpression( - outerPlus(oversaturatedPlus), - knownCtx - ) - val expectedInnerMeta = CallSaturation.Over(1) - - // The outer should be reported as fully saturated - result.getMetadata(ApplicationSaturation).foreach { - case _: CallSaturation.Exact => succeed - case _ => fail() - } - - // The inner should be reported as under saturateD - result.getInnerMetadata - .foreach(t => t shouldEqual expectedInnerMeta) - } - } - - "Shadowed known functions" should { - val rawIR = - """ - |main = - | foo = x -> y -> z -> x + y + z - | - | foo a b c - |""".stripMargin.toIrExpression - - val inputIR = rawIR.get - .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[Expression] - - val result = ApplicationSaturation - .runExpression(inputIR, knownCtx) - .asInstanceOf[Expression.Binding] - - "be tagged as unknown even if their name is known" in { - // Needs alias analysis to work - result.expression - .asInstanceOf[Expression.Block] - .returnValue - .getMetadata(ApplicationSaturation) - .foreach { - case _: CallSaturation.Unknown => succeed - case _ => fail() - } - } - } - -} diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/PatternsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/PatternsTest.scala index b5d2f2d59b..4ec1bcd112 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/PatternsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/PatternsTest.scala @@ -8,7 +8,6 @@ import org.enso.compiler.core.ir.expression.{errors, Case} import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.PassConfiguration.ToPair import org.enso.compiler.pass.analyse.AliasAnalysis -import org.enso.compiler.pass.optimise.ApplicationSaturation import org.enso.compiler.pass.resolve.Patterns import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -28,8 +27,7 @@ class PatternsTest extends CompilerTest { passes.getPrecursors(Patterns).get val passConfiguration: PassConfiguration = PassConfiguration( - AliasAnalysis -->> AliasAnalysis.Configuration(), - ApplicationSaturation -->> ApplicationSaturation.Configuration() + AliasAnalysis -->> AliasAnalysis.Configuration() ) implicit val passManager: PassManager =