From 24f263b20b474ac61bd7ae7bf7379ea15520778f Mon Sep 17 00:00:00 2001 From: Hubert Plociniczak Date: Thu, 31 Aug 2023 17:42:53 +0200 Subject: [PATCH] Towards shallow nesting in IR (#7681) Refactoring deeply nested IR classes to shallow nesting. Fixes #7017 # Important Notes It's a big PR but fairly consistent. Split multiple hierarchy levels into subpackages. --- docs/runtime/caching.md | 3 +- .../compiler/context/ChangesetBuilder.scala | 21 +- .../execution/LocationResolver.scala | 3 +- .../instrument/job/EnsureCompiledJob.scala | 9 +- .../instrument/job/RefactoringRenameJob.scala | 12 +- .../job/UpsertVisualizationJob.scala | 12 +- .../test/context/ChangesetBuilderTest.scala | 111 +- .../org/enso/compiler/core/EnsoParser.java | 8 +- .../java/org/enso/compiler/core/TreeToIr.java | 558 +- .../scala/org/enso/compiler/core/IR.scala | 9084 +---------------- .../enso/compiler/core/ir/CallArgument.scala | 148 + .../compiler/core/ir/DefinitionArgument.scala | 206 + .../enso/compiler/core/ir/Diagnostic.scala | 38 + .../compiler/core/ir/DiagnosticStorage.scala | 17 +- .../org/enso/compiler/core/ir/Empty.scala | 86 + .../enso/compiler/core/ir/Expression.scala | 269 + .../org/enso/compiler/core/ir/Function.scala | 296 + .../org/enso/compiler/core/ir/IRKind.scala | 28 + .../compiler/core/ir/IdentifiedLocation.scala | 36 + .../org/enso/compiler/core/ir/Literal.scala | 228 + .../org/enso/compiler/core/ir/Module.scala | 128 + .../org/enso/compiler/core/ir/Name.scala | 855 ++ .../org/enso/compiler/core/ir/Pattern.scala | 542 + .../org/enso/compiler/core/ir/Type.scala | 417 + .../org/enso/compiler/core/ir/Warning.scala | 113 + .../core/ir/expression/Application.scala | 435 + .../compiler/core/ir/expression/Case.scala | 333 + .../compiler/core/ir/expression/Comment.scala | 108 + .../compiler/core/ir/expression/Error.scala | 119 + .../compiler/core/ir/expression/Foreign.scala | 114 + .../core/ir/expression/Operator.scala | 139 + .../compiler/core/ir/expression/Section.scala | 318 + .../ir/expression/errors/Conversion.scala | 141 + .../ir/expression/errors/ImportExport.scala | 202 + .../core/ir/expression/errors/Pattern.scala | 112 + .../core/ir/expression/errors/Redefined.scala | 664 ++ .../ir/expression/errors/Resolution.scala | 214 + .../core/ir/expression/errors/Syntax.scala | 240 + .../ir/expression/errors/Unexpected.scala | 116 + .../ir/expression/warnings/Shadowed.scala | 100 + .../ir/expression/warnings/Unreachable.scala | 30 + .../core/ir/expression/warnings/Unused.scala | 49 + .../enso/compiler/core/ir/module/Scope.scala | 24 + .../core/ir/module/scope/Definition.scala | 398 + .../core/ir/module/scope/Export.scala | 198 + .../core/ir/module/scope/Import.scala | 197 + .../ir/module/scope/definition/Method.scala | 456 + .../ir/module/scope/imports/Polyglot.scala | 146 + .../org/enso/compiler/core/ir/type/Set.scala | 757 ++ .../enso/compiler/core/EnsoParserTest.java | 23 +- .../instrument/IncrementalUpdatesTest.java | 6 +- .../java/org/enso/compiler/ModuleCache.java | 17 +- .../compiler/context/CompilerContext.java | 11 +- .../enso/compiler/context/SimpleUpdate.java | 6 +- .../node/expression/literal/LiteralNode.java | 4 +- .../literal/PatchableLiteralNode.java | 16 +- .../org/enso/interpreter/runtime/Module.java | 16 +- .../runtime/PatchedModuleValues.java | 11 +- .../runtime/TruffleCompilerContext.java | 11 +- .../interpreter/runtime/tag/Patchable.java | 4 +- .../scala/org/enso/compiler/Compiler.scala | 81 +- .../enso/compiler/SerializationManager.scala | 12 +- .../enso/compiler/codegen/IrToTruffle.scala | 276 +- .../compiler/context/FreshNameSupply.scala | 8 +- .../enso/compiler/context/InlineContext.scala | 4 +- .../enso/compiler/context/ModuleContext.scala | 4 +- .../compiler/context/SuggestionBuilder.scala | 97 +- .../org/enso/compiler/data/BindingsMap.scala | 21 +- .../scala/org/enso/compiler/pass/IRPass.scala | 8 +- .../org/enso/compiler/pass/PassManager.scala | 28 +- .../compiler/pass/analyse/AliasAnalysis.scala | 179 +- .../analyse/AmbiguousImportsAnalysis.scala | 114 +- .../pass/analyse/AutomaticParallelism.scala | 109 +- .../pass/analyse/BindingAnalysis.scala | 57 +- .../analyse/CachePreferenceAnalysis.scala | 57 +- .../pass/analyse/DataflowAnalysis.scala | 171 +- .../pass/analyse/DemandAnalysis.scala | 116 +- .../pass/analyse/GatherDiagnostics.scala | 29 +- .../pass/analyse/ImportSymbolAnalysis.scala | 38 +- .../enso/compiler/pass/analyse/TailCall.scala | 149 +- .../compiler/pass/desugar/ComplexType.scala | 101 +- .../pass/desugar/FunctionBinding.scala | 102 +- .../pass/desugar/GenerateMethodBodies.scala | 115 +- .../enso/compiler/pass/desugar/Imports.scala | 45 +- .../desugar/LambdaShorthandToLambda.scala | 126 +- .../pass/desugar/NestedPatternMatch.scala | 67 +- .../pass/desugar/OperatorToFunction.scala | 17 +- .../pass/desugar/SectionsToBinOp.scala | 79 +- .../pass/lint/ModuleNameConflicts.scala | 29 +- .../compiler/pass/lint/NoSelfInStatic.scala | 45 +- .../pass/lint/ShadowedPatternFields.scala | 41 +- .../compiler/pass/lint/UnusedBindings.scala | 71 +- .../pass/optimise/ApplicationSaturation.scala | 23 +- .../pass/optimise/LambdaConsolidate.scala | 120 +- .../optimise/UnreachableMatchBranches.scala | 35 +- .../pass/resolve/DocumentationComments.scala | 87 +- .../pass/resolve/ExpressionAnnotations.scala | 37 +- .../resolve/FullyAppliedFunctionUses.scala | 20 +- .../pass/resolve/FullyQualifiedNames.scala | 65 +- .../pass/resolve/GenericAnnotations.scala | 24 +- .../compiler/pass/resolve/GlobalNames.scala | 94 +- .../pass/resolve/IgnoredBindings.scala | 70 +- .../compiler/pass/resolve/MethodCalls.scala | 20 +- .../pass/resolve/MethodDefinitions.scala | 73 +- .../pass/resolve/ModuleAnnotations.scala | 27 +- .../pass/resolve/OverloadsResolution.scala | 55 +- .../enso/compiler/pass/resolve/Patterns.scala | 75 +- .../pass/resolve/SuspendedArguments.scala | 94 +- .../compiler/pass/resolve/TypeFunctions.scala | 112 +- .../compiler/pass/resolve/TypeNames.scala | 46 +- .../pass/resolve/TypeSignatures.scala | 100 +- .../enso/compiler/phase/ImportResolver.scala | 30 +- .../enso/compiler/refactoring/IRUtils.scala | 17 +- .../compiler/AnnotationsCompilerTest.java | 40 +- .../java/org/enso/compiler/CompilerTest.java | 19 +- .../org/enso/compiler/ErrorCompilerTest.java | 107 +- .../org/enso/compiler/SerdeCompilerTest.java | 6 +- .../compiler/VectorArraySignatureTest.java | 38 +- .../interpreter/runtime/ModuleTestUtils.java | 3 +- .../compiler/refactoring/IRUtilsTest.scala | 47 +- .../org/enso/compiler/test/CompilerTest.scala | 54 +- .../org/enso/compiler/test/PassesTest.scala | 11 +- .../test/context/FreshNameSupplyTest.scala | 4 +- .../test/context/SuggestionBuilderTest.scala | 8 +- .../test/core/ir/DiagnosticStorageTest.scala | 23 +- .../test/core/ir/MetadataStorageTest.scala | 19 +- .../test/pass/PassConfigurationTest.scala | 19 +- .../test/pass/analyse/AliasAnalysisTest.scala | 220 +- .../pass/analyse/BindingAnalysisTest.scala | 6 +- .../pass/analyse/DataflowAnalysisTest.scala | 220 +- .../pass/analyse/DemandAnalysisTest.scala | 96 +- .../pass/analyse/GatherDiagnosticsTest.scala | 59 +- .../test/pass/analyse/TailCallTest.scala | 105 +- .../test/pass/desugar/ComplexTypeTest.scala | 58 +- .../pass/desugar/FunctionBindingTest.scala | 134 +- .../desugar/GenerateMethodBodiesTest.scala | 192 +- .../test/pass/desugar/ImportsTest.scala | 4 +- .../desugar/LambdaShorthandToLambdaTest.scala | 316 +- .../pass/desugar/NestedPatternMatchTest.scala | 114 +- .../pass/desugar/OperatorToFunctionTest.scala | 42 +- .../pass/desugar/SectionsToBinOpTest.scala | 89 +- .../test/pass/lint/NoSelfInStaticTests.scala | 22 +- .../pass/lint/ShadowedPatternFieldsTest.scala | 18 +- .../test/pass/lint/UnusedBindingsTest.scala | 62 +- .../optimise/ApplicationSaturationTest.scala | 89 +- .../pass/optimise/LambdaConsolidateTest.scala | 120 +- .../UnreachableMatchBranchesTest.scala | 16 +- .../resolve/DocumentationCommentsTest.scala | 72 +- .../resolve/ExpressionAnnotationsTest.scala | 64 +- .../test/pass/resolve/GlobalNamesTest.scala | 71 +- .../pass/resolve/IgnoredBindingsTest.scala | 52 +- .../pass/resolve/MethodDefinitionsTest.scala | 28 +- .../pass/resolve/ModuleAnnotationsTest.scala | 44 +- .../resolve/OverloadsResolutionTest.scala | 39 +- .../test/pass/resolve/PatternsTest.scala | 24 +- .../resolve/SugaredTypeFunctionsTest.scala | 56 +- .../pass/resolve/SuspendedArgumentsTest.scala | 70 +- .../test/pass/resolve/TypeNamesTest.scala | 27 +- .../pass/resolve/TypeSignaturesTest.scala | 63 +- .../test/semantic/ImportExportTest.scala | 98 +- .../test/semantic/TypeSignaturesTest.scala | 29 +- 161 files changed, 13207 insertions(+), 12493 deletions(-) create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/CallArgument.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DefinitionArgument.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Expression.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Function.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IRKind.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IdentifiedLocation.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Literal.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Module.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Name.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Pattern.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Application.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Case.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Comment.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Foreign.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Operator.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Section.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/Scope.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Definition.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Export.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Import.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/definition/Method.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/imports/Polyglot.scala create mode 100644 engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/type/Set.scala diff --git a/docs/runtime/caching.md b/docs/runtime/caching.md index 3000c705080e..ee546780ff3a 100644 --- a/docs/runtime/caching.md +++ b/docs/runtime/caching.md @@ -359,8 +359,7 @@ typesetMember <- memberValue #### Typing Operators -All typing operators in Enso (`IR.Type`) are dependent on their constituent -parts: +All typing operators in Enso (`Type`) are dependent on their constituent parts: ``` typingExpr <- expressionChildren diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/compiler/context/ChangesetBuilder.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/compiler/context/ChangesetBuilder.scala index e646567db051..7d5bcbbb8fb3 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/compiler/context/ChangesetBuilder.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/compiler/context/ChangesetBuilder.scala @@ -4,6 +4,9 @@ import com.oracle.truffle.api.source.Source import java.util.UUID import org.enso.compiler.core.EnsoParser import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Literal +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.analyse.DataflowAnalysis import org.enso.interpreter.instrument.execution.model.PendingEdit @@ -80,7 +83,7 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource]( ir.preorder.filter(_.getExternalId == directlyAffectedId) val oldIr = literals.head - def newIR(edit: PendingEdit): Option[IR.Literal] = { + def newIR(edit: PendingEdit): Option[Literal] = { val value = edit match { case pending: PendingEdit.SetExpressionValue => pending.value case other: PendingEdit.ApplyEdit => other.edit.text @@ -91,16 +94,16 @@ final class ChangesetBuilder[A: TextEditor: IndexedSource]( compiler .generateIRInline(compiler.parse(source.getCharacters())) .flatMap(_ match { - case ir: IR.Literal => Some(ir.setLocation(oldIr.location)) - case _ => None + case ir: Literal => Some(ir.setLocation(oldIr.location)) + case _ => None }) }.get } oldIr match { - case node: IR.Literal.Number => + case node: Literal.Number => newIR(pending).map(ir => new SimpleUpdate(node, pending.edit, ir)) - case node: IR.Literal.Text => + case node: Literal.Text => newIR(pending).map(ir => new SimpleUpdate(node, pending.edit, ir)) case _ => None } @@ -322,8 +325,8 @@ object ChangesetBuilder { /** Get the IR name if available. */ private def getName(ir: IR): Option[String] = ir match { - case name: IR.Name => Some(name.name) - case _ => None + case name: Name => Some(name.name) + case _ => None } /** Build an internal representation of the [[IR]]. @@ -511,9 +514,9 @@ object ChangesetBuilder { */ private def getExpressionName(ir: IR, id: IR.Identifier): Option[String] = ir.preorder.find(_.getId == id).collect { - case name: IR.Name => + case name: Name => name.name - case method: IR.Module.Scope.Definition.Method => + case method: definition.Method => method.methodName.name } diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/LocationResolver.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/LocationResolver.scala index 38a1899bdf10..982186ddd9a7 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/LocationResolver.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/execution/LocationResolver.scala @@ -2,6 +2,7 @@ package org.enso.interpreter.instrument.execution import com.oracle.truffle.api.source.SourceSection import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.IdentifiedLocation import org.enso.interpreter.runtime.Module import org.enso.syntax.text.Location import org.enso.text.editing.{model, IndexedSource} @@ -58,7 +59,7 @@ object LocationResolver { */ def getExpressionId( ir: IR, - location: IR.IdentifiedLocation + location: IdentifiedLocation ): Option[ExpressionId] = ir.preorder .find(_.location.contains(location)) diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala index 95cf32c8e238..295fc346f733 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/EnsureCompiledJob.scala @@ -5,7 +5,8 @@ import com.oracle.truffle.api.TruffleLogger import org.enso.compiler.CompilerResult import org.enso.compiler.context._ import org.enso.compiler.core.CompilerError -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Diagnostic, Warning} +import org.enso.compiler.core.ir.expression.Error import org.enso.compiler.pass.analyse.{ CachePreferenceAnalysis, GatherDiagnostics @@ -177,9 +178,9 @@ final class EnsureCompiledJob( ) .diagnostics val diagnostics = pass.collect { - case warn: IR.Warning => + case warn: Warning => createDiagnostic(Api.DiagnosticType.Warning, module, warn) - case error: IR.Error => + case error: Error => createDiagnostic(Api.DiagnosticType.Error, module, error) } sendDiagnosticUpdates(diagnostics) @@ -196,7 +197,7 @@ final class EnsureCompiledJob( private def createDiagnostic( kind: Api.DiagnosticType, module: Module, - diagnostic: IR.Diagnostic + diagnostic: Diagnostic ): Api.ExecutionResult.Diagnostic = { Api.ExecutionResult.Diagnostic( kind, diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/RefactoringRenameJob.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/RefactoringRenameJob.scala index a2e1564ca84d..ea3f2b24baf2 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/RefactoringRenameJob.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/RefactoringRenameJob.scala @@ -1,6 +1,7 @@ package org.enso.interpreter.instrument.job import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Name import org.enso.compiler.refactoring.IRUtils import org.enso.interpreter.instrument.execution.RuntimeContext import org.enso.interpreter.instrument.execution.model.PendingEdit @@ -160,16 +161,15 @@ final class RefactoringRenameJob( } } - private def getLiteral(ir: IR): Option[IR.Name.Literal] = + private def getLiteral(ir: IR): Option[Name.Literal] = ir match { - case literal: IR.Name.Literal => Some(literal) - case _ => None + case literal: Name.Literal => Some(literal) + case _ => None } - private def getMethodDefinition(ir: IR): Option[IR.Name] = + private def getMethodDefinition(ir: IR): Option[Name] = ir match { - case methodRef: IR.Name.MethodReference - if methodRef.typePointer.isEmpty => + case methodRef: Name.MethodReference if methodRef.typePointer.isEmpty => Some(methodRef.methodName) case _ => None diff --git a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/UpsertVisualizationJob.scala b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/UpsertVisualizationJob.scala index 384f05764a0d..9ba25c5264e0 100644 --- a/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/UpsertVisualizationJob.scala +++ b/engine/runtime-instrument-common/src/main/scala/org/enso/interpreter/instrument/job/UpsertVisualizationJob.scala @@ -2,7 +2,9 @@ package org.enso.interpreter.instrument.job import cats.implicits._ import com.oracle.truffle.api.TruffleLogger -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.analyse.{ CachePreferenceAnalysis, DataflowAnalysis @@ -390,14 +392,14 @@ object UpsertVisualizationJob { visualizationExpression match { case Api.VisualizationExpression.ModuleMethod(methodPointer, _) => module.getIr.bindings - .collect { case method: IR.Module.Scope.Definition.Method => + .collect { case method: definition.Method => val methodReference = method.methodReference val methodReferenceName = methodReference.methodName.name val methodReferenceTypeOpt = methodReference.typePointer.map(_.name) val externalIdOpt = method.body match { - case fun: IR.Function => fun.body.getExternalId - case _ => method.getExternalId + case fun: Function => fun.body.getExternalId + case _ => method.getExternalId } externalIdOpt.filter { _ => methodReferenceName == methodPointer.name && @@ -479,7 +481,7 @@ object UpsertVisualizationJob { module.getIr.preorder .find(_.getExternalId.contains(expressionId)) .collect { - case name: IR.Name => + case name: Name.Literal => DataflowAnalysis.DependencyInfo.Type .Dynamic(name.name, Some(expressionId)) case ir => diff --git a/engine/runtime-instrument-common/src/test/scala/org/enso/compiler/test/context/ChangesetBuilderTest.scala b/engine/runtime-instrument-common/src/test/scala/org/enso/compiler/test/context/ChangesetBuilderTest.scala index 106031134eb1..e553c0b853e4 100644 --- a/engine/runtime-instrument-common/src/test/scala/org/enso/compiler/test/context/ChangesetBuilderTest.scala +++ b/engine/runtime-instrument-common/src/test/scala/org/enso/compiler/test/context/ChangesetBuilderTest.scala @@ -8,7 +8,10 @@ import org.enso.compiler.context.{ ModuleContext } import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Application +import org.enso.compiler.core.ir.{CallArgument, Expression, Function} +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.PassManager import org.enso.compiler.test.CompilerTest import org.enso.interpreter.runtime.scope.LocalScope @@ -30,9 +33,9 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] - val two = rhs.arguments(1).asInstanceOf[IR.CallArgument.Specified].value + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] + val two = rhs.arguments(1).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( two.getId @@ -46,9 +49,9 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] - val two = rhs.arguments(1).asInstanceOf[IR.CallArgument.Specified].value + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] + val two = rhs.arguments(1).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( two.getId @@ -62,9 +65,9 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] - val two = rhs.arguments(1).asInstanceOf[IR.CallArgument.Specified].value + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] + val two = rhs.arguments(1).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( two.getId @@ -78,7 +81,7 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val x = ir.name invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -93,7 +96,7 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val x = ir.name invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -108,10 +111,10 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] val plus = rhs.function - val two = rhs.arguments(1).asInstanceOf[IR.CallArgument.Specified].value + val two = rhs.arguments(1).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( plus.getId, @@ -126,10 +129,10 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] val x = ir.name - val one = rhs.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + val one = rhs.arguments(0).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( x.getId, @@ -144,10 +147,10 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val x = ir.name - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] - val one = rhs.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + val rhs = ir.expression.asInstanceOf[Application.Prefix] + val one = rhs.arguments(0).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( x.getId, @@ -162,8 +165,8 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val undefinedExpr = ir.expression.asInstanceOf[IR.Error.Resolution] + .asInstanceOf[Expression.Binding] + val undefinedExpr = ir.expression.asInstanceOf[errors.Resolution] val undefinedName = undefinedExpr.originalName invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -178,11 +181,11 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Expression.Binding] + val rhs = ir.expression.asInstanceOf[Application.Prefix] val undefinedArg = - rhs.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val undefinedError = undefinedArg.value.asInstanceOf[IR.Error.Resolution] + rhs.arguments(1).asInstanceOf[CallArgument.Specified] + val undefinedError = undefinedArg.value.asInstanceOf[errors.Resolution] val undefinedName = undefinedError.originalName invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -200,14 +203,14 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val secondLine = - ir.body.children(1).asInstanceOf[IR.Application.Prefix] + ir.body.children(1).asInstanceOf[Application.Prefix] val y = - secondLine.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + secondLine.arguments(0).asInstanceOf[CallArgument.Specified].value val plus = secondLine.function val x = - secondLine.arguments(1).asInstanceOf[IR.CallArgument.Specified].value + secondLine.arguments(1).asInstanceOf[CallArgument.Specified].value invalidated(ir, code, edit) should contain theSameElementsAs Seq( y.getId, @@ -226,7 +229,7 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] invalidated(ir, code, edit) should contain theSameElementsAs Seq() } @@ -241,8 +244,8 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Function.Lambda] - val firstLine = ir.body.children(0).asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Function.Lambda] + val firstLine = ir.body.children(0).asInstanceOf[Expression.Binding] val five = firstLine.expression invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -261,13 +264,13 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Function.Lambda] - val secondLine = ir.body.children(1).asInstanceOf[IR.Expression.Binding] - val z = secondLine.expression.asInstanceOf[IR.Application.Force].target + .asInstanceOf[Function.Lambda] + val secondLine = ir.body.children(1).asInstanceOf[Expression.Binding] + val z = secondLine.expression.asInstanceOf[Application.Force].target val thirdLine = - ir.body.children(2).asInstanceOf[IR.Application.Prefix] + ir.body.children(2).asInstanceOf[Application.Prefix] val y = - thirdLine.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + thirdLine.arguments(0).asInstanceOf[CallArgument.Specified].value val plus = thirdLine.function invalidated(ir, code, edit) should contain theSameElementsAs Seq( @@ -289,10 +292,10 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val x = ir.name - val rhs = ir.expression.asInstanceOf[IR.Application.Prefix] - val one = rhs.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + val rhs = ir.expression.asInstanceOf[Application.Prefix] + val one = rhs.arguments(0).asInstanceOf[CallArgument.Specified].value val plus = rhs.function invalidated(ir, code, edits: _*) should contain theSameElementsAs Seq( @@ -316,13 +319,13 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code .preprocessExpression(freshInlineContext) .get - .asInstanceOf[IR.Expression.Binding] - val body = ir.expression.asInstanceOf[IR.Function.Lambda].body - val secondLine = body.children(1).asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] + val body = ir.expression.asInstanceOf[Function.Lambda].body + val secondLine = body.children(1).asInstanceOf[Expression.Binding] val z = secondLine.expression.asInstanceOf[Application.Force].target - val thirdLine = body.children(2).asInstanceOf[IR.Application.Prefix] + val thirdLine = body.children(2).asInstanceOf[Application.Prefix] val y = - thirdLine.arguments(0).asInstanceOf[IR.CallArgument.Specified].value + thirdLine.arguments(0).asInstanceOf[CallArgument.Specified].value val plus = thirdLine.function invalidated(ir, code, edits: _*) should contain theSameElementsAs Seq( @@ -351,18 +354,18 @@ class ChangesetBuilderTest extends CompilerTest { val ir = code.preprocessModule val main = - ir.bindings(0).asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + ir.bindings(0).asInstanceOf[definition.Method.Explicit] val mainBody = main.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] - val x = mainBody.expressions(0).asInstanceOf[IR.Expression.Binding] - val xExpr = x.expression.asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Expression.Block] + val x = mainBody.expressions(0).asInstanceOf[Expression.Binding] + val xExpr = x.expression.asInstanceOf[Application.Prefix] val undefinedName = xExpr .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Error.Resolution] + .asInstanceOf[errors.Resolution] .originalName invalidated(ir, code, edit) should contain theSameElementsAs Seq( diff --git a/engine/runtime-parser/src/main/java/org/enso/compiler/core/EnsoParser.java b/engine/runtime-parser/src/main/java/org/enso/compiler/core/EnsoParser.java index 648c7fa1f148..d784ca0cdeb3 100644 --- a/engine/runtime-parser/src/main/java/org/enso/compiler/core/EnsoParser.java +++ b/engine/runtime-parser/src/main/java/org/enso/compiler/core/EnsoParser.java @@ -1,5 +1,7 @@ package org.enso.compiler.core; +import org.enso.compiler.core.ir.Expression; +import org.enso.compiler.core.ir.Module; import org.enso.syntax2.Parser; import org.enso.syntax2.Tree; @@ -24,7 +26,7 @@ public void close() throws Exception { } } - public IR.Module compile(CharSequence src) { + public Module compile(CharSequence src) { var tree = parser.parse(src); return generateIR(tree); } @@ -33,11 +35,11 @@ public Tree parse(CharSequence src) { return parser.parse(src); } - public IR.Module generateIR(Tree t) { + public Module generateIR(Tree t) { return TreeToIr.MODULE.translate(t); } - public scala.Option generateIRInline(Tree t) { + public scala.Option generateIRInline(Tree t) { return TreeToIr.MODULE.translateInline(t); } } diff --git a/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java b/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java index 83a993e2fd88..f73ab6648537 100644 --- a/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java +++ b/engine/runtime-parser/src/main/java/org/enso/compiler/core/TreeToIr.java @@ -4,9 +4,31 @@ import java.util.Objects; import java.util.UUID; -import org.enso.compiler.core.IR.IdentifiedLocation; +import org.enso.compiler.core.ir.IdentifiedLocation; +import org.enso.compiler.core.ir.CallArgument; +import org.enso.compiler.core.ir.DefinitionArgument; import org.enso.compiler.core.ir.DiagnosticStorage; +import org.enso.compiler.core.ir.Empty; +import org.enso.compiler.core.ir.Expression; +import org.enso.compiler.core.ir.Function; +import org.enso.compiler.core.ir.Literal; +import org.enso.compiler.core.ir.Name; import org.enso.compiler.core.ir.MetadataStorage; +import org.enso.compiler.core.ir.Module; +import org.enso.compiler.core.ir.Pattern; +import org.enso.compiler.core.ir.Type; +import org.enso.compiler.core.ir.expression.Application; +import org.enso.compiler.core.ir.expression.Case; +import org.enso.compiler.core.ir.expression.Comment; +import org.enso.compiler.core.ir.expression.Foreign; +import org.enso.compiler.core.ir.expression.Operator; +import org.enso.compiler.core.ir.expression.Section; +import org.enso.compiler.core.ir.expression.errors.Syntax; +import org.enso.compiler.core.ir.module.scope.Definition; +import org.enso.compiler.core.ir.module.scope.definition.Method; +import org.enso.compiler.core.ir.module.scope.Export; +import org.enso.compiler.core.ir.module.scope.Import; +import org.enso.compiler.core.ir.module.scope.imports.Polyglot; import org.enso.syntax.text.Location; import org.enso.syntax2.ArgumentDefinition; import org.enso.syntax2.Base; @@ -37,7 +59,7 @@ private TreeToIr() { * @param ast the tree representing the program to translate * @return the IR representation of `inputAST` */ - IR.Module translate(Tree ast) { + Module translate(Tree ast) { return translateModule(ast); } @@ -52,27 +74,27 @@ IR.Module translate(Tree ast) { * @return The {@link IR} representation of the given ast if it is valid, otherwise * {@link Option#empty()}. */ - Option translateInline(Tree ast) { + Option translateInline(Tree ast) { return switch(ast) { case Tree.BodyBlock b -> { - List expressions = nil(); - java.util.List locations = new ArrayList<>(); + List expressions = nil(); + java.util.List locations = new ArrayList<>(); for (Line statement : b.getStatements()) { Tree exprTree = statement.getExpression(); - IR.Expression expr = switch (exprTree) { + Expression expr = switch (exprTree) { case null -> null; case Tree.Export x -> null; case Tree.Import x -> null; case Tree.Invalid x -> null; case Tree.TypeSignature sig -> { - IR.Expression methodReference; + Expression methodReference; try { methodReference = translateMethodReference(sig.getVariable(), true); } catch (SyntaxException ex) { methodReference = translateExpression(sig.getVariable()); } var signature = translateType(sig.getType(), false); - var ascription = new IR$Type$Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); + var ascription = new Type.Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); yield ascription; } default -> translateExpression(exprTree); @@ -104,8 +126,8 @@ yield switch (expressions.size()) { } var returnValue = expressions.head(); @SuppressWarnings("unchecked") - var statements = ((List) expressions.tail()).reverse(); - yield Option.apply(new IR$Expression$Block( + var statements = ((List) expressions.tail()).reverse(); + yield Option.apply(new Expression.Block( statements, returnValue, combinedLocation, @@ -127,18 +149,18 @@ yield switch (expressions.size()) { * @param module the [[AST]] representation of the module to translate * @return the [[IR]] representation of `module` */ - IR.Module translateModule(Tree module) { + Module translateModule(Tree module) { return switch (module) { case Tree.BodyBlock b -> { - List bindings = nil(); - List imports = nil(); - List exports = nil(); + List bindings = nil(); + List imports = nil(); + List exports = nil(); for (Line line : b.getStatements()) { var expr = line.getExpression(); // Documentation found among imports/exports or at the top of the module (if it starts with imports) is // placed in `bindings` by AstToIr. while (expr instanceof Tree.Documented doc) { - IR$Module$Scope$Definition c; + Definition c; try { c = translateComment(doc, doc.getDocumentation()); } catch (SyntaxException ex) { @@ -154,11 +176,11 @@ IR.Module translateModule(Tree module) { default -> bindings = translateModuleSymbol(expr, bindings); } } - yield new IR.Module(imports.reverse(), exports.reverse(), bindings.reverse(), getIdentifiedLocation(module), meta(), diag()); + yield new Module(imports.reverse(), exports.reverse(), bindings.reverse(), getIdentifiedLocation(module), meta(), diag()); } - default -> new IR.Module( + default -> new Module( nil(), nil(), - cons(translateSyntaxError(module, new IR$Error$Syntax$UnsupportedSyntax("translateModule")), nil()), + cons(translateSyntaxError(module, new Syntax.UnsupportedSyntax("translateModule")), nil()), getIdentifiedLocation(module), meta(), diag() ); }; @@ -171,7 +193,7 @@ IR.Module translateModule(Tree module) { * @param appendTo list of already collected definitions * @return the [[IR]] representation of `inputAST` appended */ - List translateModuleSymbol(Tree inputAst, List appendTo) { + List translateModuleSymbol(Tree inputAst, List appendTo) { try { return translateModuleSymbolImpl(inputAst, appendTo); } catch (SyntaxException ex) { @@ -179,7 +201,7 @@ IR.Module translateModule(Tree module) { } } - private List translateModuleSymbolImpl(Tree inputAst, List appendTo) throws SyntaxException { + private List translateModuleSymbolImpl(Tree inputAst, List appendTo) throws SyntaxException { return switch (inputAst) { case null -> appendTo; @@ -189,8 +211,8 @@ IR.Module translateModule(Tree module) { for (var line : def.getBody()) { irBody = translateTypeBodyExpression(line.getExpression(), irBody); } - List args = translateArgumentsDefinition(def.getParams()); - var type = new IR$Module$Scope$Definition$SugaredType( + List args = translateArgumentsDefinition(def.getParams()); + var type = new Definition.SugaredType( typeName, args, irBody.reverse(), @@ -206,10 +228,10 @@ IR.Module translateModule(Tree module) { var body = translateExpression(fn.getBody()); if (body == null) { - var error = translateSyntaxError(inputAst, new IR$Error$Syntax$UnsupportedSyntax("Block without body")); + var error = translateSyntaxError(inputAst, new Syntax.UnsupportedSyntax("Block without body")); yield cons(error, appendTo); } - var binding = new IR$Module$Scope$Definition$Method$Binding( + var binding = new Method.Binding( methodRef, args, body, @@ -222,31 +244,31 @@ IR.Module translateModule(Tree module) { case Tree.ForeignFunction fn when fn.getBody() instanceof Tree.TextLiteral body -> { var name = fn.getName(); var nameLoc = getIdentifiedLocation(name); - var methodRef = new IR$Name$MethodReference(Option.empty(), buildName(name), nameLoc, meta(), diag()); + var methodRef = new Name.MethodReference(Option.empty(), buildName(name), nameLoc, meta(), diag()); var args = translateArgumentsDefinition(fn.getArgs()); var languageName = fn.getLanguage().codeRepr(); var language = languageName; if (language == null) { var message = "Language '" + languageName + "' is not a supported polyglot language."; - var error = translateSyntaxError(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message)); + var error = translateSyntaxError(inputAst, new Syntax.InvalidForeignDefinition(message)); yield cons(error, appendTo); } var text = buildTextConstant(body, body.getElements()); - var def = new IR$Foreign$Definition(language, text, getIdentifiedLocation(fn.getBody()), meta(), diag()); - var binding = new IR$Module$Scope$Definition$Method$Binding( + var def = new Foreign.Definition(language, text, getIdentifiedLocation(fn.getBody()), meta(), diag()); + var binding = new Method.Binding( methodRef, args, def, getIdentifiedLocation(inputAst), meta(), diag() ); yield cons(binding, appendTo); } case Tree.AnnotatedBuiltin anno -> { - var annotation = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); + var annotation = new Name.BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); yield translateModuleSymbol(anno.getExpression(), cons(annotation, appendTo)); } case Tree.Annotated anno -> { var annotationArgument = translateExpression(anno.getArgument()); - var annotation = new IR$Name$GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag()); + var annotation = new Name.GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag()); yield translateModuleSymbol(anno.getExpression(), cons(annotation, appendTo)); } @@ -262,7 +284,7 @@ methodRef, args, def, getIdentifiedLocation(inputAst), meta(), diag() throw new NullPointerException(); } var aLoc = expandToContain(getIdentifiedLocation(a.getExpr()), body.location()); - var binding = new IR$Module$Scope$Definition$Method$Binding( + var binding = new Method.Binding( reference, nil(), body.setLocation(aLoc), @@ -275,19 +297,19 @@ methodRef, args, def, getIdentifiedLocation(inputAst), meta(), diag() case Tree.TypeSignature sig -> { var methodReference = translateMethodReference(sig.getVariable(), true); var signature = translateType(sig.getType(), false); - var ascription = new IR$Type$Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); + var ascription = new Type.Ascription(methodReference, signature, getIdentifiedLocation(sig), meta(), diag()); yield cons(ascription, appendTo); } default -> { - var error = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + var error = translateSyntaxError(inputAst, Syntax.UnexpectedExpression$.MODULE$); yield cons(error, appendTo); } }; } - private List translateArgumentsDefinition(java.util.List args) throws SyntaxException { - List res = nil(); + private List translateArgumentsDefinition(java.util.List args) throws SyntaxException { + List res = nil(); for (var p : args) { var d = translateArgumentDefinition(p); res = cons(d, res); @@ -298,9 +320,9 @@ private List translateArgumentsDefinition(java.util.List< IR translateConstructorDefinition(Tree.ConstructorDefinition cons, Tree inputAst) { try { var constructorName = buildName(inputAst, cons.getConstructor()); - List args = translateArgumentsDefinition(cons.getArguments()); + List args = translateArgumentsDefinition(cons.getArguments()); var cAt = getIdentifiedLocation(inputAst); - return new IR$Module$Scope$Definition$Data(constructorName, args, nil(), cAt, meta(), diag()); + return new Definition.Data(constructorName, args, nil(), cAt, meta(), diag()); } catch (SyntaxException ex) { return ex.toError(); } @@ -329,7 +351,7 @@ private List translateTypeBodyExpressionImpl(Tree exp, List appendTo) th case Tree.ConstructorDefinition cons -> cons(translateConstructorDefinition(cons, inputAst), appendTo); case Tree.TypeDef def -> { - var ir = translateSyntaxError(def, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$); + var ir = translateSyntaxError(def, Syntax.UnexpectedDeclarationInType$.MODULE$); yield cons(ir, appendTo); } @@ -346,7 +368,7 @@ private List translateTypeBodyExpressionImpl(Tree exp, List appendTo) th } case Tree.Function fun -> { - IR.Name name; + Name name; if (fun.getName() instanceof Tree.Ident ident) { var isMethod = ident.getToken().isOperatorLexically(); name = buildName(getIdentifiedLocation(fun.getName()), ident.getToken(), isMethod); @@ -373,12 +395,12 @@ private List translateTypeBodyExpressionImpl(Tree exp, List appendTo) th var language = languageName; if (language == null) { var message = "Language '" + languageName + "' is not a supported polyglot language."; - var error = translateSyntaxError(inputAst, new IR$Error$Syntax$InvalidForeignDefinition(message)); + var error = translateSyntaxError(inputAst, new Syntax.InvalidForeignDefinition(message)); yield cons(error, appendTo); } var text = buildTextConstant(body, body.getElements()); - var def = new IR$Foreign$Definition(language, text, getIdentifiedLocation(fn.getBody()), meta(), diag()); - var binding = new IR$Function$Binding(name, args, def, getIdentifiedLocation(fn), true, meta(), diag()); + var def = new Foreign.Definition(language, text, getIdentifiedLocation(fn.getBody()), meta(), diag()); + var binding = new Function.Binding(name, args, def, getIdentifiedLocation(fn), true, meta(), diag()); yield cons(binding, appendTo); } case Tree.Documented doc -> { @@ -387,32 +409,32 @@ private List translateTypeBodyExpressionImpl(Tree exp, List appendTo) th } case Tree.AnnotatedBuiltin anno -> { - var ir = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); + var ir = new Name.BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); var annotation = translateAnnotation(ir, anno.getExpression(), nil()); yield cons(annotation, appendTo); } case Tree.Annotated anno -> { var annotationArgument = translateExpression(anno.getArgument()); - var annotation = new IR$Name$GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag()); + var annotation = new Name.GenericAnnotation(anno.getAnnotation().codeRepr(), annotationArgument, getIdentifiedLocation(anno), meta(), diag()); yield translateTypeBodyExpression(anno.getExpression(), cons(annotation, appendTo)); } default -> { - var ir = translateSyntaxError(inputAst, IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$); + var ir = translateSyntaxError(inputAst, Syntax.UnexpectedDeclarationInType$.MODULE$); yield cons(ir, appendTo); } }; } @SuppressWarnings("unchecked") - private IR.Application translateTypeApplication(Tree.App app) throws SyntaxException { - List args = nil(); + private Application translateTypeApplication(Tree.App app) throws SyntaxException { + List args = nil(); Tree t = app; - IR$Name$Literal in = null; + Name.Literal in = null; while (t instanceof Tree.App tApp) { var typeArg = translateTypeCallArgument(tApp.getArg()); - if (typeArg.value() instanceof IR$Name$Literal l && "in".equals(l.name())) { + if (typeArg.value() instanceof Name.Literal l && "in".equals(l.name())) { in = l.copy( l.copy$default$1(), true, @@ -432,30 +454,30 @@ private IR.Application translateTypeApplication(Tree.App app) throws SyntaxExcep case 1 -> fullQualifiedNames.head(); default -> { var name = fullQualifiedNames.head(); - name = new IR$Name$Literal(name.name(), true, name.location(), name.passData(), name.diagnostics()); - List tail = (List)fullQualifiedNames.tail(); + name = new Name.Literal(name.name(), true, name.location(), name.passData(), name.diagnostics()); + List tail = (List)fullQualifiedNames.tail(); tail = tail.reverse(); final Option loc = getIdentifiedLocation(app); - IR.Name arg; + Name arg; if (segments == 2) { arg = tail.head(); } else { - arg = new IR$Name$Qualified(tail, loc, meta(), diag()); + arg = new Name.Qualified(tail, loc, meta(), diag()); } - var ca = new IR$CallArgument$Specified(Option.empty(), arg, loc, meta(), diag()); + var ca = new CallArgument.Specified(Option.empty(), arg, loc, meta(), diag()); args = cons(ca, args); yield name; } }; if (in == null) { - return new IR$Application$Prefix(type, args, false, getIdentifiedLocation(app), meta(), diag()); + return new Application.Prefix(type, args, false, getIdentifiedLocation(app), meta(), diag()); } else { - var fn = new IR$CallArgument$Specified(Option.empty(), type, getIdentifiedLocation(app), meta(), diag()); - return new IR$Application$Operator$Binary(fn, in, args.head(), getIdentifiedLocation(app), meta(), diag()); + var fn = new CallArgument.Specified(Option.empty(), type, getIdentifiedLocation(app), meta(), diag()); + return new Operator.Binary(fn, in, args.head(), getIdentifiedLocation(app), meta(), diag()); } } - private IR.Expression translateFunction(Tree fun, IR.Name name, java.util.List arguments, final Tree treeBody) { - List args; + private Expression translateFunction(Tree fun, Name name, java.util.List arguments, final Tree treeBody) { + List args; try { args = translateArgumentsDefinition(arguments); } catch (SyntaxException ex) { @@ -463,7 +485,7 @@ private IR.Expression translateFunction(Tree fun, IR.Name name, java.util.List type; + Name.MethodReference translateMethodReference(Tree sig, boolean alwaysLocation) throws SyntaxException { + Name method; + Option type; Option loc; switch (sig) { case Tree.Ident id -> { @@ -523,13 +545,13 @@ private IR.Expression translateFunction(Tree fun, IR.Name name, java.util.List throw translateEntity(sig, "translateMethodReference"); } - return new IR$Name$MethodReference(type, method, + return new Name.MethodReference(type, method, loc, meta(), diag() ); } - private IR.Expression translateCall(Tree ast) { - var args = new java.util.ArrayList(); + private Expression translateCall(Tree ast) { + var args = new java.util.ArrayList(); var hasDefaultsSuspended = false; var tree = ast; for (;;) { @@ -541,24 +563,24 @@ private IR.Expression translateCall(Tree ast) { case Tree.App app -> { var expr = translateExpression(app.getArg(), false); var loc = getIdentifiedLocation(app.getArg()); - args.add(new IR$CallArgument$Specified(Option.empty(), expr, loc, meta(), diag())); + args.add(new CallArgument.Specified(Option.empty(), expr, loc, meta(), diag())); tree = app.getFunc(); } case Tree.NamedApp app -> { var expr = translateExpression(app.getArg(), false); var loc = getIdentifiedLocation(app.getArg()); var id = buildName(app, app.getName()); - args.add(new IR$CallArgument$Specified(Option.apply(id), expr, loc, meta(), diag())); + args.add(new CallArgument.Specified(Option.apply(id), expr, loc, meta(), diag())); tree = app.getFunc(); } case Tree.DefaultApp app -> { var loc = getIdentifiedLocation(app.getDefault()); var expr = buildName(app.getDefault()); - args.add(new IR$CallArgument$Specified(Option.empty(), expr, loc, meta(), diag())); + args.add(new CallArgument.Specified(Option.empty(), expr, loc, meta(), diag())); tree = app.getFunc(); } default -> { - IR.Expression func; + Expression func; if (tree instanceof Tree.OprApp oprApp && oprApp.getOpr().getRight() != null && ".".equals(oprApp.getOpr().getRight().codeRepr()) @@ -570,7 +592,7 @@ private IR.Expression translateCall(Tree ast) { if (oprApp.getLhs() != null) { var self = translateExpression(oprApp.getLhs(), false); var loc = getIdentifiedLocation(oprApp.getLhs()); - args.add(new IR$CallArgument$Specified(Option.empty(), self, loc, meta(), diag())); + args.add(new CallArgument.Specified(Option.empty(), self, loc, meta(), diag())); } } else if (args.isEmpty()) { return null; @@ -579,7 +601,7 @@ private IR.Expression translateCall(Tree ast) { } java.util.Collections.reverse(args); var argsList = CollectionConverters.asScala(args.iterator()).toList(); - return new IR$Application$Prefix( + return new Application.Prefix( func, argsList, hasDefaultsSuspended, getIdentifiedLocation(ast), @@ -591,10 +613,10 @@ private IR.Expression translateCall(Tree ast) { } } - private IR.Name translateOldStyleLambdaArgumentName(Tree arg, boolean[] suspended, IR.Expression[] defaultValue) throws SyntaxException { + private Name translateOldStyleLambdaArgumentName(Tree arg, boolean[] suspended, Expression[] defaultValue) throws SyntaxException { return switch (arg) { case Tree.Group g -> translateOldStyleLambdaArgumentName(g.getBody(), suspended, defaultValue); - case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild.getToken()), meta(), diag()); + case Tree.Wildcard wild -> new Name.Blank(getIdentifiedLocation(wild.getToken()), meta(), diag()); case Tree.OprApp app when "=".equals(app.getOpr().getRight().codeRepr()) -> { if (defaultValue != null) { defaultValue[0] = translateExpression(app.getRhs(), false); @@ -602,9 +624,9 @@ private IR.Name translateOldStyleLambdaArgumentName(Tree arg, boolean[] suspende yield translateOldStyleLambdaArgumentName(app.getLhs(), suspended, null); } case Tree.Ident id -> { - IR.Expression identifier = translateIdent(id, false); + Expression identifier = translateIdent(id, false); yield switch (identifier) { - case IR.Name name_ -> name_; + case Name name_ -> name_; default -> throw translateEntity(id, "translateOldStyleLambdaArgumentName"); }; } @@ -623,10 +645,10 @@ yield switch (identifier) { * @param tree the expression to be translated * @return the {@link IR} representation of `tree` */ - IR.Expression translateExpression(Tree tree) { + Expression translateExpression(Tree tree) { return translateExpression(tree, false); } - IR.Expression translateExpression(Tree tree, boolean isMethod) { + Expression translateExpression(Tree tree, boolean isMethod) { try { return translateExpressionImpl(tree, isMethod); } catch (SyntaxException ex) { @@ -634,7 +656,7 @@ IR.Expression translateExpression(Tree tree, boolean isMethod) { } } - private IR.Expression translateExpressionImpl(Tree tree, boolean isMethod) throws SyntaxException { + private Expression translateExpressionImpl(Tree tree, boolean isMethod) throws SyntaxException { if (tree == null) { return null; } @@ -650,11 +672,11 @@ private IR.Expression translateExpressionImpl(Tree tree, boolean isMethod) throw var arr = app.getOpr().getLeft().getOperators(); if (arr.size() > 0 && arr.get(0).codeRepr().equals("=")) { var errLoc = arr.size() > 1 ? getIdentifiedLocation(arr.get(1)) : at; - var err = translateSyntaxError(errLoc.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$); + var err = translateSyntaxError(errLoc.get(), Syntax.UnrecognizedToken$.MODULE$); var name = buildName(app.getLhs()); - yield new IR$Expression$Binding(name, err, at, meta(), diag()); + yield new Expression.Binding(name, err, at, meta(), diag()); } else { - yield translateSyntaxError(at.get(), IR$Error$Syntax$UnrecognizedToken$.MODULE$); + yield translateSyntaxError(at.get(), Syntax.UnrecognizedToken$.MODULE$); } } yield switch (op.codeRepr()) { @@ -671,16 +693,16 @@ yield switch (op.codeRepr()) { // Old-style lambdas; this syntax will be eliminated after the parser transition is complete. var arg = app.getLhs(); if (arg == null) { - yield translateSyntaxError(app, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + yield translateSyntaxError(app, Syntax.UnexpectedExpression$.MODULE$); } var isSuspended = new boolean[1]; if (arg instanceof Tree.UnaryOprApp susApp && "~".equals(susApp.getOpr().codeRepr())) { arg = susApp.getRhs(); isSuspended[0] = true; } - var defaultValue = new IR.Expression[1]; - IR.Name name = translateOldStyleLambdaArgumentName(arg, isSuspended, defaultValue); - var arg_ = new IR$DefinitionArgument$Specified( + var defaultValue = new Expression[1]; + Name name = translateOldStyleLambdaArgumentName(arg, isSuspended, defaultValue); + var arg_ = new DefinitionArgument.Specified( name, Option.empty(), Option.apply(defaultValue[0]), @@ -689,53 +711,53 @@ yield switch (op.codeRepr()) { meta(), diag() ); - List args = cons(arg_, nil()); + List args = cons(arg_, nil()); var body = translateExpression(app.getRhs(), false); if (body == null) { - body = new IR$Expression$Block( - nil(), new IR$Name$Blank(Option.empty(), meta(), diag()), + body = new Expression.Block( + nil(), new Name.Blank(Option.empty(), meta(), diag()), Option.empty(), true, meta(), diag() ); } var at = expandToContain(switch (body) { - case IR$Expression$Block __ -> getIdentifiedLocation(tree, 0, 1, null); + case Expression.Block __ -> getIdentifiedLocation(tree, 0, 1, null); default -> getIdentifiedLocation(tree); }, body.location()); - yield new IR$Function$Lambda(args, body, at, true, meta(), diag()); + yield new Function.Lambda(args, body, at, true, meta(), diag()); } default -> { var lhs = unnamedCallArgument(app.getLhs()); var rhs = unnamedCallArgument(app.getRhs()); - var name = new IR$Name$Literal( + var name = new Name.Literal( op.codeRepr(), true, getIdentifiedLocation(op), meta(), diag() ); var loc = getIdentifiedLocation(app); if (lhs == null && rhs == null) { - yield new IR$Application$Operator$Section$Sides(name, loc, meta(), diag()); + yield new Section.Sides(name, loc, meta(), diag()); } else if (lhs == null) { - yield new IR$Application$Operator$Section$Right(name, rhs, loc, meta(), diag()); + yield new Section.Right(name, rhs, loc, meta(), diag()); } else if (rhs == null) { - yield new IR$Application$Operator$Section$Left(lhs, name, loc, meta(), diag()); + yield new Section.Left(lhs, name, loc, meta(), diag()); } else { - yield new IR$Application$Operator$Binary(lhs, name, rhs, loc,meta(), diag()); + yield new Operator.Binary(lhs, name, rhs, loc,meta(), diag()); } } }; } case Tree.Array arr -> { - List items = nil(); + List items = nil(); if (arr.getFirst() != null) { var exp = translateExpression(arr.getFirst(), false); items = cons(exp, items); for (var next : arr.getRest()) { exp = translateExpression(next.getBody(), false); if (exp == null) { - yield translateSyntaxError(arr, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + yield translateSyntaxError(arr, Syntax.UnexpectedExpression$.MODULE$); } items = cons(exp, items); } } - yield new IR$Application$Literal$Sequence( + yield new Application.Sequence( items.reverse(), getIdentifiedLocation(arr), meta(), diag() ); @@ -745,7 +767,7 @@ yield switch (op.codeRepr()) { case Tree.MultiSegmentApp app -> { var fnName = new StringBuilder(); var sep = ""; - List args = nil(); + List args = nil(); for (var seg : app.getSegments()) { var id = seg.getHeader().codeRepr(); fnName.append(sep); @@ -764,15 +786,15 @@ yield switch (op.codeRepr()) { var subexpression = Objects.requireNonNullElse(applySkip(body), body); yield translateExpression(subexpression, false); } - var fn = new IR$Name$Literal(fullName, true, Option.empty(), meta(), diag()); + var fn = new Name.Literal(fullName, true, Option.empty(), meta(), diag()); if (!checkArgs(args)) { - yield translateSyntaxError(app, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + yield translateSyntaxError(app, Syntax.UnexpectedExpression$.MODULE$); } - yield new IR$Application$Prefix(fn, args.reverse(), false, getIdentifiedLocation(tree), meta(), diag()); + yield new Application.Prefix(fn, args.reverse(), false, getIdentifiedLocation(tree), meta(), diag()); } case Tree.BodyBlock body -> { - var expressions = new java.util.ArrayList(); - IR.Expression last = null; + var expressions = new java.util.ArrayList(); + Expression last = null; for (var line : body.getStatements()) { Tree expr = line.getExpression(); if (expr == null) { @@ -802,19 +824,19 @@ yield switch (op.codeRepr()) { var id = new IdentifiedLocation(patched, last.location().get().id()); last = last.setLocation(Option.apply(id)); } - yield new IR$Expression$Block(list, last, locationWithANewLine, false, meta(), diag()); + yield new Expression.Block(list, last, locationWithANewLine, false, meta(), diag()); } case Tree.Assignment assign -> { var name = buildNameOrQualifiedName(assign.getPattern()); var expr = translateExpression(assign.getExpr(), false); if (expr == null) { - expr = translateSyntaxError(assign, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + expr = translateSyntaxError(assign, Syntax.UnexpectedExpression$.MODULE$); } - yield new IR$Expression$Binding(name, expr, getIdentifiedLocation(tree), meta(), diag()); + yield new Expression.Binding(name, expr, getIdentifiedLocation(tree), meta(), diag()); } case Tree.ArgumentBlockApplication body -> { - List expressions = nil(); - IR.Expression last = null; + List expressions = nil(); + Expression last = null; for (var line : body.getArguments()) { final Tree expr = line.getExpression(); if (expr == null) { @@ -826,12 +848,12 @@ yield switch (op.codeRepr()) { last = translateExpression(expr, false); } if (last == null) { - last = new IR$Name$Blank(Option.empty(), meta(), diag()); + last = new Name.Blank(Option.empty(), meta(), diag()); } - var block = new IR$Expression$Block(expressions.reverse(), last, getIdentifiedLocation(body), false, meta(), diag()); + var block = new Expression.Block(expressions.reverse(), last, getIdentifiedLocation(body), false, meta(), diag()); if (body.getLhs() != null) { var fn = translateExpression(body.getLhs(), isMethod); - List args = nil(); + List args = nil(); for (var line : body.getArguments()) { var expr = line.getExpression(); if (expr instanceof Tree.Ident) { @@ -840,7 +862,7 @@ yield switch (op.codeRepr()) { } } yield switch (fn) { - case IR$Application$Prefix pref -> patchPrefixWithBlock(pref, block, args); + case Application.Prefix pref -> patchPrefixWithBlock(pref, block, args); default -> block; }; } else { @@ -850,12 +872,12 @@ yield switch (fn) { case Tree.TypeAnnotated anno -> translateTypeAnnotated(anno); case Tree.Group group -> { yield switch (translateExpression(group.getBody(), false)) { - case null -> translateSyntaxError(group, IR$Error$Syntax$EmptyParentheses$.MODULE$); - case IR$Application$Prefix pref -> { + case null -> translateSyntaxError(group, Syntax.EmptyParentheses$.MODULE$); + case Application.Prefix pref -> { final Option groupWithoutParenthesis = getIdentifiedLocation(group, 1, -1, pref.getExternalId()); yield pref.setLocation(groupWithoutParenthesis); } - case IR.Expression in -> in; + case Expression in -> in; }; } case Tree.TextLiteral txt -> { @@ -867,7 +889,7 @@ yield switch (translateExpression(group.getBody(), false)) { } case Tree.CaseOf cas -> { var expr = translateExpression(cas.getExpression(), false); - List branches = nil(); + List branches = nil(); for (var line : cas.getCases()) { if (line.getCase() == null) { continue; @@ -876,10 +898,10 @@ yield switch (translateExpression(group.getBody(), false)) { if (branch.getDocumentation() != null) { var comment = translateComment(cas, branch.getDocumentation()); var loc = getIdentifiedLocation(cas); - var doc = new IR$Pattern$Documentation(comment.doc(), loc, meta(), diag()); - var br= new IR$Case$Branch( + var doc = new Pattern.Documentation(comment.doc(), loc, meta(), diag()); + var br= new Case.Branch( doc, - new IR.Empty(Option.empty(), meta(), diag()), + new Empty(Option.empty(), meta(), diag()), loc, meta(), diag() ); branches = cons(br, branches); @@ -887,7 +909,7 @@ loc, meta(), diag() // A branch with no expression is used to hold any orphaned documentation at the end of the case-of // expression, with no case to attach it to. if (branch.getExpression() != null) { - var br = new IR$Case$Branch( + var br = new Case.Branch( translatePattern(branch.getPattern()), translateExpression(branch.getExpression(), false), getIdentifiedLocation(branch.getExpression()), meta(), diag() @@ -895,7 +917,7 @@ loc, meta(), diag() branches = cons(br, branches); } } - yield new IR$Case$Expr(expr, branches.reverse(), getIdentifiedLocation(tree), meta(), diag()); + yield new Case.Expr(expr, branches.reverse(), getIdentifiedLocation(tree), meta(), diag()); } case Tree.Function fun -> { var name = buildName(fun.getName()); @@ -904,7 +926,7 @@ loc, meta(), diag() case Tree.OprSectionBoundary bound -> translateExpression(bound.getAst(), false); case Tree.UnaryOprApp un when "-".equals(un.getOpr().codeRepr()) -> switch (translateExpression(un.getRhs(), false)) { - case IR$Literal$Number n -> n.copy( + case Literal.Number n -> n.copy( n.copy$default$1(), "-" + n.copy$default$2(), n.copy$default$3(), @@ -912,15 +934,15 @@ loc, meta(), diag() n.copy$default$5(), n.copy$default$6() ); - case IR.Expression expr -> { - var negate = new IR$Name$Literal("negate", true, Option.empty(), meta(), diag()); - var arg = new IR$CallArgument$Specified(Option.empty(), expr, expr.location(), meta(), diag()); - yield new IR$Application$Prefix(negate, cons(arg, nil()), false, expr.location(), meta(), diag()); + case Expression expr -> { + var negate = new Name.Literal("negate", true, Option.empty(), meta(), diag()); + var arg = new CallArgument.Specified(Option.empty(), expr, expr.location(), meta(), diag()); + yield new Application.Prefix(negate, cons(arg, nil()), false, expr.location(), meta(), diag()); } }; case Tree.TypeSignature sig -> { var methodName = buildName(sig.getVariable()); - var methodReference = new IR$CallArgument$Specified( + var methodReference = new CallArgument.Specified( Option.empty(), methodName, methodName.location(), @@ -928,12 +950,12 @@ loc, meta(), diag() ); var opName = buildName(Option.empty(), sig.getOperator(), true); var signature = translateTypeCallArgument(sig.getType()); - yield new IR$Application$Operator$Binary(methodReference, opName, signature, getIdentifiedLocation(sig), meta(), diag()); + yield new Operator.Binary(methodReference, opName, signature, getIdentifiedLocation(sig), meta(), diag()); } case Tree.TemplateFunction templ -> translateExpression(templ.getAst(), false); - case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild), meta(), diag()); + case Tree.Wildcard wild -> new Name.Blank(getIdentifiedLocation(wild), meta(), diag()); case Tree.AnnotatedBuiltin anno -> { - var ir = new IR$Name$BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); + var ir = new Name.BuiltinAnnotation("@" + anno.getAnnotation().codeRepr(), getIdentifiedLocation(anno), meta(), diag()); yield translateAnnotation(ir, anno.getExpression(), nil()); } // Documentation can be attached to an expression in a few cases, like if someone documents a line of an @@ -943,13 +965,13 @@ loc, meta(), diag() var fn = translateExpression(app.getFunc(), isMethod); var loc = getIdentifiedLocation(app); if (app.getArg() instanceof Tree.AutoScope) { - yield new IR$Application$Prefix(fn, nil(), true, loc, meta(), diag()); + yield new Application.Prefix(fn, nil(), true, loc, meta(), diag()); } else { yield fn.setLocation(loc); } } - case Tree.Invalid __ -> translateSyntaxError(tree, IR$Error$Syntax$UnexpectedExpression$.MODULE$); - default -> translateSyntaxError(tree, new IR$Error$Syntax$UnsupportedSyntax("translateExpression")); + case Tree.Invalid __ -> translateSyntaxError(tree, Syntax.UnexpectedExpression$.MODULE$); + default -> translateSyntaxError(tree, new Syntax.UnsupportedSyntax("translateExpression")); }; } @@ -1020,7 +1042,7 @@ boolean isApplication(Tree tree) { // The `insideTypeAscription` argument replicates an AstToIr quirk. Once the parser // transition is complete, we should eliminate it, keeping only the `false` branches. - IR.Expression translateType(Tree tree, boolean insideTypeAscription) { + Expression translateType(Tree tree, boolean insideTypeAscription) { return switch (tree) { case null -> null; case Tree.App app -> { @@ -1033,7 +1055,7 @@ IR.Expression translateType(Tree tree, boolean insideTypeAscription) { case Tree.OprApp app -> { var op = app.getOpr().getRight(); if (op == null) { - yield translateSyntaxError(app, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + yield translateSyntaxError(app, Syntax.UnexpectedExpression$.MODULE$); } yield switch (op.codeRepr()) { case "." -> { @@ -1048,32 +1070,32 @@ yield switch (op.codeRepr()) { var literal = translateType(app.getLhs(), insideTypeAscription); var body = translateType(app.getRhs(), insideTypeAscription); if (body == null) { - yield new IR$Error$Syntax(getIdentifiedLocation(app).get(), IR$Error$Syntax$UnexpectedExpression$.MODULE$, meta(), diag()); + yield new Syntax(getIdentifiedLocation(app).get(), Syntax.UnexpectedExpression$.MODULE$, meta(), diag()); } var args = switch (body) { - case IR$Type$Function fn -> { + case Type.Function fn -> { body = fn.result(); yield cons(literal, fn.args()); } default -> cons(literal, nil()); }; - yield new IR$Type$Function(args, body, Option.empty(), meta(), diag()); + yield new Type.Function(args, body, Option.empty(), meta(), diag()); } default -> { var lhs = translateTypeCallArgument(app.getLhs()); var rhs = translateTypeCallArgument(app.getRhs()); - var name = new IR$Name$Literal( + var name = new Name.Literal( op.codeRepr(), true, getIdentifiedLocation(app), meta(), diag() ); var loc = getIdentifiedLocation(app); - yield new IR$Application$Operator$Binary(lhs, name, rhs, loc, meta(), diag()); + yield new Operator.Binary(lhs, name, rhs, loc, meta(), diag()); } }; } case Tree.Array arr -> { - List items = nil(); + List items = nil(); if (arr.getFirst() != null) { var exp = translateType(arr.getFirst(), false); items = cons(exp, items); @@ -1082,7 +1104,7 @@ yield switch (op.codeRepr()) { items = cons(exp, items); } } - yield new IR$Application$Literal$Sequence( + yield new Application.Literal.Sequence( items.reverse(), getIdentifiedLocation(arr), meta(), diag() ); @@ -1097,16 +1119,16 @@ yield switch (op.codeRepr()) { case Tree.Ident id -> buildName(getIdentifiedLocation(id), id.getToken(), false); case Tree.Group group -> translateType(group.getBody(), insideTypeAscription); case Tree.UnaryOprApp un -> translateType(un.getRhs(), insideTypeAscription); - case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild), meta(), diag()); + case Tree.Wildcard wild -> new Name.Blank(getIdentifiedLocation(wild), meta(), diag()); case Tree.TypeAnnotated anno -> translateTypeAnnotated(anno); - default -> translateSyntaxError(tree, new IR$Error$Syntax$UnsupportedSyntax("translateType")); + default -> translateSyntaxError(tree, new Syntax.UnsupportedSyntax("translateType")); }; } - IR.Expression translateTypeAnnotated(Tree.TypeAnnotated anno) { + Expression translateTypeAnnotated(Tree.TypeAnnotated anno) { var type = translateTypeCallArgument(anno.getType()); var expr = translateCallArgument(anno.getExpression()); - var opName = new IR$Name$Literal(anno.getOperator().codeRepr(), true, Option.empty(), meta(), diag()); - return new IR$Application$Operator$Binary( + var opName = new Name.Literal(anno.getOperator().codeRepr(), true, Option.empty(), meta(), diag()); + return new Operator.Binary( expr, opName, type, @@ -1116,23 +1138,23 @@ IR.Expression translateTypeAnnotated(Tree.TypeAnnotated anno) { } @SuppressWarnings("unchecked") - private IR.Expression patchPrefixWithBlock(IR$Application$Prefix pref, IR$Expression$Block block, List args) { - if (block.expressions().isEmpty() && block.returnValue() instanceof IR$Name$Blank) { + private Expression patchPrefixWithBlock(Application.Prefix pref, Expression.Block block, List args) { + if (block.expressions().isEmpty() && block.returnValue() instanceof Name.Blank) { return pref; } if (args.nonEmpty() && args.head() == null) { - args = (List) args.tail(); + args = (List) args.tail(); } - List allArgs = (List) pref.arguments().appendedAll(args.reverse()); - final IR$CallArgument$Specified blockArg = new IR$CallArgument$Specified(Option.empty(), block, block.location(), meta(), diag()); - List withBlockArgs = (List) allArgs.appended(blockArg); + List allArgs = (List) pref.arguments().appendedAll(args.reverse()); + final CallArgument.Specified blockArg = new CallArgument.Specified(Option.empty(), block, block.location(), meta(), diag()); + List withBlockArgs = (List) allArgs.appended(blockArg); if (!checkArgs(withBlockArgs)) { - return translateSyntaxError(pref.location().get(), IR$Error$Syntax$UnexpectedExpression$.MODULE$); + return translateSyntaxError(pref.location().get(), Syntax.UnexpectedExpression$.MODULE$); } - return new IR$Application$Prefix(pref.function(), withBlockArgs, pref.hasDefaultsSuspended(), pref.location(), meta(), diag()); + return new Application.Prefix(pref.function(), withBlockArgs, pref.hasDefaultsSuspended(), pref.location(), meta(), diag()); } - private IR$Application$Prefix translateAnnotation(IR$Name$BuiltinAnnotation ir, Tree expr, List callArgs) { + private Application.Prefix translateAnnotation(Name.BuiltinAnnotation ir, Tree expr, List callArgs) { return switch (expr) { case Tree.App fn -> { var fnAsArg = translateCallArgument(fn.getArg()); @@ -1149,7 +1171,7 @@ private IR.Expression patchPrefixWithBlock(IR$Application$Prefix pref, IR$Expres yield translateAnnotation(ir, null, callArgs); } case null -> { - yield new IR$Application$Prefix(ir, callArgs, false, ir.location(), meta(), diag()); + yield new Application.Prefix(ir, callArgs, false, ir.location(), meta(), diag()); } default -> { var arg = translateCallArgument(expr); @@ -1159,7 +1181,7 @@ private IR.Expression patchPrefixWithBlock(IR$Application$Prefix pref, IR$Expres }; } - IR.Expression translateNumber(Tree.Number ast) { + Expression translateNumber(Tree.Number ast) { var intPart = ast.getInteger(); final Option base = switch (intPart.getBase()) { case Base.Binary b -> Option.apply("2"); @@ -1170,22 +1192,22 @@ IR.Expression translateNumber(Tree.Number ast) { }; var fracPart = ast.getFractionalDigits(); String literal = fracPart != null ? intPart.codeRepr() + "." + fracPart.getDigits().codeRepr() : intPart.codeRepr(); - return new IR$Literal$Number(base, literal, getIdentifiedLocation(ast), meta(), diag()); + return new Literal.Number(base, literal, getIdentifiedLocation(ast), meta(), diag()); } - IR.Literal translateLiteral(Tree.TextLiteral txt) throws SyntaxException { + Literal translateLiteral(Tree.TextLiteral txt) throws SyntaxException { if (txt.getClose() == null) { if (txt.getOpen() == null || switch (txt.getOpen().codeRepr()) { case "'''" -> false; case "\"\"\"" -> false; default -> true; }) { - throw new SyntaxException(txt, IR$Error$Syntax$UnclosedTextLiteral$.MODULE$); + throw new SyntaxException(txt, Syntax.UnclosedTextLiteral$.MODULE$); } } // Splices are not yet supported in the IR. var value = buildTextConstant(txt, txt.getElements()); - return new IR$Literal$Text(value, getIdentifiedLocation(txt), meta(), diag()); + return new Literal.Text(value, getIdentifiedLocation(txt), meta(), diag()); } private String buildTextConstant(Tree at, Iterable elements) throws SyntaxException { @@ -1207,7 +1229,7 @@ private String buildTextConstant(Tree at, Iterable elements) throws } } if (error != null) { - throw translateEntity(at, IR$Error$Syntax$InvalidEscapeSequence$.MODULE$.apply(sb.toString())); + throw translateEntity(at, new Syntax.InvalidEscapeSequence(sb.toString())); } return sb.toString(); } @@ -1218,14 +1240,14 @@ private String buildTextConstant(Tree at, Iterable elements) throws * @param def the argument to translate * @return the [[IR]] representation of `arg` */ - IR.DefinitionArgument translateArgumentDefinition(ArgumentDefinition def) throws SyntaxException { + DefinitionArgument translateArgumentDefinition(ArgumentDefinition def) throws SyntaxException { Tree pattern = def.getPattern(); - IR.Name name = switch (pattern) { - case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild.getToken()), meta(), diag()); + Name name = switch (pattern) { + case Tree.Wildcard wild -> new Name.Blank(getIdentifiedLocation(wild.getToken()), meta(), diag()); case Tree.Ident id -> { - IR.Expression identifier = translateIdent(id, false); + Expression identifier = translateIdent(id, false); yield switch (identifier) { - case IR.Name name_ -> name_; + case Name name_ -> name_; // TODO: Other types of pattern. Needs IR support. default -> throw translateEntity(pattern, "translateArgumentDefinition"); }; @@ -1236,7 +1258,7 @@ yield switch (identifier) { boolean isSuspended = def.getSuspension() != null; var ascribedType = Option.apply(def.getType()).map(ascription -> translateType(ascription.getType(), true)); var defaultValue = Option.apply(def.getDefault()).map(default_ -> translateExpression(default_.getExpression(), false)); - return new IR$DefinitionArgument$Specified( + return new DefinitionArgument.Specified( name, ascribedType, defaultValue, @@ -1253,33 +1275,33 @@ yield switch (identifier) { * @param arg the argument to translate * @return the [[IR]] representation of `arg` */ - IR$CallArgument$Specified translateCallArgument(Tree arg) { + CallArgument.Specified translateCallArgument(Tree arg) { var loc = getIdentifiedLocation(arg); return switch (arg) { case Tree.NamedApp app -> { var expr = translateExpression(app.getArg(), false); var id = sanitizeName(buildName(app, app.getName())); - yield new IR$CallArgument$Specified(Option.apply(id), expr, loc, meta(), diag()); + yield new CallArgument.Specified(Option.apply(id), expr, loc, meta(), diag()); } case null -> null; default -> { var expr = translateExpression(arg, false); - yield new IR$CallArgument$Specified(Option.empty(), expr, loc, meta(), diag()); + yield new CallArgument.Specified(Option.empty(), expr, loc, meta(), diag()); } }; } - IR$CallArgument$Specified translateTypeCallArgument(Tree arg) { + CallArgument.Specified translateTypeCallArgument(Tree arg) { var loc = getIdentifiedLocation(arg); var expr = translateType(arg, false); - return new IR$CallArgument$Specified(Option.empty(), expr, loc, meta(), diag()); + return new CallArgument.Specified(Option.empty(), expr, loc, meta(), diag()); } - IR$CallArgument$Specified unnamedCallArgument(Tree arg) { + CallArgument.Specified unnamedCallArgument(Tree arg) { if (arg == null) { return null; } var loc = getIdentifiedLocation(arg); var expr = translateExpression(arg); - return new IR$CallArgument$Specified(Option.empty(), expr, loc, meta(), diag()); + return new CallArgument.Specified(Option.empty(), expr, loc, meta(), diag()); } /** Translates an arbitrary program identifier from its [[AST]] representation @@ -1288,11 +1310,11 @@ yield switch (identifier) { * @param identifier the identifier to translate * @return the [[IR]] representation of `identifier` */ - IR.Expression translateIdent(Tree identifier, boolean isMethod) { + Expression translateIdent(Tree identifier, boolean isMethod) { return switch (identifier) { case null -> null; case Tree.Ident id -> sanitizeName(buildName(getIdentifiedLocation(id), id.getToken(), isMethod)); - default -> translateSyntaxError(identifier, new IR$Error$Syntax$UnsupportedSyntax("translateIdent")); + default -> translateSyntaxError(identifier, new Syntax.UnsupportedSyntax("translateIdent")); }; } @@ -1302,31 +1324,31 @@ IR.Expression translateIdent(Tree identifier, boolean isMethod) { * @param block the case pattern to translate * @return */ - IR.Pattern translatePattern(Tree block) throws SyntaxException { + Pattern translatePattern(Tree block) throws SyntaxException { var pattern = maybeManyParensed(block); var elements = unrollApp(pattern); var fields = translatePatternFields(elements.subList(1, elements.size())); return switch (elements.get(0)) { case Tree.Ident id when id.getToken().isTypeOrConstructor() || !fields.isEmpty() -> { - yield new IR$Pattern$Constructor( + yield new Pattern.Constructor( sanitizeName(buildName(id)), fields, getIdentifiedLocation(id), meta(), diag() ); } - case Tree.Ident id -> new IR$Pattern$Name(buildName(id), getIdentifiedLocation(id), meta(), diag()); + case Tree.Ident id -> new Pattern.Name(buildName(id), getIdentifiedLocation(id), meta(), diag()); case Tree.OprApp app when ".".equals(app.getOpr().getRight().codeRepr()) -> { var qualifiedName = buildQualifiedName(app); - yield new IR$Pattern$Constructor( + yield new Pattern.Constructor( qualifiedName, fields, getIdentifiedLocation(app), meta(), diag() ); } case Tree.Wildcard wild -> translateWildcardPattern(wild); case Tree.TextLiteral lit -> - new IR$Pattern$Literal(translateLiteral(lit), getIdentifiedLocation(lit), meta(), diag()); + new Pattern.Literal(translateLiteral(lit), getIdentifiedLocation(lit), meta(), diag()); case Tree.Number num -> - new IR$Pattern$Literal((IR.Literal) translateNumber(num), getIdentifiedLocation(num), meta(), diag()); + new Pattern.Literal((Literal) translateNumber(num), getIdentifiedLocation(num), meta(), diag()); case Tree.UnaryOprApp num when num.getOpr().codeRepr().equals("-") -> { - var n = (IR$Literal$Number) translateExpression(num.getRhs()); + var n = (Literal.Number) translateExpression(num.getRhs()); var t = n.copy( n.copy$default$1(), "-" + n.copy$default$2(), @@ -1335,20 +1357,20 @@ qualifiedName, fields, getIdentifiedLocation(app), meta(), diag() n.copy$default$5(), n.copy$default$6() ); - yield new IR$Pattern$Literal(t, getIdentifiedLocation(num), meta(), diag()); + yield new Pattern.Literal(t, getIdentifiedLocation(num), meta(), diag()); } case Tree.TypeAnnotated anno -> { var type = buildNameOrQualifiedName(maybeManyParensed(anno.getType())); var expr = buildNameOrQualifiedName(maybeManyParensed(anno.getExpression())); - yield new IR$Pattern$Type(expr, type instanceof IR.Name ? (IR.Name) type : null, Option.empty(), meta(), diag()); + yield new Pattern.Type(expr, type instanceof Name ? (Name) type : null, Option.empty(), meta(), diag()); } case Tree.Group group -> translatePattern(group.getBody()); default -> throw translateEntity(pattern, "translatePattern"); }; } - private List translatePatternFields(java.util.List tail) throws SyntaxException { - List args = nil(); + private List translatePatternFields(java.util.List tail) throws SyntaxException { + List args = nil(); for (var t : tail) { var p = translatePattern(t); args = cons(p, args); @@ -1357,27 +1379,27 @@ private List translatePatternFields(java.util.List tail) throw return fields; } - private IR$Pattern$Name translateWildcardPattern(Tree.Wildcard wild) { + private Pattern.Name translateWildcardPattern(Tree.Wildcard wild) { var at = getIdentifiedLocation(wild); - var blank = new IR$Name$Blank(at, meta(), diag()); - return new IR$Pattern$Name(blank, at, meta(), diag()); + var blank = new Name.Blank(at, meta(), diag()); + return new Pattern.Name(blank, at, meta(), diag()); } - private IR$Name$Qualified buildQualifiedName(Tree t) throws SyntaxException { + private Name.Qualified buildQualifiedName(Tree t) throws SyntaxException { return buildQualifiedName(t, Option.empty(), false); } - private IR$Name$Qualified buildQualifiedName(Tree t, Option loc, boolean generateId) throws SyntaxException { - return new IR$Name$Qualified(qualifiedNameSegments(t, generateId), loc, meta(), diag()); + private Name.Qualified buildQualifiedName(Tree t, Option loc, boolean generateId) throws SyntaxException { + return new Name.Qualified(qualifiedNameSegments(t, generateId), loc, meta(), diag()); } - private IR.Name buildNameOrQualifiedName(Tree t) throws SyntaxException { + private Name buildNameOrQualifiedName(Tree t) throws SyntaxException { return buildNameOrQualifiedName(t, Option.empty()); } - private IR.Name buildNameOrQualifiedName(Tree t, Option loc) throws SyntaxException { + private Name buildNameOrQualifiedName(Tree t, Option loc) throws SyntaxException { var segments = qualifiedNameSegments(t, false); if (segments.length() == 1) { return segments.head(); } else { - return new IR$Name$Qualified(segments, loc, meta(), diag()); + return new Name.Qualified(segments, loc, meta(), diag()); } } private java.util.List unrollOprRhs(Tree list, String operator) throws SyntaxException { @@ -1390,7 +1412,7 @@ private java.util.List unrollOprRhs(Tree list, String operator) throws Syn if (app.getRhs() != null) { segments.add(app.getRhs()); } else { - throw translateEntity(app, IR$Error$Syntax$UnexpectedExpression$.MODULE$); + throw translateEntity(app, Syntax.UnexpectedExpression$.MODULE$); } list = app.getLhs(); } @@ -1408,34 +1430,34 @@ private java.util.List unrollApp(Tree list) { java.util.Collections.reverse(elems); return elems; } - private IR.Name qualifiedNameSegment(Tree tree, boolean generateId) throws SyntaxException { + private Name qualifiedNameSegment(Tree tree, boolean generateId) throws SyntaxException { return switch (tree) { case Tree.Ident id -> sanitizeName(buildName(id, generateId)); - case Tree.Wildcard wild -> new IR$Name$Blank(getIdentifiedLocation(wild.getToken(), generateId), meta(), diag()); + case Tree.Wildcard wild -> new Name.Blank(getIdentifiedLocation(wild.getToken(), generateId), meta(), diag()); default -> throw translateEntity(tree, "qualifiedNameSegment"); }; } - private List qualifiedNameSegments(Tree t, boolean generateId) throws SyntaxException { - List result = nil(); + private List qualifiedNameSegments(Tree t, boolean generateId) throws SyntaxException { + List result = nil(); var first = true; for (var segment : unrollOprRhs(t, ".")) { var qns = switch (qualifiedNameSegment(segment, generateId)) { - case IR$Name$Blank underscore -> { + case Name.Blank underscore -> { if (first) { yield underscore; } else { - throw new SyntaxException(segment, IR$Error$Syntax$InvalidUnderscore$.MODULE$); + throw new SyntaxException(segment, Syntax.InvalidUnderscore$.MODULE$); } } - case IR.Name any -> any; + case Name any -> any; }; result = cons(qns, result); first = false; } return result.reverse(); } - private List buildNameSequence(Tree t) throws SyntaxException { - List res = nil(); + private List buildNameSequence(Tree t) throws SyntaxException { + List res = nil(); for (var segment : unrollOprRhs(t, ",")) { var n = buildName(segment, true); res = cons(n, res); @@ -1450,9 +1472,9 @@ private List qualifiedNameSegments(Tree t, boolean generateId) throws S * @return the [[IR]] representation of `imp` */ @SuppressWarnings("unchecked") - IR$Module$Scope$Import translateImport(Tree.Import imp) { + Import translateImport(Tree.Import imp) { try { - Option rename; + Option rename; if (imp.getAs() == null) { rename = Option.empty(); } else { @@ -1460,20 +1482,22 @@ private List qualifiedNameSegments(Tree t, boolean generateId) throws S } if (imp.getPolyglot() != null) { if (!imp.getPolyglot().getBody().codeRepr().equals("java")) { - return translateSyntaxError(imp, IR$Error$Syntax$UnrecognizedToken$.MODULE$); + return translateSyntaxError(imp, Syntax.UnrecognizedToken$.MODULE$); } - List qualifiedName = qualifiedNameSegments(imp.getImport().getBody(), true); + List qualifiedName = qualifiedNameSegments(imp.getImport().getBody(), true); StringBuilder pkg = new StringBuilder(); String cls = extractPackageAndName(qualifiedName, pkg); - return new IR$Module$Scope$Import$Polyglot( - new IR$Module$Scope$Import$Polyglot$Java(pkg.toString(), cls), - rename.map(name -> name.name()), getIdentifiedLocation(imp), - meta(), diag() + return new Polyglot( + new Polyglot.Java(pkg.toString(), cls), + rename.map(name -> name.name()), + getIdentifiedLocation(imp), + meta(), + diag() ); } var isAll = imp.getAll() != null; - IR$Name$Qualified qualifiedName; - Option> onlyNames = Option.empty(); + Name.Qualified qualifiedName; + Option> onlyNames = Option.empty(); if (imp.getFrom() != null) { qualifiedName = buildQualifiedName(imp.getFrom().getBody(), Option.empty(), true); if (!isAll) { @@ -1482,13 +1506,13 @@ private List qualifiedNameSegments(Tree t, boolean generateId) throws S } else { qualifiedName = buildQualifiedName(imp.getImport().getBody(), Option.empty(), true); } - Option> hidingNames; + Option> hidingNames; if (imp.getHiding() == null) { hidingNames = Option.empty(); } else { hidingNames = Option.apply(buildNameSequence(imp.getHiding().getBody())); } - return new IR$Module$Scope$Import$Module( + return new Import.Module( qualifiedName, rename, isAll || onlyNames.isDefined() || hidingNames.isDefined(), onlyNames, hidingNames, getIdentifiedLocation(imp), false, meta(), diag() @@ -1502,20 +1526,20 @@ hidingNames, getIdentifiedLocation(imp), false, } } - private IR$Error$Syntax$Reason invalidImportReason(String msg) { - return new IR$Error$Syntax$InvalidImport( + private Syntax.Reason invalidImportReason(String msg) { + return new Syntax.InvalidImport( Objects.requireNonNullElse(msg, "Imports must have a valid module path")); } - private IR$Error$Syntax$Reason invalidExportReason(String msg) { - return new IR$Error$Syntax$InvalidExport( + private Syntax.Reason invalidExportReason(String msg) { + return new Syntax.InvalidExport( Objects.requireNonNullElse(msg, "Exports must have a valid module path")); } @SuppressWarnings("unchecked") - private String extractPackageAndName(List qualifiedName, StringBuilder pkg) { + private String extractPackageAndName(List qualifiedName, StringBuilder pkg) { String cls = null; - for (List next = qualifiedName; !next.isEmpty();) { + for (List next = qualifiedName; !next.isEmpty();) { if (cls != null) { if (pkg.length() != 0) { pkg.append("."); @@ -1523,7 +1547,7 @@ private String extractPackageAndName(List qualifiedName, StringBuilder pkg.append(cls); } cls = next.head().name(); - next = (List) next.tail(); + next = (List) next.tail(); } return cls; } @@ -1535,22 +1559,22 @@ private String extractPackageAndName(List qualifiedName, StringBuilder * @return the [[IR]] representation of `imp` */ @SuppressWarnings("unchecked") - IR$Module$Scope$Export translateExport(Tree.Export exp) { + Export translateExport(Tree.Export exp) { try { - Option rename; + Option rename; if (exp.getAs() == null) { rename = Option.empty(); } else { rename = Option.apply(buildName(exp.getAs().getBody(), true)); } - Option> hidingNames; + Option> hidingNames; if (exp.getHiding() == null) { hidingNames = Option.empty(); } else { hidingNames = Option.apply(buildNameSequence(exp.getHiding().getBody())); } - IR$Name$Qualified qualifiedName; - Option> onlyNames = Option.empty(); + Name.Qualified qualifiedName; + Option> onlyNames = Option.empty(); if (exp.getFrom() != null) { qualifiedName = buildQualifiedName(exp.getFrom().getBody(), Option.empty(), true); var onlyBodies = exp.getExport().getBody(); @@ -1560,7 +1584,7 @@ private String extractPackageAndName(List qualifiedName, StringBuilder } else { qualifiedName = buildQualifiedName(exp.getExport().getBody(), Option.empty(), true); } - return new IR$Module$Scope$Export$Module( + return new Export.Module( qualifiedName, rename, (exp.getFrom() != null), onlyNames, hidingNames, getIdentifiedLocation(exp), false, meta(), diag() @@ -1580,58 +1604,58 @@ hidingNames, getIdentifiedLocation(exp), false, * @param doc the comment to transform * @return the [[IR]] representation of `comment` */ - IR$Comment$Documentation translateComment(Tree where, DocComment doc) throws SyntaxException { + Comment.Documentation translateComment(Tree where, DocComment doc) throws SyntaxException { var text = buildTextConstant(where, doc.getElements()); - return new IR$Comment$Documentation(text, getIdentifiedLocation(where), meta(), diag()); + return new Comment.Documentation(text, getIdentifiedLocation(where), meta(), diag()); } - IR$Error$Syntax translateSyntaxError(Tree where, IR$Error$Syntax$Reason reason) { + Syntax translateSyntaxError(Tree where, Syntax.Reason reason) { var at = getIdentifiedLocation(where).get(); - return new IR$Error$Syntax(at, reason, meta(), diag()); + return new Syntax(at, reason, meta(), diag()); } - IR$Error$Syntax translateSyntaxError(IdentifiedLocation where, IR$Error$Syntax$Reason reason) { - return new IR$Error$Syntax(where, reason, meta(), diag()); + Syntax translateSyntaxError(IdentifiedLocation where, Syntax.Reason reason) { + return new Syntax(where, reason, meta(), diag()); } SyntaxException translateEntity(Tree where, String msg) throws SyntaxException { - var reason = new IR$Error$Syntax$UnsupportedSyntax(msg); + var reason = new Syntax.UnsupportedSyntax(msg); throw new SyntaxException(where, reason); } - SyntaxException translateEntity(Tree where, IR$Error$Syntax$Reason reason) throws SyntaxException { + SyntaxException translateEntity(Tree where, Syntax.Reason reason) throws SyntaxException { throw new SyntaxException(where, reason); } - private IR$Name$Literal buildName(Token name) { + private Name.Literal buildName(Token name) { return buildName(getIdentifiedLocation(name), name, false); } - private IR$Name$Literal buildName(Token name, boolean generateId) { + private Name.Literal buildName(Token name, boolean generateId) { return buildName(getIdentifiedLocation(name, generateId), name, false); } - private IR$Name$Literal buildName(Tree ident) throws SyntaxException { + private Name.Literal buildName(Tree ident) throws SyntaxException { return buildName(ident, false); } - private IR$Name$Literal buildName(Tree ident, boolean generateId) throws SyntaxException { + private Name.Literal buildName(Tree ident, boolean generateId) throws SyntaxException { return switch (ident) { case Tree.Ident id -> buildName(getIdentifiedLocation(ident, generateId), id.getToken(), false); default -> throw translateEntity(ident, "buildName"); }; } - private IR$Name$Literal buildName(Tree ident, Token id) { + private Name.Literal buildName(Tree ident, Token id) { return buildName(getIdentifiedLocation(ident), id, false); } - private IR$Name$Literal buildName(Option loc, Token id, boolean isMethod) { + private Name.Literal buildName(Option loc, Token id, boolean isMethod) { final String name = id.codeRepr(); - return new IR$Name$Literal(name, isMethod, loc, meta(), diag()); + return new Name.Literal(name, isMethod, loc, meta(), diag()); } - private IR.Name sanitizeName(IR$Name$Literal id) { + private Name sanitizeName(Name.Literal id) { return switch (id.name()) { - case "self" -> new IR$Name$Self(id.location(), false, id.passData(), id.diagnostics()); - case "Self" -> new IR$Name$SelfType(id.location(), id.passData(), id.diagnostics()); + case "self" -> new Name.Self(id.location(), false, id.passData(), id.diagnostics()); + case "Self" -> new Name.SelfType(id.location(), id.passData(), id.diagnostics()); default -> id; }; } @@ -1750,31 +1774,31 @@ private static Tree maybeManyParensed(Tree t) { } } - private boolean checkArgs(List args) { - LinearSeq a = args; + private boolean checkArgs(List args) { + LinearSeq a = args; while (!a.isEmpty()) { if (a.head() == null) { return false; } - a = (LinearSeq) a.tail(); + a = (LinearSeq) a.tail(); } return true; } private final class SyntaxException extends Exception { final Tree where; - final IR$Error$Syntax$Reason reason; + final Syntax.Reason reason; - SyntaxException(Tree where, IR$Error$Syntax$Reason r) { + SyntaxException(Tree where, Syntax.Reason r) { this.where = where; this.reason = r; } - IR$Error$Syntax toError() { + Syntax toError() { return translateSyntaxError(where, reason); } - IR$Error$Syntax toError(IR$Error$Syntax$Reason r) { + Syntax toError(Syntax.Reason r) { return translateSyntaxError(where, r); } } diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/IR.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/IR.scala index a0b2d746f9fd..e027009e9c97 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/IR.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/IR.scala @@ -1,15 +1,19 @@ package org.enso.compiler.core -import org.enso.compiler.core.ConstantsNames -import org.enso.compiler.core.IR.{Expression, IdentifiedLocation} -import org.enso.compiler.core.ir.MetadataStorage.MetadataPair -import org.enso.compiler.core.ir.{DiagnosticStorage, MetadataStorage} -import org.enso.compiler.core.ir.ProcessingPass -import org.enso.syntax.text.{Debug, Location} import com.oracle.truffle.api.source.Source +import org.enso.compiler.core.ir.MetadataStorage.MetadataPair +import org.enso.compiler.core.ir.{ + Diagnostic, + DiagnosticStorage, + Expression, + IdentifiedLocation, + MetadataStorage, + ProcessingPass +} +import org.enso.syntax.text.Debug + import java.util.UUID -import scala.annotation.unused /** [[IR]] is a temporary and fairly unsophisticated internal representation * format for Enso programs. @@ -30,7 +34,7 @@ import scala.annotation.unused * * See also: Note [IR Equality and hashing] */ -sealed trait IR extends Serializable { +trait IR extends Serializable { /** Storage for metadata that the node has been tagged with as the result of * various compiler passes. @@ -156,36 +160,6 @@ object IR { /** The type of external identifiers */ type ExternalId = UUID - /** Couples a location with a possible source identifier. - * - * @param location the code location. - * @param id the identifier for the location. - */ - case class IdentifiedLocation(location: Location, id: Option[UUID]) { - - /** @return the character index of the start of this source location. - */ - def start: Int = location.start - - /** @return the character index of the end of this source location. - */ - def end: Int = location.end - - /** @return the length in characters of this location. - */ - def length: Int = location.length - } - object IdentifiedLocation { - - /** Utility constructor, building a location without an ID. - * - * @param location the code location. - * @return an [[IdentifiedLocation]] corresponding to the input location. - */ - def apply(location: Location): IdentifiedLocation = - IdentifiedLocation(location, None) - } - /** Generates an indent of `n` spaces. * * @param n the number of spaces @@ -195,8950 +169,172 @@ object IR { " " * n } - private def fileLocationFromSection( - loc: IR.IdentifiedLocation, - source: Source - ): String = { - val section = - source.createSection(loc.location.start, loc.location.length) - val locStr = - "" + section.getStartLine + ":" + - section.getStartColumn + "-" + - section.getEndLine + ":" + - section.getEndColumn - source.getName + "[" + locStr + "]" - } - /** The size of a single indentation level. */ val indentLevel: Int = 4 - // === Basic Shapes ========================================================= + // ========================================================================== + // === Extension Methods ==================================================== + // ========================================================================== - /** A node representing an empty IR construct that can be used in any place. + /** This class adds an extension method to control how the pass data element + * of the IR is printed. * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node + * @param ir the IR to print the pass data for */ - sealed case class Empty( - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends IR - with Expression - with Diagnostic - with IRKind.Primitive { - override protected var id: Identifier = randomId + implicit class ShowPassData(ir: IR) { - /** Creates a copy of `this` + /** Creates a string representation of the pass data for a given IR node. * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this` with the specified fields updated + * @return a string representation of the pass data for [[ir]] */ - def copy( - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Empty = { - val res = Empty(location, passData, diagnostics) - res.id = id - res + def showPassData: String = { + val metaString: Seq[String] = + ir.passData.map((p, m) => (p, m.metadataName)).values.toSeq + val alphabetical = metaString.sorted + s"$alphabetical" } + } - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Empty = - copy( - location = if (keepLocations) location else None, - passData = if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Empty = - copy(location = location) + /** Adds extension methods on strings to aid in writing custom to string + * overrides. + * + * @param string the string to process + */ + implicit class ToStringHelper(string: String) { - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Empty = this + /** Converts a multiline string to a single line + * + * @return [[string]], converted to a single line + */ + def toSingleLine: String = { + val lines = string.stripMargin.split("\n").toList.filterNot(_ == "") - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Empty( - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine + val body = lines.tail.dropRight(1).mkString(" ") - /** @inheritdoc */ - override def children: List[IR] = List() + s"${lines.head}$body${lines.last}" + } + } - /** @inheritdoc */ - override def message: String = - "Empty IR: Please report this as a compiler bug." + // ========================================================================== + // === Useful Extension Methods ============================================= + // ========================================================================== - /** @inheritdoc */ - override def diagnosticKeys(): Array[Any] = Array() + /** Adds extension methods for working directly with the diagnostics on the + * IR. + * + * @param ir the IR to add the methods to + * @tparam T the concrete type of the IR + */ + implicit class AsDiagnostics[T <: IR](ir: T) { - /** @inheritdoc */ - override def showCode(indent: Int): String = "IR.Empty" + /** Adds a new diagnostic entity to [[IR]]. + * + * @param diagnostic the diagnostic to add + * @return [[ir]] with added diagnostics + */ + def addDiagnostic(diagnostic: Diagnostic): T = { + ir.diagnostics.add(diagnostic) + ir + } } - // === Module =============================================================== - - /** A representation of a top-level Enso module. - * - * Modules may only contain imports and top-level bindings, with no top-level - * executable code. + /** Adds extension methods for working directly with the metadata on the IR. * - * @param imports the import statements that bring other modules into scope - * @param exports the export statements for this module - * @param bindings the top-level bindings for this module - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node + * @param ir the IR to add the methods to + * @tparam T the concrete type of the IR */ - @SerialVersionUID( - 6655L // SuggestionBuilder needs to send ascribedType of constructor parameters - ) // prevents reading broken caches, see PR-3692 for details - sealed case class Module( - imports: List[Module.Scope.Import], - exports: List[Module.Scope.Export], - bindings: List[Module.Scope.Definition], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends IR - with IRKind.Primitive { - override protected var id: Identifier = randomId + implicit class AsMetadata[T <: IR](ir: T) { + + /** Adds a metadata pair to the node metadata. + * + * This will overwrite any entry whose key matches [[MetadataPair#pass]]. + * + * @param metadataPair the pair to add to the storage + * @tparam K the concrete type of the pass + */ + def updateMetadata[K <: ProcessingPass]( + metadataPair: MetadataPair[K] + ): T = { + ir.passData.update(metadataPair) + ir + } + + /** Gets the metadata for the specified pass. + * + * @param pass the pass to get the metadata for + * @tparam K the concrete type of `pass` + * @return the metadata for `pass`, if it exists + */ + def getMetadata[K <: ProcessingPass](pass: K): Option[pass.Metadata] = { + ir.passData.get(pass) + } - /** Creates a copy of `this`. + /** Unsafely gets the metadata for the specified pass, if it exists. * - * @param imports the import statements that bring other modules into scope - * @param exports the export statements for this module - * @param bindings the top-level bindings for this module - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values + * @param pass the pass to get metadata for + * @param msg the message to throw with if the unsafe get fails + * @tparam K the concrete type of `pass` + * @throws CompilerError if no metadata exists for `pass` + * @return the metadata for `pass`, if it exists */ - def copy( - imports: List[Module.Scope.Import] = imports, - exports: List[Module.Scope.Export] = exports, - bindings: List[Module.Scope.Definition] = bindings, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Module = { - val res = - Module(imports, exports, bindings, location, passData, diagnostics) - res.id = id - res + @throws[CompilerError] + def unsafeGetMetadata[K <: ProcessingPass]( + pass: ProcessingPass, + msg: => String + ): pass.Metadata = { + ir.passData.getUnsafe(pass)(msg) } + } + + /** Adds extension methods for working with lists of [[IR]]. + * + * @param list the list + * @tparam T the concrete IR type + */ + implicit class ListAsIr[T <: IR](list: List[T]) { - /** @inheritdoc */ - override def duplicate( + /** Calls [[IR.duplicate]] on the elements in [[list]]. + * + * @param keepLocations whether or not locations should be kept in the + * duplicated IR + * @param keepMetadata whether or not the pass metadata should be kept in + * the duplicated IR + * @param keepDiagnostics whether or not the diagnostics should be kept in + * the duplicated IR + * @param keepIdentifiers whether or not the identifiers should be + * regenerated in the duplicated IR + * @return a duplicate of [[list]] + */ + def duplicate( keepLocations: Boolean = true, keepMetadata: Boolean = true, keepDiagnostics: Boolean = true, keepIdentifiers: Boolean = false - ): Module = - copy( - imports = imports.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - bindings = bindings.map( + ): List[T] = { + list + .map( _.duplicate( keepLocations, keepMetadata, keepDiagnostics, keepIdentifiers ) - ), - location = if (keepLocations) location else None, - passData = if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Module = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Module = { - copy( - imports = imports.map(_.mapExpressions(fn)), - exports = exports.map(_.mapExpressions(fn)), - bindings = bindings.map(_.mapExpressions(fn)) - ) - } - - /** @inheritdoc */ - override def children: List[IR] = imports ++ exports ++ bindings - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module( - |imports = $imports, - |exports = $exports, - |bindings = $bindings, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val importsString = imports.map(_.showCode(indent)).mkString("\n") - val exportsString = exports.map(_.showCode(indent)).mkString("\n") - val defsString = bindings.map(_.showCode(indent)).mkString("\n\n") - - List(importsString, exportsString, defsString).mkString("\n\n") + ) + .asInstanceOf[List[T]] } } - object Module { - - /** A representation of constructs that can only occur in the top-level - * module scope - */ - sealed trait Scope extends IR { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Scope - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Scope - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Scope - } - object Scope { - - /** An export statement */ - sealed trait Export extends Scope { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Export - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Export - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Export - } - - object Export { - - /** An export statement. - * - * @param name the full path representing the export - * @param rename the name this export is visible as - * @param isAll is this an unqualified export - * @param onlyNames exported names selected from the exported module - * @param hiddenNames exported names hidden from the exported module - * @param location the source location that the node corresponds to - * @param isSynthetic is this export compiler-generated - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Module( - name: IR.Name.Qualified, - rename: Option[IR.Name.Literal], - isAll: Boolean, - onlyNames: Option[List[IR.Name.Literal]], - hiddenNames: Option[List[IR.Name.Literal]], - override val location: Option[IdentifiedLocation], - isSynthetic: Boolean = false, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends IR - with IRKind.Primitive - with Export { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the full path representing the export - * @param rename the name this export is visible as - * @param isAll is this an unqualified export - * @param onlyNames exported names selected from the exported module - * @param hiddenNames exported names hidden from the exported module - * @param location the source location that the node corresponds to - * @param isSynthetic is this import compiler-generated - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name.Qualified = name, - rename: Option[IR.Name.Literal] = rename, - isAll: Boolean = isAll, - onlyNames: Option[List[IR.Name.Literal]] = onlyNames, - hiddenNames: Option[List[IR.Name.Literal]] = hiddenNames, - location: Option[IdentifiedLocation] = location, - isSynthetic: Boolean = isSynthetic, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Module = { - val res = Module( - name, - rename, - isAll, - onlyNames, - hiddenNames, - location, - isSynthetic, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Module = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Module = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Module = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Export.Module( - |name = $name, - |rename = $rename, - |isAll = $isAll, - |onlyNames = $onlyNames, - |hidingNames = $hiddenNames, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - name :: List( - rename.toList, - onlyNames.getOrElse(List()), - hiddenNames.getOrElse(List()) - ).flatten - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val renameCode = rename.map(n => s" as ${n.name}").getOrElse("") - if (isAll) { - val onlyPart = onlyNames - .map(names => " " + names.map(_.name).mkString(", ")) - .getOrElse("") - val hidingPart = hiddenNames - .map(names => s" hiding ${names.map(_.name).mkString(", ")}") - .getOrElse("") - val all = if (onlyNames.isDefined) "" else " all" - s"from ${name.name}$renameCode export$onlyPart$all$hidingPart" - } else { - s"export ${name.name}$renameCode" - } - } - - /** Gets the name of the module visible in the importing scope, - * either the original name or the rename. - * - * @return the name of this export visible in code - */ - def getSimpleName: IR.Name = rename.getOrElse(name.parts.last) - - /** Checks whether the export statement allows use of the given - * exported name. - * - * Note that it does not verify if the name is actually exported - * by the module, only checks if it is syntactically allowed. - * - * @param name the name to check - * @return whether the name could be accessed or not - */ - def allowsAccess(name: String): Boolean = { - if (!isAll) return false; - if (onlyNames.isDefined) { - onlyNames.get.exists(_.name.toLowerCase == name.toLowerCase) - } else if (hiddenNames.isDefined) { - !hiddenNames.get.exists(_.name.toLowerCase == name.toLowerCase) - } else { - true - } - } - } - } - - /** Module-level import statements. */ - sealed trait Import extends Scope { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Import - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Import - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Import - } - - object Import { - - /** An import statement. - * - * @param name the full path representing the import - * @param rename the name this import is visible as - * @param isAll is this importing exported names - * @param onlyNames exported names selected from the imported module - * @param hiddenNames exported names hidden from the imported module - * @param location the source location that the node corresponds to - * @param isSynthetic is this import compiler-generated - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Module( - name: IR.Name.Qualified, - rename: Option[IR.Name.Literal], - isAll: Boolean, - onlyNames: Option[List[IR.Name.Literal]], - hiddenNames: Option[List[IR.Name.Literal]], - override val location: Option[IdentifiedLocation], - isSynthetic: Boolean = false, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Import - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the full `.`-separated path representing the import - * @param rename the name this import is visible as - * @param isAll is this importing exported names - * @param onlyNames exported names selected from the imported module - * @param hiddenNames exported names hidden from the imported module - * @param location the source location that the node corresponds to - * @param isSynthetic is this import compiler-generated - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name.Qualified = name, - rename: Option[IR.Name.Literal] = rename, - isAll: Boolean = isAll, - onlyNames: Option[List[IR.Name.Literal]] = onlyNames, - hiddenNames: Option[List[IR.Name.Literal]] = hiddenNames, - location: Option[IdentifiedLocation] = location, - isSynthetic: Boolean = isSynthetic, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Module = { - val res = Module( - name, - rename, - isAll, - onlyNames, - hiddenNames, - location, - isSynthetic, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Module = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Module = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Module = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Import.Module( - |name = $name, - |rename = $rename, - |onlyNames = $onlyNames, - |hiddenNames = $hiddenNames, - |isAll = $isAll, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - name :: List( - rename.toList, - onlyNames.getOrElse(List()), - hiddenNames.getOrElse(List()) - ).flatten - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val renameCode = rename.map(n => s" as ${n.name}").getOrElse("") - if (isAll) { - val onlyPart = onlyNames - .map(names => " " + names.map(_.name).mkString(", ")) - .getOrElse("") - val hidingPart = hiddenNames - .map(names => s" hiding ${names.map(_.name).mkString(", ")}") - .getOrElse("") - val all = if (onlyNames.isDefined) "" else " all" - s"from ${name.name}$renameCode import$onlyPart$all$hidingPart" - } else { - s"import ${name.name}$renameCode" - } - } - - /** Gets the name of the module visible in this scope, either the - * original name or the rename. - * - * @return the name of this import visible in code - */ - def getSimpleName: IR.Name = rename.getOrElse(name.parts.last) - - /** Checks whether the import statement allows use of the given - * exported name. - * - * Note that it does not verify if the name is actually exported - * by the module, only checks if it is syntactically allowed. - * - * @param name the name to check - * @return whether the name could be accessed or not - */ - def allowsAccess(name: String): Boolean = { - if (!isAll) return false; - if (onlyNames.isDefined) { - onlyNames.get.exists(_.name == name) - } else if (hiddenNames.isDefined) { - !hiddenNames.get.exists(_.name == name) - } else { - true - } - } - } - - object Polyglot { - - /** Represents language-specific polyglot import data. */ - sealed trait Entity { - val langName: String - - /** Returns the name this object is visible as from Enso code. - * - * @return the visible name of this object - */ - def getVisibleName: String - - def showCode(indent: Int = 0): String - } - - /** Represents an import of a Java class. - * - * @param packageName the name of the package containing the imported - * class - * @param className the class name - */ - case class Java(packageName: String, className: String) - extends Entity { - val langName = "java" - - override def getVisibleName: String = className - - /** Returns the fully qualified Java name of this object. - * - * @return the Java-side name of the imported entity - */ - def getJavaName: String = s"$packageName.$className" - - override def showCode(indent: Int): String = - s"$packageName.$className" - } - } - - /** An import of a polyglot class. - * - * @param entity language-specific information on the imported entity - * @param rename the name this object should be visible under in the - * importing scope - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Polyglot( - entity: Polyglot.Entity, - rename: Option[String], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Import - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param entity language-specific information on the imported entity - * @param rename the name this object should be visible under in the - * importing scope - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - entity: Polyglot.Entity = entity, - rename: Option[String] = rename, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Polyglot = { - val res = - Polyglot(entity, rename, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Polyglot = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Polyglot = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Polyglot = - this - - /** Returns the name this object is visible as from Enso code. - * - * @return the visible name of this object - */ - def getVisibleName: String = rename.getOrElse(entity.getVisibleName) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Import.Polyglot( - |entity = $entity, - |rename = $rename, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val renamePart = rename.map(name => s"as $name").getOrElse("") - s"polyglot ${entity.langName} import ${entity.showCode(indent)} $renamePart" - } - } - } - - /** A representation of top-level definitions. */ - sealed trait Definition extends Scope { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Definition - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Definition - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Definition - } - object Definition { - - /** The definition of a union type and its members. - * - * NB: this should probably be removed once we propagate the union - * types logic through the runtime and implement statics – the whole - * notion of desugaring complex type definitions becomes obsolete then. - * - * @param name the name of the union - * @param members the members of this union - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Type( - name: IR.Name, - params: List[IR.DefinitionArgument], - members: List[IR.Module.Scope.Definition.Data], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - def copy( - name: IR.Name = name, - params: List[IR.DefinitionArgument] = params, - members: List[IR.Module.Scope.Definition.Data] = members, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Type = { - val res = - Type(name, params, members, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Type = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - members = members.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Type = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Type = - copy( - params = params.map(_.mapExpressions(fn)), - members = members.map(_.mapExpressions(fn)) - ) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.Type( - |name = $name, - |params = $params, - |members = $members, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = name :: (params :++ members) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val fields = members.map(_.showCode(indent)).mkString(" | ") - - s"type ${name.showCode(indent)} = $fields" - } - } - - /** The definition of an atom constructor and its associated arguments. - * - * @param name the name of the atom - * @param arguments the arguments to the atom constructor - * @param annotations the list of annotations - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Data( - name: IR.Name, - arguments: List[DefinitionArgument], - annotations: List[IR.Name.GenericAnnotation], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends IR - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the atom - * @param arguments the arguments to the atom constructor - * @param annotations the list of annotations - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name = name, - arguments: List[DefinitionArgument] = arguments, - annotations: List[IR.Name.GenericAnnotation] = annotations, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Data = { - val res = Data( - name, - arguments, - annotations, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Data = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Data = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Data = { - copy( - name = name.mapExpressions(fn), - arguments = arguments.map(_.mapExpressions(fn)), - annotations = annotations.map(_.mapExpressions(fn)) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.Data( - |name = $name, - |arguments = $arguments, - |annotations = $annotations, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = name :: arguments ::: annotations - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val fields = arguments.map(_.showCode(indent)).mkString(" ") - - s"type ${name.showCode(indent)} $fields" - } - } - - /** The definition of a complex type definition that may contain - * multiple atom and method definitions. - * - * @param name the name of the complex type - * @param arguments the (type) arguments to the complex type - * @param body the body of the complex type - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class SugaredType( - name: IR.Name, - arguments: List[DefinitionArgument], - body: List[IR], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Definition - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the complex type - * @param arguments the (type) arguments to the complex type - * @param body the body of the complex type - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name = name, - arguments: List[DefinitionArgument] = arguments, - body: List[IR] = body, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): SugaredType = { - val res = SugaredType( - name, - arguments, - body, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): SugaredType = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - body = body.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): SugaredType = - copy(body = body.map(_.mapExpressions(fn))) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): SugaredType = copy(location = location) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.SugaredType( - |name = $name, - |arguments = $arguments, - |body = $body, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = (name :: arguments) ::: body - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val headerArgs = arguments.map(_.showCode(indent)).mkString(" ") - val header = s"type ${name.name} $headerArgs" - val newIndent = indent + indentLevel - val bodyStr = body - .map(mkIndent(newIndent) + _.showCode(newIndent)) - .mkString("\n\n") - - s"$header\n$bodyStr" - } - } - - /** A trait representing method definitions in Enso. */ - sealed trait Method extends Definition { - val methodReference: IR.Name.MethodReference - val body: Expression - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Method - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Method - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Method - - /** Get the type name for the method. */ - def typeName: Option[IR.Name] = methodReference.typePointer - - /** Get the name of the method. */ - def methodName: IR.Name = methodReference.methodName - } - object Method { - - /** The definition of a method for a given constructor. - * - * @param methodReference a reference to the method being defined - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Explicit( - override val methodReference: IR.Name.MethodReference, - override val body: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Method - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param methodReference a reference to the method being defined - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - methodReference: IR.Name.MethodReference = methodReference, - body: Expression = body, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Explicit = { - val res = Explicit( - methodReference, - body, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Explicit = - copy( - methodReference = methodReference.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - body = body.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy - else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Explicit = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Explicit = { - copy( - methodReference = methodReference.mapExpressions(fn), - body = fn(body) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.Method.Explicit( - |methodReference = $methodReference, - |body = $body, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(methodReference, body) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val exprStr = if (body.isInstanceOf[IR.Expression.Block]) { - s"\n${body.showCode(indent)}" - } else { - s"${body.showCode(indent)}" - } - - s"${methodReference.showCode(indent)} = $exprStr" - } - - def isStatic: Boolean = body match { - case function: Function.Lambda => - function.arguments.headOption.map(_.name) match { - case Some(IR.Name.Self(_, true, _, _)) => true - case _ => false - } - case _ => - true // if it's not a function, it has no arguments, therefore no `self` - } - - def isStaticWrapperForInstanceMethod: Boolean = body match { - case function: Function.Lambda => - function.arguments.map(_.name) match { - case IR.Name.Self(_, true, _, _) :: IR.Name.Self( - _, - false, - _, - _ - ) :: _ => - true - case _ => false - } - case _ => false - } - - } - - /** The definition of a method for a given constructor using sugared - * syntax. - * - * @param methodReference a reference to the method being defined - * @param arguments the arguments to the method - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Binding( - override val methodReference: IR.Name.MethodReference, - arguments: List[IR.DefinitionArgument], - override val body: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Method - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param methodReference a reference to the method being defined - * @param arguments the arguments to the method - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - methodReference: IR.Name.MethodReference = methodReference, - arguments: List[IR.DefinitionArgument] = arguments, - body: Expression = body, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Binding = { - val res = Binding( - methodReference, - arguments, - body, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Binding = - copy( - methodReference = methodReference.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - body = body.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy - else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Binding = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Binding = { - copy( - methodReference = methodReference.mapExpressions(fn), - arguments = arguments.map(_.mapExpressions(fn)), - body = fn(body) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.Method.Binding( - |methodReference = $methodReference, - |arguments = $arguments, - |body = $body, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - (methodReference :: arguments) :+ body - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val exprStr = if (body.isInstanceOf[IR.Expression.Block]) { - s"\n${body.showCode(indent)}" - } else { - s"${body.showCode(indent)}" - } - - val argsStr = arguments.map(_.showCode(indent)).mkString(" ") - - s"${methodReference.showCode(indent)} $argsStr = $exprStr" - } - } - - /** A method that represents a conversion from one type to another. - * - * @param methodReference a reference to the type on which the - * conversion is being defined - * @param sourceTypeName the type of the source value for this - * conversion - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Conversion( - override val methodReference: Name.MethodReference, - sourceTypeName: Expression, - override val body: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Method - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param methodReference a reference to the type on which the - * conversion is being defined - * @param sourceTypeName the type of the source value for this - * conversion - * @param body the body of the method - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - methodReference: Name.MethodReference = methodReference, - sourceTypeName: Expression = sourceTypeName, - body: Expression = body, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Conversion = { - val res = Conversion( - methodReference, - sourceTypeName, - body, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean, - keepMetadata: Boolean, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Conversion = { - copy( - methodReference = methodReference.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - sourceTypeName = sourceTypeName.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - body = body.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy - else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - } - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Conversion = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Conversion = { - copy( - methodReference = methodReference.mapExpressions(fn), - sourceTypeName = sourceTypeName.mapExpressions(fn), - body = fn(body) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Module.Scope.Definition.Method.Conversion( - |methodReference = $methodReference, - |sourceTypeName = $sourceTypeName, - |body = $body, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - List(methodReference, sourceTypeName, body) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val exprStr = if (body.isInstanceOf[IR.Expression.Block]) { - s"\n${body.showCode(indent)}" - } else { - s"${body.showCode(indent)}" - } - - s"${methodReference.showCode(indent)} = $exprStr" - } - } - } - } - } - } - - // === Expression =========================================================== - sealed trait Expression extends IR { - - /** Performs a recursive traversal of the IR, potentially transforming it. - * - * @param fn the function to apply across the IR - * @return the IR, potentially transformed - */ - def transformExpressions( - fn: PartialFunction[Expression, Expression] - ): Expression = { - if (fn.isDefinedAt(this)) { - fn(this) - } else { - mapExpressions(_.transformExpressions(fn)) - } - } - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Expression - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Expression - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Expression - } - object Expression { - - // TODO Remove suspended blocks from Enso. - /** A block expression. - * - * @param expressions the expressions in the block - * @param returnValue the final expression in the block - * @param location the source location that the node corresponds to - * @param suspended whether or not the block is suspended - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Block( - expressions: List[Expression], - returnValue: Expression, - override val location: Option[IdentifiedLocation], - suspended: Boolean = false, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Expression - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param expressions the expressions in the block - * @param returnValue the final expression in the block - * @param location the source location that the node corresponds to - * @param suspended whether or not the block is suspended - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - expressions: List[Expression] = expressions, - returnValue: Expression = returnValue, - location: Option[IdentifiedLocation] = location, - suspended: Boolean = suspended, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Block = { - val res = Block( - expressions, - returnValue, - location, - suspended, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Block = - copy( - expressions = expressions.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - returnValue = returnValue.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Block = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Block = { - copy( - expressions = expressions.map(fn), - returnValue = fn(returnValue) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Expression.Block( - |expressions = $expressions, - |returnValue = $returnValue, - |location = $location, - |suspended = $suspended, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = expressions :+ returnValue - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val newIndent = indent + indentLevel - val expressionsStr = expressions - .map(mkIndent(newIndent) + _.showCode(newIndent)) - .mkString("\n") - val returnStr = mkIndent(newIndent) + returnValue.showCode(newIndent) - - s"\n$expressionsStr\n$returnStr" - } - } - - /** A binding expression of the form `name = expr` - * - * To create a binding that binds no available name, set the name of the - * binding to an [[IR.Name.Blank]] (e.g. _ = foo a b). - * - * @param name the name being bound to - * @param expression the expression being bound to `name` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Binding( - name: IR.Name, - expression: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Expression - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name being bound to - * @param expression the expression being bound to `name` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name = name, - expression: Expression = expression, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Binding = { - val res = Binding(name, expression, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Binding = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - expression = expression.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Binding = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Binding = { - copy(name = name.mapExpressions(fn), expression = fn(expression)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Expression.Binding( - |name = $name, - |expression = $expression, - |location = $location - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(name, expression) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"${name.showCode(indent)} = ${expression.showCode(indent)}" - } - } - - // === Literals ============================================================= - - /** Enso literals. */ - sealed trait Literal extends Expression with IRKind.Primitive { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Literal - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Literal - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Literal - } - object Literal { - - /** A numeric Enso literal. - * - * @param base the optional base for the number, expressed in decimal - * @param value the textual representation of the numeric literal - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Number( - base: Option[String], - value: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Literal { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param base the optional base for the number, expressed in decimal - * @param value the textual representation of the numeric literal - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - base: Option[String] = base, - value: String = value, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Number = { - val res = Number(base, value, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Number = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Number = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Number = this - - /** @inheritdoc */ - override def toString: String = - s"""IR.Literal.Number( - |base = $base, - |value = $value, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = if (this.base.isDefined) { - s"${base.get}_$value" - } else value - - /** Checks whether the literal represents a fractional value. - * - * @return `true` if the value is fractional, `false` otherwise. - */ - def isFractional: Boolean = value.contains(".") - - /** Checks the values in the literal converts that to approviate JVM value. - * @return Double, Long, BigInteger - */ - @throws[CompilerError] - def numericValue: Any = { - if (isFractional) { - value.toDouble - } else if (base.isDefined) { - val baseNum = - try { - Integer.parseInt(base.get) - } catch { - case _: NumberFormatException => - throw new CompilerError( - s"Invalid number base $base seen during codegen." - ) - } - try { - val longVal = java.lang.Long.parseLong(value, baseNum) - longVal - } catch { - case _: NumberFormatException => - try { - new java.math.BigInteger(value, baseNum) - } catch { - case _: NumberFormatException => - throw new CompilerError( - s"Invalid number base $base seen during codegen." - ) - } - } - } else { - value.toLongOption.getOrElse(new java.math.BigInteger(value)) - } - } - } - - /** A textual Enso literal. - * - * @param text the text of the literal - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Text( - text: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Literal { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param text the text of the literal - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - text: String = text, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Text = { - val res = Text(text, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Text = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Text = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Text = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Literal.String( - |text = $text, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = s""""$text"""" - } - } - - // === Names ================================================================ - - /** Enso names. */ - sealed trait Name extends Expression with IRKind.Primitive { - val name: String - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Name - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Name - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Name - - /** Checks whether a name is a call-site method name. - * - * @return `true` if the name was created through a method call - */ - def isMethod: Boolean = false - - } - object Name { - - /** A representation of a method reference of the form `Type_Path.method`. - * - * @param typePointer the type name - * @param methodName the method on `typeName` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class MethodReference( - typePointer: Option[IR.Name], - methodName: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name - with IRKind.Sugar { - - override val name: String = showCode() - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param typePointer the type name - * @param methodName the method on `typeName` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - typePointer: Option[IR.Name] = typePointer, - methodName: IR.Name = methodName, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): MethodReference = { - val res = - MethodReference( - typePointer, - methodName, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): MethodReference = - copy( - typePointer = typePointer.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - methodName = methodName.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): MethodReference = - copy( - typePointer = typePointer.map(_.mapExpressions(fn)), - methodName = methodName.mapExpressions(fn) - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): MethodReference = { - copy(location = location) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.MethodReference( - |typePointer = $typePointer, - |methodName = $methodName, - |location = $location, - |passData = $passData, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - typePointer.map(_ :: methodName :: Nil).getOrElse(methodName :: Nil) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val tPointer = typePointer.map(_.showCode(indent) + ".").getOrElse("") - s"$tPointer${methodName.showCode(indent)}" - } - - /** Checks whether `this` and `that` reference the same method. - * - * @param that the other method reference to check against - * @return `true`, if `this` and `that` represent the same method, - * otherwise `false` - */ - def isSameReferenceAs(that: MethodReference): Boolean = { - val sameTypePointer = typePointer - .map(thisTp => - that.typePointer.map(_.name == thisTp.name).getOrElse(false) - ) - .getOrElse(that.typePointer.isEmpty) - sameTypePointer && (methodName.name == that.methodName.name) - } - } - object MethodReference { - - /** Generates a location for the reference from the segments. - * - * @param segments the reference segments - * @return a location for the method reference - */ - def genLocation(segments: List[IR.Name]): Option[IdentifiedLocation] = { - segments.foldLeft(None: Option[IdentifiedLocation])( - (identLoc, segment) => { - identLoc.flatMap(loc => { - Some( - IdentifiedLocation( - Location( - loc.location.start, - segment.location - .flatMap(l => Some(l.location.end)) - .getOrElse(loc.location.end) - ) - ) - ) - }) - } - ) - } - } - - /** A representation of a qualified (multi-part) name. - * - * @param parts the segments of the name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @return a copy of `this`, updated with the specified values - */ - sealed case class Qualified( - parts: List[IR.Name], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name - with IRKind.Primitive { - - override val name: String = parts.map(_.name).mkString(".") - - override def mapExpressions(fn: Expression => Expression): Name = this - - override def setLocation(location: Option[IdentifiedLocation]): Name = - copy(location = location) - - /** Creates a copy of `this`. - * - * @param parts the segments of the name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - parts: List[IR.Name] = parts, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Qualified = { - val res = - Qualified( - parts, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Qualified = - copy( - parts = parts.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def children: List[IR] = parts - - /** @inheritdoc */ - override protected var id: Identifier = randomId - - /** @inheritdoc */ - override def showCode(indent: Int): String = name - } - - /** Represents occurrences of blank (`_`) expressions. - * - * @param location the source location that the node corresponds to. - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Blank( - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name - with IRKind.Sugar { - override val name: String = "_" - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param location the source location that the node corresponds to. - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Blank = { - val res = Blank(location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Blank = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Blank = - this - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Blank = - copy(location = location) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.Blank( - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = "_" - } - - sealed case class Special( - specialName: Special.Ident, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name - with IRKind.Sugar { - override val name: String = s"" - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param location the source location that the node corresponds to. - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - specialName: Special.Ident = specialName, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Special = { - val res = Special(specialName, location, passData, diagnostics) - res.id = id - res - } - - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Special = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - override def mapExpressions(fn: Expression => Expression): Special = - this - - override def setLocation(location: Option[IdentifiedLocation]): Special = - copy(location = location) - - override def toString: String = - s""" - |IR.Name.Special( - |specialName = $specialName, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - override def children: List[IR] = List() - - override def showCode(indent: Int): String = name - } - - object Special { - sealed trait Ident - case object NewRef extends Ident - case object ReadRef extends Ident - case object WriteRef extends Ident - case object RunThread extends Ident - case object JoinThread extends Ident - } - - /** The representation of a literal name. - * - * @param name the literal text of the name - * @param isMethod is this a method call name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Literal( - override val name: String, - override val isMethod: Boolean, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the literal text of the name - * @param isMethod is this a method call name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: String = name, - isMethod: Boolean = isMethod, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Literal = { - val res = - Literal(name, isMethod, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Literal = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Literal = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Literal = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.Literal( - |name = $name, - |isMethod = $isMethod, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = name - } - - /** Base trait for annotations. */ - sealed trait Annotation extends Name with IR.Module.Scope.Definition { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Annotation - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Annotation - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Annotation - } - - /** The representation of builtin annotation. - * - * @param name the annotation text of the name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class BuiltinAnnotation( - override val name: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Annotation - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the annotation text of the name - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: String = name, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): BuiltinAnnotation = { - val res = BuiltinAnnotation(name, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): BuiltinAnnotation = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): BuiltinAnnotation = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): BuiltinAnnotation = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.BuiltinAnnotation( - |name = $name, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = s"@$name" - } - - /** Common annotations of form `@name expression`. - * - * @param name the annotation text of the name - * @param expression the annotation expression - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class GenericAnnotation( - override val name: String, - expression: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Annotation { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the annotation text of the name - * @param expression the annotation expression - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: String = name, - expression: Expression = expression, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): GenericAnnotation = { - val res = - GenericAnnotation(name, expression, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): GenericAnnotation = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): GenericAnnotation = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): GenericAnnotation = - copy(expression = fn(expression)) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.GenericAnnotation( - |name = $name, - |expression = $expression, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(expression) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"@$name ${expression.showCode(indent)}" - } - - /** A representation of the name `self`, used to refer to the current type. - * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Self( - override val location: Option[IdentifiedLocation], - synthetic: Boolean = false, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name { - override protected var id: Identifier = randomId - override val name: String = ConstantsNames.SELF_ARGUMENT - - /** Creates a copy of `self`. - * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - location: Option[IdentifiedLocation] = location, - synthetic: Boolean = synthetic, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Self = { - val res = Self(location, synthetic, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Self = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Self = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Self = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.Self( - |location = $location, - |synthetic = $synthetic, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = name - } - - /** A representation of the name `Self`, used to refer to the current type. - * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class SelfType( - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Name { - override protected var id: Identifier = randomId - override val name: String = ConstantsNames.SELF_TYPE_ARGUMENT - - /** Creates a copy of `Self`. - * - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): SelfType = { - val res = SelfType(location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): SelfType = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): SelfType = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): SelfType = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Name.SelfType( - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = name - } - } - - // === Typing =============================================================== - - /** Constructs that operate on types. */ - sealed trait Type extends Expression { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Type - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Type - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Type - } - object Type { - - /** Static information about the type operators. */ - sealed trait Info { - val name: String - } - - sealed case class Function( - args: List[Expression], - result: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Type { - override protected var id: Identifier = randomId - - def copy( - args: List[Expression] = args, - result: Expression = result, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Function = { - val res = Function(args, result, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Function = - copy( - args = args.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - result = result.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Function = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Function = { - copy(args = args.map(fn), result = fn(result)) - } - - /** @inheritdoc */ - override def toString: String = - s"""IR.Type.Function( - |args = $args, - |result = $result, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = args :+ result - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"${args.map(_.showCode()).mkString(" -> ")} -> ${result.showCode()}" - } - - /** The ascription of a type to a value. - * - * @param typed the expression being ascribed a type - * @param signature the signature being ascribed to `typed` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Ascription( - typed: Expression, - signature: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Type - with Module.Scope.Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param typed the expression being ascribed a type - * @param signature the signature being ascribed to `typed` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - typed: Expression = typed, - signature: Expression = signature, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Ascription = { - val res = Ascription(typed, signature, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Ascription = - copy( - typed = typed.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - signature = signature.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Ascription = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Ascription = { - copy(typed = fn(typed), signature = fn(signature)) - } - - /** @inheritdoc */ - override def toString: String = - s"""IR.Type.Ascription( - |typed = $typed, - |signature = $signature, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(typed, signature) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"${typed.showCode(indent)} : ${signature.showCode(indent)}" - } - object Ascription extends Info { - override val name: String = ":" - } - - /** A representation of the `in` portion of a type signature that represents - * the ascription of a monadic context. - * - * @param typed the type being ascribed a monadic context - * @param context the context being ascribed to `typed` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Context( - typed: Expression, - context: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Type - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates ac opy of `this`. - * - * @param typed the type being ascribed a monadic context - * @param context the context being ascribed to `typed` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - typed: Expression = typed, - context: Expression = context, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Context = { - val res = Context(typed, context, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Context = - copy( - typed = typed.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - context = context.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Context = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Context = { - copy(typed = fn(typed), context = fn(context)) - } - - /** @inheritdoc */ - override def toString: String = - s"""IR.Type.Context( - |typed = $typed, - |context = $context, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(typed, context) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"${typed.showCode(indent)} in ${context.showCode(indent)}" - } - object Context extends Info { - override val name: String = "in" - } - - /** Represents the ascription of an error context to an expression. - * - * @param typed the expression being ascribed an error context - * @param error the error being ascribed - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Error( - typed: Expression, - error: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Type - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param typed the expression being ascribed an error context - * @param error the error being ascribed - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - typed: Expression = typed, - error: Expression = error, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Error = { - val res = Error(typed, error, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Error = - copy( - typed = typed.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepLocations - ), - error = error.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepLocations - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Error = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Error = - copy(typed = fn(typed), error = fn(error)) - - /** @inheritdoc */ - override def toString: String = - s"""IR.Type.Error( - |typed = $typed, - |error = $error, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(typed, error) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${typed.showCode(indent)} ! ${error.showCode(indent)})" - } - object Error extends Info { - override val name: String = "!" - } - - /** IR nodes for dealing with typesets. */ - sealed trait Set extends Type { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Set - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Set - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Set - } - object Set { - - /** The representation of a typeset member. - * - * @param label the member's label, if given - * @param memberType the member's type, if given - * @param value the member's value, if given - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Member( - label: Name, - memberType: Expression, - value: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param label the member's label, if given - * @param memberType the member's type, if given - * @param value the member's value, if given - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - label: Name = label, - memberType: Expression = memberType, - value: Expression = value, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Member = { - val res = - Member(label, memberType, value, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Member = - copy( - label = label.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - memberType = memberType - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - value = value.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Member = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Member = { - copy( - label = label.mapExpressions(fn), - memberType = fn(memberType), - value = fn(value) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Member( - |label = $label, - |memberType = $memberType, - |value = $value, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(label, memberType, value) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val typeString = s" : ${memberType.showCode(indent)}" - val valueString = s" = ${value.showCode(indent)}" - s"(${label.showCode(indent)}$typeString$valueString)" - } - } - object Member extends Info { - override val name: String = "_ : _ = _" - } - - /** The typeset subsumption judgement `<:`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Subsumption( - left: Expression, - right: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: Expression = left, - right: Expression = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Subsumption = { - val res = Subsumption(left, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Subsumption = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Subsumption = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Subsumption = { - copy(left = fn(left), right = fn(right)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Subsumption( - |left = $left, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${left.showCode(indent)} <: ${right.showCode(indent)})" - } - object Subsumption extends Info { - override val name: String = "<:" - } - - /** The typeset equality judgement `~`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Equality( - left: Expression, - right: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: Expression = left, - right: Expression = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Equality = { - val res = Equality(left, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Equality = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Equality = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Equality = { - copy(left = fn(left), right = fn(right)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Equality( - |left = $left, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${left.showCode(indent)} ~ ${right.showCode(indent)}" - } - object Equality extends Info { - override val name: String = "~" - } - - /** The typeset concatenation operator `,`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Concat( - left: Expression, - right: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: Expression = left, - right: Expression = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Concat = { - val res = Concat(left, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Concat = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Concat = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Concat = { - copy(left = fn(left), right = fn(right)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Concat( - |left = $left, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${left.showCode(indent)}; ${right.showCode(indent)})" - } - object Concat extends Info { - override val name: String = ";" - } - - /** The typeset union operator `|`. - * - * @param operands the operands - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Union( - operands: List[Expression], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - operands: List[Expression] = operands, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Union = { - val res = Union(operands, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Union = - copy( - operands = operands.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Union = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Union = { - copy(operands = operands.map(fn)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Union( - |operands = $operands, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = operands.toList - - /** @inheritdoc */ - override def showCode(indent: Int): String = - operands.map(_.showCode(indent)).toList.mkString(" | ") - } - object Union extends Info { - override val name: String = "|" - } - - /** The typeset intersection operator `&`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Intersection( - left: Expression, - right: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: Expression = left, - right: Expression = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Intersection = { - val res = Intersection(left, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Intersection = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Intersection = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Intersection = { - copy(left = fn(left), right = fn(right)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Intersection( - |left = $left, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${left.showCode(indent)} & ${right.showCode(indent)})" - } - object Intersection extends Info { - override val name: String = "&" - } - - /** The typeset subtraction operator `\`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Subtraction( - left: Expression, - right: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Set - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand - * @param right the right operand - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: Expression = left, - right: Expression = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Subtraction = { - val res = Subtraction(left, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Subtraction = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Subtraction = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Subtraction = { - copy(left = fn(left), right = fn(right)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Type.Set.Subtraction( - |left = $left, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${left.showCode(indent)} \\ ${right.showCode(indent)})" - } - object Subtraction extends Info { - override val name: String = "\\" - } - } - } - - // === Function ============================================================= - - /** Functions in Enso. */ - sealed trait Function extends Expression { - - /** The function arguments. - * - * Please note that while the source language does not represent - * multi-argument lambdas, the internal language can and does. - */ - val arguments: List[DefinitionArgument] - - /** The body of the function */ - val body: Expression - - /** Whether or not the function _can_ be tail-call optimised. - * - * Please note that this being set to `true` does not _guarantee_ that the - * function is optimised. - */ - val canBeTCO: Boolean - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Function - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Function - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Function - } - object Function { - - /** The primitive function type in Enso: `->`. - * - * It should be noted that while the _surface_ language does not support - * multi-argument lambdas, our internal representation does so to allow for - * better optimisation. - * - * @param arguments the arguments to the lambda - * @param body the body of the lambda - * @param location the source location that the node corresponds to - * @param canBeTCO whether or not the function can be tail-call optimised - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Lambda( - override val arguments: List[DefinitionArgument], - override val body: Expression, - override val location: Option[IdentifiedLocation], - override val canBeTCO: Boolean = true, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Function - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param arguments the arguments to the lambda - * @param body the body of the lambda - * @param location the source location that the node corresponds to - * @param canBeTCO whether or not the function can be tail-call optimised - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - arguments: List[DefinitionArgument] = arguments, - body: Expression = body, - location: Option[IdentifiedLocation] = location, - canBeTCO: Boolean = canBeTCO, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Lambda = { - val res = - Lambda(arguments, body, location, canBeTCO, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Lambda = - copy( - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - body = body.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Lambda = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Lambda = { - copy(arguments = arguments.map(_.mapExpressions(fn)), body = fn(body)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Function.Lambda( - |arguments = $arguments, - |body = $body, - |location = $location, - |canBeTCO = $canBeTCO, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = arguments :+ body - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val args = arguments.map(_.showCode(indent)).mkString(" ") - val bodyStr = if (body.isInstanceOf[IR.Expression.Block]) { - s"\n${body.showCode(indent)}" - } else { - s"${body.showCode(indent)}" - } - - s"$args -> $bodyStr" - } - } - - /** A representation of the syntactic sugar for defining functions. - * - * @param name the name of the function - * @param arguments the arguments to the function - * @param body the body of the function - * @param location the source location that the node corresponds to - * @param canBeTCO whether or not the function can be tail-call optimised - * @param passData the pass metadata associated with this node - * @param diagnostics the compiler diagnostics for this node - */ - sealed case class Binding( - name: IR.Name, - override val arguments: List[DefinitionArgument], - override val body: Expression, - override val location: Option[IdentifiedLocation], - override val canBeTCO: Boolean = true, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Function - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the function - * @param arguments the arguments to the function - * @param body the body of the function - * @param location the source location that the node corresponds to - * @param canBeTCO whether or not the function can be tail-call optimised - * @param passData the pass metadata associated with this node - * @param diagnostics the compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name = name, - arguments: List[DefinitionArgument] = arguments, - body: Expression = body, - location: Option[IdentifiedLocation] = location, - canBeTCO: Boolean = canBeTCO, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Binding = { - val res = - Binding( - name, - arguments, - body, - location, - canBeTCO, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Binding = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - body = body.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Binding = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Binding = - copy( - name = name.mapExpressions(fn), - arguments = arguments.map(_.mapExpressions(fn)), - body = fn(body) - ) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Function.Binding( - |name = $name, - |arguments = $arguments, - |body = $body, - |location = $location, - |canBeTCO = $canBeTCO, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = (name :: arguments) :+ body - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val argsStr = arguments.map(_.showCode(indent)).mkString(" ") - val bodyStr = if (body.isInstanceOf[IR.Expression.Block]) { - s"\n${body.showCode(indent)}" - } else { - s"${body.showCode(indent)}" - } - - s"${name.name} $argsStr = $bodyStr" - } - } - } - - // === Definition-Site Arguments ============================================ - - /** Definition-site arguments in Enso. */ - sealed trait DefinitionArgument extends IR { - - /** The name of the argument. */ - val name: IR.Name - - /** The type of the argument */ - val ascribedType: Option[Expression] - - /** The default value of the argument. */ - val defaultValue: Option[Expression] - - /** Whether or not the argument is suspended. */ - val suspended: Boolean - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): DefinitionArgument - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): DefinitionArgument - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): DefinitionArgument - - def withName(ir: IR.Name): DefinitionArgument - } - object DefinitionArgument { - - /** The representation of an argument from a [[Function]] or - * [[IR.Module.Scope.Definition.Data]] definition site. - * - * To create an ignored argument, the argument name should be an - * [[IR.Name.Blank]]. - * - * @param name the name of the argument - * @param ascribedType the explicitly ascribed type of the argument, if - * present - * @param defaultValue the default value of the argument, if present - * @param suspended whether or not the argument has its execution suspended - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Specified( - override val name: IR.Name, - override val ascribedType: Option[Expression], - override val defaultValue: Option[Expression], - override val suspended: Boolean, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends DefinitionArgument - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the argument - * @param ascribedType the explicitly ascribed type of the argument, if - * present - * @param defaultValue the default value of the argument, if present - * @param suspended whether or not the argument has its execution suspended - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: IR.Name = name, - ascribedType: Option[Expression] = ascribedType, - defaultValue: Option[Expression] = defaultValue, - suspended: Boolean = suspended, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Specified = { - val res = Specified( - name, - ascribedType, - defaultValue, - suspended, - location, - passData, - diagnostics - ) - res.id = id - res - } - - override def withName(ir: Name): DefinitionArgument = copy(name = ir) - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Specified = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - ascribedType = ascribedType.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - defaultValue = defaultValue.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Specified = copy(location = location) - - /** @inheritdoc */ - def mapExpressions(fn: Expression => Expression): Specified = { - copy( - name = name.mapExpressions(fn), - ascribedType = ascribedType.map(fn), - defaultValue = defaultValue.map(fn) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.DefinitionArgument.Specified( - |name = $name, - |ascribedType = $ascribedType, - |defaultValue = $defaultValue, - |suspended = $suspended, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - name :: ascribedType.toList ++ defaultValue.toList - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val withoutLazy = - if (defaultValue.isDefined && ascribedType.isDefined) { - val name = this.name.showCode(indent) - val typeExpr = this.ascribedType.get.showCode(indent) - val defaultExpr = this.defaultValue.get.showCode(indent) - s"($name : ($typeExpr) = ($defaultExpr))" - } else if (defaultValue.isDefined) { - val name = this.name.showCode(indent) - val defaultExpr = this.defaultValue.get.showCode(indent) - s"($name = $defaultExpr)" - } else if (ascribedType.isDefined) { - val name = this.name.showCode(indent) - val typeExpr = this.ascribedType.get.showCode(indent) - s"($name : $typeExpr)" - } else { - s"${name.showCode(indent)}" - } - - if (suspended) { - s"~$withoutLazy" - } else { - withoutLazy - } - } - } - } - - // === Applications ========================================================= - - /** All function applications in Enso. */ - sealed trait Application extends Expression { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Application - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Application - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Application - } - object Application { - - /** A standard prefix function application. - * - * @param function the function being called - * @param arguments the arguments to the function being called - * @param hasDefaultsSuspended whether the function application has any - * argument defaults in `function` suspended - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Prefix( - function: Expression, - arguments: List[CallArgument], - hasDefaultsSuspended: Boolean, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Application - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param function the function being called - * @param arguments the arguments to the function being called - * @param hasDefaultsSuspended whether the function application has any - * argument defaults in `function` suspended - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - function: Expression = function, - arguments: List[CallArgument] = arguments, - hasDefaultsSuspended: Boolean = hasDefaultsSuspended, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Prefix = { - val res = - Prefix( - function, - arguments, - hasDefaultsSuspended, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Prefix = - copy( - function = function.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arguments = arguments.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Prefix = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Prefix = { - copy(function = fn(function), arguments.map(_.mapExpressions(fn))) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Prefix( - |function = $function, - |arguments = $arguments, - |hasDefaultsSuspended = $hasDefaultsSuspended, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = function :: arguments - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val argStr = arguments.map(_.showCode(indent)).mkString(" ") - - s"((${function.showCode(indent)}) $argStr)" - } - } - - /** A representation of a term that is explicitly forced. - * - * @param target the expression being forced - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Force( - target: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Application - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param target the expression being forced - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - target: Expression = target, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Force = { - val res = Force(target, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Force = - copy( - target = target.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Force = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Force = { - copy(target = fn(target)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Force( - |target = $target, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(target) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(FORCE ${target.showCode(indent)})" - } - - /** Literal applications in Enso. */ - sealed trait Literal extends Application { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Literal - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Literal - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Literal - } - - object Literal { - - /** A representation of a typeset literal. - * - * These are necessary as they delimit pattern contexts. - * - * @param expression the expression of the typeset body - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Typeset( - expression: Option[Expression], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Literal - with IRKind.Primitive { - override protected var id: Identifier = randomId - - override def mapExpressions(fn: Expression => Expression): Typeset = - copy(expression = expression.map(fn)) - - /** Creates a copy of `this`. - * - * @param expression the expression of the typeset body - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updataed with the specified values - */ - def copy( - expression: Option[Expression] = expression, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Typeset = { - val res = Typeset(expression, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Typeset = - copy( - expression = expression.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Typeset = copy(location = location) - - /** @inheritdoc */ - override def toString: String = - s"""IR.Application.Literal.Typeset( - |expression = $expression, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = - expression.map(List(_)).getOrElse(List()) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val exprString = if (expression.isDefined) { - expression.get.showCode(indent) - } else "" - - s"{ $exprString }" - } - } - - /** A representation of a vector literal. - * - * @param items the items being put in the vector - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Sequence( - items: List[Expression], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Literal - with IRKind.Primitive { - override protected var id: Identifier = randomId - - override def mapExpressions(fn: Expression => Expression): Sequence = - copy(items = items.map(fn)) - - /** Creates a copy of `this`. - * - * @param items the items held by this vector - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - items: List[Expression] = items, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Sequence = { - val res = Sequence(items, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Sequence = - copy( - items = items.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Sequence = copy(location = location) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Literal.Vector( - |items = $items, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = items - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val itemsStr = items.map(_.showCode(indent)).mkString(", ") - s"[$itemsStr]" - } - } - } - - /** Operator applications in Enso. */ - sealed trait Operator extends Application { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Operator - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Operator - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Operator - } - object Operator { - - /** A representation of a generic binary operator application in Enso. - * - * @param left the left operand to `operator` - * @param operator the operator function being called - * @param right the right operand to `operator` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Binary( - left: CallArgument, - operator: IR.Name, - right: CallArgument, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Operator - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param left the left operand to `operator` - * @param operator the operator function being called - * @param right the right operand to `operator` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - left: CallArgument = left, - operator: IR.Name = operator, - right: CallArgument = right, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Binary = { - val res = - Binary(left, operator, right, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Binary = - copy( - left = left.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - operator = operator.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - right = right.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Binary = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Binary = { - copy(left = left.mapExpressions(fn), right = right.mapExpressions(fn)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Operator.Binary( - |left = $left, - |operator = $operator, - |right = $right, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(left, operator, right) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val opStr = operator.showCode(indent) - - s"((${left.showCode(indent)}) $opStr (${right.showCode(indent)}))" - } - } - - /** Operator sections. */ - sealed trait Section extends Operator { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Section - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Section - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Section - } - object Section { - - /** Represents a left operator section of the form `(arg op)`. - * - * @param arg the argument (on the left of the operator) - * @param operator the operator - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Left( - arg: CallArgument, - operator: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Section - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param arg the argument (on the left of the operator) - * @param operator the operator - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - arg: CallArgument = arg, - operator: IR.Name = operator, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: IR.Identifier = id - ): Left = { - val res = Left(arg, operator, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Left = - copy( - arg = arg.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - operator = operator - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Left = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Section = - copy( - arg = arg.mapExpressions(fn), - operator = operator.mapExpressions(fn) - ) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Operator.Section.Left( - |arg = $arg, - |operator = $operator, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(arg, operator) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${arg.showCode(indent)} ${operator.showCode(indent)})" - } - - /** Represents a sides operator section of the form `(op)` - * - * @param operator the operator - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Sides( - operator: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Section - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param operator the operator - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - operator: IR.Name = operator, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Sides = { - val res = Sides(operator, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Sides = - copy( - operator = operator - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Sides = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Section = - copy(operator = operator.mapExpressions(fn)) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Operator.Section.Sides( - |operator = $operator, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(operator) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${operator.showCode(indent)})" - } - - /** Represents a right operator section of the form `(op arg)` - * - * @param operator the operator - * @param arg the argument (on the right of the operator) - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Right( - operator: IR.Name, - arg: CallArgument, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Section - with IRKind.Sugar { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param operator the operator - * @param arg the argument (on the right of the operator) - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - operator: IR.Name = operator, - arg: CallArgument = arg, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Right = { - val res = Right(operator, arg, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Right = - copy( - operator = operator - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - arg = arg.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Right = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Section = { - copy( - operator = operator.mapExpressions(fn), - arg = arg.mapExpressions(fn) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Application.Operator.Section.Right( - |operator = $operator, - |arg = $arg, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(operator, arg) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(${operator.showCode(indent)} ${arg.showCode(indent)})" - } - } - } - } - - // === Call-Site Arguments ================================================== - - /** Call-site arguments in Enso. */ - sealed trait CallArgument extends IR { - - /** The name of the argument, if present. */ - val name: Option[IR.Name] - - /** The expression of the argument, if present. */ - val value: Expression - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): CallArgument - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): CallArgument - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): CallArgument - } - object CallArgument { - - /** A representation of an argument at a function call site. - * - * A [[CallArgument]] where the `value` is an [[IR.Name.Blank]] is a - * representation of a lambda shorthand argument. - * - * @param name the name of the argument being called, if present - * @param value the expression being passed as the argument's value - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Specified( - override val name: Option[IR.Name], - override val value: Expression, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends CallArgument - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the argument being called, if present - * @param value the expression being passed as the argument's value - * @param location the source location that the node corresponds to - * @param shouldBeSuspended whether or not the argument should be passed - * suspended - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - name: Option[IR.Name] = name, - value: Expression = value, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Specified = { - val res = Specified( - name, - value, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Specified = - copy( - name = name.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - value = value.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Specified = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Specified = { - copy(name = name.map(n => n.mapExpressions(fn)), value = fn(value)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.CallArgument.Specified( - |name = $name, - |value = $value, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = name.toList :+ value - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - if (name.isDefined) { - s"(${name.get.showCode(indent)} = ${value.showCode(indent)})" - } else { - s"${value.showCode(indent)}" - } - } - } - } - - // === Case Expression ====================================================== - - /** The Enso case expression. */ - sealed trait Case extends Expression { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Case - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Case - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Case - } - object Case { - - /** The main body of the Enso case expression. - * - * @param scrutinee the expression whose value is being matched on - * @param branches the branches of the case expression - * @param isNested if true, the flag indicates that the expr represents a desugared nested case - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Expr( - scrutinee: Expression, - branches: Seq[Branch], - isNested: Boolean, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Case - with IRKind.Primitive { - override protected var id: Identifier = randomId - - def this( - scrutinee: Expression, - branches: Seq[Branch], - location: Option[IdentifiedLocation], - passData: MetadataStorage, - diagnostics: DiagnosticStorage - ) = { - this(scrutinee, branches, false, location, passData, diagnostics) - } - - /** Creates a copy of `this`. - * - * @param scrutinee the expression whose value is being matched on - * @param branches the branches of the case expression - * @param isNested if true, the flag indicates that the expr represents a desugared nested case - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - scrutinee: Expression = scrutinee, - branches: Seq[Branch] = branches, - isNested: Boolean = isNested, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Expr = { - val res = - Expr(scrutinee, branches, isNested, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Expr = - copy( - scrutinee = scrutinee.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - branches = branches.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - isNested = isNested, - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Expr = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Expr = { - copy( - scrutinee = fn(scrutinee), - branches.map(_.mapExpressions(fn)) - ) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Expr( - |scrutinee = $scrutinee, - |branches = $branches, - |isNested = $isNested, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = scrutinee :: branches.toList - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val newIndent = indent + indentLevel - val headerStr = s"case ${scrutinee.showCode(indent)} of" - val branchesStr = branches - .map(mkIndent(newIndent) + _.showCode(newIndent)) - .mkString("\n") - - s"$headerStr\n$branchesStr" - } - } - - object Expr { - def apply( - scrutinee: Expression, - branches: Seq[Branch], - location: Option[IdentifiedLocation] - ): Expr = - apply( - scrutinee, - branches, - location, - new MetadataStorage(), - new DiagnosticStorage() - ) - - def apply( - scrutinee: Expression, - branches: Seq[Branch], - location: Option[IdentifiedLocation], - passData: MetadataStorage, - diagnostics: DiagnosticStorage - ): Expr = new Expr(scrutinee, branches, location, passData, diagnostics) - } - - /** A branch in a case statement. - * - * @param pattern the pattern that attempts to match against the scrutinee - * @param expression the expression that is executed if the pattern matches - * @param terminalBranch the flag indicating whether the branch represents the final pattern to be checked - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Branch( - pattern: Pattern, - expression: Expression, - terminalBranch: Boolean, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Case - with IRKind.Primitive { - override protected var id: Identifier = randomId - - def this( - pattern: Pattern, - expression: Expression, - location: Option[IdentifiedLocation], - passData: MetadataStorage, - diagnostics: DiagnosticStorage - ) = { - this(pattern, expression, true, location, passData, diagnostics) - } - - /** Creates a copy of `this`. - * - * @param pattern the pattern that attempts to match against the scrutinee - * @param expression the expression that is executed if the pattern matches - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - pattern: Pattern = pattern, - expression: Expression = expression, - terminalBranch: Boolean = terminalBranch, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Branch = { - val res = Branch( - pattern, - expression, - terminalBranch, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Branch = - copy( - pattern = pattern.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - expression = expression.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - terminalBranch = terminalBranch, - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Branch = - copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Branch = { - copy(pattern = pattern.mapExpressions(fn), expression = fn(expression)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Branch( - |pattern = $pattern, - |expression = $expression, - |terminalBranch = $terminalBranch, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(pattern, expression) - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val newIndent = indent + indentLevel - val bodyStr = if (expression.isInstanceOf[IR.Expression.Block]) { - s"\n${mkIndent(newIndent)}${expression.showCode(newIndent)}" - } else { - s"${expression.showCode(indent)}" - } - s"${pattern.showCode(indent)} -> $bodyStr" - } - } - - object Branch { - def apply( - pattern: Pattern, - expression: Expression, - location: Option[IdentifiedLocation] - ): Branch = - apply( - pattern, - expression, - location, - new MetadataStorage(), - new DiagnosticStorage() - ) - - def apply( - pattern: Pattern, - expression: Expression, - location: Option[IdentifiedLocation], - passData: MetadataStorage, - diagnostics: DiagnosticStorage - ): Branch = - new Branch(pattern, expression, location, passData, diagnostics) - } - } - - // === Patterns ============================================================= - - /** The different types of patterns that can occur in a match. */ - sealed trait Pattern extends IR { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Pattern - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Pattern - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Pattern - } - object Pattern { - - /** A named pattern. - * - * Named patterns take the form of a single identifier (e.g. `a` or `_`). - * As a result they can be used to represent a catch all pattern (e.g. - * `_ -> ...` or `a -> ...`). - * - * @param name the name that constitutes the pattern - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Name( - name: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Pattern { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name that constitutes the pattern - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the provided values - */ - def copy( - name: IR.Name = name, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Name = { - val res = Name(name, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Name = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Name = { - copy(name = name.mapExpressions(fn)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Pattern.Name( - |name = $name, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Name = - copy(location = location) - - /** @inheritdoc */ - override def children: List[IR] = List(name) - - /** @inheritdoc */ - override def showCode(indent: Int): String = name.showCode(indent) - } - - /** A pattern that destructures a constructor application. - * - * The first part of the pattern must be a refferent name. The fields of - * the constructor may be any available kind of pattern. - * - * @param constructor the constructor being matched on - * @param fields the asserted fields of the constructor - * @param location the source location for this IR node - * @param passData any pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Constructor( - constructor: IR.Name, - fields: List[IR.Pattern], - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Pattern { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param constructor the constructor being matched on - * @param fields the asserted fields of the constructor - * @param location the source location for this IR node - * @param passData any pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the new identifier for this node - * @return a copy of `this`, updated with the provided values - */ - def copy( - constructor: IR.Name = constructor, - fields: List[IR.Pattern] = fields, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Constructor = { - val res = - Constructor(constructor, fields, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Constructor = - copy( - constructor = constructor.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - fields = fields.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** Checks if the constructor pattern has been desugared. - * - * A constructor pattern has been desugared if all of its fields are - * [[Pattern.Name]]. - * - * @return `true` if the pattern has been desugared, `false` otherwise - */ - def isDesugared: Boolean = { - fields.forall { - case _: Pattern.Name => true - case _: Pattern.Constructor => false - case _: Pattern.Literal => true - case _: Pattern.Type => true - case _: Pattern.Documentation => - throw new CompilerError( - "Branch documentation should not be present " + - "inside a constructor pattern." - ) - case _: Error.Pattern => true - } - } - - /** Gets the patterns fields as [[Pattern.Name]] if they are. - * - * @return the fields from `this` - */ - def fieldsAsNamed: List[Option[Pattern.Name]] = { - fields.map { - case f: Pattern.Name => Some(f) - case _ => None - } - } - - /** Unsafely gets the pattern's fields as if they are [[Pattern.Name]]. - * - * @return the fields from `this` - */ - def unsafeFieldsAsNamed: List[Pattern.Name] = { - fieldsAsNamed.map(_.get) - } - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Constructor = - copy( - constructor = constructor.mapExpressions(fn), - fields = fields.map(_.mapExpressions(fn)) - ) - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Pattern.Constructor( - |constructor = $constructor, - |fields = $fields, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Constructor = copy(location = location) - - /** @inheritdoc */ - override def children: List[IR] = constructor :: fields - - /** @inheritdoc */ - override def showCode(indent: Int): String = { - val fieldsStr = - fields.map(f => s"(${f.showCode(indent)})").mkString(" ") - - s"${constructor.name} $fieldsStr" - } - } - - /** A literal pattern. - * - * A literal pattern matches on constants. - * - * @param literal the literal representing the pattern - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Literal( - literal: IR.Literal, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Pattern { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param literal the literal representing the pattern - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the provided values - */ - def copy( - literal: IR.Literal = literal, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Literal = { - val res = Literal(literal, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Literal = - copy( - literal = literal.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Literal = { - copy(literal = literal.mapExpressions(fn)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Pattern.Literal( - |literal = $literal, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Literal = - copy(location = location) - - /** @inheritdoc */ - override def children: List[IR] = List(literal) - - /** @inheritdoc */ - override def showCode(indent: Int): String = literal.showCode(indent) - } - - /** A type pattern. - * - * A type pattern matches on types. Type pattern is composed of two parts: - * - a single identifier (e.g. `a` or `_`) - * - a (potentially fully qualified) type name - * E.g., `a : Foo -> ...` or `_ : Bar -> ...`` - * - * @param name the name of the bound variable, or wildcard - * @param tpe the name of the type to match on - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Type( - name: IR.Name, - tpe: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Pattern { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param name the name of the bound variable, or wildcard - * @param tpe the name of the type to match on - * @param location the source location for this IR node - * @param passData any pass metadata associated with the node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the provided values - */ - def copy( - name: IR.Name = name, - tpe: IR.Name = tpe, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Type = { - val res = Type(name, tpe, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Type = - copy( - name = name.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - tpe = tpe.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Type = { - copy(name = name.mapExpressions(fn), tpe = tpe.mapExpressions(fn)) - } - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Pattern.Type( - |name = $name, - |tpe = $tpe, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Type = - copy(location = location) - - /** @inheritdoc */ - override def children: List[IR] = List(name, tpe) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"${name.showCode(indent)} : ${tpe.showCode()}" - } - - /** A dummy pattern used for storing documentation comments between branches - * in a pattern match. - * - * To store a documentation comment next to a branch, a dummy branch is - * created with its pattern being an instance of this Doc and expression - * being empty. - * - * @param doc the documentation entity - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - final case class Documentation( - doc: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Pattern { - override protected var id: Identifier = randomId - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Documentation = - this - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Documentation = - copy(location = location) - - /** Creates a copy of `this`. - * - * @param doc the documentation entity - * @param location the source location for this IR node - * @param passData any pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the new identifier for this node - * @return a copy of `this`, updated with the provided values - */ - def copy( - doc: String = doc, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Documentation = { - val res = Documentation(doc, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean, - keepMetadata: Boolean, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Documentation = - copy( - doc, - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def children: List[IR] = Nil - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Case.Pattern.Doc( - |doc = $doc, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def showCode(indent: Int): String = s"## $doc" - } - } - - // === Comments ============================================================= - - /** Enso comment entities. */ - sealed trait Comment extends Expression with Module.Scope.Definition { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Comment - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Comment - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Comment - } - object Comment { - - /** A documentation comment in the Enso source. - * - * @param doc the documentation entity - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Documentation( - doc: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Comment - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param doc the documentation of `commented` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - doc: String = doc, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Documentation = { - val res = Documentation(doc, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Documentation = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Documentation = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): Documentation = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Comment.Documentation( - |doc = $doc, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"## $doc" - } - } - - // === Foreign ============================================================== - - /** Foreign code entities. */ - sealed trait Foreign extends Expression { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Foreign - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Foreign - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Foreign - } - object Foreign { - - /** A foreign code definition in Enso. - * - * @param lang the foreign language being written - * @param code the code written in `lang` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Definition( - lang: String, - code: String, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Foreign - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param lang the foreign language being written - * @param code the code written in `lang` - * @param location the source location that the node corresponds to - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - lang: String = lang, - code: String = code, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Definition = { - val res = Definition(lang, code, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Definition = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Definition = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Definition = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Foreign.Definition( - |lang = $lang, - |code = $code, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = "FOREIGN DEF" - } - } - - // === Diagnostics ========================================================== - - /** A representation of various kinds of diagnostic in the IR. */ - sealed trait Diagnostic extends Serializable { - - /** @return a human-readable description of this error condition. - */ - def message: String - - /** @return a human-readable description of this error condition, formatted for immediate reporting. */ - def formattedMessage: String = message - - /** The location at which the diagnostic occurs. */ - val location: Option[IdentifiedLocation] - - /** The important keys identifying identity of the diagnostic - */ - def diagnosticKeys(): Array[Any] - } - object Diagnostic { - - /** Represents the various kinds of diagnostics in the IR. */ - sealed trait Kind - object Kind { - - /** Diagnostics that should be reported during the static compilation - * phase of execution. - */ - sealed trait Static extends Kind - - /** Diagnostics that should remain at runtime for display during - * interactive execution. - */ - sealed trait Interactive extends Kind - } - } - - // === Warnings ============================================================= - - /** A trait for all warnings in Enso's IR. */ - sealed trait Warning extends Diagnostic - object Warning { - - /** Warnings about unused language entities. */ - sealed trait Unused extends Warning { - val name: IR.Name - } - object Unused { - - /** A warning about an unused function argument. - * - * @param name the name that is unused - */ - sealed case class FunctionArgument(override val name: Name) - extends Unused { - override def message: String = s"Unused function argument ${name.name}." - - override def diagnosticKeys(): Array[Any] = Array(name.name) - - override def toString: String = s"Unused.FunctionArgument(${name.name})" - - override val location: Option[IdentifiedLocation] = name.location - } - - sealed case class PatternBinding(override val name: Name) extends Unused { - override def message: String = s"Unused pattern binding ${name.name}." - - override def diagnosticKeys(): Array[Any] = Array(name.name) - - override def toString: String = s"Unused.PatternBinding(${name.name})" - - override val location: Option[IdentifiedLocation] = name.location - } - - /** A warning about an unused binding. - * - * @param name the name that is unused - */ - sealed case class Binding(override val name: Name) extends Unused { - override def message: String = s"Unused variable ${name.name}." - - override def diagnosticKeys(): Array[Any] = Array(name.name) - - override def toString: String = s"Unused.Binding(${name.name})" - - override val location: Option[IdentifiedLocation] = name.location - } - } - - /** Warnings for unreachable code. */ - sealed trait Unreachable extends Warning { - val location: Option[IdentifiedLocation] - } - object Unreachable { - - /** A warning for unreachable branches in a case expression. - * - * @param location the location of the unreachable branches - */ - sealed case class Branches( - override val location: Option[IdentifiedLocation] - ) extends Unreachable { - val atLocation = - if (location.isDefined) { s" at location ${location.get}" } - else { "" } - - override def message: String = s"Unreachable case branches$atLocation." - - override def diagnosticKeys(): Array[Any] = Array(atLocation) - } - } - - case class DuplicatedImport( - override val location: Option[IdentifiedLocation], - originalImport: IR.Module.Scope.Import, - symbolName: String, - source: Source - ) extends Warning { - override def message: String = { - val originalImportRepr = - originalImport.location match { - case Some(location) => - s"'${originalImport.showCode()}' in ${fileLocationFromSection(location, source)}" - case None => originalImport.showCode() - } - s"Duplicated import of $symbolName. The original import is ${originalImportRepr}." - } - - override def diagnosticKeys(): Array[Any] = Array() - } - - /** A warning about a `@Tail_Call` annotation placed in a non-tail - * position. - * @param location the location of the annotated application - */ - case class WrongTco(override val location: Option[IdentifiedLocation]) - extends Warning { - override def message: String = - "A @Tail_Call annotation was placed in a non-tail-call position." - - override def diagnosticKeys(): Array[Any] = Array() - } - - /** A warning about a `@Builtin_Method` annotation placed in a method - * with unexpected body. - * @param location the location of the annotated application - */ - case class WrongBuiltinMethod( - override val location: Option[IdentifiedLocation] - ) extends Warning { - override def message: String = - "A @Builtin_Method annotation allows only the name of the builtin node in the body." - - override def diagnosticKeys(): Array[Any] = Array() - } - - /** A warning raised when a method is defined with a `self` parameter defined - * not in the first position in the parameters' list.` - * - * @param ir the annotated application - * @param paramPosition the reason why the annotation cannot be obeyed - */ - case class WrongSelfParameterPos( - funName: IR.Name, - ir: IR, - paramPosition: Int - ) extends Warning { - override val location: Option[IdentifiedLocation] = ir.location - override def message: String = - s"${funName.name}: Self parameter should be declared as the first parameter. Instead its position is: ${paramPosition + 1}." - - override def diagnosticKeys(): Array[Any] = - Array(ir.showCode(), paramPosition) - } - - /** Warnings about shadowing names. */ - sealed trait Shadowed extends Warning { - - /** The [[IR]] shadowing the warned expression. */ - val shadower: IR - } - object Shadowed { - - /** A warning that a later-defined lambda parameter shadows an - * earlier-defined lambda parameter. - * - * @param shadowedName the name being shadowed - * @param shadower the expression shadowing `warnedExpr` - * @param location the location at which the shadowing takes place - */ - sealed case class FunctionParam( - shadowedName: String, - override val shadower: IR, - override val location: Option[IdentifiedLocation] - ) extends Shadowed { - override def message: String = - s"The argument $shadowedName is shadowed by $shadower" - - override def diagnosticKeys(): Array[Any] = - Array(shadowedName, shadower) - } - - /** A warning that a later-defined pattern variable shadows an - * earlier-defined pattern variable. - * - * @param shadowedName the name being shadowed - * @param shadower the expression shadowing `warnedExpr` - * @param location the location at which the shadowing takes place - */ - sealed case class PatternBinding( - shadowedName: String, - override val shadower: IR, - override val location: Option[IdentifiedLocation] - ) extends Shadowed { - override def message: String = - s"The pattern field $shadowedName is shadowed by $shadower." - - override def diagnosticKeys(): Array[Any] = - Array(shadowedName, shadower) - } - - /** A warning that a submodule is being shadowed by the type of the same name - * therefore preventing the user from accessing the module via a qualified name. - * - * @param typename the type name shadowing the module - * @param moduleName the module being shadowed - * @param shadower the expression shadowing `moduleName` - * @param location the location at which the shadowing takes place - */ - sealed case class SyntheticModule( - typeName: String, - moduleName: IR.Name.Qualified, - override val shadower: IR, - override val location: Option[IdentifiedLocation] - ) extends Shadowed { - override def message: String = - s"""Declaration of type $typeName shadows module ${moduleName.name} making it inaccessible via a qualified name.""" - override def diagnosticKeys(): Array[Any] = - Array(typeName, moduleName, shadower) - - } - - /** Used when the exported type of the module can name conflict with fully qualified names of submodules. - * - * @param name the module name - * @param tpeName the name of the exported type leading to conflicts - * @param firstConflict the name of the module that can be innaccessible because of the name conflict - * @param shadower the export statement leading to a conflict - * @param location the location of the export statement - */ - sealed case class TypeInModuleNameConflicts( - name: String, - tpeName: String, - firstConflict: String, - override val shadower: IR, - override val location: Option[IdentifiedLocation] - ) extends Shadowed { - override def message: String = - s"The exported type `$tpeName` in `$name` module will cause name conflict " + - s"when attempting to use a fully qualified name of the `$firstConflict` module." - - /** The important keys identifying identity of the diagnostic - */ - override def diagnosticKeys(): Array[Any] = - Array(name, tpeName, shadower) - } - } - - /** A warning raised when a call is annotated with `@Auto_Parallel`, but the - * annotation cannot be obeyed. - * - * @param ir the annotated application - * @param reason the reason why the annotation cannot be obeyed - */ - case class FailedParallelism( - ir: IR, - reason: String - ) extends Warning { - override val location: Option[IdentifiedLocation] = ir.location - override def message: String = - s"The expression ${ir.showCode()} could not be parallelised: $reason." - - override def diagnosticKeys(): Array[Any] = Array(ir.showCode(), reason) - } - - case class NonUnitTypeUsedOnValueLevel(ir: IR.Name, context: String) - extends Warning { - - /** @return a human-readable description of this error condition. - */ - override def message: String = - s"A non-unit type ${ir.name} is used on value level (in ${context})." + - " This is probably an error." - - /** The location at which the diagnostic occurs. */ - override val location: Option[IdentifiedLocation] = ir.location - - /** The important keys identifying identity of the diagnostic - */ - override def diagnosticKeys(): Array[Any] = Array(ir.name) - } - } - - // === Errors =============================================================== - - /** A trait for all errors in Enso's IR. */ - sealed trait Error - extends Expression - with IR.Module.Scope.Definition - with Diagnostic { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Error - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Error - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Error - } - object Error { - - /** An error resulting from processing conversion methods. - * - * @param storedIr the IR that contains the error - * @param reason the explanation for the error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler dianostics for this node - */ - sealed case class Conversion( - storedIr: IR, - reason: Conversion.Reason, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Interactive - with IRKind.Primitive - with IR.Name { - override val name: String = "conversion_error" - - override def mapExpressions(fn: Expression => Expression): Conversion = - this - - override def setLocation( - location: Option[IdentifiedLocation] - ): Conversion = { - copy(storedIr = storedIr.setLocation(location)) - } - - /** Create a copy of `this`. - * - * @param storedIr the IR that contains the error - * @param reason the explanation for the error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler dianostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - storedIr: IR = storedIr, - reason: Conversion.Reason = reason, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Conversion = { - val res = Conversion(storedIr, reason, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean, - keepMetadata: Boolean, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Conversion = { - copy( - storedIr = storedIr.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - } - - /** @inheritdoc */ - override def children: List[IR] = List(storedIr) - - /** @inheritdoc */ - override protected var id: Identifier = randomId - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Error: ${storedIr.showCode(indent)})" - - /** @inheritdoc */ - override def message: String = reason.explain - - override def diagnosticKeys(): Array[Any] = Array(reason.explain) - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = storedIr.location - } - object Conversion { - - /** The reason for the error. */ - sealed trait Reason { - def explain: String - } - - case object MissingArgs extends Reason { - override def explain: String = - "A conversion definition must have at least one argument." - } - - case object UnsupportedSourceType extends Reason { - override def explain: String = - "Arbitrary expressions are not yet supported as source types." - } - - case class MissingSourceType(argName: String) extends Reason { - override def explain: String = - s"The argument `$argName` does not define a source type." - } - - case class MissingSelfParam(argName: String) extends Reason { - override def explain: String = - s"""|Conversion definition must have an explicit `self` parameter in the first position. - |Got `$argName` instead.""".stripMargin - } - - case class NonDefaultedArgument(argName: String) extends Reason { - override def explain: String = - s"Additional arguments in a conversion must have a default, but " + - s"`$argName` does not." - } - - case class SuspendedSourceArgument(argName: String) extends Reason { - override def explain: String = - s"The `that` type argument in a conversion (here $argName) cannot " + - s"be suspended." - } - - case class InvalidSourceArgumentName(argName: String) extends Reason { - override def explain: String = - s"The source type argument must be ignored or named `that`, but" + - s" ${argName} was found." - } - } - - /** A representation of an error resulting from name resolution. - * - * @param originalName the original name that could not be resolved - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Resolution( - originalName: IR.Name, - reason: Resolution.Reason, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Interactive - with IRKind.Primitive - with IR.Name { - override val name: String = originalName.name - - override def mapExpressions(fn: Expression => Expression): Resolution = - this - - override def setLocation( - location: Option[IdentifiedLocation] - ): Resolution = - copy(originalName = originalName.setLocation(location)) - - /** Creates a copy of `this`. - * - * @param originalName the original name that could not be resolved - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - originalName: IR.Name = originalName, - reason: Resolution.Reason = reason, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Resolution = { - val res = Resolution(originalName, reason, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Resolution = - copy( - originalName = originalName - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = randomId - ) - - /** @inheritdoc */ - override def children: List[IR] = List(originalName) - - /** @inheritdoc */ - override protected var id: Identifier = randomId - - /** @inheritdoc */ - override def showCode(indent: Int): String = originalName.showCode(indent) - - /** @inheritdoc */ - override def message: String = reason.explain(originalName) - - /** @inheritdoc */ - override def formattedMessage: String = s"${message}." - - override def diagnosticKeys(): Array[Any] = Array(reason) - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = originalName.location - } - - object Resolution { - - /** A representation of a symbol resolution error. - */ - sealed trait Reason { - def explain(originalName: IR.Name): String - } - - case object UnresolvedSequenceMacro extends Reason { - override def explain(originalName: Name): String = - "No definition for the sequence macro could be found. Try" + - " importing the default definition from the Standard.Base module" - } - - /** An error coming from an unknown annotation name. - */ - case object UnknownAnnotation extends Reason { - override def explain(originalName: Name): String = - s"The annotation ${originalName.name} is not defined" - } - - /** An error coming from a tail call annotation placed in a syntactically - * incorrect position. - */ - case object UnexpectedAnnotation extends Reason { - override def explain(originalName: Name): String = - s"Unexpected ${originalName.name} annotation. This annotation can " + - s"only be used with function applications" - } - - /** An error coming from an unexpected occurence of a polyglot symbol. - * - * @param context the description of a context in which the error - * happened. - */ - case class UnexpectedPolyglot(context: String) extends Reason { - override def explain(originalName: Name): String = - s"The name ${originalName.name} resolved to a polyglot symbol, " + - s"but polyglot symbols are not allowed in $context" - } - - /** An error coming from an unexpected occurence of a constructor. - * - * @param context the description of a context in which the error - * happened. - */ - case class UnexpectedConstructor(context: String) extends Reason { - override def explain(originalName: Name): String = - s"The name ${originalName.name} resolved to a constructor, " + - s"but constructors are not allowed in $context" - } - - /** An error coming from an unexpected occurence of a static method. - * - * @param context the description of a context in which the error - * happened. - */ - case class UnexpectedMethod(context: String) extends Reason { - override def explain(originalName: Name): String = - s"The name ${originalName.name} resolved to a method, " + - s"but methods are not allowed in $context" - } - - /** An error coming from an unexpected occurence of a module. - * - * @param context the description of a context in which the error - * happened. - */ - case class UnexpectedModule(context: String) extends Reason { - override def explain(originalName: Name): String = - s"The name ${originalName.name} resolved to a module, " + - s"but modules are not allowed in $context" - } - - /** An error coming from an unexpected occurence of a type. - * - * @param context the description of a context in which the error - * happened. - */ - case class UnexpectedType(context: String) extends Reason { - override def explain(originalName: Name): String = - s"The name ${originalName.name} resolved to a type, " + - s"but types are not allowed in $context" - } - - /** An error coming from usage of an undefined variable name. - */ - case object VariableNotInScope extends Reason { - override def explain(originalName: Name): String = - s"Variable `${originalName.name}` is not defined" - } - - /** An error coming from name resolver. - * - * @param err the original error. - */ - case class ResolverError(private val explain: ExplainResolution) - extends Reason { - - /** Provides a human-readable explanation of the error. - * @param originalName the original unresolved name. - * @return a human-readable message. - */ - override def explain(originalName: IR.Name): String = - this.explain.explain(originalName) - } - - trait ExplainResolution { - def explain(originalName: IR.Name): String - } - - case class MissingLibraryImportInFQNError(namespace: String) - extends Reason { - override def explain(originalName: IR.Name): String = - s"Fully qualified name references a library $namespace.${originalName.name} but an import statement for it is missing" - } - - } - - /** A representation of an error resulting from wrong pattern matches. - * - * @param originalPattern pattern that resulted in the error - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @return a copy of `this`, updated with the specified values - */ - sealed case class Pattern( - originalPattern: IR.Pattern, - reason: Pattern.Reason, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Interactive - with IR.Pattern { - override def mapExpressions(fn: Expression => Expression): Pattern = - copy(originalPattern = originalPattern.mapExpressions(fn)) - - override def setLocation(location: Option[IdentifiedLocation]): Pattern = - copy(originalPattern = originalPattern.setLocation(location)) - - /** Creates a copy of `this`. - * - * @param originalPattern the pattern that resulted in the error - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - originalPattern: IR.Pattern = originalPattern, - reason: Pattern.Reason = reason, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Pattern = { - val res = Pattern(originalPattern, reason, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Pattern = - copy( - originalPattern = originalPattern - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - override def message: String = reason.explain - - override def diagnosticKeys(): Array[Any] = Array(reason) - - override val location: Option[IdentifiedLocation] = - originalPattern.location - - override def children: List[IR] = List(originalPattern) - - override protected var id: Identifier = randomId - - override def showCode(indent: Int): String = - originalPattern.showCode(indent) - } - - object Pattern { - - /** A representation of the reason the pattern is erroneous. - */ - sealed trait Reason { - - /** Provides a human-readable explanation of the error. - * @return - */ - def explain: String - } - - /** A reason for pattern failing due to wrong arity. - * - * @param consName the constructor name. - * @param expected expected field count. - * @param actual actual field count. - */ - case class WrongArity(consName: String, expected: Int, actual: Int) - extends Reason { - override def explain: String = - s"Wrong number of fields when matching on $consName." + - s" Expected $expected fields, but provided $actual" - } - } - - /** A representation of an Enso syntax error. - * - * @param at the error location - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Syntax( - at: IdentifiedLocation, - reason: Syntax.Reason, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Interactive - with IR.Module.Scope.Definition - with IR.Module.Scope.Export - with IR.Module.Scope.Import - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param ast the error location - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - at: IdentifiedLocation = at, - reason: Syntax.Reason = reason, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Syntax = { - val res = Syntax(at, reason, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - @unused keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Syntax = - copy( - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Syntax = - this - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = Option(at) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Syntax = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Syntax( - |at = $at, - |reason = $reason, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def message: String = reason.explanation - - /** @inheritdoc */ - override def formattedMessage: String = s"${message}." - - override def diagnosticKeys(): Array[Any] = Array(reason) - - /** @inheritdoc */ - override def showCode(indent: Int): String = "Syntax_Error" - } - object Syntax { - - /** A common type for all syntax errors expected by the language. - */ - sealed trait Reason { - - /** @return a human-readable description of the error. - */ - def explanation: String - } - - case object SuspendedArgInAtom extends Reason { - override def explanation: String = - "Atoms may not have suspended arguments" - } - - case class InvalidEscapeSequence(lit: String) extends Reason { - override def explanation: String = s"Invalid escape sequence $lit" - } - - case object InvalidBaseInDecimalLiteral extends Reason { - override def explanation: String = - "Cannot change base of the fractional part of a number literal" - } - - case class InvalidBase(base: String) extends Reason { - override def explanation: String = - s"$base is not a valid numeric base" - } - - case class InvalidNumberForBase(base: String, number: String) - extends Reason { - override def explanation: String = - s"$number is not valid in $base" - } - - case class UnsupportedSyntax(syntaxName: String) extends Reason { - override def explanation: String = - s"Syntax is not supported yet: $syntaxName" - } - - case object InvalidUnderscore extends Reason { - override def explanation: String = - s"Invalid use of _" - } - - case object InvalidPattern extends Reason { - override def explanation: String = - s"Cannot define a pattern outside a pattern context" - } - - case class InvalidImport( - message: String = "Imports must have a valid module path" - ) extends Reason { - override def explanation: String = - s"Invalid Import: $message" - } - - case class InvalidExport( - message: String = "Exports must have a valid module path" - ) extends Reason { - override def explanation: String = - s"Invalid Export: $message" - } - - case object InvalidStandaloneSignature extends Reason { - override def explanation: String = - s"Invalid stand-alone signature expression" - } - - case class MethodDefinedInline(methodName: String) extends Reason { - override def explanation: String = - s"Cannot define $methodName, methods are not supported in the " + - s"inline flow" - } - - case object UnexpectedDeclarationInType extends Reason { - override def explanation: String = - "Unexpected declaration in the body of a type" - } - - case object InvalidTypeDefinition extends Reason { - override def explanation: String = - "Invalid definition of a type" - } - - case class TypeDefinedInline(typeName: String) extends Reason { - override def explanation: String = - s"Cannot define $typeName, type definitions are not supported " + - s"in the inline flow" - } - - case object EmptyParentheses extends Reason { - override def explanation: String = - "Parentheses can't be empty" - } - - case object UnexpectedExpression extends Reason { - override def explanation: String = "Unexpected expression" - } - - case object AmbiguousExpression extends Reason { - override def explanation: String = "Ambiguous expression" - } - - case object InvalidSelfArgUsage extends Reason { - override def explanation: String = - "Self argument cannot be used in static methods" - } - - case object UnrecognizedToken extends Reason { - override def explanation: String = "Unrecognized token" - } - - case object InvalidSuffix extends Reason { - override def explanation: String = "Invalid suffix" - } - - case object UnclosedTextLiteral extends Reason { - override def explanation: String = "Unclosed text literal" - } - - case object NamedArgInSection extends Reason { - override def explanation: String = "Named argument in operator section" - } - - case object NamedArgInOperator extends Reason { - override def explanation: String = "Named argument in operator section" - } - - case object InvalidOperatorName extends Reason { - override def explanation: String = "Invalid operator name" - } - - case class InvalidForeignDefinition(details: String) extends Reason { - override def explanation: String = - s"Invalid foreign definition. $details" - } - } - - /** A representation of an invalid piece of IR. - * - * @param ir the IR that is invalid - * @param passData any annotations from compiler passes - * @param diagnostics compiler diagnostics for this node - */ - sealed case class InvalidIR( - ir: IR, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Static - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param ir the IR that is invalid - * @param passData any annotations from compiler passes - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - ir: IR = ir, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): InvalidIR = { - val res = InvalidIR(ir, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): InvalidIR = - copy( - ir = ir.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): InvalidIR = this - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = ir.location - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): InvalidIR = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.InvalidIR( - |ir = $ir, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(ir) - - /** @inheritdoc */ - override def message: String = - "InvalidIR: Please report this as a compiler bug." - - override def diagnosticKeys(): Array[Any] = Array() - - /** @inheritdoc */ - override def showCode(indent: Int): String = "Invalid_Ir" - } - - /** Errors pertaining to the redefinition of language constructs that are - * not allowed to be. - */ - sealed trait Redefined extends Error { - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Redefined - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Redefined - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Redefined - } - object Redefined { - - /** An error representing the redefinition or incorrect positioning of - * the `self` argument to methods. - * - * @param location the source location of the error - * @param passData the pass metadata for this node - * @param diagnostics compiler diagnostics associated with the node - */ - sealed case class SelfArg( - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `self`. - * - * @param location the source location of the error - * @param passData the pass metadata for this node - * @param diagnostics compiler diagnostics associated with the node - * @param id the node's identifier - * @return a copy of `this`, with the specified values updated - */ - def copy( - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): SelfArg = { - val res = SelfArg(location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): SelfArg = - copy( - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): SelfArg = copy(location = location) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): SelfArg = - this - - /** @inheritdoc */ - override def message: String = - "Methods must have only one definition of the `this` argument, and " + - "it must be the first." - - override def diagnosticKeys(): Array[Any] = Array() - - /** @inheritdoc */ - override def children: List[IR] = List() - - /** @inheritdoc */ - override def showCode(indent: Int): String = "(Redefined This_Arg)" - } - - /** An error representing the redefinition of a conversion in a given - * module. This is also known as a method overload. - * - * @param targetType the name of the atom the conversion was being - * redefined on - * @param sourceType the source type for the conversion - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - */ - sealed case class Conversion( - targetType: Option[IR.Name], - sourceType: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with Module.Scope.Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param targetType the name of the atom the conversion was being - * redefined on - * @param sourceType the source type for the conversion - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - targetType: Option[IR.Name] = targetType, - sourceType: IR.Name = sourceType, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Conversion = { - val res = - Conversion(targetType, sourceType, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Conversion = - copy( - targetType = targetType.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - sourceType = sourceType - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Conversion = - copy(location = location) - - /** @inheritdoc */ - override def message: String = - s"Method overloads are not supported: ${targetType.map(_.name + ".").getOrElse("")}from " + - s"${sourceType.showCode()} is defined multiple times in this module." - - override def diagnosticKeys(): Array[Any] = targetType - .map(_.name :: sourceType.showCode() :: Nil) - .getOrElse(sourceType.showCode() :: Nil) - .toArray - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Conversion = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Redefined.Method( - |targetType = $targetType, - |sourceType = $sourceType, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = - targetType - .map(_ :: sourceType :: Nil) - .getOrElse(sourceType :: Nil) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Redefined (Conversion ${targetType.map(_.showCode() + ".").getOrElse("")}from $sourceType))" - } - - /** An error representing the redefinition of a method in a given module. - * This is also known as a method overload. - * - * @param atomName the name of the atom the method was being redefined on - * @param methodName the method name being redefined on `atomName` - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - */ - sealed case class Method( - atomName: Option[IR.Name], - methodName: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with Module.Scope.Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param atomName the name of the atom the method was being redefined on - * @param methodName the method name being redefined on `atomName` - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - atomName: Option[IR.Name] = atomName, - methodName: IR.Name = methodName, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Method = { - val res = - Method(atomName, methodName, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Method = - copy( - atomName = atomName.map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ), - methodName = methodName - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Method = - copy(location = location) - - /** @inheritdoc */ - override def message: String = - s"Method overloads are not supported: ${atomName.map(_.name + ".").getOrElse("")}" + - s"${methodName.name} is defined multiple times in this module." - - override def diagnosticKeys(): Array[Any] = { - atomName - .map(_.name :: methodName.name :: Nil) - .getOrElse(methodName.name :: Nil) - .toArray - } - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Method = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Redefined.Method( - |atomName = $atomName, - |methodName = $methodName, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = - atomName - .map(_ :: methodName :: Nil) - .getOrElse(methodName :: Nil) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Redefined (Method ${atomName.map(_.showCode() + ".").getOrElse("")}$methodName))" - } - - /** An error representing the redefinition of a method in a given module, - * when the module defines a method with the same name as an atom. - * This is also known as a name clash. - * - * @param atomName the name of the atom that clashes with the method - * @param methodName the method name being redefined in the module - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - */ - sealed case class MethodClashWithAtom( - atomName: IR.Name, - methodName: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with Module.Scope.Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param atomName the name of the atom that clashes with the method - * @param methodName the method name being redefined in the module - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - atomName: IR.Name = atomName, - methodName: IR.Name = methodName, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): MethodClashWithAtom = { - val res = MethodClashWithAtom( - atomName, - methodName, - location, - passData, - diagnostics - ) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): MethodClashWithAtom = - copy( - atomName = atomName.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - methodName = methodName - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): MethodClashWithAtom = - copy(location = location) - - /** @inheritdoc */ - override def message: String = - s"Method definitions with the same name as atoms are not supported. " + - s"Method ${methodName.name} clashes with the atom ${atomName.name} in this module." - - override def diagnosticKeys(): Array[Any] = - Array(methodName.name, atomName.name) - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): MethodClashWithAtom = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Redefined.MethodClashWithAtom( - |atomName = $atomName, - |methodName = $methodName, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = List(atomName, methodName) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Redefined (MethodClash $atomName $methodName))" - } - - /** An error representing the redefinition of an atom in a given module. - * - * @param typeName the name of the atom being redefined - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - */ - sealed case class Type( - typeName: IR.Name, - override val location: Option[IdentifiedLocation], - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with Module.Scope.Definition - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param atomName the name of the atom the method was being redefined - * on - * @param location the location in the source to which this error - * corresponds - * @param passData the pass metadata for the error - * @param diagnostics any diagnostics associated with this error. - * @param id the identifier for the node - * @return a copy of `this`, updated with the specified values - */ - def copy( - atomName: IR.Name = typeName, - location: Option[IdentifiedLocation] = location, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Type = { - val res = - Type(atomName, location, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Type = - copy( - atomName = typeName.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - location = if (keepLocations) location else None, - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Type = - copy(location = location) - - /** @inheritdoc */ - override def message: String = - s"Redefining atoms is not supported: ${typeName.name} is " + - s"defined multiple times in this module." - - override def diagnosticKeys(): Array[Any] = Array(typeName.name) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Type = this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Redefined.Atom( - |atomName = $typeName, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = List(typeName) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Redefined (Atom $typeName))" - } - - /** An error representing the redefinition of a binding in a given scope. - * - * While bindings in child scopes are allowed to _shadow_ bindings in - * parent scopes, a binding cannot be redefined within a given scope. - * - * @param invalidBinding the invalid binding - * @param passData the pass metadata for the error - * @param diagnostics compiler diagnostics for this node - */ - sealed case class Binding( - invalidBinding: IR.Expression.Binding, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Redefined - with Diagnostic.Kind.Interactive - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param invalidBinding the invalid binding - * @param passData the pass metadata for the error - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - invalidBinding: IR.Expression.Binding = invalidBinding, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): Binding = { - val res = Binding(invalidBinding, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Binding = - copy( - invalidBinding = invalidBinding - .duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): Binding = this - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = - invalidBinding.location - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Binding = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.Redefined.Binding( - |invalidBinding = $invalidBinding, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".stripMargin - - /** @inheritdoc */ - override def children: List[IR] = List(invalidBinding) - - /** @inheritdoc */ - override def message: String = - s"Variable ${invalidBinding.name.name} is being redefined." - - override def diagnosticKeys(): Array[Any] = Array( - invalidBinding.name.name - ) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Redefined (Binding $invalidBinding))" - } - } - - /** A trait for errors about unexpected language constructs. */ - sealed trait Unexpected extends Error { - - /** The unexpected construct. */ - val ir: IR - - /** The name of the unexpected entity. */ - val entity: String - - override val location: Option[IdentifiedLocation] = ir.location - - /** @inheritdoc */ - override def message: String = s"Unexpected $entity." - - /** @inheritdoc */ - override def diagnosticKeys(): Array[Any] = Array(entity) - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): Unexpected - - /** @inheritdoc */ - override def setLocation(location: Option[IdentifiedLocation]): Unexpected - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): Unexpected - } - object Unexpected { - - /** An error representing a type signature not associated with a - * binding of some kind. - * - * @param ir the erroneous signature - * @param passData any pass metadata associated with this node - * @param diagnostics any compiler diagnostics for this node - */ - sealed case class TypeSignature( - override val ir: IR, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Unexpected - with IRKind.Primitive - with IR.Module.Scope.Definition { - override val entity: String = "type signature" - - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param ir the erroneous signature - * @param passData any pass metadata associated with this node - * @param diagnostics any compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - ir: IR = ir, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): TypeSignature = { - val res = TypeSignature(ir, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def mapExpressions( - fn: Expression => Expression - ): TypeSignature = this - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): TypeSignature = this - - /** @inheritdoc */ - override def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): TypeSignature = - copy( - ir = ir.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ), - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def children: List[IR] = List(ir) - - /** @inheritdoc */ - override def showCode(indent: Int): String = - s"(Unexpected.TypeSignature ${ir.showCode(indent)})" - } - } - - object ImportExport { - - /** A reason for a statement being erroneous. - */ - sealed trait Reason { - - /** @return A human-readable description of the error. - */ - def message: String - } - - /** Used when the `project` keyword is used in an impossible position. - * @param statementType the type of statement being affected, see the - * implementation for its grammatical use. - */ - case class ProjectKeywordUsedButNotInProject(statementType: String) - extends Reason { - override def message: String = - s"The `project` keyword was used in an $statementType statement," + - " but the module does not belong to a project." - } - - /** Used when an import statement triggers loading of a package that could - * not be loaded. - * - * @param name the module name. - */ - case class PackageCouldNotBeLoaded(name: String, reason: String) - extends Reason { - override def message: String = s"Package containing the module $name" + - s" could not be loaded: $reason" - } - - /** Used when an import statement refers to a module that does not exist. - * @param name the module name. - */ - case class ModuleDoesNotExist(name: String) extends Reason { - override def message: String = s"The module $name does not exist." - } - - case class TypeDoesNotExist( - typeName: String, - moduleName: String - ) extends Reason { - override def message: String = - s"The type $typeName does not exist in module $moduleName" - } - - case class SymbolDoesNotExist( - symbolName: String, - moduleName: String - ) extends Reason { - override def message: String = - s"The symbol $symbolName (module or type) does not exist in module $moduleName." - } - - case class NoSuchConstructor( - typeName: String, - constructorName: String - ) extends Reason { - override def message: String = - s"No such constructor ${constructorName} in type $typeName" - } - - /** Represents an ambiguous import resolution error, where the same symbol is imported more than once refereing - * to different objects. The objects are represented by their physical path in the project. - * @param originalImport the original import statement. - * @param originalSymbolPath the original symbol path. - * @param symbolName the symbol name that is ambiguous. - * @param symbolPath the symbol path that is different than [[originalSymbolPath]]. - * @param source Location of the original import. - */ - case class AmbiguousImport( - originalImport: IR.Module.Scope.Import, - originalSymbolPath: String, - symbolName: String, - symbolPath: String, - source: Source - ) extends Reason { - override def message: String = { - val originalImportRepr = - originalImport.location match { - case Some(location) => - fileLocationFromSection(location, source) - case None => originalImport.showCode() - } - s"Symbol '$symbolName' resolved ambiguously to '$symbolPath' in the import Statement. " + - s"The symbol was first resolved to '$originalSymbolPath' in the import statement '$originalImportRepr'." - } - - } - } - - /** An erroneous import or export statement. - * - * @param ir the original statement - * @param reason the reason it's erroneous - * @param passData the pass data - * @param diagnostics the attached diagnostics - */ - sealed case class ImportExport( - ir: IR, - reason: ImportExport.Reason, - override val passData: MetadataStorage = MetadataStorage(), - override val diagnostics: DiagnosticStorage = DiagnosticStorage() - ) extends Error - with Diagnostic.Kind.Interactive - with IR.Module.Scope.Import - with IR.Module.Scope.Export - with IRKind.Primitive { - override protected var id: Identifier = randomId - - /** Creates a copy of `this`. - * - * @param ir the original IR - * @param reason the cause of this error - * @param passData the pass metadata associated with this node - * @param diagnostics compiler diagnostics for this node - * @param id the identifier for the new node - * @return a copy of `this`, updated with the specified values - */ - def copy( - ir: IR = ir, - reason: ImportExport.Reason = reason, - passData: MetadataStorage = passData, - diagnostics: DiagnosticStorage = diagnostics, - id: Identifier = id - ): ImportExport = { - val res = ImportExport(ir, reason, passData, diagnostics) - res.id = id - res - } - - /** @inheritdoc */ - override def duplicate( - @unused keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): ImportExport = - copy( - passData = - if (keepMetadata) passData.duplicate else MetadataStorage(), - diagnostics = - if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), - id = if (keepIdentifiers) id else randomId - ) - - /** @inheritdoc */ - override def setLocation( - location: Option[IdentifiedLocation] - ): ImportExport = - this - - /** @inheritdoc */ - override val location: Option[IdentifiedLocation] = ir.location - - /** @inheritdoc */ - override def mapExpressions(fn: Expression => Expression): ImportExport = - this - - /** @inheritdoc */ - override def toString: String = - s""" - |IR.Error.ImportExport( - |ir = $ir, - |reason = $reason, - |location = $location, - |passData = ${this.showPassData}, - |diagnostics = $diagnostics, - |id = $id - |) - |""".toSingleLine - - /** @inheritdoc */ - override def children: List[IR] = List(ir) - - /** @inheritdoc */ - override def message: String = reason.message - - override def diagnosticKeys(): Array[Any] = Array(reason) - - /** @inheritdoc */ - override def showCode(indent: Int): String = "Import_Export_Error" - } - } - - // ========================================================================== - // === Primitive / Sugar ==================================================== - // ========================================================================== - - /** A trait representing the classification of IR nodes into either primitive - * (constructs which will remain after desugaring) or sugar (constructs that - * should be removed by the desugaring passes). - */ - sealed trait IRKind - object IRKind { - - /** This trait encodes that a given piece of the [[IR]] is considered to be - * a primitive construct in Enso. - */ - sealed trait Primitive extends IRKind - - /** This trait encodes that a given piece of the [[IR]] is considered to - * represent syntax sugar in Enso. - * - * All [[Sugar]] constructs should be desugared into [[Primitive]] - * constructs as soon as possible. - */ - sealed trait Sugar extends IRKind - - /** This trait encodes that a given piece of [[IR]] is used to represent an - * optimisation on the IR in Enso. - */ - sealed trait Optimisation extends IRKind - } - - // ========================================================================== - // === Extension Methods ==================================================== - // ========================================================================== - - /** This class adds an extension method to control how the pass data element - * of the IR is printed. - * - * @param ir the IR to print the pass data for - */ - implicit class ShowPassData(ir: IR) { - - /** Creates a string representation of the pass data for a given IR node. - * - * @return a string representation of the pass data for [[ir]] - */ - def showPassData: String = { - val metaString: Seq[String] = - ir.passData.map((p, m) => (p, m.metadataName)).values.toSeq - val alphabetical = metaString.sorted - s"$alphabetical" - } - } - - /** Adds extension methods on strings to aid in writing custom to string - * overrides. - * - * @param string the string to process - */ - implicit class ToStringHelper(string: String) { - - /** Converts a multiline string to a single line - * - * @return [[string]], converted to a single line - */ - def toSingleLine: String = { - val lines = string.stripMargin.split("\n").toList.filterNot(_ == "") - - val body = lines.tail.dropRight(1).mkString(" ") - - s"${lines.head}$body${lines.last}" - } - } - - // ========================================================================== - // === Useful Extension Methods ============================================= - // ========================================================================== - - /** Adds extension methods for working directly with the diagnostics on the - * IR. - * - * @param ir the IR to add the methods to - * @tparam T the concrete type of the IR - */ - implicit class AsDiagnostics[T <: IR](ir: T) { - - /** Adds a new diagnostic entity to [[IR]]. - * - * @param diagnostic the diagnostic to add - * @return [[ir]] with added diagnostics - */ - def addDiagnostic(diagnostic: IR.Diagnostic): T = { - ir.diagnostics.add(diagnostic) - ir - } - } - - /** Adds extension methods for working directly with the metadata on the IR. - * - * @param ir the IR to add the methods to - * @tparam T the concrete type of the IR - */ - implicit class AsMetadata[T <: IR](ir: T) { - - /** Adds a metadata pair to the node metadata. - * - * This will overwrite any entry whose key matches [[MetadataPair#pass]]. - * - * @param metadataPair the pair to add to the storage - * @tparam K the concrete type of the pass - */ - def updateMetadata[K <: ProcessingPass]( - metadataPair: MetadataPair[K] - ): T = { - ir.passData.update(metadataPair) - ir - } - - /** Gets the metadata for the specified pass. - * - * @param pass the pass to get the metadata for - * @tparam K the concrete type of `pass` - * @return the metadata for `pass`, if it exists - */ - def getMetadata[K <: ProcessingPass](pass: K): Option[pass.Metadata] = { - ir.passData.get(pass) - } - - /** Unsafely gets the metadata for the specified pass, if it exists. - * - * @param pass the pass to get metadata for - * @param msg the message to throw with if the unsafe get fails - * @tparam K the concrete type of `pass` - * @throws CompilerError if no metadata exists for `pass` - * @return the metadata for `pass`, if it exists - */ - @throws[CompilerError] - def unsafeGetMetadata[K <: ProcessingPass]( - pass: ProcessingPass, - msg: => String - ): pass.Metadata = { - ir.passData.getUnsafe(pass)(msg) - } - } - - /** Adds extension methods for working with lists of [[IR]]. - * - * @param list the list - * @tparam T the concrete IR type - */ - implicit class ListAsIr[T <: IR](list: List[T]) { - - /** Calls [[IR.duplicate]] on the elements in [[list]]. - * - * @param keepLocations whether or not locations should be kept in the - * duplicated IR - * @param keepMetadata whether or not the pass metadata should be kept in - * the duplicated IR - * @param keepDiagnostics whether or not the diagnostics should be kept in - * the duplicated IR - * @param keepIdentifiers whether or not the identifiers should be - * regenerated in the duplicated IR - * @return a duplicate of [[list]] - */ - def duplicate( - keepLocations: Boolean = true, - keepMetadata: Boolean = true, - keepDiagnostics: Boolean = true, - keepIdentifiers: Boolean = false - ): List[T] = { - list - .map( - _.duplicate( - keepLocations, - keepMetadata, - keepDiagnostics, - keepIdentifiers - ) - ) - .asInstanceOf[List[T]] - } + def fileLocationFromSection( + loc: IdentifiedLocation, + source: Source + ): String = { + val section = + source.createSection(loc.location.start, loc.location.length) + val locStr = + "" + section.getStartLine + ":" + + section.getStartColumn + "-" + + section.getEndLine + ":" + + section.getEndColumn + source.getName + "[" + locStr + "]" } } diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/CallArgument.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/CallArgument.scala new file mode 100644 index 000000000000..fa6f7bca5cf4 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/CallArgument.scala @@ -0,0 +1,148 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Call-site arguments in Enso. */ +sealed trait CallArgument extends IR { + + /** The name of the argument, if present. */ + val name: Option[Name] + + /** The expression of the argument, if present. */ + val value: Expression + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): CallArgument + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): CallArgument + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): CallArgument +} + +object CallArgument { + + /** A representation of an argument at a function call site. + * + * A [[CallArgument]] where the `value` is an [[Name.Blank]] is a + * representation of a lambda shorthand argument. + * + * @param name the name of the argument being called, if present + * @param value the expression being passed as the argument's value + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Specified( + override val name: Option[Name], + override val value: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends CallArgument + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the argument being called, if present + * @param value the expression being passed as the argument's value + * @param location the source location that the node corresponds to + * @param shouldBeSuspended whether or not the argument should be passed + * suspended + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Option[Name] = name, + value: Expression = value, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Specified = { + val res = Specified( + name, + value, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Specified = + copy( + name = name.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + value = value.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Specified = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Specified = { + copy(name = name.map(n => n.mapExpressions(fn)), value = fn(value)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |CallArgument.Specified( + |name = $name, + |value = $value, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = name.toList :+ value + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + if (name.isDefined) { + s"(${name.get.showCode(indent)} = ${value.showCode(indent)})" + } else { + s"${value.showCode(indent)}" + } + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DefinitionArgument.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DefinitionArgument.scala new file mode 100644 index 000000000000..39f0cd577534 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DefinitionArgument.scala @@ -0,0 +1,206 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Definition-site arguments in Enso. */ +sealed trait DefinitionArgument extends IR { + + /** The name of the argument. */ + val name: Name + + /** The type of the argument */ + val ascribedType: Option[Expression] + + /** The default value of the argument. */ + val defaultValue: Option[Expression] + + /** Whether or not the argument is suspended. */ + val suspended: Boolean + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): DefinitionArgument + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): DefinitionArgument + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): DefinitionArgument + + def withName(ir: Name): DefinitionArgument +} + +object DefinitionArgument { + + /** The representation of an argument from a [[Function]] or + * [[module.scope.Definition.Data]] definition site. + * + * To create an ignored argument, the argument name should be an + * [[Name.Blank]]. + * + * @param name the name of the argument + * @param ascribedType the explicitly ascribed type of the argument, if + * present + * @param defaultValue the default value of the argument, if present + * @param suspended whether or not the argument has its execution suspended + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Specified( + override val name: Name, + override val ascribedType: Option[Expression], + override val defaultValue: Option[Expression], + override val suspended: Boolean, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends DefinitionArgument + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the argument + * @param ascribedType the explicitly ascribed type of the argument, if + * present + * @param defaultValue the default value of the argument, if present + * @param suspended whether or not the argument has its execution suspended + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name = name, + ascribedType: Option[Expression] = ascribedType, + defaultValue: Option[Expression] = defaultValue, + suspended: Boolean = suspended, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Specified = { + val res = Specified( + name, + ascribedType, + defaultValue, + suspended, + location, + passData, + diagnostics + ) + res.id = id + res + } + + override def withName(ir: Name): DefinitionArgument = copy(name = ir) + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Specified = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + ascribedType = ascribedType.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + defaultValue = defaultValue.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Specified = copy(location = location) + + /** @inheritdoc */ + def mapExpressions(fn: Expression => Expression): Specified = { + copy( + name = name.mapExpressions(fn), + ascribedType = ascribedType.map(fn), + defaultValue = defaultValue.map(fn) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |DefinitionArgument.Specified( + |name = $name, + |ascribedType = $ascribedType, + |defaultValue = $defaultValue, + |suspended = $suspended, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + name :: ascribedType.toList ++ defaultValue.toList + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val withoutLazy = + if (defaultValue.isDefined && ascribedType.isDefined) { + val name = this.name.showCode(indent) + val typeExpr = this.ascribedType.get.showCode(indent) + val defaultExpr = this.defaultValue.get.showCode(indent) + s"($name : ($typeExpr) = ($defaultExpr))" + } else if (defaultValue.isDefined) { + val name = this.name.showCode(indent) + val defaultExpr = this.defaultValue.get.showCode(indent) + s"($name = $defaultExpr)" + } else if (ascribedType.isDefined) { + val name = this.name.showCode(indent) + val typeExpr = this.ascribedType.get.showCode(indent) + s"($name : $typeExpr)" + } else { + s"${name.showCode(indent)}" + } + + if (suspended) { + s"~$withoutLazy" + } else { + withoutLazy + } + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala new file mode 100644 index 000000000000..a55f2852d053 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Diagnostic.scala @@ -0,0 +1,38 @@ +package org.enso.compiler.core.ir + +/** A representation of various kinds of diagnostic in the IR. */ +trait Diagnostic extends Serializable { + + /** @return a human-readable description of this error condition. + */ + def message: String + + /** @return a human-readable description of this error condition, formatted for immediate reporting. */ + def formattedMessage: String = message + + /** The location at which the diagnostic occurs. */ + val location: Option[IdentifiedLocation] + + /** The important keys identifying identity of the diagnostic + */ + def diagnosticKeys(): Array[Any] +} + +object Diagnostic { + + /** Represents the various kinds of diagnostics in the IR. */ + sealed trait Kind + + object Kind { + + /** Diagnostics that should be reported during the static compilation + * phase of execution. + */ + trait Static extends Kind + + /** Diagnostics that should remain at runtime for display during + * interactive execution. + */ + trait Interactive extends Kind + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DiagnosticStorage.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DiagnosticStorage.scala index a371fabfb9c2..e72390c61b33 100644 --- a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DiagnosticStorage.scala +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/DiagnosticStorage.scala @@ -1,8 +1,5 @@ package org.enso.compiler.core.ir -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Diagnostic - /** Storage for diagnostics in IR nodes. * * @param initDiagnostics the initial diagnostics @@ -34,7 +31,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * @tparam R the result type of `f` * @return the sequence that results from applying `f` over the storage */ - def map[R](f: IR.Diagnostic => R): Seq[R] = { + def map[R](f: Diagnostic => R): Seq[R] = { diagnostics.map(f) } @@ -42,7 +39,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * * @param f the function to apply */ - def mapInPlace(f: IR.Diagnostic => IR.Diagnostic): Unit = { + def mapInPlace(f: Diagnostic => Diagnostic): Unit = { diagnostics = diagnostics.map(f) } @@ -53,7 +50,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * @tparam R the result type of the partial function * @return the result of collecting across the storage with `pf` */ - def collect[R](pf: PartialFunction[IR.Diagnostic, R]): Seq[R] = { + def collect[R](pf: PartialFunction[Diagnostic, R]): Seq[R] = { diagnostics.collect(pf) } @@ -63,7 +60,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * @return a new diagnostic storage instance containing elements matching * `pred` */ - def filter(pred: IR.Diagnostic => Boolean): DiagnosticStorage = { + def filter(pred: Diagnostic => Boolean): DiagnosticStorage = { new DiagnosticStorage(diagnostics.filter(pred)) } @@ -72,7 +69,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * * @param pred the predicate to filter with */ - def filterInPlace(pred: IR.Diagnostic => Boolean): Unit = { + def filterInPlace(pred: Diagnostic => Boolean): Unit = { diagnostics = diagnostics.filter(pred) } @@ -84,7 +81,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * @return the result of folding over the storage using `op` starting wit * `init` */ - def foldLeft[L](init: L)(op: (L, IR.Diagnostic) => L): L = { + def foldLeft[L](init: L)(op: (L, Diagnostic) => L): L = { diagnostics.foldLeft(init)(op) } @@ -110,7 +107,7 @@ sealed class DiagnosticStorage(initDiagnostics: Seq[Diagnostic] = Seq()) * * @return a list of the diagnostics in the storage */ - def toList: List[IR.Diagnostic] = { + def toList: List[Diagnostic] = { diagnostics } diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala new file mode 100644 index 000000000000..db4e1d9babd3 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Empty.scala @@ -0,0 +1,86 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, ToStringHelper} + +/** A node representing an empty IR construct that can be used in any place. + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ +sealed case class Empty( + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends IR + with Expression + with Diagnostic + with IRKind.Primitive { + override protected var id: IR.Identifier = randomId + + /** Creates a copy of `this` + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this` with the specified fields updated + */ + def copy( + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: IR.Identifier = id + ): Empty = { + val res = Empty(location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Empty = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Empty = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Empty = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Empty( + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def message: String = + "Empty IR: Please report this as a compiler bug." + + /** @inheritdoc */ + override def diagnosticKeys(): Array[Any] = Array() + + /** @inheritdoc */ + override def showCode(indent: Int): String = "IR.Empty" +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Expression.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Expression.scala new file mode 100644 index 000000000000..b8573f17c5ba --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Expression.scala @@ -0,0 +1,269 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{ + indentLevel, + mkIndent, + randomId, + ToStringHelper +} + +trait Expression extends IR { + + /** Performs a recursive traversal of the IR, potentially transforming it. + * + * @param fn the function to apply across the IR + * @return the IR, potentially transformed + */ + def transformExpressions( + fn: PartialFunction[Expression, Expression] + ): Expression = { + if (fn.isDefinedAt(this)) { + fn(this) + } else { + mapExpressions(_.transformExpressions(fn)) + } + } + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Expression + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Expression + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Expression +} + +object Expression { + + // TODO Remove suspended blocks from Enso. + + /** A block expression. + * + * @param expressions the expressions in the block + * @param returnValue the final expression in the block + * @param location the source location that the node corresponds to + * @param suspended whether or not the block is suspended + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Block( + expressions: List[Expression], + returnValue: Expression, + override val location: Option[IdentifiedLocation], + suspended: Boolean = false, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Expression + with IRKind.Primitive { + override protected var id: IR.Identifier = randomId + + /** Creates a copy of `this`. + * + * @param expressions the expressions in the block + * @param returnValue the final expression in the block + * @param location the source location that the node corresponds to + * @param suspended whether or not the block is suspended + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + expressions: List[Expression] = expressions, + returnValue: Expression = returnValue, + location: Option[IdentifiedLocation] = location, + suspended: Boolean = suspended, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: IR.Identifier = id + ): Block = { + val res = Block( + expressions, + returnValue, + location, + suspended, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Block = + copy( + expressions = expressions.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + returnValue = returnValue.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Block = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Block = { + copy( + expressions = expressions.map(fn), + returnValue = fn(returnValue) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Expression.Block( + |expressions = $expressions, + |returnValue = $returnValue, + |location = $location, + |suspended = $suspended, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = expressions :+ returnValue + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val newIndent = indent + indentLevel + val expressionsStr = expressions + .map(mkIndent(newIndent) + _.showCode(newIndent)) + .mkString("\n") + val returnStr = mkIndent(newIndent) + returnValue.showCode(newIndent) + + s"\n$expressionsStr\n$returnStr" + } + } + + /** A binding expression of the form `name = expr` + * + * To create a binding that binds no available name, set the name of the + * binding to an [[Name.Blank]] (e.g. _ = foo a b). + * + * @param name the name being bound to + * @param expression the expression being bound to `name` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Binding( + name: Name, + expression: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Expression + with IRKind.Primitive { + override protected var id: IR.Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name being bound to + * @param expression the expression being bound to `name` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name = name, + expression: Expression = expression, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: IR.Identifier = id + ): Binding = { + val res = Binding(name, expression, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Binding = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + expression = expression.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Binding = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Binding = { + copy(name = name.mapExpressions(fn), expression = fn(expression)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Expression.Binding( + |name = $name, + |expression = $expression, + |location = $location + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(name, expression) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"${name.showCode(indent)} = ${expression.showCode(indent)}" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Function.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Function.scala new file mode 100644 index 000000000000..5a9a57942302 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Function.scala @@ -0,0 +1,296 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Functions in Enso. */ +sealed trait Function extends Expression { + + /** The function arguments. + * + * Please note that while the source language does not represent + * multi-argument lambdas, the internal language can and does. + */ + val arguments: List[DefinitionArgument] + + /** The body of the function */ + val body: Expression + + /** Whether or not the function _can_ be tail-call optimised. + * + * Please note that this being set to `true` does not _guarantee_ that the + * function is optimised. + */ + val canBeTCO: Boolean + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Function + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Function + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Function +} + +object Function { + + /** The primitive function type in Enso: `->`. + * + * It should be noted that while the _surface_ language does not support + * multi-argument lambdas, our internal representation does so to allow for + * better optimisation. + * + * @param arguments the arguments to the lambda + * @param body the body of the lambda + * @param location the source location that the node corresponds to + * @param canBeTCO whether or not the function can be tail-call optimised + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Lambda( + override val arguments: List[DefinitionArgument], + override val body: Expression, + override val location: Option[IdentifiedLocation], + override val canBeTCO: Boolean = true, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Function + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param arguments the arguments to the lambda + * @param body the body of the lambda + * @param location the source location that the node corresponds to + * @param canBeTCO whether or not the function can be tail-call optimised + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + arguments: List[DefinitionArgument] = arguments, + body: Expression = body, + location: Option[IdentifiedLocation] = location, + canBeTCO: Boolean = canBeTCO, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Lambda = { + val res = + Lambda(arguments, body, location, canBeTCO, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Lambda = + copy( + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + body = body.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Lambda = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Lambda = { + copy(arguments = arguments.map(_.mapExpressions(fn)), body = fn(body)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Function.Lambda( + |arguments = $arguments, + |body = $body, + |location = $location, + |canBeTCO = $canBeTCO, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = arguments :+ body + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val args = arguments.map(_.showCode(indent)).mkString(" ") + val bodyStr = if (body.isInstanceOf[Expression.Block]) { + s"\n${body.showCode(indent)}" + } else { + s"${body.showCode(indent)}" + } + + s"$args -> $bodyStr" + } + } + + /** A representation of the syntactic sugar for defining functions. + * + * @param name the name of the function + * @param arguments the arguments to the function + * @param body the body of the function + * @param location the source location that the node corresponds to + * @param canBeTCO whether or not the function can be tail-call optimised + * @param passData the pass metadata associated with this node + * @param diagnostics the compiler diagnostics for this node + */ + sealed case class Binding( + name: Name, + override val arguments: List[DefinitionArgument], + override val body: Expression, + override val location: Option[IdentifiedLocation], + override val canBeTCO: Boolean = true, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Function + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the function + * @param arguments the arguments to the function + * @param body the body of the function + * @param location the source location that the node corresponds to + * @param canBeTCO whether or not the function can be tail-call optimised + * @param passData the pass metadata associated with this node + * @param diagnostics the compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name = name, + arguments: List[DefinitionArgument] = arguments, + body: Expression = body, + location: Option[IdentifiedLocation] = location, + canBeTCO: Boolean = canBeTCO, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Binding = { + val res = + Binding( + name, + arguments, + body, + location, + canBeTCO, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Binding = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + body = body.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Binding = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Binding = + copy( + name = name.mapExpressions(fn), + arguments = arguments.map(_.mapExpressions(fn)), + body = fn(body) + ) + + /** @inheritdoc */ + override def toString: String = + s""" + |Function.Binding( + |name = $name, + |arguments = $arguments, + |body = $body, + |location = $location, + |canBeTCO = $canBeTCO, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = (name :: arguments) :+ body + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val argsStr = arguments.map(_.showCode(indent)).mkString(" ") + val bodyStr = if (body.isInstanceOf[Expression.Block]) { + s"\n${body.showCode(indent)}" + } else { + s"${body.showCode(indent)}" + } + + s"${name.name} $argsStr = $bodyStr" + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IRKind.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IRKind.scala new file mode 100644 index 000000000000..20c857fed2df --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IRKind.scala @@ -0,0 +1,28 @@ +package org.enso.compiler.core.ir + +/** A trait representing the classification of IR nodes into either primitive + * (constructs which will remain after desugaring) or sugar (constructs that + * should be removed by the desugaring passes). + */ +sealed trait IRKind + +object IRKind { + + /** This trait encodes that a given piece of the [[IR]] is considered to be + * a primitive construct in Enso. + */ + trait Primitive extends IRKind + + /** This trait encodes that a given piece of the [[IR]] is considered to + * represent syntax sugar in Enso. + * + * All [[Sugar]] constructs should be desugared into [[Primitive]] + * constructs as soon as possible. + */ + trait Sugar extends IRKind + + /** This trait encodes that a given piece of [[IR]] is used to represent an + * optimisation on the IR in Enso. + */ + trait Optimisation extends IRKind +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IdentifiedLocation.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IdentifiedLocation.scala new file mode 100644 index 000000000000..22d78130b80c --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/IdentifiedLocation.scala @@ -0,0 +1,36 @@ +package org.enso.compiler.core.ir + +import org.enso.syntax.text.Location + +import java.util.UUID + +/** Couples a location with a possible source identifier. + * + * @param location the code location. + * @param id the identifier for the location. + */ +case class IdentifiedLocation(location: Location, id: Option[UUID]) { + + /** @return the character index of the start of this source location. + */ + def start: Int = location.start + + /** @return the character index of the end of this source location. + */ + def end: Int = location.end + + /** @return the length in characters of this location. + */ + def length: Int = location.length +} + +object IdentifiedLocation { + + /** Utility constructor, building a location without an ID. + * + * @param location the code location. + * @return an [[IdentifiedLocation]] corresponding to the input location. + */ + def apply(location: Location): IdentifiedLocation = + IdentifiedLocation(location, None) +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Literal.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Literal.scala new file mode 100644 index 000000000000..8df0c2c1fb16 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Literal.scala @@ -0,0 +1,228 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.{CompilerError, IR} +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Enso literals. */ +sealed trait Literal extends Expression with IRKind.Primitive { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Literal + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Literal + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Literal +} + +object Literal { + + /** A numeric Enso literal. + * + * @param base the optional base for the number, expressed in decimal + * @param value the textual representation of the numeric literal + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Number( + base: Option[String], + value: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Literal { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param base the optional base for the number, expressed in decimal + * @param value the textual representation of the numeric literal + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + base: Option[String] = base, + value: String = value, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Number = { + val res = Number(base, value, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Number = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Number = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Number = this + + /** @inheritdoc */ + override def toString: String = + s"""Literal.Number( + |base = $base, + |value = $value, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = if (this.base.isDefined) { + s"${base.get}_$value" + } else value + + /** Checks whether the literal represents a fractional value. + * + * @return `true` if the value is fractional, `false` otherwise. + */ + def isFractional: Boolean = value.contains(".") + + /** Checks the values in the literal converts that to approviate JVM value. + * + * @return Double, Long, BigInteger + */ + @throws[CompilerError] + def numericValue: Any = { + if (isFractional) { + value.toDouble + } else if (base.isDefined) { + val baseNum = + try { + Integer.parseInt(base.get) + } catch { + case _: NumberFormatException => + throw new CompilerError( + s"Invalid number base $base seen during codegen." + ) + } + try { + val longVal = java.lang.Long.parseLong(value, baseNum) + longVal + } catch { + case _: NumberFormatException => + try { + new java.math.BigInteger(value, baseNum) + } catch { + case _: NumberFormatException => + throw new CompilerError( + s"Invalid number base $base seen during codegen." + ) + } + } + } else { + value.toLongOption.getOrElse(new java.math.BigInteger(value)) + } + } + } + + /** A textual Enso literal. + * + * @param text the text of the literal + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Text( + text: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Literal { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param text the text of the literal + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + text: String = text, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Text = { + val res = Text(text, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Text = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Text = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Text = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Literal.String( + |text = $text, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = s""""$text"""" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Module.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Module.scala new file mode 100644 index 000000000000..ef511e901e08 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Module.scala @@ -0,0 +1,128 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.module.scope.{Definition, Export, Import} + +/** A representation of a top-level Enso module. + * + * Modules may only contain imports and top-level bindings, with no top-level + * executable code. + * + * @param imports the import statements that bring other modules into scope + * @param exports the export statements for this module + * @param bindings the top-level bindings for this module + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ +@SerialVersionUID( + 7681L // SuggestionBuilder needs to send ascribedType of constructor parameters +) // prevents reading broken caches, see PR-3692 for details +sealed case class Module( + imports: List[Import], + exports: List[Export], + bindings: List[Definition], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends IR + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param imports the import statements that bring other modules into scope + * @param exports the export statements for this module + * @param bindings the top-level bindings for this module + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + imports: List[Import] = imports, + exports: List[Export] = exports, + bindings: List[Definition] = bindings, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Module = { + val res = + Module(imports, exports, bindings, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Module = + copy( + imports = imports.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + bindings = bindings.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Module = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Module = { + copy( + imports = imports.map(_.mapExpressions(fn)), + exports = exports.map(_.mapExpressions(fn)), + bindings = bindings.map(_.mapExpressions(fn)) + ) + } + + /** @inheritdoc */ + override def children: List[IR] = imports ++ exports ++ bindings + + /** @inheritdoc */ + override def toString: String = + s""" + |Module( + |imports = $imports, + |exports = $exports, + |bindings = $bindings, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val importsString = imports.map(_.showCode(indent)).mkString("\n") + val exportsString = exports.map(_.showCode(indent)).mkString("\n") + val defsString = bindings.map(_.showCode(indent)).mkString("\n\n") + + List(importsString, exportsString, defsString).mkString("\n\n") + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Name.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Name.scala new file mode 100644 index 000000000000..fd6d0b56ab57 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Name.scala @@ -0,0 +1,855 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.{ConstantsNames, IR} +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.syntax.text.Location + +/** Enso names. */ +trait Name extends Expression with IRKind.Primitive { + val name: String + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Name + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Name + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Name + + /** Checks whether a name is a call-site method name. + * + * @return `true` if the name was created through a method call + */ + def isMethod: Boolean = false + +} + +object Name { + + /** A representation of a method reference of the form `Type_Path.method`. + * + * @param typePointer the type name + * @param methodName the method on `typeName` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class MethodReference( + typePointer: Option[Name], + methodName: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name + with IRKind.Sugar { + + override val name: String = showCode() + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param typePointer the type name + * @param methodName the method on `typeName` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + typePointer: Option[Name] = typePointer, + methodName: Name = methodName, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): MethodReference = { + val res = + MethodReference( + typePointer, + methodName, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): MethodReference = + copy( + typePointer = typePointer.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + methodName = methodName.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): MethodReference = + copy( + typePointer = typePointer.map(_.mapExpressions(fn)), + methodName = methodName.mapExpressions(fn) + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): MethodReference = { + copy(location = location) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.MethodReference( + |typePointer = $typePointer, + |methodName = $methodName, + |location = $location, + |passData = $passData, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + typePointer.map(_ :: methodName :: Nil).getOrElse(methodName :: Nil) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val tPointer = typePointer.map(_.showCode(indent) + ".").getOrElse("") + s"$tPointer${methodName.showCode(indent)}" + } + + /** Checks whether `this` and `that` reference the same method. + * + * @param that the other method reference to check against + * @return `true`, if `this` and `that` represent the same method, + * otherwise `false` + */ + def isSameReferenceAs(that: MethodReference): Boolean = { + val sameTypePointer = typePointer + .map(thisTp => + that.typePointer.map(_.name == thisTp.name).getOrElse(false) + ) + .getOrElse(that.typePointer.isEmpty) + sameTypePointer && (methodName.name == that.methodName.name) + } + } + + object MethodReference { + + /** Generates a location for the reference from the segments. + * + * @param segments the reference segments + * @return a location for the method reference + */ + def genLocation(segments: List[Name]): Option[IdentifiedLocation] = { + segments.foldLeft(None: Option[IdentifiedLocation])( + (identLoc, segment) => { + identLoc.flatMap(loc => { + Some( + IdentifiedLocation( + Location( + loc.location.start, + segment.location + .flatMap(l => Some(l.location.end)) + .getOrElse(loc.location.end) + ) + ) + ) + }) + } + ) + } + } + + /** A representation of a qualified (multi-part) name. + * + * @param parts the segments of the name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @return a copy of `this`, updated with the specified values + */ + sealed case class Qualified( + parts: List[Name], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name + with IRKind.Primitive { + + override val name: String = parts.map(_.name).mkString(".") + + override def mapExpressions(fn: Expression => Expression): Name = this + + override def setLocation(location: Option[IdentifiedLocation]): Name = + copy(location = location) + + /** Creates a copy of `this`. + * + * @param parts the segments of the name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + parts: List[Name] = parts, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Qualified = { + val res = + Qualified( + parts, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Qualified = + copy( + parts = parts.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def children: List[IR] = parts + + /** @inheritdoc */ + override protected var id: Identifier = randomId + + /** @inheritdoc */ + override def showCode(indent: Int): String = name + } + + /** Represents occurrences of blank (`_`) expressions. + * + * @param location the source location that the node corresponds to. + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Blank( + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name + with IRKind.Sugar { + override val name: String = "_" + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param location the source location that the node corresponds to. + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Blank = { + val res = Blank(location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Blank = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Blank = + this + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Blank = + copy(location = location) + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.Blank( + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = "_" + } + + sealed case class Special( + specialName: Special.Ident, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name + with IRKind.Sugar { + override val name: String = s"" + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param location the source location that the node corresponds to. + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + specialName: Special.Ident = specialName, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Special = { + val res = Special(specialName, location, passData, diagnostics) + res.id = id + res + } + + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Special = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + override def mapExpressions(fn: Expression => Expression): Special = + this + + override def setLocation(location: Option[IdentifiedLocation]): Special = + copy(location = location) + + override def toString: String = + s""" + |Name.Special( + |specialName = $specialName, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + override def children: List[IR] = List() + + override def showCode(indent: Int): String = name + } + + object Special { + sealed trait Ident + + case object NewRef extends Ident + + case object ReadRef extends Ident + + case object WriteRef extends Ident + + case object RunThread extends Ident + + case object JoinThread extends Ident + } + + /** The representation of a literal name. + * + * @param name the literal text of the name + * @param isMethod is this a method call name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Literal( + override val name: String, + override val isMethod: Boolean, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the literal text of the name + * @param isMethod is this a method call name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: String = name, + isMethod: Boolean = isMethod, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Literal = { + val res = + Literal(name, isMethod, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Literal = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Literal = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Literal = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.Literal( + |name = $name, + |isMethod = $isMethod, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = name + } + + /** Base trait for annotations. */ + sealed trait Annotation extends Name with module.scope.Definition { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Annotation + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Annotation + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Annotation + } + + /** The representation of builtin annotation. + * + * @param name the annotation text of the name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class BuiltinAnnotation( + override val name: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Annotation + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the annotation text of the name + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: String = name, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): BuiltinAnnotation = { + val res = BuiltinAnnotation(name, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): BuiltinAnnotation = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): BuiltinAnnotation = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): BuiltinAnnotation = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.BuiltinAnnotation( + |name = $name, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = s"@$name" + } + + /** Common annotations of form `@name expression`. + * + * @param name the annotation text of the name + * @param expression the annotation expression + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class GenericAnnotation( + override val name: String, + expression: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Annotation { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the annotation text of the name + * @param expression the annotation expression + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: String = name, + expression: Expression = expression, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): GenericAnnotation = { + val res = + GenericAnnotation(name, expression, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): GenericAnnotation = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): GenericAnnotation = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): GenericAnnotation = + copy(expression = fn(expression)) + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.GenericAnnotation( + |name = $name, + |expression = $expression, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(expression) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"@$name ${expression.showCode(indent)}" + } + + /** A representation of the name `self`, used to refer to the current type. + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Self( + override val location: Option[IdentifiedLocation], + synthetic: Boolean = false, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name { + override protected var id: Identifier = randomId + override val name: String = ConstantsNames.SELF_ARGUMENT + + /** Creates a copy of `self`. + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + location: Option[IdentifiedLocation] = location, + synthetic: Boolean = synthetic, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Self = { + val res = Self(location, synthetic, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Self = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Self = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Self = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.Self( + |location = $location, + |synthetic = $synthetic, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = name + } + + /** A representation of the name `Self`, used to refer to the current type. + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class SelfType( + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Name { + override protected var id: Identifier = randomId + override val name: String = ConstantsNames.SELF_TYPE_ARGUMENT + + /** Creates a copy of `Self`. + * + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): SelfType = { + val res = SelfType(location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): SelfType = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): SelfType = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): SelfType = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Name.SelfType( + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = name + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Pattern.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Pattern.scala new file mode 100644 index 000000000000..f5b2a2827534 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Pattern.scala @@ -0,0 +1,542 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.{CompilerError, IR} +import org.enso.compiler.core.ir.{Name => IRName, Literal => IRLiteral} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** The different types of patterns that can occur in a match. */ +trait Pattern extends IR { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Pattern + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Pattern + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Pattern +} + +object Pattern { + + /** A named pattern. + * + * Named patterns take the form of a single identifier (e.g. `a` or `_`). + * As a result they can be used to represent a catch all pattern (e.g. + * `_ -> ...` or `a -> ...`). + * + * @param name the name that constitutes the pattern + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Name( + name: IRName, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Pattern { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name that constitutes the pattern + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the provided values + */ + def copy( + name: IRName = name, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Name = { + val res = Name(name, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Name = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Name = { + copy(name = name.mapExpressions(fn)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Pattern.Name( + |name = $name, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Name = + copy(location = location) + + /** @inheritdoc */ + override def children: List[IR] = List(name) + + /** @inheritdoc */ + override def showCode(indent: Int): String = name.showCode(indent) + } + + /** A pattern that destructures a constructor application. + * + * The first part of the pattern must be a refferent name. The fields of + * the constructor may be any available kind of pattern. + * + * @param constructor the constructor being matched on + * @param fields the asserted fields of the constructor + * @param location the source location for this IR node + * @param passData any pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Constructor( + constructor: IRName, + fields: List[Pattern], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Pattern { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param constructor the constructor being matched on + * @param fields the asserted fields of the constructor + * @param location the source location for this IR node + * @param passData any pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the new identifier for this node + * @return a copy of `this`, updated with the provided values + */ + def copy( + constructor: IRName = constructor, + fields: List[Pattern] = fields, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Constructor = { + val res = + Constructor(constructor, fields, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Constructor = + copy( + constructor = constructor.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + fields = fields.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** Checks if the constructor pattern has been desugared. + * + * A constructor pattern has been desugared if all of its fields are + * [[Pattern.Name]]. + * + * @return `true` if the pattern has been desugared, `false` otherwise + */ + def isDesugared: Boolean = { + fields.forall { + case _: Pattern.Name => true + case _: Pattern.Constructor => false + case _: Pattern.Literal => true + case _: Pattern.Type => true + case _: Pattern.Documentation => + throw new CompilerError( + "Branch documentation should not be present " + + "inside a constructor pattern." + ) + case _: errors.Pattern => true + } + } + + /** Gets the patterns fields as [[Pattern.Name]] if they are. + * + * @return the fields from `this` + */ + def fieldsAsNamed: List[Option[Pattern.Name]] = { + fields.map { + case f: Name => Some(f) + case _ => None + } + } + + /** Unsafely gets the pattern's fields as if they are [[Pattern.Name]]. + * + * @return the fields from `this` + */ + def unsafeFieldsAsNamed: List[Pattern.Name] = { + fieldsAsNamed.map(_.get) + } + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Constructor = + copy( + constructor = constructor.mapExpressions(fn), + fields = fields.map(_.mapExpressions(fn)) + ) + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Pattern.Constructor( + |constructor = $constructor, + |fields = $fields, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Constructor = copy(location = location) + + /** @inheritdoc */ + override def children: List[IR] = constructor :: fields + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val fieldsStr = + fields.map(f => s"(${f.showCode(indent)})").mkString(" ") + + s"${constructor.name} $fieldsStr" + } + } + + /** A literal pattern. + * + * A literal pattern matches on constants. + * + * @param literal the literal representing the pattern + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Literal( + literal: IRLiteral, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Pattern { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param literal the literal representing the pattern + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the provided values + */ + def copy( + literal: IRLiteral = literal, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Literal = { + val res = Literal(literal, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Literal = + copy( + literal = literal.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Literal = { + copy(literal = literal.mapExpressions(fn)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Pattern.Literal( + |literal = $literal, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Literal = + copy(location = location) + + /** @inheritdoc */ + override def children: List[IR] = List(literal) + + /** @inheritdoc */ + override def showCode(indent: Int): String = literal.showCode(indent) + } + + /** A type pattern. + * + * A type pattern matches on types. Type pattern is composed of two parts: + * - a single identifier (e.g. `a` or `_`) + * - a (potentially fully qualified) type name + * E.g., `a : Foo -> ...` or `_ : Bar -> ...`` + * + * @param name the name of the bound variable, or wildcard + * @param tpe the name of the type to match on + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Type( + name: IRName, + tpe: IRName, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Pattern { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the bound variable, or wildcard + * @param tpe the name of the type to match on + * @param location the source location for this IR node + * @param passData any pass metadata associated with the node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the provided values + */ + def copy( + name: IRName = name, + tpe: IRName = tpe, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Type = { + val res = Type(name, tpe, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Type = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + tpe = tpe.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Type = { + copy(name = name.mapExpressions(fn), tpe = tpe.mapExpressions(fn)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Pattern.Type( + |name = $name, + |tpe = $tpe, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Type = + copy(location = location) + + /** @inheritdoc */ + override def children: List[IR] = List(name, tpe) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"${name.showCode(indent)} : ${tpe.showCode()}" + } + + /** A dummy pattern used for storing documentation comments between branches + * in a pattern match. + * + * To store a documentation comment next to a branch, a dummy branch is + * created with its pattern being an instance of this Doc and expression + * being empty. + * + * @param doc the documentation entity + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + final case class Documentation( + doc: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Pattern { + override protected var id: Identifier = randomId + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Documentation = + this + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Documentation = + copy(location = location) + + /** Creates a copy of `this`. + * + * @param doc the documentation entity + * @param location the source location for this IR node + * @param passData any pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the new identifier for this node + * @return a copy of `this`, updated with the provided values + */ + def copy( + doc: String = doc, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Documentation = { + val res = Documentation(doc, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean, + keepMetadata: Boolean, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Documentation = + copy( + doc, + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def children: List[IR] = Nil + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Pattern.Documentation( + |doc = $doc, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def showCode(indent: Int): String = s"## $doc" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala new file mode 100644 index 000000000000..94da38463bc0 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Type.scala @@ -0,0 +1,417 @@ +package org.enso.compiler.core.ir + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Constructs that operate on types. */ +trait Type extends Expression { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Type + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Type + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Type +} + +object Type { + + /** Static information about the type operators. */ + trait Info { + val name: String + } + + sealed case class Function( + args: List[Expression], + result: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Type { + override protected var id: Identifier = randomId + + def copy( + args: List[Expression] = args, + result: Expression = result, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Function = { + val res = Function(args, result, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Function = + copy( + args = args.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + result = result.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Function = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Function = { + copy(args = args.map(fn), result = fn(result)) + } + + /** @inheritdoc */ + override def toString: String = + s"""Type.Function( + |args = $args, + |result = $result, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = args :+ result + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"${args.map(_.showCode()).mkString(" -> ")} -> ${result.showCode()}" + } + + /** The ascription of a type to a value. + * + * @param typed the expression being ascribed a type + * @param signature the signature being ascribed to `typed` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Ascription( + typed: Expression, + signature: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Type + with module.scope.Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param typed the expression being ascribed a type + * @param signature the signature being ascribed to `typed` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + typed: Expression = typed, + signature: Expression = signature, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Ascription = { + val res = Ascription(typed, signature, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Ascription = + copy( + typed = typed.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + signature = signature.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Ascription = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Ascription = { + copy(typed = fn(typed), signature = fn(signature)) + } + + /** @inheritdoc */ + override def toString: String = + s"""Type.Ascription( + |typed = $typed, + |signature = $signature, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(typed, signature) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"${typed.showCode(indent)} : ${signature.showCode(indent)}" + } + + object Ascription extends Info { + override val name: String = ":" + } + + /** A representation of the `in` portion of a type signature that represents + * the ascription of a monadic context. + * + * @param typed the type being ascribed a monadic context + * @param context the context being ascribed to `typed` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Context( + typed: Expression, + context: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Type + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates ac opy of `this`. + * + * @param typed the type being ascribed a monadic context + * @param context the context being ascribed to `typed` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + typed: Expression = typed, + context: Expression = context, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Context = { + val res = Context(typed, context, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Context = + copy( + typed = typed.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + context = context.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Context = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Context = { + copy(typed = fn(typed), context = fn(context)) + } + + /** @inheritdoc */ + override def toString: String = + s"""Type.Context( + |typed = $typed, + |context = $context, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(typed, context) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"${typed.showCode(indent)} in ${context.showCode(indent)}" + } + + object Context extends Info { + override val name: String = "in" + } + + /** Represents the ascription of an error context to an expression. + * + * @param typed the expression being ascribed an error context + * @param error the error being ascribed + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Error( + typed: Expression, + error: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Type + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param typed the expression being ascribed an error context + * @param error the error being ascribed + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + typed: Expression = typed, + error: Expression = error, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Error = { + val res = Error(typed, error, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Error = + copy( + typed = typed.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepLocations + ), + error = error.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepLocations + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Error = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Error = + copy(typed = fn(typed), error = fn(error)) + + /** @inheritdoc */ + override def toString: String = + s"""Type.Error( + |typed = $typed, + |error = $error, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(typed, error) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${typed.showCode(indent)} ! ${error.showCode(indent)})" + } + + object Error extends Info { + override val name: String = "!" + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala new file mode 100644 index 000000000000..60738bd86ec3 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/Warning.scala @@ -0,0 +1,113 @@ +package org.enso.compiler.core.ir + +import com.oracle.truffle.api.source.Source +import org.enso.compiler.core.IR.fileLocationFromSection +import org.enso.compiler.core.{ir, IR} + +/** A trait for all warnings in Enso's IR. */ +trait Warning extends Diagnostic + +object Warning { + + case class DuplicatedImport( + override val location: Option[IdentifiedLocation], + originalImport: ir.module.scope.Import, + symbolName: String, + source: Source + ) extends Warning { + override def message: String = { + val originalImportRepr = + originalImport.location match { + case Some(location) => + s"'${originalImport.showCode()}' in ${fileLocationFromSection(location, source)}" + case None => originalImport.showCode() + } + s"Duplicated import of $symbolName. The original import is ${originalImportRepr}." + } + + override def diagnosticKeys(): Array[Any] = Array() + } + + /** A warning about a `@Tail_Call` annotation placed in a non-tail + * position. + * + * @param location the location of the annotated application + */ + case class WrongTco(override val location: Option[IdentifiedLocation]) + extends Warning { + override def message: String = + "A @Tail_Call annotation was placed in a non-tail-call position." + + override def diagnosticKeys(): Array[Any] = Array() + } + + /** A warning about a `@Builtin_Method` annotation placed in a method + * with unexpected body. + * + * @param location the location of the annotated application + */ + case class WrongBuiltinMethod( + override val location: Option[IdentifiedLocation] + ) extends Warning { + override def message: String = + "A @Builtin_Method annotation allows only the name of the builtin node in the body." + + override def diagnosticKeys(): Array[Any] = Array() + } + + /** A warning raised when a method is defined with a `self` parameter defined + * not in the first position in the parameters' list.` + * + * @param ir the annotated application + * @param paramPosition the reason why the annotation cannot be obeyed + */ + case class WrongSelfParameterPos( + funName: Name, + ir: IR, + paramPosition: Int + ) extends Warning { + override val location: Option[IdentifiedLocation] = ir.location + + override def message: String = + s"${funName.name}: Self parameter should be declared as the first parameter. Instead its position is: ${paramPosition + 1}." + + override def diagnosticKeys(): Array[Any] = + Array(ir.showCode(), paramPosition) + } + + /** A warning raised when a call is annotated with `@Auto_Parallel`, but the + * annotation cannot be obeyed. + * + * @param ir the annotated application + * @param reason the reason why the annotation cannot be obeyed + */ + case class FailedParallelism( + ir: IR, + reason: String + ) extends Warning { + override val location: Option[IdentifiedLocation] = ir.location + + override def message: String = + s"The expression ${ir.showCode()} could not be parallelised: $reason." + + override def diagnosticKeys(): Array[Any] = Array(ir.showCode(), reason) + } + + case class NonUnitTypeUsedOnValueLevel(ir: Name, context: String) + extends Warning { + + /** @return a human-readable description of this error condition. + */ + override def message: String = + s"A non-unit type ${ir.name} is used on value level (in ${context})." + + " This is probably an error." + + /** The location at which the diagnostic occurs. */ + override val location: Option[IdentifiedLocation] = ir.location + + /** The important keys identifying identity of the diagnostic + */ + override def diagnosticKeys(): Array[Any] = Array(ir.name) + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Application.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Application.scala new file mode 100644 index 000000000000..f1aa70d705d9 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Application.scala @@ -0,0 +1,435 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** All function applications in Enso. */ +trait Application extends Expression { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Application + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Application + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Application +} + +object Application { + + /** A standard prefix function application. + * + * @param function the function being called + * @param arguments the arguments to the function being called + * @param hasDefaultsSuspended whether the function application has any + * argument defaults in `function` suspended + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Prefix( + function: Expression, + arguments: List[CallArgument], + hasDefaultsSuspended: Boolean, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Application + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param function the function being called + * @param arguments the arguments to the function being called + * @param hasDefaultsSuspended whether the function application has any + * argument defaults in `function` suspended + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + function: Expression = function, + arguments: List[CallArgument] = arguments, + hasDefaultsSuspended: Boolean = hasDefaultsSuspended, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Prefix = { + val res = + Prefix( + function, + arguments, + hasDefaultsSuspended, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Prefix = + copy( + function = function.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Prefix = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Prefix = { + copy(function = fn(function), arguments.map(_.mapExpressions(fn))) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Application.Prefix( + |function = $function, + |arguments = $arguments, + |hasDefaultsSuspended = $hasDefaultsSuspended, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = function :: arguments + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val argStr = arguments.map(_.showCode(indent)).mkString(" ") + + s"((${function.showCode(indent)}) $argStr)" + } + } + + /** A representation of a term that is explicitly forced. + * + * @param target the expression being forced + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Force( + target: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Application + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param target the expression being forced + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + target: Expression = target, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Force = { + val res = Force(target, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Force = + copy( + target = target.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Force = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Force = { + copy(target = fn(target)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Application.Force( + |target = $target, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(target) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(FORCE ${target.showCode(indent)})" + } + + /** Literal applications in Enso. */ + sealed trait Literal extends Application { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Literal + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Literal + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Literal + } + + /** A representation of a typeset literal. + * + * These are necessary as they delimit pattern contexts. + * + * @param expression the expression of the typeset body + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Typeset( + expression: Option[Expression], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Literal + with IRKind.Primitive { + override protected var id: Identifier = randomId + + override def mapExpressions(fn: Expression => Expression): Typeset = + copy(expression = expression.map(fn)) + + /** Creates a copy of `this`. + * + * @param expression the expression of the typeset body + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updataed with the specified values + */ + def copy( + expression: Option[Expression] = expression, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Typeset = { + val res = Typeset(expression, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Typeset = + copy( + expression = expression.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Typeset = copy(location = location) + + /** @inheritdoc */ + override def toString: String = + s"""Application.Typeset( + |expression = $expression, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + expression.map(List(_)).getOrElse(List()) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val exprString = if (expression.isDefined) { + expression.get.showCode(indent) + } else "" + + s"{ $exprString }" + } + } + + /** A representation of a vector literal. + * + * @param items the items being put in the vector + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Sequence( + items: List[Expression], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Literal + with IRKind.Primitive { + override protected var id: Identifier = randomId + + override def mapExpressions(fn: Expression => Expression): Sequence = + copy(items = items.map(fn)) + + /** Creates a copy of `this`. + * + * @param items the items held by this vector + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + items: List[Expression] = items, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Sequence = { + val res = Sequence(items, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Sequence = + copy( + items = items.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Sequence = copy(location = location) + + /** @inheritdoc */ + override def toString: String = + s""" + |Application.Vector( + |items = $items, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = items + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val itemsStr = items.map(_.showCode(indent)).mkString(", ") + s"[$itemsStr]" + } + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Case.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Case.scala new file mode 100644 index 000000000000..e6e67bca83ee --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Case.scala @@ -0,0 +1,333 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{ + indentLevel, + mkIndent, + randomId, + Identifier, + ToStringHelper +} + +/** The Enso case expression. */ +sealed trait Case extends Expression { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Case + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Case + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Case +} + +object Case { + + /** The main body of the Enso case expression. + * + * @param scrutinee the expression whose value is being matched on + * @param branches the branches of the case expression + * @param isNested if true, the flag indicates that the expr represents a desugared nested case + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Expr( + scrutinee: Expression, + branches: Seq[Branch], + isNested: Boolean, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Case + with IRKind.Primitive { + override protected var id: Identifier = randomId + + def this( + scrutinee: Expression, + branches: Seq[Branch], + location: Option[IdentifiedLocation], + passData: MetadataStorage, + diagnostics: DiagnosticStorage + ) = { + this(scrutinee, branches, false, location, passData, diagnostics) + } + + /** Creates a copy of `this`. + * + * @param scrutinee the expression whose value is being matched on + * @param branches the branches of the case expression + * @param isNested if true, the flag indicates that the expr represents a desugared nested case + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + scrutinee: Expression = scrutinee, + branches: Seq[Branch] = branches, + isNested: Boolean = isNested, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Expr = { + val res = + Expr(scrutinee, branches, isNested, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Expr = + copy( + scrutinee = scrutinee.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + branches = branches.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + isNested = isNested, + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Expr = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Expr = { + copy( + scrutinee = fn(scrutinee), + branches.map(_.mapExpressions(fn)) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Expr( + |scrutinee = $scrutinee, + |branches = $branches, + |isNested = $isNested, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = scrutinee :: branches.toList + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val newIndent = indent + indentLevel + val headerStr = s"case ${scrutinee.showCode(indent)} of" + val branchesStr = branches + .map(mkIndent(newIndent) + _.showCode(newIndent)) + .mkString("\n") + + s"$headerStr\n$branchesStr" + } + } + + object Expr { + def apply( + scrutinee: Expression, + branches: Seq[Branch], + location: Option[IdentifiedLocation] + ): Expr = + apply( + scrutinee, + branches, + location, + new MetadataStorage(), + new DiagnosticStorage() + ) + + def apply( + scrutinee: Expression, + branches: Seq[Branch], + location: Option[IdentifiedLocation], + passData: MetadataStorage, + diagnostics: DiagnosticStorage + ): Expr = new Expr(scrutinee, branches, location, passData, diagnostics) + } + + /** A branch in a case statement. + * + * @param pattern the pattern that attempts to match against the scrutinee + * @param expression the expression that is executed if the pattern matches + * @param terminalBranch the flag indicating whether the branch represents the final pattern to be checked + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Branch( + pattern: Pattern, + expression: Expression, + terminalBranch: Boolean, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Case + with IRKind.Primitive { + override protected var id: Identifier = randomId + + def this( + pattern: Pattern, + expression: Expression, + location: Option[IdentifiedLocation], + passData: MetadataStorage, + diagnostics: DiagnosticStorage + ) = { + this(pattern, expression, true, location, passData, diagnostics) + } + + /** Creates a copy of `this`. + * + * @param pattern the pattern that attempts to match against the scrutinee + * @param expression the expression that is executed if the pattern matches + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + pattern: Pattern = pattern, + expression: Expression = expression, + terminalBranch: Boolean = terminalBranch, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Branch = { + val res = Branch( + pattern, + expression, + terminalBranch, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Branch = + copy( + pattern = pattern.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + expression = expression.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + terminalBranch = terminalBranch, + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Branch = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Branch = { + copy(pattern = pattern.mapExpressions(fn), expression = fn(expression)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Case.Branch( + |pattern = $pattern, + |expression = $expression, + |terminalBranch = $terminalBranch, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(pattern, expression) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val newIndent = indent + indentLevel + val bodyStr = if (expression.isInstanceOf[Expression.Block]) { + s"\n${mkIndent(newIndent)}${expression.showCode(newIndent)}" + } else { + s"${expression.showCode(indent)}" + } + s"${pattern.showCode(indent)} -> $bodyStr" + } + } + + object Branch { + def apply( + pattern: Pattern, + expression: Expression, + location: Option[IdentifiedLocation] + ): Branch = + apply( + pattern, + expression, + location, + new MetadataStorage(), + new DiagnosticStorage() + ) + + def apply( + pattern: Pattern, + expression: Expression, + location: Option[IdentifiedLocation], + passData: MetadataStorage, + diagnostics: DiagnosticStorage + ): Branch = + new Branch(pattern, expression, location, passData, diagnostics) + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Comment.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Comment.scala new file mode 100644 index 000000000000..f882e9622f4a --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Comment.scala @@ -0,0 +1,108 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Enso comment entities. */ +sealed trait Comment extends Expression with module.scope.Definition { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Comment + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Comment + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Comment +} + +object Comment { + + /** A documentation comment in the Enso source. + * + * @param doc the documentation entity + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Documentation( + doc: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Comment + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param doc the documentation of `commented` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + doc: String = doc, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Documentation = { + val res = Documentation(doc, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Documentation = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Documentation = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Documentation = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Comment.Documentation( + |doc = $doc, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"## $doc" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala new file mode 100644 index 000000000000..71fece0e7458 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Error.scala @@ -0,0 +1,119 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.{ir, IR} + +/** A trait for all errors in Enso's IR. */ +trait Error extends Expression with ir.module.scope.Definition with Diagnostic { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Error + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Error + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Error +} + +object Error { + + /** A representation of an invalid piece of IR. + * + * @param ir the IR that is invalid + * @param passData any annotations from compiler passes + * @param diagnostics compiler diagnostics for this node + */ + sealed case class InvalidIR( + ir: IR, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Error + with Diagnostic.Kind.Static + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param ir the IR that is invalid + * @param passData any annotations from compiler passes + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + ir: IR = ir, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): InvalidIR = { + val res = InvalidIR(ir, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): InvalidIR = + copy( + ir = ir.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): InvalidIR = this + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = ir.location + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): InvalidIR = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.InvalidIR( + |ir = $ir, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(ir) + + /** @inheritdoc */ + override def message: String = + "InvalidIR: Please report this as a compiler bug." + + override def diagnosticKeys(): Array[Any] = Array() + + /** @inheritdoc */ + override def showCode(indent: Int): String = "Invalid_Ir" + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Foreign.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Foreign.scala new file mode 100644 index 000000000000..7ba96b6f45e6 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Foreign.scala @@ -0,0 +1,114 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.MetadataStorage + +// === Foreign ============================================================== + +/** Foreign code entities. */ +sealed trait Foreign extends Expression { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Foreign + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Foreign + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Foreign +} + +object Foreign { + + /** A foreign code definition in Enso. + * + * @param lang the foreign language being written + * @param code the code written in `lang` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Definition( + lang: String, + code: String, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Foreign + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param lang the foreign language being written + * @param code the code written in `lang` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + lang: String = lang, + code: String = code, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Definition = { + val res = Definition(lang, code, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Definition = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Definition = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Definition = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Foreign.Definition( + |lang = $lang, + |code = $code, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = "FOREIGN DEF" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Operator.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Operator.scala new file mode 100644 index 000000000000..12127cc6177c --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Operator.scala @@ -0,0 +1,139 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper}; + +/** Operator applications in Enso. */ +trait Operator extends Application { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Operator + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Operator + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Operator +} + +object Operator { + + /** A representation of a generic binary operator application in Enso. + * + * @param left the left operand to `operator` + * @param operator the operator function being called + * @param right the right operand to `operator` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Binary( + left: CallArgument, + operator: Name, + right: CallArgument, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Operator + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand to `operator` + * @param operator the operator function being called + * @param right the right operand to `operator` + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: CallArgument = left, + operator: Name = operator, + right: CallArgument = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Binary = { + val res = + Binary(left, operator, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Binary = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + operator = operator.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Binary = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Binary = { + copy(left = left.mapExpressions(fn), right = right.mapExpressions(fn)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Operator.Binary( + |left = $left, + |operator = $operator, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, operator, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val opStr = operator.showCode(indent) + + s"((${left.showCode(indent)}) $opStr (${right.showCode(indent)}))" + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Section.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Section.scala new file mode 100644 index 000000000000..4c93477bccc4 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/Section.scala @@ -0,0 +1,318 @@ +package org.enso.compiler.core.ir +package expression + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** Operator sections. */ +sealed trait Section extends Operator { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Section + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Section + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Section +} + +object Section { + + /** Represents a left operator section of the form `(arg op)`. + * + * @param arg the argument (on the left of the operator) + * @param operator the operator + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Left( + arg: CallArgument, + operator: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Section + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param arg the argument (on the left of the operator) + * @param operator the operator + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + arg: CallArgument = arg, + operator: Name = operator, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: IR.Identifier = id + ): Left = { + val res = Left(arg, operator, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Left = + copy( + arg = arg.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + operator = operator + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Left = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Section = + copy( + arg = arg.mapExpressions(fn), + operator = operator.mapExpressions(fn) + ) + + /** @inheritdoc */ + override def toString: String = + s""" + |Section.Left( + |arg = $arg, + |operator = $operator, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(arg, operator) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${arg.showCode(indent)} ${operator.showCode(indent)})" + } + + /** Represents a sides operator section of the form `(op)` + * + * @param operator the operator + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Sides( + operator: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Section + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param operator the operator + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + operator: Name = operator, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Sides = { + val res = Sides(operator, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Sides = + copy( + operator = operator + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Sides = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Section = + copy(operator = operator.mapExpressions(fn)) + + /** @inheritdoc */ + override def toString: String = + s""" + |Section.Sides( + |operator = $operator, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(operator) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${operator.showCode(indent)})" + } + + /** Represents a right operator section of the form `(op arg)` + * + * @param operator the operator + * @param arg the argument (on the right of the operator) + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Right( + operator: Name, + arg: CallArgument, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Section + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param operator the operator + * @param arg the argument (on the right of the operator) + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + operator: Name = operator, + arg: CallArgument = arg, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Right = { + val res = Right(operator, arg, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Right = + copy( + operator = operator + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arg = arg.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Right = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Section = { + copy( + operator = operator.mapExpressions(fn), + arg = arg.mapExpressions(fn) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Section.Right( + |operator = $operator, + |arg = $arg, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(operator, arg) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${operator.showCode(indent)} ${arg.showCode(indent)})" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala new file mode 100644 index 000000000000..4852679f08d2 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Conversion.scala @@ -0,0 +1,141 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier} + +/** An error resulting from processing conversion methods. + * + * @param storedIr the IR that contains the error + * @param reason the explanation for the error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler dianostics for this node + */ +sealed case class Conversion( + storedIr: IR, + reason: Conversion.Reason, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Error + with Diagnostic.Kind.Interactive + with IRKind.Primitive + with Name { + override val name: String = "conversion_error" + + override def mapExpressions(fn: Expression => Expression): Conversion = + this + + override def setLocation( + location: Option[IdentifiedLocation] + ): Conversion = { + copy(storedIr = storedIr.setLocation(location)) + } + + /** Create a copy of `this`. + * + * @param storedIr the IR that contains the error + * @param reason the explanation for the error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler dianostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + storedIr: IR = storedIr, + reason: Conversion.Reason = reason, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Conversion = { + val res = Conversion(storedIr, reason, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean, + keepMetadata: Boolean, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Conversion = { + copy( + storedIr = storedIr.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + } + + /** @inheritdoc */ + override def children: List[IR] = List(storedIr) + + /** @inheritdoc */ + override protected var id: Identifier = randomId + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Error: ${storedIr.showCode(indent)})" + + /** @inheritdoc */ + override def message: String = reason.explain + + override def diagnosticKeys(): Array[Any] = Array(reason.explain) + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = storedIr.location +} + +object Conversion { + + /** The reason for the error. */ + sealed trait Reason { + def explain: String + } + + case object MissingArgs extends Reason { + override def explain: String = + "A conversion definition must have at least one argument." + } + + case object UnsupportedSourceType extends Reason { + override def explain: String = + "Arbitrary expressions are not yet supported as source types." + } + + case class MissingSourceType(argName: String) extends Reason { + override def explain: String = + s"The argument `$argName` does not define a source type." + } + + case class MissingSelfParam(argName: String) extends Reason { + override def explain: String = + s"""|Conversion definition must have an explicit `self` parameter in the first position. + |Got `$argName` instead.""".stripMargin + } + + case class NonDefaultedArgument(argName: String) extends Reason { + override def explain: String = + s"Additional arguments in a conversion must have a default, but " + + s"`$argName` does not." + } + + case class SuspendedSourceArgument(argName: String) extends Reason { + override def explain: String = + s"The `that` type argument in a conversion (here $argName) cannot " + + s"be suspended." + } + + case class InvalidSourceArgumentName(argName: String) extends Reason { + override def explain: String = + s"The source type argument must be ignored or named `that`, but" + + s" ${argName} was found." + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala new file mode 100644 index 000000000000..b36066e126a3 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/ImportExport.scala @@ -0,0 +1,202 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import com.oracle.truffle.api.source.Source +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{ + fileLocationFromSection, + randomId, + Identifier, + ToStringHelper +} + +import scala.annotation.unused + +/** An erroneous import or export statement. + * + * @param ir the original statement + * @param reason the reason it's erroneous + * @param passData the pass data + * @param diagnostics the attached diagnostics + */ +sealed case class ImportExport( + ir: IR, + reason: ImportExport.Reason, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Error + with Diagnostic.Kind.Interactive + with org.enso.compiler.core.ir.module.scope.Import + with org.enso.compiler.core.ir.module.scope.Export + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param ir the original IR + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + ir: IR = ir, + reason: ImportExport.Reason = reason, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): ImportExport = { + val res = ImportExport(ir, reason, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + @unused keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): ImportExport = + copy( + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): ImportExport = + this + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = ir.location + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): ImportExport = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.ImportExport( + |ir = $ir, + |reason = $reason, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(ir) + + /** @inheritdoc */ + override def message: String = reason.message + + override def diagnosticKeys(): Array[Any] = Array(reason) + + /** @inheritdoc */ + override def showCode(indent: Int): String = "Import_Export_Error" +} + +object ImportExport { + + /** A reason for a statement being erroneous. + */ + sealed trait Reason { + + /** @return A human-readable description of the error. + */ + def message: String + } + + /** Used when the `project` keyword is used in an impossible position. + * + * @param statementType the type of statement being affected, see the + * implementation for its grammatical use. + */ + case class ProjectKeywordUsedButNotInProject(statementType: String) + extends Reason { + override def message: String = + s"The `project` keyword was used in an $statementType statement," + + " but the module does not belong to a project." + } + + /** Used when an import statement triggers loading of a package that could + * not be loaded. + * + * @param name the module name. + */ + case class PackageCouldNotBeLoaded(name: String, reason: String) + extends Reason { + override def message: String = s"Package containing the module $name" + + s" could not be loaded: $reason" + } + + /** Used when an import statement refers to a module that does not exist. + * + * @param name the module name. + */ + case class ModuleDoesNotExist(name: String) extends Reason { + override def message: String = s"The module $name does not exist." + } + + case class TypeDoesNotExist( + typeName: String, + moduleName: String + ) extends Reason { + override def message: String = + s"The type $typeName does not exist in module $moduleName" + } + + case class SymbolDoesNotExist( + symbolName: String, + moduleName: String + ) extends Reason { + override def message: String = + s"The symbol $symbolName (module or type) does not exist in module $moduleName." + } + + case class NoSuchConstructor( + typeName: String, + constructorName: String + ) extends Reason { + override def message: String = + s"No such constructor ${constructorName} in type $typeName" + } + + /** Represents an ambiguous import resolution error, where the same symbol is imported more than once refereing + * to different objects. The objects are represented by their physical path in the project. + * + * @param originalImport the original import statement. + * @param originalSymbolPath the original symbol path. + * @param symbolName the symbol name that is ambiguous. + * @param symbolPath the symbol path that is different than [[originalSymbolPath]]. + * @param source Location of the original import. + */ + case class AmbiguousImport( + originalImport: module.scope.Import, + originalSymbolPath: String, + symbolName: String, + symbolPath: String, + source: Source + ) extends Reason { + override def message: String = { + val originalImportRepr = + originalImport.location match { + case Some(location) => + fileLocationFromSection(location, source) + case None => originalImport.showCode() + } + s"Symbol '$symbolName' resolved ambiguously to '$symbolPath' in the import Statement. " + + s"The symbol was first resolved to '$originalSymbolPath' in the import statement '$originalImportRepr'." + } + + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala new file mode 100644 index 000000000000..a70113d28f7b --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Pattern.scala @@ -0,0 +1,112 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier} + +/** A representation of an error resulting from wrong pattern matches. + * + * @param originalPattern pattern that resulted in the error + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @return a copy of `this`, updated with the specified values + */ +sealed case class Pattern( + originalPattern: org.enso.compiler.core.ir.Pattern, + reason: Pattern.Reason, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Error + with Diagnostic.Kind.Interactive + with org.enso.compiler.core.ir.Pattern { + override def mapExpressions(fn: Expression => Expression): Pattern = + copy(originalPattern = originalPattern.mapExpressions(fn)) + + override def setLocation(location: Option[IdentifiedLocation]): Pattern = + copy(originalPattern = originalPattern.setLocation(location)) + + /** Creates a copy of `this`. + * + * @param originalPattern the pattern that resulted in the error + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + originalPattern: org.enso.compiler.core.ir.Pattern = originalPattern, + reason: Pattern.Reason = reason, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Pattern = { + val res = Pattern(originalPattern, reason, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Pattern = + copy( + originalPattern = originalPattern + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + override def message: String = reason.explain + + override def diagnosticKeys(): Array[Any] = Array(reason) + + override val location: Option[IdentifiedLocation] = + originalPattern.location + + override def children: List[IR] = List(originalPattern) + + override protected var id: Identifier = randomId + + override def showCode(indent: Int): String = + originalPattern.showCode(indent) +} + +object Pattern { + + /** A representation of the reason the pattern is erroneous. + */ + sealed trait Reason { + + /** Provides a human-readable explanation of the error. + * + * @return + */ + def explain: String + } + + /** A reason for pattern failing due to wrong arity. + * + * @param consName the constructor name. + * @param expected expected field count. + * @param actual actual field count. + */ + case class WrongArity(consName: String, expected: Int, actual: Int) + extends Reason { + override def explain: String = + s"Wrong number of fields when matching on $consName." + + s" Expected $expected fields, but provided $actual" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala new file mode 100644 index 000000000000..dd25ae7c4089 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Redefined.scala @@ -0,0 +1,664 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier} + +/** Errors pertaining to the redefinition of language constructs that are + * not allowed to be. + */ +sealed trait Redefined extends Error { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Redefined + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Redefined + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Redefined +} + +object Redefined { + + /** An error representing the redefinition or incorrect positioning of + * the `self` argument to methods. + * + * @param location the source location of the error + * @param passData the pass metadata for this node + * @param diagnostics compiler diagnostics associated with the node + */ + sealed case class SelfArg( + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `self`. + * + * @param location the source location of the error + * @param passData the pass metadata for this node + * @param diagnostics compiler diagnostics associated with the node + * @param id the node's identifier + * @return a copy of `this`, with the specified values updated + */ + def copy( + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): SelfArg = { + val res = SelfArg(location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): SelfArg = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): SelfArg = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): SelfArg = + this + + /** @inheritdoc */ + override def message: String = + "Methods must have only one definition of the `this` argument, and " + + "it must be the first." + + override def diagnosticKeys(): Array[Any] = Array() + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = "(Redefined This_Arg)" + } + + /** An error representing the redefinition of a conversion in a given + * module. This is also known as a method overload. + * + * @param targetType the name of the atom the conversion was being + * redefined on + * @param sourceType the source type for the conversion + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + */ + sealed case class Conversion( + targetType: Option[Name], + sourceType: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with module.scope.Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param targetType the name of the atom the conversion was being + * redefined on + * @param sourceType the source type for the conversion + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + targetType: Option[Name] = targetType, + sourceType: Name = sourceType, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Conversion = { + val res = + Conversion(targetType, sourceType, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Conversion = + copy( + targetType = targetType.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + sourceType = sourceType + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Conversion = + copy(location = location) + + /** @inheritdoc */ + override def message: String = + s"Method overloads are not supported: ${targetType.map(_.name + ".").getOrElse("")}from " + + s"${sourceType.showCode()} is defined multiple times in this module." + + override def diagnosticKeys(): Array[Any] = targetType + .map(_.name :: sourceType.showCode() :: Nil) + .getOrElse(sourceType.showCode() :: Nil) + .toArray + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Conversion = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Redefined.Method( + |targetType = $targetType, + |sourceType = $sourceType, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = + targetType + .map(_ :: sourceType :: Nil) + .getOrElse(sourceType :: Nil) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Redefined (Conversion ${targetType.map(_.showCode() + ".").getOrElse("")}from $sourceType))" + } + + /** An error representing the redefinition of a method in a given module. + * This is also known as a method overload. + * + * @param atomName the name of the atom the method was being redefined on + * @param methodName the method name being redefined on `atomName` + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + */ + sealed case class Method( + atomName: Option[Name], + methodName: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with module.scope.Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param atomName the name of the atom the method was being redefined on + * @param methodName the method name being redefined on `atomName` + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + atomName: Option[Name] = atomName, + methodName: Name = methodName, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Method = { + val res = + Method(atomName, methodName, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Method = + copy( + atomName = atomName.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + methodName = methodName + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Method = + copy(location = location) + + /** @inheritdoc */ + override def message: String = + s"Method overloads are not supported: ${atomName.map(_.name + ".").getOrElse("")}" + + s"${methodName.name} is defined multiple times in this module." + + override def diagnosticKeys(): Array[Any] = { + atomName + .map(_.name :: methodName.name :: Nil) + .getOrElse(methodName.name :: Nil) + .toArray + } + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Method = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Redefined.Method( + |atomName = $atomName, + |methodName = $methodName, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = + atomName + .map(_ :: methodName :: Nil) + .getOrElse(methodName :: Nil) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Redefined (Method ${atomName.map(_.showCode() + ".").getOrElse("")}$methodName))" + } + + /** An error representing the redefinition of a method in a given module, + * when the module defines a method with the same name as an atom. + * This is also known as a name clash. + * + * @param atomName the name of the atom that clashes with the method + * @param methodName the method name being redefined in the module + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + */ + sealed case class MethodClashWithAtom( + atomName: Name, + methodName: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with module.scope.Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param atomName the name of the atom that clashes with the method + * @param methodName the method name being redefined in the module + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + atomName: Name = atomName, + methodName: Name = methodName, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): MethodClashWithAtom = { + val res = MethodClashWithAtom( + atomName, + methodName, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): MethodClashWithAtom = + copy( + atomName = atomName.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + methodName = methodName + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): MethodClashWithAtom = + copy(location = location) + + /** @inheritdoc */ + override def message: String = + s"Method definitions with the same name as atoms are not supported. " + + s"Method ${methodName.name} clashes with the atom ${atomName.name} in this module." + + override def diagnosticKeys(): Array[Any] = + Array(methodName.name, atomName.name) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): MethodClashWithAtom = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Redefined.MethodClashWithAtom( + |atomName = $atomName, + |methodName = $methodName, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = List(atomName, methodName) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Redefined (MethodClash $atomName $methodName))" + } + + /** An error representing the redefinition of an atom in a given module. + * + * @param typeName the name of the atom being redefined + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + */ + sealed case class Type( + typeName: Name, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with module.scope.Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param atomName the name of the atom the method was being redefined + * on + * @param location the location in the source to which this error + * corresponds + * @param passData the pass metadata for the error + * @param diagnostics any diagnostics associated with this error. + * @param id the identifier for the node + * @return a copy of `this`, updated with the specified values + */ + def copy( + atomName: Name = typeName, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Type = { + val res = + Type(atomName, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Type = + copy( + atomName = typeName.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Type = + copy(location = location) + + /** @inheritdoc */ + override def message: String = + s"Redefining atoms is not supported: ${typeName.name} is " + + s"defined multiple times in this module." + + override def diagnosticKeys(): Array[Any] = Array(typeName.name) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Type = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Redefined.Atom( + |atomName = $typeName, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = List(typeName) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Redefined (Atom $typeName))" + } + + /** An error representing the redefinition of a binding in a given scope. + * + * While bindings in child scopes are allowed to _shadow_ bindings in + * parent scopes, a binding cannot be redefined within a given scope. + * + * @param invalidBinding the invalid binding + * @param passData the pass metadata for the error + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Binding( + invalidBinding: Expression.Binding, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Redefined + with Diagnostic.Kind.Interactive + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param invalidBinding the invalid binding + * @param passData the pass metadata for the error + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + invalidBinding: Expression.Binding = invalidBinding, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Binding = { + val res = Binding(invalidBinding, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Binding = + copy( + invalidBinding = invalidBinding + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Binding = this + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = + invalidBinding.location + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Binding = + this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Redefined.Binding( + |invalidBinding = $invalidBinding, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".stripMargin + + /** @inheritdoc */ + override def children: List[IR] = List(invalidBinding) + + /** @inheritdoc */ + override def message: String = + s"Variable ${invalidBinding.name.name} is being redefined." + + override def diagnosticKeys(): Array[Any] = Array( + invalidBinding.name.name + ) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Redefined (Binding $invalidBinding))" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala new file mode 100644 index 000000000000..6f73ab864aef --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Resolution.scala @@ -0,0 +1,214 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier} + +/** A representation of an error resulting from name resolution. + * + * @param originalName the original name that could not be resolved + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ +sealed case class Resolution( + originalName: Name, + reason: Resolution.Reason, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Error + with Diagnostic.Kind.Interactive + with IRKind.Primitive + with Name { + override val name: String = originalName.name + + override def mapExpressions(fn: Expression => Expression): Resolution = + this + + override def setLocation( + location: Option[IdentifiedLocation] + ): Resolution = + copy(originalName = originalName.setLocation(location)) + + /** Creates a copy of `this`. + * + * @param originalName the original name that could not be resolved + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + originalName: Name = originalName, + reason: Resolution.Reason = reason, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Resolution = { + val res = Resolution(originalName, reason, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Resolution = + copy( + originalName = originalName + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = randomId + ) + + /** @inheritdoc */ + override def children: List[IR] = List(originalName) + + /** @inheritdoc */ + override protected var id: Identifier = randomId + + /** @inheritdoc */ + override def showCode(indent: Int): String = originalName.showCode(indent) + + /** @inheritdoc */ + override def message: String = reason.explain(originalName) + + /** @inheritdoc */ + override def formattedMessage: String = s"${message}." + + override def diagnosticKeys(): Array[Any] = Array(reason) + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = originalName.location +} + +object Resolution { + + /** A representation of a symbol resolution error. + */ + sealed trait Reason { + def explain(originalName: Name): String + } + + case object UnresolvedSequenceMacro extends Reason { + override def explain(originalName: Name): String = + "No definition for the sequence macro could be found. Try" + + " importing the default definition from the Standard.Base module" + } + + /** An error coming from an unknown annotation name. + */ + case object UnknownAnnotation extends Reason { + override def explain(originalName: Name): String = + s"The annotation ${originalName.name} is not defined" + } + + /** An error coming from a tail call annotation placed in a syntactically + * incorrect position. + */ + case object UnexpectedAnnotation extends Reason { + override def explain(originalName: Name): String = + s"Unexpected ${originalName.name} annotation. This annotation can " + + s"only be used with function applications" + } + + /** An error coming from an unexpected occurence of a polyglot symbol. + * + * @param context the description of a context in which the error + * happened. + */ + case class UnexpectedPolyglot(context: String) extends Reason { + override def explain(originalName: Name): String = + s"The name ${originalName.name} resolved to a polyglot symbol, " + + s"but polyglot symbols are not allowed in $context" + } + + /** An error coming from an unexpected occurence of a constructor. + * + * @param context the description of a context in which the error + * happened. + */ + case class UnexpectedConstructor(context: String) extends Reason { + override def explain(originalName: Name): String = + s"The name ${originalName.name} resolved to a constructor, " + + s"but constructors are not allowed in $context" + } + + /** An error coming from an unexpected occurence of a static method. + * + * @param context the description of a context in which the error + * happened. + */ + case class UnexpectedMethod(context: String) extends Reason { + override def explain(originalName: Name): String = + s"The name ${originalName.name} resolved to a method, " + + s"but methods are not allowed in $context" + } + + /** An error coming from an unexpected occurence of a module. + * + * @param context the description of a context in which the error + * happened. + */ + case class UnexpectedModule(context: String) extends Reason { + override def explain(originalName: Name): String = + s"The name ${originalName.name} resolved to a module, " + + s"but modules are not allowed in $context" + } + + /** An error coming from an unexpected occurence of a type. + * + * @param context the description of a context in which the error + * happened. + */ + case class UnexpectedType(context: String) extends Reason { + override def explain(originalName: Name): String = + s"The name ${originalName.name} resolved to a type, " + + s"but types are not allowed in $context" + } + + /** An error coming from usage of an undefined variable name. + */ + case object VariableNotInScope extends Reason { + override def explain(originalName: Name): String = + s"Variable `${originalName.name}` is not defined" + } + + /** An error coming from name resolver. + * + * @param err the original error. + */ + case class ResolverError(private val explain: ExplainResolution) + extends Reason { + + /** Provides a human-readable explanation of the error. + * + * @param originalName the original unresolved name. + * @return a human-readable message. + */ + override def explain(originalName: Name): String = + this.explain.explain(originalName) + } + + trait ExplainResolution { + def explain(originalName: Name): String + } + + case class MissingLibraryImportInFQNError(namespace: String) extends Reason { + override def explain(originalName: Name): String = + s"Fully qualified name references a library $namespace.${originalName.name} but an import statement for it is missing" + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala new file mode 100644 index 000000000000..6cc2224dbc15 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Syntax.scala @@ -0,0 +1,240 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +import scala.annotation.unused + +/** A representation of an Enso syntax error. + * + * @param at the error location + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ +sealed case class Syntax( + at: IdentifiedLocation, + reason: Syntax.Reason, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Error + with Diagnostic.Kind.Interactive + with module.scope.Definition + with module.scope.Export + with module.scope.Import + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param ast the error location + * @param reason the cause of this error + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + at: IdentifiedLocation = at, + reason: Syntax.Reason = reason, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Syntax = { + val res = Syntax(at, reason, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + @unused keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Syntax = + copy( + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Syntax = + this + + /** @inheritdoc */ + override val location: Option[IdentifiedLocation] = Option(at) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Syntax = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Error.Syntax( + |at = $at, + |reason = $reason, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def message: String = reason.explanation + + /** @inheritdoc */ + override def formattedMessage: String = s"${message}." + + override def diagnosticKeys(): Array[Any] = Array(reason) + + /** @inheritdoc */ + override def showCode(indent: Int): String = "Syntax_Error" +} + +object Syntax { + + /** A common type for all syntax errors expected by the language. + */ + sealed trait Reason { + + /** @return a human-readable description of the error. + */ + def explanation: String + } + + case object SuspendedArgInAtom extends Reason { + override def explanation: String = + "Atoms may not have suspended arguments" + } + + case class InvalidEscapeSequence(lit: String) extends Reason { + override def explanation: String = s"Invalid escape sequence $lit" + } + + case object InvalidBaseInDecimalLiteral extends Reason { + override def explanation: String = + "Cannot change base of the fractional part of a number literal" + } + + case class InvalidBase(base: String) extends Reason { + override def explanation: String = + s"$base is not a valid numeric base" + } + + case class InvalidNumberForBase(base: String, number: String) extends Reason { + override def explanation: String = + s"$number is not valid in $base" + } + + case class UnsupportedSyntax(syntaxName: String) extends Reason { + override def explanation: String = + s"Syntax is not supported yet: $syntaxName" + } + + case object InvalidUnderscore extends Reason { + override def explanation: String = + s"Invalid use of _" + } + + case object InvalidPattern extends Reason { + override def explanation: String = + s"Cannot define a pattern outside a pattern context" + } + + case class InvalidImport( + message: String = "Imports must have a valid module path" + ) extends Reason { + override def explanation: String = + s"Invalid Import: $message" + } + + case class InvalidExport( + message: String = "Exports must have a valid module path" + ) extends Reason { + override def explanation: String = + s"Invalid Export: $message" + } + + case object InvalidStandaloneSignature extends Reason { + override def explanation: String = + s"Invalid stand-alone signature expression" + } + + case class MethodDefinedInline(methodName: String) extends Reason { + override def explanation: String = + s"Cannot define $methodName, methods are not supported in the " + + s"inline flow" + } + + case object UnexpectedDeclarationInType extends Reason { + override def explanation: String = + "Unexpected declaration in the body of a type" + } + + case object InvalidTypeDefinition extends Reason { + override def explanation: String = + "Invalid definition of a type" + } + + case class TypeDefinedInline(typeName: String) extends Reason { + override def explanation: String = + s"Cannot define $typeName, type definitions are not supported " + + s"in the inline flow" + } + + case object EmptyParentheses extends Reason { + override def explanation: String = + "Parentheses can't be empty" + } + + case object UnexpectedExpression extends Reason { + override def explanation: String = "Unexpected expression" + } + + case object AmbiguousExpression extends Reason { + override def explanation: String = "Ambiguous expression" + } + + case object InvalidSelfArgUsage extends Reason { + override def explanation: String = + "Self argument cannot be used in static methods" + } + + case object UnrecognizedToken extends Reason { + override def explanation: String = "Unrecognized token" + } + + case object InvalidSuffix extends Reason { + override def explanation: String = "Invalid suffix" + } + + case object UnclosedTextLiteral extends Reason { + override def explanation: String = "Unclosed text literal" + } + + case object NamedArgInSection extends Reason { + override def explanation: String = "Named argument in operator section" + } + + case object NamedArgInOperator extends Reason { + override def explanation: String = "Named argument in operator section" + } + + case object InvalidOperatorName extends Reason { + override def explanation: String = "Invalid operator name" + } + + case class InvalidForeignDefinition(details: String) extends Reason { + override def explanation: String = + s"Invalid foreign definition. $details" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala new file mode 100644 index 000000000000..8f138b4554e3 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/errors/Unexpected.scala @@ -0,0 +1,116 @@ +package org.enso.compiler.core.ir +package expression +package errors + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier} + +/** A trait for errors about unexpected language constructs. */ +sealed trait Unexpected extends Error { + + /** The unexpected construct. */ + val ir: IR + + /** The name of the unexpected entity. */ + val entity: String + + override val location: Option[IdentifiedLocation] = ir.location + + /** @inheritdoc */ + override def message: String = s"Unexpected $entity." + + /** @inheritdoc */ + override def diagnosticKeys(): Array[Any] = Array(entity) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Unexpected + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Unexpected + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Unexpected +} + +object Unexpected { + + /** An error representing a type signature not associated with a + * binding of some kind. + * + * @param ir the erroneous signature + * @param passData any pass metadata associated with this node + * @param diagnostics any compiler diagnostics for this node + */ + sealed case class TypeSignature( + override val ir: IR, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Unexpected + with IRKind.Primitive + with org.enso.compiler.core.ir.module.scope.Definition { + override val entity: String = "type signature" + + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param ir the erroneous signature + * @param passData any pass metadata associated with this node + * @param diagnostics any compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + ir: IR = ir, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): TypeSignature = { + val res = TypeSignature(ir, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): TypeSignature = this + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): TypeSignature = this + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): TypeSignature = + copy( + ir = ir.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def children: List[IR] = List(ir) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(Unexpected.TypeSignature ${ir.showCode(indent)})" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala new file mode 100644 index 000000000000..28b9ff7e443b --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Shadowed.scala @@ -0,0 +1,100 @@ +package org.enso.compiler.core.ir +package expression +package warnings + +import org.enso.compiler.core.IR + +/** Warnings about shadowing names. */ +sealed trait Shadowed extends Warning { + + /** The [[IR]] shadowing the warned expression. */ + val shadower: IR +} + +object Shadowed { + + /** A warning that a later-defined lambda parameter shadows an + * earlier-defined lambda parameter. + * + * @param shadowedName the name being shadowed + * @param shadower the expression shadowing `warnedExpr` + * @param location the location at which the shadowing takes place + */ + sealed case class FunctionParam( + shadowedName: String, + override val shadower: IR, + override val location: Option[IdentifiedLocation] + ) extends Shadowed { + override def message: String = + s"The argument $shadowedName is shadowed by $shadower" + + override def diagnosticKeys(): Array[Any] = + Array(shadowedName, shadower) + } + + /** A warning that a later-defined pattern variable shadows an + * earlier-defined pattern variable. + * + * @param shadowedName the name being shadowed + * @param shadower the expression shadowing `warnedExpr` + * @param location the location at which the shadowing takes place + */ + sealed case class PatternBinding( + shadowedName: String, + override val shadower: IR, + override val location: Option[IdentifiedLocation] + ) extends Shadowed { + override def message: String = + s"The pattern field $shadowedName is shadowed by $shadower." + + override def diagnosticKeys(): Array[Any] = + Array(shadowedName, shadower) + } + + /** A warning that a submodule is being shadowed by the type of the same name + * therefore preventing the user from accessing the module via a qualified name. + * + * @param typename the type name shadowing the module + * @param moduleName the module being shadowed + * @param shadower the expression shadowing `moduleName` + * @param location the location at which the shadowing takes place + */ + sealed case class SyntheticModule( + typeName: String, + moduleName: Name.Qualified, + override val shadower: IR, + override val location: Option[IdentifiedLocation] + ) extends Shadowed { + override def message: String = + s"""Declaration of type $typeName shadows module ${moduleName.name} making it inaccessible via a qualified name.""" + + override def diagnosticKeys(): Array[Any] = + Array(typeName, moduleName, shadower) + + } + + /** Used when the exported type of the module can name conflict with fully qualified names of submodules. + * + * @param name the module name + * @param tpeName the name of the exported type leading to conflicts + * @param firstConflict the name of the module that can be innaccessible because of the name conflict + * @param shadower the export statement leading to a conflict + * @param location the location of the export statement + */ + sealed case class TypeInModuleNameConflicts( + name: String, + tpeName: String, + firstConflict: String, + override val shadower: IR, + override val location: Option[IdentifiedLocation] + ) extends Shadowed { + override def message: String = + s"The exported type `$tpeName` in `$name` module will cause name conflict " + + s"when attempting to use a fully qualified name of the `$firstConflict` module." + + /** The important keys identifying identity of the diagnostic + */ + override def diagnosticKeys(): Array[Any] = + Array(name, tpeName, shadower) + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala new file mode 100644 index 000000000000..3a6ff656dc9f --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unreachable.scala @@ -0,0 +1,30 @@ +package org.enso.compiler.core.ir +package expression +package warnings + +/** Warnings for unreachable code. */ +sealed trait Unreachable extends Warning { + val location: Option[IdentifiedLocation] +} + +object Unreachable { + + /** A warning for unreachable branches in a case expression. + * + * @param location the location of the unreachable branches + */ + sealed case class Branches( + override val location: Option[IdentifiedLocation] + ) extends Unreachable { + val atLocation = + if (location.isDefined) { + s" at location ${location.get}" + } else { + "" + } + + override def message: String = s"Unreachable case branches$atLocation." + + override def diagnosticKeys(): Array[Any] = Array(atLocation) + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala new file mode 100644 index 000000000000..c309c949f4d7 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/expression/warnings/Unused.scala @@ -0,0 +1,49 @@ +package org.enso.compiler.core.ir +package expression +package warnings + +/** Warnings about unused language entities. */ +sealed trait Unused extends Warning { + val name: Name +} + +object Unused { + + /** A warning about an unused function argument. + * + * @param name the name that is unused + */ + sealed case class FunctionArgument(override val name: Name) extends Unused { + override def message: String = s"Unused function argument ${name.name}." + + override def diagnosticKeys(): Array[Any] = Array(name.name) + + override def toString: String = s"Unused.FunctionArgument(${name.name})" + + override val location: Option[IdentifiedLocation] = name.location + } + + sealed case class PatternBinding(override val name: Name) extends Unused { + override def message: String = s"Unused pattern binding ${name.name}." + + override def diagnosticKeys(): Array[Any] = Array(name.name) + + override def toString: String = s"Unused.PatternBinding(${name.name})" + + override val location: Option[IdentifiedLocation] = name.location + } + + /** A warning about an unused binding. + * + * @param name the name that is unused + */ + sealed case class Binding(override val name: Name) extends Unused { + override def message: String = s"Unused variable ${name.name}." + + override def diagnosticKeys(): Array[Any] = Array(name.name) + + override def toString: String = s"Unused.Binding(${name.name})" + + override val location: Option[IdentifiedLocation] = name.location + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/Scope.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/Scope.scala new file mode 100644 index 000000000000..0e4c7488e4f2 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/Scope.scala @@ -0,0 +1,24 @@ +package org.enso.compiler.core.ir.module + +import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, IdentifiedLocation} + +/** A representation of constructs that can only occur in the top-level + * module scope + */ +trait Scope extends IR { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Scope + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Scope + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Scope +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Definition.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Definition.scala new file mode 100644 index 000000000000..c72f51cb5407 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Definition.scala @@ -0,0 +1,398 @@ +package org.enso.compiler.core.ir.module.scope + +import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + DefinitionArgument, + DiagnosticStorage, + Expression, + IRKind, + IdentifiedLocation, + MetadataStorage, + Name +} +import org.enso.compiler.core.ir.module.Scope +import org.enso.compiler.core.IR.{ + indentLevel, + mkIndent, + randomId, + Identifier, + ToStringHelper +} + +/** A representation of top-level definitions. */ +trait Definition extends Scope { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Definition + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Definition + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Definition +} + +object Definition { + + /** The definition of a union type and its members. + * + * NB: this should probably be removed once we propagate the union + * types logic through the runtime and implement statics – the whole + * notion of desugaring complex type definitions becomes obsolete then. + * + * @param name the name of the union + * @param members the members of this union + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Type( + name: Name, + params: List[DefinitionArgument], + members: List[Data], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Definition + with IRKind.Primitive { + override protected var id: Identifier = randomId + + def copy( + name: Name = name, + params: List[DefinitionArgument] = params, + members: List[Data] = members, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Type = { + val res = + Type(name, params, members, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Type = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + members = members.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Type = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Type = + copy( + params = params.map(_.mapExpressions(fn)), + members = members.map(_.mapExpressions(fn)) + ) + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.Type( + |name = $name, + |params = $params, + |members = $members, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = name :: (params :++ members) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val fields = members.map(_.showCode(indent)).mkString(" | ") + + s"type ${name.showCode(indent)} = $fields" + } + } + + /** The definition of an atom constructor and its associated arguments. + * + * @param name the name of the atom + * @param arguments the arguments to the atom constructor + * @param annotations the list of annotations + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Data( + name: Name, + arguments: List[DefinitionArgument], + annotations: List[Name.GenericAnnotation], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends IR + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the atom + * @param arguments the arguments to the atom constructor + * @param annotations the list of annotations + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name = name, + arguments: List[DefinitionArgument] = arguments, + annotations: List[Name.GenericAnnotation] = annotations, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Data = { + val res = Data( + name, + arguments, + annotations, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Data = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Data = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Data = { + copy( + name = name.mapExpressions(fn), + arguments = arguments.map(_.mapExpressions(fn)), + annotations = annotations.map(_.mapExpressions(fn)) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.Data( + |name = $name, + |arguments = $arguments, + |annotations = $annotations, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = name :: arguments ::: annotations + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val fields = arguments.map(_.showCode(indent)).mkString(" ") + + s"type ${name.showCode(indent)} $fields" + } + } + + /** The definition of a complex type definition that may contain + * multiple atom and method definitions. + * + * @param name the name of the complex type + * @param arguments the (type) arguments to the complex type + * @param body the body of the complex type + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class SugaredType( + name: Name, + arguments: List[DefinitionArgument], + body: List[IR], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Definition + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the name of the complex type + * @param arguments the (type) arguments to the complex type + * @param body the body of the complex type + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name = name, + arguments: List[DefinitionArgument] = arguments, + body: List[IR] = body, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): SugaredType = { + val res = SugaredType( + name, + arguments, + body, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): SugaredType = + copy( + name = name.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + body = body.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): SugaredType = + copy(body = body.map(_.mapExpressions(fn))) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): SugaredType = copy(location = location) + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.SugaredType( + |name = $name, + |arguments = $arguments, + |body = $body, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = (name :: arguments) ::: body + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val headerArgs = arguments.map(_.showCode(indent)).mkString(" ") + val header = s"type ${name.name} $headerArgs" + val newIndent = indent + indentLevel + val bodyStr = body + .map(mkIndent(newIndent) + _.showCode(newIndent)) + .mkString("\n\n") + + s"$header\n$bodyStr" + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Export.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Export.scala new file mode 100644 index 000000000000..496f72df1e10 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Export.scala @@ -0,0 +1,198 @@ +package org.enso.compiler.core.ir.module.scope + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.module.Scope +import org.enso.compiler.core.ir.{ + DiagnosticStorage, + Expression, + IRKind, + IdentifiedLocation, + MetadataStorage, + Name +} + +/** An export statement */ +trait Export extends Scope { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Export + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Export + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Export +} + +object Export { + + /** An export statement. + * + * @param name the full path representing the export + * @param rename the name this export is visible as + * @param isAll is this an unqualified export + * @param onlyNames exported names selected from the exported module + * @param hiddenNames exported names hidden from the exported module + * @param location the source location that the node corresponds to + * @param isSynthetic is this export compiler-generated + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Module( + name: Name.Qualified, + rename: Option[Name.Literal], + isAll: Boolean, + onlyNames: Option[List[Name.Literal]], + hiddenNames: Option[List[Name.Literal]], + override val location: Option[IdentifiedLocation], + isSynthetic: Boolean = false, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends IR + with IRKind.Primitive + with Export { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the full path representing the export + * @param rename the name this export is visible as + * @param isAll is this an unqualified export + * @param onlyNames exported names selected from the exported module + * @param hiddenNames exported names hidden from the exported module + * @param location the source location that the node corresponds to + * @param isSynthetic is this import compiler-generated + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name.Qualified = name, + rename: Option[Name.Literal] = rename, + isAll: Boolean = isAll, + onlyNames: Option[List[Name.Literal]] = onlyNames, + hiddenNames: Option[List[Name.Literal]] = hiddenNames, + location: Option[IdentifiedLocation] = location, + isSynthetic: Boolean = isSynthetic, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Module = { + val res = Module( + name, + rename, + isAll, + onlyNames, + hiddenNames, + location, + isSynthetic, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Module = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Module = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Module = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Export.Module( + |name = $name, + |rename = $rename, + |isAll = $isAll, + |onlyNames = $onlyNames, + |hidingNames = $hiddenNames, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + name :: List( + rename.toList, + onlyNames.getOrElse(List()), + hiddenNames.getOrElse(List()) + ).flatten + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val renameCode = rename.map(n => s" as ${n.name}").getOrElse("") + if (isAll) { + val onlyPart = onlyNames + .map(names => " " + names.map(_.name).mkString(", ")) + .getOrElse("") + val hidingPart = hiddenNames + .map(names => s" hiding ${names.map(_.name).mkString(", ")}") + .getOrElse("") + val all = if (onlyNames.isDefined) "" else " all" + s"from ${name.name}$renameCode export$onlyPart$all$hidingPart" + } else { + s"export ${name.name}$renameCode" + } + } + + /** Gets the name of the module visible in the importing scope, + * either the original name or the rename. + * + * @return the name of this export visible in code + */ + def getSimpleName: Name = rename.getOrElse(name.parts.last) + + /** Checks whether the export statement allows use of the given + * exported name. + * + * Note that it does not verify if the name is actually exported + * by the module, only checks if it is syntactically allowed. + * + * @param name the name to check + * @return whether the name could be accessed or not + */ + def allowsAccess(name: String): Boolean = { + if (!isAll) return false; + if (onlyNames.isDefined) { + onlyNames.get.exists(_.name.toLowerCase == name.toLowerCase) + } else if (hiddenNames.isDefined) { + !hiddenNames.get.exists(_.name.toLowerCase == name.toLowerCase) + } else { + true + } + } + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Import.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Import.scala new file mode 100644 index 000000000000..2677d40531da --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/Import.scala @@ -0,0 +1,197 @@ +package org.enso.compiler.core.ir.module.scope + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.module.Scope +import org.enso.compiler.core.ir.{ + DiagnosticStorage, + Expression, + IRKind, + IdentifiedLocation, + MetadataStorage, + Name +} + +/** Module-level import statements. */ +trait Import extends Scope { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Import + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Import + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Import +} + +object Import { + + /** An import statement. + * + * @param name the full path representing the import + * @param rename the name this import is visible as + * @param isAll is this importing exported names + * @param onlyNames exported names selected from the imported module + * @param hiddenNames exported names hidden from the imported module + * @param location the source location that the node corresponds to + * @param isSynthetic is this import compiler-generated + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Module( + name: Name.Qualified, + rename: Option[Name.Literal], + isAll: Boolean, + onlyNames: Option[List[Name.Literal]], + hiddenNames: Option[List[Name.Literal]], + override val location: Option[IdentifiedLocation], + isSynthetic: Boolean = false, + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Import + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param name the full `.`-separated path representing the import + * @param rename the name this import is visible as + * @param isAll is this importing exported names + * @param onlyNames exported names selected from the imported module + * @param hiddenNames exported names hidden from the imported module + * @param location the source location that the node corresponds to + * @param isSynthetic is this import compiler-generated + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + name: Name.Qualified = name, + rename: Option[Name.Literal] = rename, + isAll: Boolean = isAll, + onlyNames: Option[List[Name.Literal]] = onlyNames, + hiddenNames: Option[List[Name.Literal]] = hiddenNames, + location: Option[IdentifiedLocation] = location, + isSynthetic: Boolean = isSynthetic, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Module = { + val res = Module( + name, + rename, + isAll, + onlyNames, + hiddenNames, + location, + isSynthetic, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Module = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Module = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Module = this + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Import.Module( + |name = $name, + |rename = $rename, + |onlyNames = $onlyNames, + |hiddenNames = $hiddenNames, + |isAll = $isAll, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + name :: List( + rename.toList, + onlyNames.getOrElse(List()), + hiddenNames.getOrElse(List()) + ).flatten + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val renameCode = rename.map(n => s" as ${n.name}").getOrElse("") + if (isAll) { + val onlyPart = onlyNames + .map(names => " " + names.map(_.name).mkString(", ")) + .getOrElse("") + val hidingPart = hiddenNames + .map(names => s" hiding ${names.map(_.name).mkString(", ")}") + .getOrElse("") + val all = if (onlyNames.isDefined) "" else " all" + s"from ${name.name}$renameCode import$onlyPart$all$hidingPart" + } else { + s"import ${name.name}$renameCode" + } + } + + /** Gets the name of the module visible in this scope, either the + * original name or the rename. + * + * @return the name of this import visible in code + */ + def getSimpleName: Name = rename.getOrElse(name.parts.last) + + /** Checks whether the import statement allows use of the given + * exported name. + * + * Note that it does not verify if the name is actually exported + * by the module, only checks if it is syntactically allowed. + * + * @param name the name to check + * @return whether the name could be accessed or not + */ + def allowsAccess(name: String): Boolean = { + if (!isAll) return false; + if (onlyNames.isDefined) { + onlyNames.get.exists(_.name == name) + } else if (hiddenNames.isDefined) { + !hiddenNames.get.exists(_.name == name) + } else { + true + } + } + } + +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/definition/Method.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/definition/Method.scala new file mode 100644 index 000000000000..49b01bfac45d --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/definition/Method.scala @@ -0,0 +1,456 @@ +package org.enso.compiler.core.ir +package module +package scope +package definition + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} + +/** A trait representing method definitions in Enso. */ +sealed trait Method extends Definition { + val methodReference: Name.MethodReference + val body: Expression + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Method + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Method + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Method + + /** Get the type name for the method. */ + def typeName: Option[Name] = methodReference.typePointer + + /** Get the name of the method. */ + def methodName: Name = methodReference.methodName +} + +object Method { + + /** The definition of a method for a given constructor. + * + * @param methodReference a reference to the method being defined + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Explicit( + override val methodReference: Name.MethodReference, + override val body: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Method + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param methodReference a reference to the method being defined + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + methodReference: Name.MethodReference = methodReference, + body: Expression = body, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Explicit = { + val res = Explicit( + methodReference, + body, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Explicit = + copy( + methodReference = methodReference.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + body = body.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy + else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Explicit = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Explicit = { + copy( + methodReference = methodReference.mapExpressions(fn), + body = fn(body) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.Method.Explicit( + |methodReference = $methodReference, + |body = $body, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(methodReference, body) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val exprStr = if (body.isInstanceOf[Expression.Block]) { + s"\n${body.showCode(indent)}" + } else { + s"${body.showCode(indent)}" + } + + s"${methodReference.showCode(indent)} = $exprStr" + } + + def isStatic: Boolean = body match { + case function: Function.Lambda => + function.arguments.headOption.map(_.name) match { + case Some(Name.Self(_, true, _, _)) => true + case _ => false + } + case _ => + true // if it's not a function, it has no arguments, therefore no `self` + } + + def isStaticWrapperForInstanceMethod: Boolean = body match { + case function: Function.Lambda => + function.arguments.map(_.name) match { + case Name.Self(_, true, _, _) :: Name.Self( + _, + false, + _, + _ + ) :: _ => + true + case _ => false + } + case _ => false + } + + } + + /** The definition of a method for a given constructor using sugared + * syntax. + * + * @param methodReference a reference to the method being defined + * @param arguments the arguments to the method + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Binding( + override val methodReference: Name.MethodReference, + arguments: List[DefinitionArgument], + override val body: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Method + with IRKind.Sugar { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param methodReference a reference to the method being defined + * @param arguments the arguments to the method + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + methodReference: Name.MethodReference = methodReference, + arguments: List[DefinitionArgument] = arguments, + body: Expression = body, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Binding = { + val res = Binding( + methodReference, + arguments, + body, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Binding = + copy( + methodReference = methodReference.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + arguments = arguments.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + body = body.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy + else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Binding = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Binding = { + copy( + methodReference = methodReference.mapExpressions(fn), + arguments = arguments.map(_.mapExpressions(fn)), + body = fn(body) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.Method.Binding( + |methodReference = $methodReference, + |arguments = $arguments, + |body = $body, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + (methodReference :: arguments) :+ body + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val exprStr = if (body.isInstanceOf[Expression.Block]) { + s"\n${body.showCode(indent)}" + } else { + s"${body.showCode(indent)}" + } + + val argsStr = arguments.map(_.showCode(indent)).mkString(" ") + + s"${methodReference.showCode(indent)} $argsStr = $exprStr" + } + } + + /** A method that represents a conversion from one type to another. + * + * @param methodReference a reference to the type on which the + * conversion is being defined + * @param sourceTypeName the type of the source value for this + * conversion + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Conversion( + override val methodReference: Name.MethodReference, + sourceTypeName: Expression, + override val body: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Method + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param methodReference a reference to the type on which the + * conversion is being defined + * @param sourceTypeName the type of the source value for this + * conversion + * @param body the body of the method + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + methodReference: Name.MethodReference = methodReference, + sourceTypeName: Expression = sourceTypeName, + body: Expression = body, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Conversion = { + val res = Conversion( + methodReference, + sourceTypeName, + body, + location, + passData, + diagnostics + ) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean, + keepMetadata: Boolean, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Conversion = { + copy( + methodReference = methodReference.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + sourceTypeName = sourceTypeName.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + body = body.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy + else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + } + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Conversion = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Conversion = { + copy( + methodReference = methodReference.mapExpressions(fn), + sourceTypeName = sourceTypeName.mapExpressions(fn), + body = fn(body) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Definition.Method.Conversion( + |methodReference = $methodReference, + |sourceTypeName = $sourceTypeName, + |body = $body, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = + List(methodReference, sourceTypeName, body) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val exprStr = if (body.isInstanceOf[Expression.Block]) { + s"\n${body.showCode(indent)}" + } else { + s"${body.showCode(indent)}" + } + + s"${methodReference.showCode(indent)} = $exprStr" + } + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/imports/Polyglot.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/imports/Polyglot.scala new file mode 100644 index 000000000000..b48821a80d21 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/module/scope/imports/Polyglot.scala @@ -0,0 +1,146 @@ +package org.enso.compiler.core.ir.module.scope.imports + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.{ + DiagnosticStorage, + Expression, + IRKind, + IdentifiedLocation, + MetadataStorage +} + +/** An import of a polyglot class. + * + * @param entity language-specific information on the imported entity + * @param rename the name this object should be visible under in the + * importing scope + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ +sealed case class Polyglot( + entity: Polyglot.Entity, + rename: Option[String], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() +) extends Import + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param entity language-specific information on the imported entity + * @param rename the name this object should be visible under in the + * importing scope + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + entity: Polyglot.Entity = entity, + rename: Option[String] = rename, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Polyglot = { + val res = + Polyglot(entity, rename, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Polyglot = + copy( + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Polyglot = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Polyglot = + this + + /** Returns the name this object is visible as from Enso code. + * + * @return the visible name of this object + */ + def getVisibleName: String = rename.getOrElse(entity.getVisibleName) + + /** @inheritdoc */ + override def toString: String = + s""" + |Module.Scope.Import.Polyglot( + |entity = $entity, + |rename = $rename, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List() + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val renamePart = rename.map(name => s"as $name").getOrElse("") + s"polyglot ${entity.langName} import ${entity.showCode(indent)} $renamePart" + } +} + +object Polyglot { + + /** Represents language-specific polyglot import data. */ + sealed trait Entity { + val langName: String + + /** Returns the name this object is visible as from Enso code. + * + * @return the visible name of this object + */ + def getVisibleName: String + + def showCode(indent: Int = 0): String + } + + /** Represents an import of a Java class. + * + * @param packageName the name of the package containing the imported + * class + * @param className the class name + */ + case class Java(packageName: String, className: String) extends Entity { + val langName = "java" + + override def getVisibleName: String = className + + /** Returns the fully qualified Java name of this object. + * + * @return the Java-side name of the imported entity + */ + def getJavaName: String = s"$packageName.$className" + + override def showCode(indent: Int): String = + s"$packageName.$className" + } +} diff --git a/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/type/Set.scala b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/type/Set.scala new file mode 100644 index 000000000000..dc0c6c523902 --- /dev/null +++ b/engine/runtime-parser/src/main/scala/org/enso/compiler/core/ir/type/Set.scala @@ -0,0 +1,757 @@ +package org.enso.compiler.core.ir +package `type` + +import org.enso.compiler.core.IR +import org.enso.compiler.core.IR.{randomId, Identifier, ToStringHelper} +import org.enso.compiler.core.ir.Type.Info + +/** IR nodes for dealing with typesets. */ +sealed trait Set extends Type { + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Set + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Set + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Set +} + +object Set { + + /** The representation of a typeset member. + * + * @param label the member's label, if given + * @param memberType the member's type, if given + * @param value the member's value, if given + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Member( + label: Name, + memberType: Expression, + value: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param label the member's label, if given + * @param memberType the member's type, if given + * @param value the member's value, if given + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + label: Name = label, + memberType: Expression = memberType, + value: Expression = value, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Member = { + val res = + Member(label, memberType, value, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Member = + copy( + label = label.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + memberType = memberType + .duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + value = value.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Member = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Member = { + copy( + label = label.mapExpressions(fn), + memberType = fn(memberType), + value = fn(value) + ) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Member( + |label = $label, + |memberType = $memberType, + |value = $value, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |) + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(label, memberType, value) + + /** @inheritdoc */ + override def showCode(indent: Int): String = { + val typeString = s" : ${memberType.showCode(indent)}" + val valueString = s" = ${value.showCode(indent)}" + s"(${label.showCode(indent)}$typeString$valueString)" + } + } + + object Member extends Info { + override val name: String = "_ : _ = _" + } + + /** The typeset subsumption judgement `<:`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Subsumption( + left: Expression, + right: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: Expression = left, + right: Expression = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Subsumption = { + val res = Subsumption(left, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Subsumption = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Subsumption = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Subsumption = { + copy(left = fn(left), right = fn(right)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Subsumption( + |left = $left, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${left.showCode(indent)} <: ${right.showCode(indent)})" + } + + object Subsumption extends Info { + override val name: String = "<:" + } + + /** The typeset equality judgement `~`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Equality( + left: Expression, + right: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: Expression = left, + right: Expression = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Equality = { + val res = Equality(left, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Equality = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Equality = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Equality = { + copy(left = fn(left), right = fn(right)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Equality( + |left = $left, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${left.showCode(indent)} ~ ${right.showCode(indent)}" + } + + object Equality extends Info { + override val name: String = "~" + } + + /** The typeset concatenation operator `,`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Concat( + left: Expression, + right: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: Expression = left, + right: Expression = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Concat = { + val res = Concat(left, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Concat = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Concat = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Concat = { + copy(left = fn(left), right = fn(right)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Concat( + |left = $left, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${left.showCode(indent)}; ${right.showCode(indent)})" + } + + object Concat extends Info { + override val name: String = ";" + } + + /** The typeset union operator `|`. + * + * @param operands the operands + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Union( + operands: List[Expression], + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + operands: List[Expression] = operands, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Union = { + val res = Union(operands, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Union = + copy( + operands = operands.map( + _.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ) + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation(location: Option[IdentifiedLocation]): Union = + copy(location = location) + + /** @inheritdoc */ + override def mapExpressions(fn: Expression => Expression): Union = { + copy(operands = operands.map(fn)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Union( + |operands = $operands, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = operands.toList + + /** @inheritdoc */ + override def showCode(indent: Int): String = + operands.map(_.showCode(indent)).toList.mkString(" | ") + } + + object Union extends Info { + override val name: String = "|" + } + + /** The typeset intersection operator `&`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Intersection( + left: Expression, + right: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: Expression = left, + right: Expression = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Intersection = { + val res = Intersection(left, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Intersection = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Intersection = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Intersection = { + copy(left = fn(left), right = fn(right)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Intersection( + |left = $left, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${left.showCode(indent)} & ${right.showCode(indent)})" + } + + object Intersection extends Info { + override val name: String = "&" + } + + /** The typeset subtraction operator `\`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + */ + sealed case class Subtraction( + left: Expression, + right: Expression, + override val location: Option[IdentifiedLocation], + override val passData: MetadataStorage = MetadataStorage(), + override val diagnostics: DiagnosticStorage = DiagnosticStorage() + ) extends Set + with IRKind.Primitive { + override protected var id: Identifier = randomId + + /** Creates a copy of `this`. + * + * @param left the left operand + * @param right the right operand + * @param location the source location that the node corresponds to + * @param passData the pass metadata associated with this node + * @param diagnostics compiler diagnostics for this node + * @param id the identifier for the new node + * @return a copy of `this`, updated with the specified values + */ + def copy( + left: Expression = left, + right: Expression = right, + location: Option[IdentifiedLocation] = location, + passData: MetadataStorage = passData, + diagnostics: DiagnosticStorage = diagnostics, + id: Identifier = id + ): Subtraction = { + val res = Subtraction(left, right, location, passData, diagnostics) + res.id = id + res + } + + /** @inheritdoc */ + override def duplicate( + keepLocations: Boolean = true, + keepMetadata: Boolean = true, + keepDiagnostics: Boolean = true, + keepIdentifiers: Boolean = false + ): Subtraction = + copy( + left = left.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + right = right.duplicate( + keepLocations, + keepMetadata, + keepDiagnostics, + keepIdentifiers + ), + location = if (keepLocations) location else None, + passData = if (keepMetadata) passData.duplicate else MetadataStorage(), + diagnostics = + if (keepDiagnostics) diagnostics.copy else DiagnosticStorage(), + id = if (keepIdentifiers) id else randomId + ) + + /** @inheritdoc */ + override def setLocation( + location: Option[IdentifiedLocation] + ): Subtraction = copy(location = location) + + /** @inheritdoc */ + override def mapExpressions( + fn: Expression => Expression + ): Subtraction = { + copy(left = fn(left), right = fn(right)) + } + + /** @inheritdoc */ + override def toString: String = + s""" + |`type`.Set.Subtraction( + |left = $left, + |right = $right, + |location = $location, + |passData = ${this.showPassData}, + |diagnostics = $diagnostics, + |id = $id + |""".toSingleLine + + /** @inheritdoc */ + override def children: List[IR] = List(left, right) + + /** @inheritdoc */ + override def showCode(indent: Int): String = + s"(${left.showCode(indent)} \\ ${right.showCode(indent)})" + } + + object Subtraction extends Info { + override val name: String = "\\" + } +} diff --git a/engine/runtime-parser/src/test/java/org/enso/compiler/core/EnsoParserTest.java b/engine/runtime-parser/src/test/java/org/enso/compiler/core/EnsoParserTest.java index 0d863951c92b..a46dd4deba36 100644 --- a/engine/runtime-parser/src/test/java/org/enso/compiler/core/EnsoParserTest.java +++ b/engine/runtime-parser/src/test/java/org/enso/compiler/core/EnsoParserTest.java @@ -6,7 +6,7 @@ import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.function.Function; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Module; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -23,7 +23,8 @@ public static void initEnsoParser() { @AfterClass public static void closeEnsoParser() throws Exception { - ensoCompiler.close(); + if (ensoCompiler != null) + ensoCompiler.close(); } @Test @@ -1268,18 +1269,18 @@ private static void equivalenceTest(String code1, String code2) throws IOExcepti assertIR(msg, old, now); } - private static IR.Module compile(String code) { + private static Module compile(String code) { return compile(ensoCompiler, code); } - public static IR.Module compile(EnsoParser c, String code) { + public static Module compile(EnsoParser c, String code) { var src = Source.newBuilder("enso", code, "test-" + Integer.toHexString(code.hashCode()) + ".enso").build(); var ir = c.compile(src.getCharacters()); assertNotNull("IR was generated", ir); return ir; } - static void assertIR(String msg, IR.Module old, IR.Module now) throws IOException { + static void assertIR(String msg, Module old, Module now) throws IOException { Function filter = f -> simplifyIR(f, true, true, false); String ir1 = filter.apply(old); String ir2 = filter.apply(now); @@ -1343,32 +1344,32 @@ private static String simplifyIR(IR ir, boolean noIds, boolean noLocations, bool } if (lessDocs) { for (;;) { - final String pref = "IR.Comment.Documentation("; + final String pref = "Comment.Documentation("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("location =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Comment.Doc(" + txt.substring(to); + txt = txt.substring(0, at) + "Comment.Doc(" + txt.substring(to); } for (;;) { - final String pref = "IR.Case.Pattern.Doc("; + final String pref = "Case.Pattern.Doc("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("location =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Comment.CaseDoc(" + txt.substring(to); + txt = txt.substring(0, at) + "Comment.CaseDoc(" + txt.substring(to); } } for (;;) { - final String pref = "IR.Error.Syntax("; + final String pref = "errors.Syntax("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("reason =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Error.Syntax (" + txt.substring(to); + txt = txt.substring(0, at) + "errors.Syntax (" + txt.substring(to); } return txt; } diff --git a/engine/runtime-with-instruments/src/test/java/org/enso/interpreter/test/instrument/IncrementalUpdatesTest.java b/engine/runtime-with-instruments/src/test/java/org/enso/interpreter/test/instrument/IncrementalUpdatesTest.java index 71142360da88..27a72d887ac0 100644 --- a/engine/runtime-with-instruments/src/test/java/org/enso/interpreter/test/instrument/IncrementalUpdatesTest.java +++ b/engine/runtime-with-instruments/src/test/java/org/enso/interpreter/test/instrument/IncrementalUpdatesTest.java @@ -6,7 +6,7 @@ import java.util.Map; import java.util.UUID; import java.util.function.Function; -import org.enso.compiler.core.IR$Literal$Number; +import org.enso.compiler.core.ir.Literal; import org.enso.interpreter.node.expression.literal.LiteralNode; import org.enso.interpreter.runtime.type.ConstantsGen; import org.enso.interpreter.test.Metadata; @@ -67,9 +67,9 @@ public void sendUpdatesWhenFunctionBodyIsChanged() { sendUpdatesWhenFunctionBodyIsChangedBySettingValue("4", ConstantsGen.INTEGER, "4", "5", "5", LiteralNode.class); var m = context.languageContext().findModule(MODULE_NAME).orElse(null); assertNotNull("Module found", m); - var numbers = m.getIr().preorder().filter((v1) -> v1 instanceof IR$Literal$Number); + var numbers = m.getIr().preorder().filter((v1) -> v1 instanceof Literal.Number); assertEquals("One number found: " + numbers, 1, numbers.size()); - if (numbers.head() instanceof IR$Literal$Number n) { + if (numbers.head() instanceof Literal.Number n) { assertEquals("updated to 5", "5", n.value()); } } diff --git a/engine/runtime/src/main/java/org/enso/compiler/ModuleCache.java b/engine/runtime/src/main/java/org/enso/compiler/ModuleCache.java index a60e257d7660..c23790b688af 100644 --- a/engine/runtime/src/main/java/org/enso/compiler/ModuleCache.java +++ b/engine/runtime/src/main/java/org/enso/compiler/ModuleCache.java @@ -9,9 +9,8 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import org.apache.commons.lang3.StringUtils; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Module; import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.Module; import org.enso.interpreter.runtime.builtin.Builtins; import org.enso.polyglot.CompilationStage; @@ -26,9 +25,9 @@ public final class ModuleCache extends Cache { - private final Module module; + private final org.enso.interpreter.runtime.Module module; - public ModuleCache(Module module) { + public ModuleCache(org.enso.interpreter.runtime.Module module) { super(Level.FINEST, module.getName().toString(), true, false); this.module = module; this.entryName = module.getName().item(); @@ -48,14 +47,14 @@ protected byte[] metadata(String sourceDigest, String blobDigest, CachedModule e @Override protected CachedModule deserialize(EnsoContext context, byte[] data, Metadata meta, TruffleLogger logger) throws ClassNotFoundException, IOException, ClassNotFoundException { try (var stream = new ObjectInputStream(new ByteArrayInputStream(data))) { - if (stream.readObject() instanceof IR.Module ir) { + if (stream.readObject() instanceof Module ir) { try { return new CachedModule(ir,CompilationStage.valueOf(meta.compilationStage()), module.getSource()); } catch (IOException ioe) { throw new ClassNotFoundException(ioe.getMessage()); } } else { - throw new ClassNotFoundException("Expected IR.Module, got " + data.getClass()); + throw new ClassNotFoundException("Expected Module, got " + data.getClass()); } } } @@ -178,16 +177,16 @@ protected Object replaceObject(Object obj) throws IOException { // CachedModule is not a record **on purpose**. There appears to be a Frgaal bug leading to invalid compilation error. static class CachedModule { - private final IR.Module _moduleIR; + private final Module _moduleIR; private final CompilationStage _compilationStage; private final Source _source; - public CachedModule(IR.Module moduleIR, CompilationStage compilationStage, Source source) { + public CachedModule(Module moduleIR, CompilationStage compilationStage, Source source) { this._moduleIR = moduleIR; this._compilationStage = compilationStage; this._source = source; } - IR.Module moduleIR() { + Module moduleIR() { return _moduleIR; } CompilationStage compilationStage() { diff --git a/engine/runtime/src/main/java/org/enso/compiler/context/CompilerContext.java b/engine/runtime/src/main/java/org/enso/compiler/context/CompilerContext.java index 51741c485010..f1179d48de4b 100644 --- a/engine/runtime/src/main/java/org/enso/compiler/context/CompilerContext.java +++ b/engine/runtime/src/main/java/org/enso/compiler/context/CompilerContext.java @@ -12,7 +12,7 @@ import org.enso.compiler.PackageRepository; import org.enso.compiler.Passes; import org.enso.compiler.SerializationManager; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; import org.enso.compiler.data.CompilerConfig; import org.enso.interpreter.node.ExpressionNode; import org.enso.interpreter.runtime.Module; @@ -60,10 +60,11 @@ public interface CompilerContext { void truffleRunCodegen(Module module, CompilerConfig config) throws IOException; - void truffleRunCodegen(Source source, ModuleScope scope, CompilerConfig config, IR.Module ir); + void truffleRunCodegen( + Source source, ModuleScope scope, CompilerConfig config, org.enso.compiler.core.ir.Module ir); ExpressionNode truffleRunInline( - Source source, LocalScope localScope, Module module, CompilerConfig config, IR.Expression ir); + Source source, LocalScope localScope, Module module, CompilerConfig config, Expression ir); // module related @@ -91,7 +92,7 @@ void initializeBuiltinsIr( boolean hasCrossModuleLinks(Module module); - IR.Module getIr(Module module); + org.enso.compiler.core.ir.Module getIr(Module module); CompilationStage getCompilationStage(Module module); @@ -100,7 +101,7 @@ void initializeBuiltinsIr( Optional saveCache(Cache cache, T entry, boolean useGlobalCacheLocations); public static interface Updater { - void ir(IR.Module ir); + void ir(org.enso.compiler.core.ir.Module ir); void compilationStage(CompilationStage stage); diff --git a/engine/runtime/src/main/java/org/enso/compiler/context/SimpleUpdate.java b/engine/runtime/src/main/java/org/enso/compiler/context/SimpleUpdate.java index 469d00620cc8..f78d6a07a0b4 100644 --- a/engine/runtime/src/main/java/org/enso/compiler/context/SimpleUpdate.java +++ b/engine/runtime/src/main/java/org/enso/compiler/context/SimpleUpdate.java @@ -1,6 +1,6 @@ package org.enso.compiler.context; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Literal; import org.enso.text.editing.model.TextEdit; /** @@ -11,8 +11,8 @@ * @param newIr the new literal */ public record SimpleUpdate( - IR.Literal ir, + Literal ir, TextEdit edit, - IR.Literal newIr + Literal newIr ) { } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/LiteralNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/LiteralNode.java index 7e4a56f06dea..5822c9700d0e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/LiteralNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/LiteralNode.java @@ -6,7 +6,7 @@ import com.oracle.truffle.api.nodes.NodeInfo; import java.math.BigInteger; import java.util.function.Predicate; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; import org.enso.interpreter.node.ExpressionNode; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.number.EnsoBigInteger; @@ -84,7 +84,7 @@ public Object executeGeneric(VirtualFrame frame) { @Override @SuppressWarnings("unchecked") - public > N asPatchableNode() { + public > N asPatchableNode() { var p = PatchableLiteralNode.build(this); notifyInserted(replace(p)); return (N) p; diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/PatchableLiteralNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/PatchableLiteralNode.java index 931d5750de15..08af8fcc5324 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/PatchableLiteralNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/literal/PatchableLiteralNode.java @@ -6,15 +6,15 @@ import com.oracle.truffle.api.source.SourceSection; import java.util.function.Predicate; import org.enso.compiler.core.IR; -import org.enso.compiler.core.IR$Literal$Number; -import org.enso.compiler.core.IR$Literal$Text; +import org.enso.compiler.core.ir.Expression; +import org.enso.compiler.core.ir.Literal; import org.enso.interpreter.node.ExpressionNode; import org.enso.interpreter.runtime.data.text.Text; import org.enso.interpreter.runtime.tag.Patchable; /** Generic literal node. */ @NodeInfo(shortName = "Literal", description = "Constant literal expression") -final class PatchableLiteralNode extends ExpressionNode implements Patchable, Predicate { +final class PatchableLiteralNode extends ExpressionNode implements Patchable, Predicate { private final LiteralNode node; private Object value; @@ -40,7 +40,7 @@ public Object executeGeneric(VirtualFrame frame) { } @Override - public boolean test(IR.Expression ir) { + public boolean test(Expression ir) { var newValue = parseLiteralIr(ir); if (newValue != null && this.value.getClass() == newValue.getClass()) { this.value = newValue; @@ -62,14 +62,14 @@ public boolean hasTag(Class> N asPatchableNode() { + public > N asPatchableNode() { return (N) this; } - private static Object parseLiteralIr(IR.Expression ir) { + private static Object parseLiteralIr(Expression ir) { return switch (ir) { - case IR$Literal$Text t -> Text.create(t.text()); - case IR$Literal$Number n -> n.numericValue(); + case Literal.Text t -> Text.create(t.text()); + case Literal.Number n -> n.numericValue(); default -> null; }; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java index 862d3f5ffa69..afc9adc5f1fc 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/Module.java @@ -25,6 +25,7 @@ import org.enso.compiler.ModuleCache; import org.enso.compiler.context.SimpleUpdate; import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; import org.enso.interpreter.node.callable.dispatch.CallOptimiserNode; import org.enso.interpreter.node.callable.dispatch.LoopingCallOptimiserNode; import org.enso.interpreter.runtime.builtin.BuiltinFunction; @@ -56,7 +57,7 @@ public final class Module implements EnsoObject { private final Package pkg; private CompilationStage compilationStage = CompilationStage.INITIAL; private boolean isIndexed = false; - private IR.Module ir; + private org.enso.compiler.core.ir.Module ir; private Map uuidsMap; private QualifiedName name; private final ModuleCache cache; @@ -68,7 +69,8 @@ public final class Module implements EnsoObject { * directory then contains submodules of this module that should be directly accessible from this * module - achieved by both filling in this list, and inserting synthetic imports and exports * into this module - See {@link - * org.enso.compiler.Compiler#injectSyntheticModuleExports(IR.Module, List)}. + * org.enso.compiler.Compiler#injectSyntheticModuleExports(org.enso.compiler.core.ir.Module, + * List)}. */ private List directModulesRefs; @@ -240,10 +242,10 @@ public void setLiteralSource(Rope source, SimpleUpdate update) { } if (patchedValues.simpleUpdate(update)) { this.sources = this.sources.newWith(source); - final Function1 fn = - new Function1() { + final Function1 fn = + new Function1() { @Override - public IR.Expression apply(IR.Expression v1) { + public Expression apply(Expression v1) { if (v1 == change) { return update.newIr(); } @@ -371,7 +373,7 @@ private void compile(EnsoContext context) throws IOException { } /** @return IR defined by this module. */ - public IR.Module getIr() { + public org.enso.compiler.core.ir.Module getIr() { return ir; } @@ -422,7 +424,7 @@ void unsafeSetCompilationStage(CompilationStage compilationStage) { * * @param ir the new IR for the module. */ - void unsafeSetIr(IR.Module ir) { + void unsafeSetIr(org.enso.compiler.core.ir.Module ir) { this.ir = ir; this.uuidsMap = null; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/PatchedModuleValues.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/PatchedModuleValues.java index 3d7c6c53c5d9..81882364ecdd 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/PatchedModuleValues.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/PatchedModuleValues.java @@ -12,6 +12,7 @@ import java.util.function.Predicate; import org.enso.compiler.context.SimpleUpdate; import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; import org.enso.interpreter.runtime.callable.function.Function; import org.enso.interpreter.runtime.tag.Patchable; @@ -22,7 +23,7 @@ final class PatchedModuleValues { private final Module module; private final TreeMap deltas = new TreeMap<>(); - private Map> values; + private Map> values; PatchedModuleValues(Module module) { this.module = module; @@ -45,7 +46,7 @@ void dispose() { * @param delta positive or negative change at the offset location */ private synchronized void performUpdates( - Map> collect, int offset, int delta + Map> collect, int offset, int delta ) { if (values == null) { var scope = module.getScope(); @@ -82,7 +83,7 @@ boolean simpleUpdate(SimpleUpdate update) { var scope = module.getScope(); var methods = scope.getMethods(); var conversions = scope.getConversions(); - var collect = new HashMap>(); + var collect = new HashMap>(); if (values != null) { for (var n : values.keySet()) { updateNode(update, n, collect); @@ -113,7 +114,7 @@ boolean simpleUpdate(SimpleUpdate update) { return true; } - private static void updateFunctionsMap(SimpleUpdate edit, Collection> values, Map> nodeValues) { + private static void updateFunctionsMap(SimpleUpdate edit, Collection> values, Map> nodeValues) { for (Map map : values) { for (Function f : map.values()) { updateNode(edit, f.getCallTarget().getRootNode(), nodeValues); @@ -121,7 +122,7 @@ private static void updateFunctionsMap(SimpleUpdate edit, Collection> nodeValues) { + private static void updateNode(SimpleUpdate update, Node root, Map> nodeValues) { LinkedList queue = new LinkedList<>(); queue.add(root); while (!queue.isEmpty()) { diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/TruffleCompilerContext.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/TruffleCompilerContext.java index 3fec49405dc1..ccea5c4d9ca2 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/TruffleCompilerContext.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/TruffleCompilerContext.java @@ -16,6 +16,7 @@ import org.enso.compiler.context.CompilerContext; import org.enso.compiler.context.FreshNameSupply; import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; import org.enso.compiler.data.CompilerConfig; import org.enso.interpreter.node.ExpressionNode; import org.enso.interpreter.runtime.scope.LocalScope; @@ -119,12 +120,12 @@ public void truffleRunCodegen(Module module, CompilerConfig config) throws IOExc } @Override - public void truffleRunCodegen(Source source, ModuleScope scope, CompilerConfig config, IR.Module ir) { + public void truffleRunCodegen(Source source, ModuleScope scope, CompilerConfig config, org.enso.compiler.core.ir.Module ir) { new IrToTruffle(context, source, scope, config).run(ir); } @Override - public ExpressionNode truffleRunInline(Source source, LocalScope localScope, Module module, CompilerConfig config, IR.Expression ir) { + public ExpressionNode truffleRunInline(Source source, LocalScope localScope, Module module, CompilerConfig config, Expression ir) { return new IrToTruffle(context, source, module.getScope(), config) .runInline(ir, localScope, ""); } @@ -161,7 +162,7 @@ public boolean hasCrossModuleLinks(Module module) { } @Override - public IR.Module getIr(Module module) { + public org.enso.compiler.core.ir.Module getIr(Module module) { return module.getIr(); } @@ -255,7 +256,7 @@ public void runStubsGenerator(Module module) { private final class ModuleUpdater implements Updater, AutoCloseable { private final Module module; - private IR.Module ir; + private org.enso.compiler.core.ir.Module ir; private CompilationStage stage; private Boolean loadedFromCache; private Boolean hasCrossModuleLinks; @@ -267,7 +268,7 @@ private ModuleUpdater(org.enso.interpreter.runtime.Module module) { } @Override - public void ir(IR.Module ir) { + public void ir(org.enso.compiler.core.ir.Module ir) { this.ir = ir; } diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/tag/Patchable.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/tag/Patchable.java index 64e08d403ddf..2702a2a5525e 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/tag/Patchable.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/tag/Patchable.java @@ -2,7 +2,7 @@ import com.oracle.truffle.api.nodes.Node; import java.util.function.Predicate; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Expression; /** Implemented by nodes that can be patched by small edits. */ public interface Patchable { @@ -14,7 +14,7 @@ public interface Patchable { * @return callback interface to communicate with * @param node that also implements {@link Predicate} for patching */ - public > N asPatchableNode(); + public > N asPatchableNode(); /** Tag to apply to nodes that support patching and implement {@link Patchable}. */ public final class Tag extends com.oracle.truffle.api.instrumentation.Tag {} diff --git a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala index 51e1c01cfc0f..5c5dc67415f0 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/Compiler.scala @@ -9,7 +9,18 @@ import org.enso.compiler.context.{ } import org.enso.compiler.core.CompilerError import org.enso.compiler.core.CompilerStub -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + Diagnostic, + Expression, + IdentifiedLocation, + Name, + Warning, + Module => IRModule +} +import org.enso.compiler.core.ir.expression.Error +import org.enso.compiler.core.ir.module.scope.Export +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.module.scope.imports; import org.enso.compiler.core.EnsoParser import org.enso.compiler.data.{BindingsMap, CompilerConfig} import org.enso.compiler.exception.CompilationAbortedException @@ -518,14 +529,14 @@ class Compiler( def gatherImportStatements(module: Module): Array[String] = { ensureParsed(module) val importedModules = context.getIr(module).imports.flatMap { - case imp: IR.Module.Scope.Import.Module => + case imp: Import.Module => imp.name.parts.take(2).map(_.name) match { case List(namespace, name) => List(LibraryName(namespace, name)) case _ => throw new CompilerError(s"Invalid module name: [${imp.name}].") } - case _: IR.Module.Scope.Import.Polyglot => + case _: imports.Polyglot => // Note [Polyglot Imports In Dependency Gathering] Nil case other => @@ -687,7 +698,7 @@ class Compiler( */ def processImport( qualifiedName: String, - loc: Option[IR.IdentifiedLocation], + loc: Option[IdentifiedLocation], source: Source ): ModuleScope = { val module = context.getTopScope @@ -760,22 +771,22 @@ class Compiler( * @return enhanced */ private def injectSyntheticModuleExports( - ir: IR.Module, + ir: IRModule, modules: java.util.List[QualifiedName] - ): IR.Module = { + ): IRModule = { import scala.jdk.CollectionConverters._ val moduleNames = modules.asScala.map { q => val name = q.path.foldRight( - List(IR.Name.Literal(q.item, isMethod = false, location = None)) + List(Name.Literal(q.item, isMethod = false, location = None)) ) { case (part, acc) => - IR.Name.Literal(part, isMethod = false, location = None) :: acc + Name.Literal(part, isMethod = false, location = None) :: acc } - IR.Name.Qualified(name, location = None) + Name.Qualified(name, location = None) }.toList ir.copy( imports = ir.imports ::: moduleNames.map(m => - IR.Module.Scope.Import.Module( + Import.Module( m, rename = None, isAll = false, @@ -786,7 +797,7 @@ class Compiler( ) ), exports = ir.exports ::: moduleNames.map(m => - IR.Module.Scope.Export.Module( + Export.Module( m, rename = None, isAll = false, @@ -800,9 +811,9 @@ class Compiler( } private def recognizeBindings( - module: IR.Module, + module: IRModule, moduleContext: ModuleContext - ): IR.Module = { + ): IRModule = { passManager.runPassesOnModule( module, moduleContext, @@ -816,16 +827,16 @@ class Compiler( * @return the output result of the */ private def runMethodBodyPasses( - ir: IR.Module, + ir: IRModule, moduleContext: ModuleContext - ): IR.Module = { + ): IRModule = { passManager.runPassesOnModule(ir, moduleContext, passes.functionBodyPasses) } private def runGlobalTypingPasses( - ir: IR.Module, + ir: IRModule, moduleContext: ModuleContext - ): IR.Module = { + ): IRModule = { passManager.runPassesOnModule(ir, moduleContext, passes.globalTypingPasses) } @@ -837,9 +848,9 @@ class Compiler( * @return the output result of the */ def runCompilerPhasesInline( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { passManager.runPassesInline(ir, inlineContext) } @@ -851,7 +862,7 @@ class Compiler( * @param inlineContext the inline compilation context. */ def runErrorHandlingInline( - ir: IR.Expression, + ir: Expression, source: Source, inlineContext: InlineContext ): Unit = @@ -883,9 +894,9 @@ class Compiler( } if (reportDiagnostics(diagnostics)) { val count = - diagnostics.map(_._2.collect { case e: IR.Error => e }.length).sum + diagnostics.map(_._2.collect { case e: Error => e }.length).sum val warnCount = - diagnostics.map(_._2.collect { case e: IR.Warning => e }.length).sum + diagnostics.map(_._2.collect { case e: Warning => e }.length).sum context.getErr.println( s"Aborting due to ${count} errors and ${warnCount} warnings." ) @@ -899,7 +910,7 @@ class Compiler( * @param module the module for which to gather diagnostics * @return the diagnostics from the module */ - def gatherDiagnostics(module: Module): List[IR.Diagnostic] = { + def gatherDiagnostics(module: Module): List[Diagnostic] = { GatherDiagnostics .runModule( context.getIr(module), @@ -914,8 +925,8 @@ class Compiler( private def hasErrors(module: Module): Boolean = gatherDiagnostics(module).exists { - case _: IR.Error => true - case _ => false + case _: Error => true + case _ => false } private def reportCycle(exception: ExportCycleException): Nothing = { @@ -971,7 +982,7 @@ class Compiler( * @return whether any errors were encountered. */ private def reportDiagnostics( - diagnostics: List[(Module, List[IR.Diagnostic])] + diagnostics: List[(Module, List[Diagnostic])] ): Boolean = { // It may be tempting to replace `.foldLeft(..)` with // `.find(...).nonEmpty. Don't. We want to report diagnostics for all modules @@ -994,13 +1005,13 @@ class Compiler( * @return whether any errors were encountered. */ private def reportDiagnostics( - diagnostics: List[IR.Diagnostic], + diagnostics: List[Diagnostic], source: Source ): Boolean = { diagnostics.foreach(diag => output.println(new DiagnosticFormatter(diag, source).format()) ) - diagnostics.exists(_.isInstanceOf[IR.Error]) + diagnostics.exists(_.isInstanceOf[Error]) } /** Formatter of IR diagnostics. Heavily inspired by GCC. Can format one-line as well as multiline @@ -1011,7 +1022,7 @@ class Compiler( * @param source the original source code */ private class DiagnosticFormatter( - private val diagnostic: IR.Diagnostic, + private val diagnostic: Diagnostic, private val source: Source ) { private val maxLineNum = 99999 @@ -1020,9 +1031,9 @@ class Compiler( private val linePrefixSize = blankLinePrefix.length private val outSupportsAnsiColors: Boolean = outSupportsColors private val (textAttrs: fansi.Attrs, subject: String) = diagnostic match { - case _: IR.Error => (fansi.Color.Red ++ fansi.Bold.On, "error: ") - case _: IR.Warning => (fansi.Color.Yellow ++ fansi.Bold.On, "warning: ") - case _ => throw new IllegalStateException("Unexpected diagnostic type") + case _: Error => (fansi.Color.Red ++ fansi.Bold.On, "error: ") + case _: Warning => (fansi.Color.Yellow ++ fansi.Bold.On, "warning: ") + case _ => throw new IllegalStateException("Unexpected diagnostic type") } private val sourceSection: Option[SourceSection] = diagnostic.location match { @@ -1182,7 +1193,7 @@ class Compiler( } private def fileLocationFromSection( - loc: Option[IR.IdentifiedLocation], + loc: Option[IdentifiedLocation], source: Source ): String = { val srcLocation = loc @@ -1207,7 +1218,7 @@ class Compiler( * @param scope the module scope in which the code is to be generated */ def truffleCodegen( - ir: IR.Module, + ir: IRModule, source: Source, scope: ModuleScope ): Unit = { @@ -1260,7 +1271,7 @@ class Compiler( * @return the result of updating metadata in `copyOfIr` globally using * information from `sourceIr` */ - def updateMetadata(sourceIr: IR.Module, copyOfIr: IR.Module): IR.Module = { + def updateMetadata(sourceIr: IRModule, copyOfIr: IRModule): IRModule = { passManager.runMetadataUpdate(sourceIr, copyOfIr) } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala b/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala index 453ed7cee77c..5977965330e2 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/SerializationManager.scala @@ -1,8 +1,8 @@ package org.enso.compiler import com.oracle.truffle.api.source.Source +import org.enso.compiler.core.ir.{Module => IRModule} import org.enso.compiler.context.{ExportsBuilder, ExportsMap, SuggestionBuilder} -import org.enso.compiler.core.IR import org.enso.compiler.pass.analyse.BindingAnalysis import org.enso.editions.LibraryName import org.enso.interpreter.runtime.Module @@ -370,7 +370,9 @@ final class SerializationManager( * relinking being successful and `false` otherwise. [[None]] if the * cache could not be deserialized. */ - def deserialize(module: Module): Option[Boolean] = { + def deserialize( + module: Module + ): Option[Boolean] = { if (isWaitingForSerialization(module)) { abort(module) None @@ -454,7 +456,9 @@ final class SerializationManager( * @param module the module to check * @return `true` if `module` is waiting for serialization, `false` otherwise */ - private def isWaitingForSerialization(module: Module): Boolean = { + private def isWaitingForSerialization( + module: Module + ): Boolean = { isWaitingForSerialization(module.getName) } @@ -573,7 +577,7 @@ final class SerializationManager( */ private def doSerializeModule( cache: ModuleCache, - ir: IR.Module, + ir: IRModule, stage: CompilationStage, name: QualifiedName, source: Source, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala index d902ced493b0..4821547a4d31 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/codegen/IrToTruffle.scala @@ -4,9 +4,35 @@ import com.oracle.truffle.api.source.{Source, SourceSection} import com.oracle.truffle.api.interop.InteropLibrary import org.enso.compiler.core.CompilerError import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Import -import org.enso.compiler.core.IR.Name.Special -import org.enso.compiler.core.IR.{Error, IdentifiedLocation, Pattern} +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Empty, + Expression, + Function, + IdentifiedLocation, + Literal, + Module, + Name, + Pattern, + `type`, + Type => Tpe +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.module.scope.imports +import org.enso.compiler.core.ir.Name.Special +import org.enso.compiler.core.ir.expression.{ + errors, + Application, + Case, + Comment, + Error, + Foreign, + Operator, + Section +} import org.enso.compiler.data.BindingsMap.{ ExportedModule, ResolvedConstructor, @@ -61,10 +87,8 @@ import org.enso.interpreter.node.{ ExpressionNode => RuntimeExpression } import org.enso.interpreter.runtime.EnsoContext -import org.enso.interpreter.runtime.callable.argument.{ - ArgumentDefinition, - CallArgument -} +import org.enso.interpreter.runtime.callable +import org.enso.interpreter.runtime.callable.argument.{ArgumentDefinition} import org.enso.interpreter.runtime.callable.atom.{Atom, AtomConstructor} import org.enso.interpreter.runtime.callable.function.{ FunctionSchema, @@ -85,7 +109,6 @@ import org.enso.interpreter.runtime.scope.{ import org.enso.interpreter.{Constants, EnsoLanguage} import java.math.BigInteger - import scala.annotation.tailrec import scala.collection.mutable import scala.collection.mutable.ArrayBuffer @@ -120,16 +143,16 @@ class IrToTruffle( /** Executes the codegen pass on the input [[IR]]. * * Please note that the IR passed to this function should not contain _any_ - * errors (members of [[IR.Error]]). These must be dealt with and reported + * errors (members of [[Error]]). These must be dealt with and reported * before codegen runs, as they will cause a compiler error. * * In future, this restriction will be relaxed to admit errors that are - * members of [[IR.Diagnostic.Kind.Interactive]], such that we can display + * members of [[org.enso.compiler.core.ir.Diagnostic.Kind.Interactive]], such that we can display * these to users during interactive execution. * * @param ir the IR to generate code for */ - def run(ir: IR.Module): Unit = processModule(ir) + def run(ir: Module): Unit = processModule(ir) /** Executes the codegen pass on an inline input. * @@ -139,7 +162,7 @@ class IrToTruffle( * @return an truffle expression representing `ir` */ def runInline( - ir: IR.Expression, + ir: Expression, localScope: LocalScope, scopeName: String ): RuntimeExpression = { @@ -158,7 +181,7 @@ class IrToTruffle( * * @param module the module for which code should be generated */ - private def processModule(module: IR.Module): Unit = { + private def processModule(module: Module): Unit = { generateReExportBindings(module) val bindingsMap = module @@ -174,9 +197,9 @@ class IrToTruffle( .foreach { exp => moduleScope.addExport(exp.unsafeAsModule().getScope) } - val imports = module.imports + val importDefs = module.imports val methodDefs = module.bindings.collect { - case method: IR.Module.Scope.Definition.Method.Explicit => method + case method: definition.Method.Explicit => method } bindingsMap.resolvedImports.foreach { imp => @@ -192,8 +215,8 @@ class IrToTruffle( } // Register the imports in scope - imports.foreach { - case poly @ Import.Polyglot(i: Import.Polyglot.Java, _, _, _, _) => + importDefs.foreach { + case poly @ imports.Polyglot(i: imports.Polyglot.Java, _, _, _, _) => val hostSymbol = context.lookupJavaClass(i.getJavaName) if (hostSymbol != null) { this.moduleScope.registerPolyglotSymbol( @@ -209,10 +232,7 @@ class IrToTruffle( case _: Error => } - val typeDefs = module.bindings.collect { - case tp: IR.Module.Scope.Definition.Type => tp - } - + val typeDefs = module.bindings.collect { case tp: Definition.Type => tp } typeDefs.foreach { tpDef => // Register the atoms and their constructors in scope val atomDefs = tpDef.members @@ -335,12 +355,12 @@ class IrToTruffle( ) @tailrec - def getContext(tp: IR.Expression): Option[String] = tp match { - case fn: IR.Type.Function => getContext(fn.result) - case ctx: IR.Type.Context => + def getContext(tp: Expression): Option[String] = tp match { + case fn: Tpe.Function => getContext(fn.result) + case ctx: Tpe.Context => ctx.context match { - case lit: IR.Name.Literal => Some(lit.name) - case _ => None + case lit: Name.Literal => Some(lit.name) + case _ => None } case _ => None } @@ -399,7 +419,7 @@ class IrToTruffle( ) val function = methodDef.body match { - case fn: IR.Function if isBuiltinMethod(fn.body) => + case fn: Function if isBuiltinMethod(fn.body) => // For builtin types that own the builtin method we only check that // the method has been registered during the initialization of builtins // and not attempt to register it in the scope (can't redefined methods). @@ -407,9 +427,9 @@ class IrToTruffle( // we have to look up the function and register it in the scope. // Static wrappers for instance methods have to be registered always. val fullMethodName = methodDef.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Literal.Text] + .asInstanceOf[Literal.Text] val builtinNameElements = fullMethodName.text.split('.') if (builtinNameElements.length != 2) { @@ -489,7 +509,7 @@ class IrToTruffle( } } ) - case fn: IR.Function => + case fn: Function => val bodyBuilder = new expressionProcessor.BuildFunctionBody( fn.arguments, @@ -513,7 +533,7 @@ class IrToTruffle( methodDef.getMetadata(GenericAnnotations).toVector.flatMap { meta => meta.annotations - .collect { case annotation: IR.Name.GenericAnnotation => + .collect { case annotation: Name.GenericAnnotation => val scopeElements = Seq( cons.getName, methodDef.methodName.name, @@ -587,7 +607,7 @@ class IrToTruffle( }) val conversionDefs = module.bindings.collect { - case conversion: IR.Module.Scope.Definition.Method.Conversion => + case conversion: definition.Method.Conversion => conversion } @@ -622,7 +642,7 @@ class IrToTruffle( ) val function = methodDef.body match { - case fn: IR.Function => + case fn: Function => val bodyBuilder = new expressionProcessor.BuildFunctionBody( fn.arguments, @@ -660,11 +680,11 @@ class IrToTruffle( // === Utility Functions ==================================================== // ========================================================================== - private def checkRuntimeTypes(arg: IR.DefinitionArgument): List[Type] = { - def extractAscribedType(t: IR.Expression): List[Type] = t match { - case u: IR.Type.Set.Union => u.operands.flatMap(extractAscribedType) - case p: IR.Application.Prefix => extractAscribedType(p.function) - case _: IR.Type.Function => + private def checkRuntimeTypes(arg: DefinitionArgument): List[Type] = { + def extractAscribedType(t: Expression): List[Type] = t match { + case u: `type`.Set.Union => u.operands.flatMap(extractAscribedType) + case p: Application.Prefix => extractAscribedType(p.function) + case _: Tpe.Function => List(context.getTopScope().getBuiltins().function()) case t => { t.getMetadata(TypeNames) match { @@ -686,7 +706,7 @@ class IrToTruffle( * @param expression the expression to check * @return 'true' if 'expression' has @Builtin_Method annotation, otherwise 'false' */ - private def isBuiltinMethod(expression: IR.Expression): Boolean = { + private def isBuiltinMethod(expression: Expression): Boolean = { expression .getMetadata(ExpressionAnnotations) .exists( @@ -747,7 +767,7 @@ class IrToTruffle( } private def getTailStatus( - expression: IR.Expression + expression: Expression ): BaseNode.TailStatus = { val isTailPosition = expression.getMetadata(TailCall).contains(TailCall.TailPosition.Tail) @@ -782,7 +802,7 @@ class IrToTruffle( expr } - private def generateReExportBindings(module: IR.Module): Unit = { + private def generateReExportBindings(module: Module): Unit = { def mkConsGetter(constructor: AtomConstructor): RuntimeFunction = { new RuntimeFunction( new QualifiedAccessorNode(language, constructor).getCallTarget, @@ -935,36 +955,36 @@ class IrToTruffle( * @return a truffle expression that represents the same program as `ir` */ def run( - ir: IR.Expression, + ir: Expression, subjectToInstrumentation: Boolean ): RuntimeExpression = run(ir, false, subjectToInstrumentation) private def run( - ir: IR.Expression, + ir: Expression, binding: Boolean, subjectToInstrumentation: Boolean ): RuntimeExpression = { val runtimeExpression = ir match { - case block: IR.Expression.Block => processBlock(block) - case literal: IR.Literal => processLiteral(literal) - case app: IR.Application => + case block: Expression.Block => processBlock(block) + case literal: Literal => processLiteral(literal) + case app: Application => processApplication(app, subjectToInstrumentation) - case name: IR.Name => processName(name) - case function: IR.Function => processFunction(function, binding) - case binding: IR.Expression.Binding => processBinding(binding) - case caseExpr: IR.Case => + case name: Name => processName(name) + case function: Function => processFunction(function, binding) + case binding: Expression.Binding => processBinding(binding) + case caseExpr: Case => processCase(caseExpr, subjectToInstrumentation) - case typ: IR.Type => processType(typ) - case _: IR.Empty => + case typ: Tpe => processType(typ) + case _: Empty => throw new CompilerError( "Empty IR nodes should not exist during code generation." ) - case _: IR.Comment => + case _: Comment => throw new CompilerError( "Comments should not be present during codegen." ) - case err: IR.Error => processError(err) - case IR.Foreign.Definition(_, _, _, _, _) => + case err: Error => processError(err) + case Foreign.Definition(_, _, _, _, _) => throw new CompilerError( s"Foreign expressions not yet implemented: $ir." ) @@ -980,7 +1000,7 @@ class IrToTruffle( * @param ir the IR to generate code for * @return a truffle expression that represents the same program as `ir` */ - def runInline(ir: IR.Expression): RuntimeExpression = { + def runInline(ir: Expression): RuntimeExpression = { val expression = run(ir, false) expression } @@ -992,7 +1012,7 @@ class IrToTruffle( * @param block the block to generate code for * @return the truffle nodes corresponding to `block` */ - private def processBlock(block: IR.Expression.Block): RuntimeExpression = { + private def processBlock(block: Expression.Block): RuntimeExpression = { if (block.suspended) { val scopeInfo = block .unsafeGetMetadata( @@ -1033,7 +1053,7 @@ class IrToTruffle( * @param value the type operation to generate code for * @return the truffle nodes corresponding to `value` */ - def processType(value: IR.Type): RuntimeExpression = { + def processType(value: Tpe): RuntimeExpression = { setLocation( ErrorNode.build( context.getBuiltins @@ -1054,11 +1074,11 @@ class IrToTruffle( * @return the truffle nodes corresponding to `caseExpr` */ def processCase( - caseExpr: IR.Case, + caseExpr: Case, subjectToInstrumentation: Boolean ): RuntimeExpression = caseExpr match { - case IR.Case.Expr(scrutinee, branches, isNested, location, _, _) => + case Case.Expr(scrutinee, branches, isNested, location, _, _) => val scrutineeNode = this.run(scrutinee, subjectToInstrumentation) val maybeCases = branches.map(processCaseBranch) @@ -1091,7 +1111,7 @@ class IrToTruffle( setLocation(ErrorNode.build(error), caseExpr.location) } - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("A CaseBranch should never occur here.") } @@ -1102,7 +1122,7 @@ class IrToTruffle( * the match is invalid */ def processCaseBranch( - branch: IR.Case.Branch + branch: Case.Branch ): Either[BadPatternMatch, BranchNode] = { val scopeInfo = branch .unsafeGetMetadata( @@ -1145,7 +1165,7 @@ class IrToTruffle( ) constructor match { - case err: IR.Error.Resolution => + case err: errors.Resolution => Left(BadPatternMatch.NonVisibleConstructor(err.name)) case _ => constructor.getMetadata(Patterns) match { @@ -1291,7 +1311,7 @@ class IrToTruffle( ) literalPattern.literal match { - case num: IR.Literal.Number => + case num: Literal.Number => num.numericValue match { case doubleVal: Double => Right( @@ -1322,7 +1342,7 @@ class IrToTruffle( "Invalid literal numeric value" ) } - case text: IR.Literal.Text => + case text: Literal.Text => Right( StringLiteralBranchNode.build( text.text, @@ -1344,7 +1364,7 @@ class IrToTruffle( ) match { case Some(tpe) => val argOfType = List( - IR.DefinitionArgument.Specified( + DefinitionArgument.Specified( varName, None, None, @@ -1382,7 +1402,7 @@ class IrToTruffle( .get(symbol.name) if (polySymbol != null) { val argOfType = List( - IR.DefinitionArgument.Specified( + DefinitionArgument.Specified( varName, None, None, @@ -1417,9 +1437,9 @@ class IrToTruffle( throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) - case IR.Error.Pattern( + case errors.Pattern( _, - IR.Error.Pattern.WrongArity(name, expected, actual), + errors.Pattern.WrongArity(name, expected, actual), _, _ ) => @@ -1442,8 +1462,8 @@ class IrToTruffle( * @param name the pattern field to generate from * @return `name` as a function definition argument. */ - def genArgFromMatchField(name: Pattern.Name): IR.DefinitionArgument = { - IR.DefinitionArgument.Specified( + def genArgFromMatchField(name: Pattern.Name): DefinitionArgument = { + DefinitionArgument.Specified( name.name, None, None, @@ -1460,7 +1480,7 @@ class IrToTruffle( * @return the truffle nodes corresponding to `binding` */ private def processBinding( - binding: IR.Expression.Binding + binding: Expression.Binding ): RuntimeExpression = { val occInfo = binding .unsafeGetMetadata( @@ -1486,14 +1506,14 @@ class IrToTruffle( * @return the truffle nodes corresponding to `function` */ private def processFunction( - function: IR.Function, + function: Function, binding: Boolean ): RuntimeExpression = { val scopeInfo = function .unsafeGetMetadata(AliasAnalysis, "No scope info on a function.") .unsafeAs[AliasAnalysis.Info.Scope.Child] - if (function.body.isInstanceOf[IR.Function]) { + if (function.body.isInstanceOf[Function]) { throw new CompilerError( "Lambda found directly as function body. It looks like Lambda " + "Consolidation hasn't run." @@ -1523,9 +1543,9 @@ class IrToTruffle( * @param name the name to generate code for * @return the truffle nodes corresponding to `name` */ - def processName(name: IR.Name): RuntimeExpression = { + def processName(name: Name): RuntimeExpression = { val nameExpr = name match { - case IR.Name.Literal(nameStr, _, _, _, _) => + case Name.Literal(nameStr, _, _, _, _) => val useInfo = name .unsafeGetMetadata( AliasAnalysis, @@ -1547,23 +1567,23 @@ class IrToTruffle( UnresolvedSymbol.build(nameStr, moduleScope) ) } - case IR.Name.Self(location, _, passData, _) => + case Name.Self(location, _, passData, _) => processName( - IR.Name.Literal( + Name.Literal( Constants.Names.SELF_ARGUMENT, isMethod = false, location, passData ) ) - case n: IR.Name.SelfType => + case n: Name.SelfType => nodeForResolution( n.unsafeGetMetadata( GlobalNames, "a Self occurence must be resolved" ).target ) - case IR.Name.Special(name, _, _, _) => + case Name.Special(name, _, _, _) => val fun = name match { case Special.NewRef => context.getBuiltins.special().getNewRef case Special.ReadRef => context.getBuiltins.special().getReadRef @@ -1573,24 +1593,24 @@ class IrToTruffle( context.getBuiltins.special().getJoinThread } ConstantObjectNode.build(fun) - case _: IR.Name.Annotation => + case _: Name.Annotation => throw new CompilerError( "Annotation should not be present at codegen time." ) - case _: IR.Name.Blank => + case _: Name.Blank => throw new CompilerError( "Blanks should not be present at codegen time." ) - case _: IR.Name.MethodReference => + case _: Name.MethodReference => throw new CompilerError( "Method references should not be present at codegen time." ) - case _: IR.Name.Qualified => + case _: Name.Qualified => throw new CompilerError( "Qualified names should not be present at codegen time." ) - case err: IR.Error.Resolution => processError(err) - case err: IR.Error.Conversion => processError(err) + case err: errors.Resolution => processError(err) + case err: errors.Conversion => processError(err) } setLocation(nameExpr, name.location) @@ -1646,16 +1666,16 @@ class IrToTruffle( * @return the truffle nodes corresponding to `literal` */ @throws[CompilerError] - def processLiteral(literal: IR.Literal): RuntimeExpression = + def processLiteral(literal: Literal): RuntimeExpression = literal match { - case lit @ IR.Literal.Number(_, _, location, _, _) => + case lit @ Literal.Number(_, _, location, _, _) => val node = lit.numericValue match { case l: Long => LiteralNode.build(l) case d: Double => LiteralNode.build(d) case b: BigInteger => LiteralNode.build(b) } setLocation(node, location) - case IR.Literal.Text(text, location, _, _) => + case Literal.Text(text, location, _, _) => setLocation(LiteralNode.build(text), location) } @@ -1664,55 +1684,55 @@ class IrToTruffle( * @param error the IR representing a compile error. * @return a runtime node representing the error. */ - def processError(error: IR.Error): RuntimeExpression = { + def processError(error: Error): RuntimeExpression = { val payload: Atom = error match { case Error.InvalidIR(_, _, _) => throw new CompilerError("Unexpected Invalid IR during codegen.") - case err: Error.Syntax => + case err: errors.Syntax => context.getBuiltins .error() .makeSyntaxError(Text.create(err.message)) - case err: Error.Redefined.Binding => + case err: errors.Redefined.Binding => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Redefined.Method => + case err: errors.Redefined.Method => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Redefined.MethodClashWithAtom => + case err: errors.Redefined.MethodClashWithAtom => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Redefined.Conversion => + case err: errors.Redefined.Conversion => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Redefined.Type => + case err: errors.Redefined.Type => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Redefined.SelfArg => + case err: errors.Redefined.SelfArg => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Unexpected.TypeSignature => + case err: errors.Unexpected.TypeSignature => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Resolution => + case err: errors.Resolution => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case err: Error.Conversion => + case err: errors.Conversion => context.getBuiltins .error() .makeCompileError(Text.create(err.message)) - case _: Error.Pattern => + case _: errors.Pattern => throw new CompilerError( "Impossible here, should be handled in the pattern match." ) - case _: Error.ImportExport => + case _: errors.ImportExport => throw new CompilerError( "Impossible here, should be handled in import/export processing" ) @@ -1729,8 +1749,8 @@ class IrToTruffle( * argument definitions. */ class BuildFunctionBody( - val arguments: List[IR.DefinitionArgument], - val body: IR.Expression, + val arguments: List[DefinitionArgument], + val body: Expression, val effectContext: Option[String], val subjectToInstrumentation: Boolean ) { @@ -1745,7 +1765,7 @@ class IrToTruffle( val (argSlotIdxs, _, argExpressions) = slots val bodyExpr = body match { - case IR.Foreign.Definition(lang, code, _, _, _) => + case Foreign.Definition(lang, code, _, _, _) => buildForeignBody( ForeignLanguage.getBySyntacticTag(lang), code, @@ -1834,8 +1854,8 @@ class IrToTruffle( * @return a truffle node representing the described function */ private def processFunctionBody( - arguments: List[IR.DefinitionArgument], - body: IR.Expression, + arguments: List[DefinitionArgument], + body: Expression, location: Option[IdentifiedLocation], binding: Boolean = false ): CreateFunctionNode = { @@ -1887,23 +1907,23 @@ class IrToTruffle( * @return the truffle nodes corresponding to `application` */ private def processApplication( - application: IR.Application, + application: Application, subjectToInstrumentation: Boolean ): RuntimeExpression = application match { - case IR.Application.Prefix(fn, Nil, true, _, _, _) => + case Application.Prefix(fn, Nil, true, _, _, _) => run(fn, subjectToInstrumentation) - case app: IR.Application.Prefix => + case app: Application.Prefix => processApplicationWithArgs(app, subjectToInstrumentation) - case IR.Application.Force(expr, location, _, _) => + case Application.Force(expr, location, _, _) => setLocation( ForceNode.build(this.run(expr, subjectToInstrumentation)), location ) - case IR.Application.Literal.Sequence(items, location, _, _) => + case Application.Sequence(items, location, _, _) => val itemNodes = items.map(run(_, subjectToInstrumentation)).toArray setLocation(SequenceLiteralNode.build(itemNodes), location) - case _: IR.Application.Literal.Typeset => + case _: Application.Typeset => setLocation( ErrorNode.build( context.getBuiltins @@ -1916,11 +1936,11 @@ class IrToTruffle( ), application.location ) - case op: IR.Application.Operator.Binary => + case op: Operator.Binary => throw new CompilerError( s"Explicit operators not supported during codegen but $op found" ) - case sec: IR.Application.Operator.Section => + case sec: Section => throw new CompilerError( s"Explicit operator sections not supported during codegen but " + s"$sec found" @@ -1928,15 +1948,15 @@ class IrToTruffle( } private def processApplicationWithArgs( - application: IR.Application.Prefix, + application: Application.Prefix, subjectToInstrumentation: Boolean ): RuntimeExpression = { - val IR.Application.Prefix(fn, args, hasDefaultsSuspended, loc, _, _) = + val Application.Prefix(fn, args, hasDefaultsSuspended, loc, _, _) = application val callArgFactory = new CallArgumentProcessor(scope, scopeName) val arguments = args - val callArgs = new ArrayBuffer[CallArgument]() + val callArgs = new ArrayBuffer[callable.argument.CallArgument]() for ((unprocessedArg, position) <- arguments.view.zipWithIndex) { val arg = @@ -1992,12 +2012,12 @@ class IrToTruffle( * `arg` */ def run( - arg: IR.CallArgument, + arg: CallArgument, position: Int, subjectToInstrumentation: Boolean - ): CallArgument = + ): callable.argument.CallArgument = arg match { - case IR.CallArgument.Specified( + case CallArgument.Specified( name, value, _, @@ -2012,10 +2032,10 @@ class IrToTruffle( .unsafeAs[AliasAnalysis.Info.Scope.Child] val shouldCreateClosureRootNode = value match { - case _: IR.Name => false - case _: IR.Literal.Text => false - case _: IR.Literal.Number => false - case _ => true + case _: Name => false + case _: Literal.Text => false + case _: Literal.Number => false + case _ => true } val childScope = if (shouldCreateClosureRootNode) { @@ -2055,7 +2075,7 @@ class IrToTruffle( CreateThunkNode.build(callTarget) } - new CallArgument(name.map(_.name).orNull, result) + new callable.argument.CallArgument(name.map(_.name).orNull, result) } } @@ -2108,12 +2128,12 @@ class IrToTruffle( * given function */ def run( - inputArg: IR.DefinitionArgument, + inputArg: DefinitionArgument, position: Int, types: List[Type] ): ArgumentDefinition = inputArg match { - case arg: IR.DefinitionArgument.Specified => + case arg: DefinitionArgument.Specified => val defaultExpression = arg.defaultValue .map(new ExpressionProcessor(scope, scopeName).run(_, false)) .orNull diff --git a/engine/runtime/src/main/scala/org/enso/compiler/context/FreshNameSupply.scala b/engine/runtime/src/main/scala/org/enso/compiler/context/FreshNameSupply.scala index f83c2a5435c8..4b98d19cb9bc 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/context/FreshNameSupply.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/context/FreshNameSupply.scala @@ -1,6 +1,6 @@ package org.enso.compiler.context -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Name /** This class provides a supply of fresh names guaranteed not to exist in this * program. @@ -11,8 +11,8 @@ class FreshNameSupply { private def mkName( numId: Long, isMethod: Boolean - ): IR.Name.Literal = { - IR.Name.Literal( + ): Name.Literal = { + Name.Literal( s"", isMethod, None @@ -26,7 +26,7 @@ class FreshNameSupply { */ def newName( isMethod: Boolean = false - ): IR.Name.Literal = { + ): Name.Literal = { val num = counter counter += 1 diff --git a/engine/runtime/src/main/scala/org/enso/compiler/context/InlineContext.scala b/engine/runtime/src/main/scala/org/enso/compiler/context/InlineContext.scala index f8c4b8f40a8d..7a4d9dd2ff2c 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/context/InlineContext.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/context/InlineContext.scala @@ -1,6 +1,6 @@ package org.enso.compiler.context -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression import org.enso.compiler.PackageRepository import org.enso.compiler.data.CompilerConfig import org.enso.compiler.pass.PassConfiguration @@ -36,7 +36,7 @@ case class InlineContext( context: CompilerContext, source: Source, config: CompilerConfig, - ir: IR.Expression + ir: Expression ): ExpressionNode = { val s = localScope.getOrElse(LocalScope.root) return module.truffleRunInline(context, source, s, config, ir) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/context/ModuleContext.scala b/engine/runtime/src/main/scala/org/enso/compiler/context/ModuleContext.scala index f0d4ce185835..7508ff20500e 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/context/ModuleContext.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/context/ModuleContext.scala @@ -1,6 +1,6 @@ package org.enso.compiler.context -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression import org.enso.compiler.PackageRepository import org.enso.compiler.data.CompilerConfig import org.enso.compiler.pass.PassConfiguration @@ -40,7 +40,7 @@ case class ModuleContext( source: Source, s: LocalScope, config: CompilerConfig, - ir: IR.Expression + ir: Expression ): ExpressionNode = { return context.truffleRunInline(source, s, module, config, ir) } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala b/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala index 0049e40353b3..83f2668916a8 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/context/SuggestionBuilder.scala @@ -2,6 +2,19 @@ package org.enso.compiler.context import org.enso.compiler.Compiler import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.expression.{Application, Operator} +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + IdentifiedLocation, + Literal, + Name, + Type +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.`type` import org.enso.compiler.data.BindingsMap import org.enso.compiler.pass.resolve.{ DocumentationComments, @@ -52,7 +65,7 @@ final class SuggestionBuilder[A: IndexedSource]( val ir = scope.queue.dequeue() val doc = ir.getMetadata(DocumentationComments).map(_.documentation) ir match { - case IR.Module.Scope.Definition.Type( + case Definition.Type( tpName, params, List(), @@ -64,7 +77,7 @@ final class SuggestionBuilder[A: IndexedSource]( buildAtomType(module, tpName.name, tpName.name, params, doc) go(tree ++= Vector(Tree.Node(tpe, Vector())), scope) - case IR.Module.Scope.Definition.Type( + case Definition.Type( tpName, params, members, @@ -75,7 +88,7 @@ final class SuggestionBuilder[A: IndexedSource]( val tpe = buildAtomType(module, tpName.name, tpName.name, params, doc) val conses = members.map { - case data @ IR.Module.Scope.Definition.Data( + case data @ Definition.Data( name, arguments, annotations, @@ -105,10 +118,10 @@ final class SuggestionBuilder[A: IndexedSource]( go(tree ++= tpSuggestions.map(Tree.Node(_, Vector())), scope) - case m @ IR.Module.Scope.Definition.Method + case m @ definition.Method .Explicit( - IR.Name.MethodReference(typePtr, methodName, _, _, _), - IR.Function.Lambda(args, body, _, _, _, _), + Name.MethodReference(typePtr, methodName, _, _, _), + Function.Lambda(args, body, _, _, _, _), _, _, _ @@ -144,11 +157,11 @@ final class SuggestionBuilder[A: IndexedSource]( ) go(tree ++= methodOpt.map(Tree.Node(_, subforest)), scope) - case IR.Module.Scope.Definition.Method + case definition.Method .Conversion( - IR.Name.MethodReference(_, _, _, _, _), - IR.Name.Literal(sourceTypeName, _, _, _, _), - IR.Function.Lambda(args, body, _, _, _, _), + Name.MethodReference(_, _, _, _, _), + Name.Literal(sourceTypeName, _, _, _, _), + Function.Lambda(args, body, _, _, _, _), _, _, _ @@ -164,9 +177,9 @@ final class SuggestionBuilder[A: IndexedSource]( ) go(tree += Tree.Node(conversion, Vector()), scope) - case IR.Expression.Binding( + case Expression.Binding( name, - IR.Function.Lambda(args, body, _, _, _, _), + Function.Lambda(args, body, _, _, _, _), _, _, _ @@ -187,7 +200,7 @@ final class SuggestionBuilder[A: IndexedSource]( ) go(tree += Tree.Node(function, subforest), scope) - case IR.Expression.Binding(name, expr, _, _, _) + case Expression.Binding(name, expr, _, _, _) if name.location.isDefined => val typeSignature = ir.getMetadata(TypeSignatures) val local = buildLocal( @@ -231,7 +244,7 @@ final class SuggestionBuilder[A: IndexedSource]( name: String, selfType: QualifiedName, isStatic: Boolean, - args: Seq[IR.DefinitionArgument], + args: Seq[DefinitionArgument], doc: Option[String], typeSignature: Option[TypeSignatures.Metadata], genericAnnotations: Option[GenericAnnotations.Metadata], @@ -273,7 +286,7 @@ final class SuggestionBuilder[A: IndexedSource]( private def buildConversion( externalId: Option[IR.ExternalId], module: QualifiedName, - args: Seq[IR.DefinitionArgument], + args: Seq[DefinitionArgument], sourceTypeName: String, doc: Option[String], typeSignature: Option[TypeSignatures.Metadata] @@ -295,8 +308,8 @@ final class SuggestionBuilder[A: IndexedSource]( private def buildFunction( externalId: Option[IR.ExternalId], module: QualifiedName, - name: IR.Name, - args: Seq[IR.DefinitionArgument], + name: Name, + args: Seq[DefinitionArgument], location: Location, doc: Option[String], typeSignature: Option[TypeSignatures.Metadata] @@ -351,7 +364,7 @@ final class SuggestionBuilder[A: IndexedSource]( module: QualifiedName, tp: String, name: String, - params: Seq[IR.DefinitionArgument], + params: Seq[DefinitionArgument], doc: Option[String] ): Suggestion.Type = { val qualifiedName = module.createChild(tp).toString @@ -372,8 +385,8 @@ final class SuggestionBuilder[A: IndexedSource]( module: QualifiedName, tp: String, name: String, - arguments: Seq[IR.DefinitionArgument], - genericAnnotations: Seq[IR.Name.GenericAnnotation], + arguments: Seq[DefinitionArgument], + genericAnnotations: Seq[Name.GenericAnnotation], doc: Option[String] ): Suggestion.Constructor = Suggestion.Constructor( @@ -390,11 +403,11 @@ final class SuggestionBuilder[A: IndexedSource]( private def buildGetter( module: QualifiedName, typeName: String, - argument: IR.DefinitionArgument + argument: DefinitionArgument ): Suggestion = { val getterName = argument.name.name - val thisArg = IR.DefinitionArgument.Specified( - name = IR.Name.Self(None), + val thisArg = DefinitionArgument.Specified( + name = Name.Self(None), ascribedType = None, defaultValue = None, suspended = false, @@ -478,25 +491,25 @@ final class SuggestionBuilder[A: IndexedSource]( * @return the list of type arguments */ private def buildTypeSignature( - typeExpr: IR.Expression + typeExpr: Expression ): Vector[TypeArg] = { - def go(expr: IR.Expression): TypeArg = expr match { - case fn: IR.Type.Function => + def go(expr: Expression): TypeArg = expr match { + case fn: Type.Function => TypeArg.Function(fn.args.map(go).toVector, go(fn.result)) - case union: IR.Type.Set.Union => + case union: `type`.Set.Union => TypeArg.Sum(None, union.operands.map(go)) - case app: IR.Application.Prefix => + case app: Application.Prefix => TypeArg.Application( go(app.function), app.arguments.map(c => go(c.value)).toVector ) - case bin: IR.Application.Operator.Binary => + case bin: Operator.Binary => TypeArg.Binary( go(bin.left.value), go(bin.right.value), bin.operator.name ) - case tname: IR.Name => + case tname: Name => tname .getMetadata(TypeNames) .map(t => buildResolvedTypeName(t.target)) @@ -521,14 +534,14 @@ final class SuggestionBuilder[A: IndexedSource]( * @return the list of arguments with a method return type */ private def buildMethodArguments( - vargs: Seq[IR.DefinitionArgument], + vargs: Seq[DefinitionArgument], targs: Seq[TypeArg], selfType: QualifiedName, isStatic: Boolean ): (Seq[Suggestion.Argument], Option[TypeArg]) = { @scala.annotation.tailrec def go( - vargs: Seq[IR.DefinitionArgument], + vargs: Seq[DefinitionArgument], targs: Seq[TypeArg], acc: Vector[Suggestion.Argument] ): (Vector[Suggestion.Argument], Option[TypeArg]) = @@ -536,8 +549,8 @@ final class SuggestionBuilder[A: IndexedSource]( (acc, targs.lastOption) } else { vargs match { - case IR.DefinitionArgument.Specified( - name: IR.Name.Self, + case DefinitionArgument.Specified( + name: Name.Self, _, defaultValue, suspended, @@ -577,12 +590,12 @@ final class SuggestionBuilder[A: IndexedSource]( * @return the list of arguments with a function return type */ private def buildFunctionArguments( - vargs: Seq[IR.DefinitionArgument], + vargs: Seq[DefinitionArgument], targs: Seq[TypeArg] ): (Seq[Suggestion.Argument], Option[TypeArg]) = { @scala.annotation.tailrec def go( - vargs: Seq[IR.DefinitionArgument], + vargs: Seq[DefinitionArgument], targs: Seq[TypeArg], acc: Vector[Suggestion.Argument] ): (Seq[Suggestion.Argument], Option[TypeArg]) = @@ -610,7 +623,7 @@ final class SuggestionBuilder[A: IndexedSource]( * @return the suggestion argument */ private def buildTypedArgument( - varg: IR.DefinitionArgument, + varg: DefinitionArgument, targ: TypeArg ): Suggestion.Argument = Suggestion.Argument( @@ -680,7 +693,7 @@ final class SuggestionBuilder[A: IndexedSource]( * @param arg the value argument * @return the suggestion argument */ - private def buildArgument(arg: IR.DefinitionArgument): Suggestion.Argument = { + private def buildArgument(arg: DefinitionArgument): Suggestion.Argument = { buildTypeSignatureFromMetadata(arg.name.getMetadata(TypeSignatures)) match { case Vector(targ) => buildTypedArgument(arg, targ) @@ -710,9 +723,9 @@ final class SuggestionBuilder[A: IndexedSource]( */ private def buildDefaultValue(expr: IR): Option[String] = expr match { - case IR.Literal.Number(_, value, _, _, _) => Some(value) - case IR.Literal.Text(text, _, _, _) => Some(text) - case _ => None + case Literal.Number(_, value, _, _, _) => Some(value) + case Literal.Text(text, _, _, _) => Some(text) + case _ => None } /** Build scope from the location. */ @@ -788,7 +801,7 @@ object SuggestionBuilder { * @param location the identified IR location * @return new scope */ - def apply(items: Seq[IR], location: Option[IR.IdentifiedLocation]): Scope = + def apply(items: Seq[IR], location: Option[IdentifiedLocation]): Scope = new Scope(mutable.Queue(items: _*), location.map(_.location)) } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/data/BindingsMap.scala b/engine/runtime/src/main/scala/org/enso/compiler/data/BindingsMap.scala index 27740971133e..7521ff1371c0 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/data/BindingsMap.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/data/BindingsMap.scala @@ -2,7 +2,8 @@ package org.enso.compiler.data import org.enso.compiler.{PackageRepository} import org.enso.compiler.PackageRepository.ModuleMap -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.data.BindingsMap.{DefinedEntity, ModuleReference} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -21,7 +22,7 @@ import scala.annotation.unused */ @SerialVersionUID( - 6584L // verify ascribed types + 7681L // verify ascribed types ) case class BindingsMap( definedEntities: List[DefinedEntity], @@ -669,8 +670,8 @@ object BindingsMap { * @param target the module or type this import resolves to */ case class ResolvedImport( - importDef: IR.Module.Scope.Import.Module, - exports: List[IR.Module.Scope.Export.Module], + importDef: ir.module.scope.Import.Module, + exports: List[ir.module.scope.Export.Module], target: ImportTarget ) { @@ -894,13 +895,13 @@ object BindingsMap { module.toConcrete(moduleMap).map(module => this.copy(module = module)) } - def getIr: Option[IR.Module.Scope.Definition] = { + def getIr: Option[ir.module.scope.Definition] = { val moduleIr = module match { case ModuleReference.Concrete(module) => Some(module.getIr) case ModuleReference.Abstract(_) => None } moduleIr.flatMap(_.bindings.find { - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: ir.module.scope.definition.Method.Explicit => method.methodReference.methodName.name == this.method.name && method.methodReference.typePointer .forall( _.getMetadata(MethodDefinitions) @@ -910,7 +911,7 @@ object BindingsMap { }) } - def unsafeGetIr(missingMessage: String): IR.Module.Scope.Definition = + def unsafeGetIr(missingMessage: String): ir.module.scope.Definition = getIr.getOrElse(throw new CompilerError(missingMessage)) override def qualifiedName: QualifiedName = @@ -959,7 +960,7 @@ object BindingsMap { /** A representation of an error during name resolution. */ - sealed trait ResolutionError extends IR.Error.Resolution.ExplainResolution + sealed trait ResolutionError extends errors.Resolution.ExplainResolution /** A representation of a resolution error due to symbol ambiguity. * @@ -967,7 +968,7 @@ object BindingsMap { */ case class ResolutionAmbiguous(candidates: List[ResolvedName]) extends ResolutionError { - override def explain(originalName: IR.Name): String = { + override def explain(originalName: ir.Name): String = { val firstLine = s"The name ${originalName.name} is ambiguous. Possible candidates are:" val lines = candidates.map { @@ -994,7 +995,7 @@ object BindingsMap { /** A resolution error due to the symbol not being found. */ case object ResolutionNotFound extends ResolutionError { - override def explain(originalName: IR.Name): String = + override def explain(originalName: ir.Name): String = s"The name `${originalName.name}` could not be found" } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/IRPass.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/IRPass.scala index 7453e0fd6d18..f8b2183011d0 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/IRPass.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/IRPass.scala @@ -3,6 +3,8 @@ package org.enso.compiler.pass import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR import org.enso.compiler.core.ir.ProcessingPass +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Expression import org.enso.compiler.core.CompilerError import shapeless.=:!= @@ -45,7 +47,7 @@ trait IRPass extends ProcessingPass { * @return `ir`, possibly having made transformations or annotations to that * IR. */ - def runModule(ir: IR.Module, moduleContext: ModuleContext): IR.Module + def runModule(ir: Module, moduleContext: ModuleContext): Module /** Executes the pass on the provided `ir`, and returns a possibly transformed * or annotated version of `ir` in an inline context. @@ -57,9 +59,9 @@ trait IRPass extends ProcessingPass { * IR. */ def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression + ): Expression /** Updates the metadata in a copy of the IR when updating that metadata * requires global state. diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/PassManager.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/PassManager.scala index c00e0d64dd7c..d3779ae3267d 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/PassManager.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/PassManager.scala @@ -1,7 +1,7 @@ package org.enso.compiler.pass import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module} import org.enso.compiler.core.CompilerError // TODO [AA] In the future, the pass ordering should be _computed_ from the list @@ -53,22 +53,22 @@ class PassManager( passes } - /** Executes all pass groups on the [[IR.Module]]. + /** Executes all pass groups on the [[Module]]. * * @param ir the module to execute the compiler passes on * @param moduleContext the module context in which the passes are executed * @return the result of executing `passGroup` on `ir` */ def runPassesOnModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { passes.foldLeft(ir)((ir, group) => runPassesOnModule(ir, moduleContext, group) ) } - /** Executes the provided `passGroup` on the [[IR.Module]]. + /** Executes the provided `passGroup` on the [[Module]]. * * @param ir the module to execute the compiler passes on * @param moduleContext the module context in which the passes are executed @@ -76,10 +76,10 @@ class PassManager( * @return the result of executing `passGroup` on `ir` */ def runPassesOnModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext, passGroup: PassGroup - ): IR.Module = { + ): Module = { if (!passes.contains(passGroup)) { throw new CompilerError("Cannot run an unvalidated pass group.") } @@ -103,22 +103,22 @@ class PassManager( } } - /** Executes all passes on the [[IR.Expression]]. + /** Executes all passes on the [[Expression]]. * * @param ir the expression to execute the compiler passes on * @param inlineContext the inline context in which the passes are executed * @return the result of executing `passGroup` on `ir` */ def runPassesInline( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { passes.foldLeft(ir)((ir, group) => runPassesInline(ir, inlineContext, group) ) } - /** Executes the provided `passGroup` on the [[IR.Expression]]. + /** Executes the provided `passGroup` on the [[Expression]]. * * @param ir the expression to execute the compiler passes on * @param inlineContext the inline context in which the passes are executed @@ -126,10 +126,10 @@ class PassManager( * @return the result of executing `passGroup` on `ir` */ def runPassesInline( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext, passGroup: PassGroup - ): IR.Expression = { + ): Expression = { if (!passes.contains(passGroup)) { throw new CompilerError("Cannot run an unvalidated pass group.") } @@ -188,7 +188,7 @@ class PassManager( * @return the result of updating metadata in `copyOfIr` globally using * information from `sourceIr` */ - def runMetadataUpdate(sourceIr: IR.Module, copyOfIr: IR.Module): IR.Module = { + def runMetadataUpdate(sourceIr: Module, copyOfIr: Module): Module = { allPasses.foldLeft(copyOfIr) { (module, pass) => pass.updateMetadataInDuplicate(sourceIr, module) } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AliasAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AliasAnalysis.scala index c0e7a7a468cd..f8d5ccfaa59d 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AliasAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AliasAnalysis.scala @@ -2,9 +2,31 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern -import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Literal, + Module, + Name, + Pattern, + Type +} +import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.{ + errors, + Application, + Case, + Comment, + Error, + Operator, + Section +} +import org.enso.compiler.core.ir.`type` import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{Occurrence, Scope} import org.enso.compiler.pass.desugar._ @@ -73,9 +95,9 @@ case object AliasAnalysis extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.copy(bindings = ir.bindings.map(analyseModuleDefinition)) } @@ -89,9 +111,9 @@ case object AliasAnalysis extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val shouldWriteState = inlineContext.passConfiguration .flatMap(config => config.get(this)) @@ -172,15 +194,15 @@ case object AliasAnalysis extends IRPass { } (sourceIr, copyOfIr) match { - case (sourceIr: IR.Module, copyOfIr: IR.Module) => + case (sourceIr: Module, copyOfIr: Module) => val sourceBindings = sourceIr.bindings val copyBindings = copyOfIr.bindings val zippedBindings = sourceBindings.lazyZip(copyBindings) zippedBindings.foreach { case ( - source: IR.Module.Scope.Definition.Type, - copy: IR.Module.Scope.Definition.Type + source: Definition.Type, + copy: Definition.Type ) => doCopy(source, copy) source.members.lazyZip(copy.members).foreach { @@ -205,14 +227,14 @@ case object AliasAnalysis extends IRPass { * @return `ir`, with the results of alias analysis attached */ def analyseModuleDefinition( - ir: IR.Module.Scope.Definition - ): IR.Module.Scope.Definition = { + ir: Definition + ): Definition = { val topLevelGraph = new Graph ir match { - case m: IR.Module.Scope.Definition.Method.Conversion => + case m: definition.Method.Conversion => m.body match { - case _: IR.Function => + case _: Function => m.copy( body = analyseExpression( m.body, @@ -226,9 +248,9 @@ case object AliasAnalysis extends IRPass { "The body of a method should always be a function." ) } - case m @ IR.Module.Scope.Definition.Method.Explicit(_, body, _, _, _) => + case m @ definition.Method.Explicit(_, body, _, _, _) => body match { - case _: IR.Function => + case _: Function => m.copy( body = analyseExpression( body, @@ -242,11 +264,11 @@ case object AliasAnalysis extends IRPass { "The body of a method should always be a function." ) } - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Method definition sugar should not occur during alias analysis." ) - case t: IR.Module.Scope.Definition.Type => + case t: Definition.Type => t.copy( params = analyseArgumentDefs( t.params, @@ -275,26 +297,26 @@ case object AliasAnalysis extends IRPass { ).updateMetadata(this -->> Info.Scope.Root(graph)) }) ).updateMetadata(this -->> Info.Scope.Root(topLevelGraph)) - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during " + "alias analysis." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation should not exist as an entity during alias analysis." ) - case _: IR.Type.Ascription => + case _: Type.Ascription => throw new CompilerError( "Type signatures should not exist at the top level during " + "alias analysis." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of alias " + "analysis." ) - case ann: IR.Name.GenericAnnotation => + case ann: Name.GenericAnnotation => ann .copy(expression = analyseExpression( @@ -304,7 +326,7 @@ case object AliasAnalysis extends IRPass { ) ) .updateMetadata(this -->> Info.Scope.Root(topLevelGraph)) - case err: IR.Error => err + case err: Error => err } } @@ -324,15 +346,15 @@ case object AliasAnalysis extends IRPass { * @return `expression`, potentially with aliasing information attached */ private def analyseExpression( - expression: IR.Expression, + expression: Expression, graph: Graph, parentScope: Scope, lambdaReuseScope: Boolean = false - ): IR.Expression = { + ): Expression = { expression match { - case fn: IR.Function => + case fn: Function => analyseFunction(fn, graph, parentScope, lambdaReuseScope) - case name: IR.Name => + case name: Name => analyseName( name, isInPatternContext = false, @@ -340,8 +362,8 @@ case object AliasAnalysis extends IRPass { graph, parentScope ) - case cse: IR.Case => analyseCase(cse, graph, parentScope) - case block @ IR.Expression.Block( + case cse: Case => analyseCase(cse, graph, parentScope) + case block @ Expression.Block( expressions, retVal, _, @@ -354,7 +376,7 @@ case object AliasAnalysis extends IRPass { block .copy( - expressions = expressions.map((expression: IR.Expression) => + expressions = expressions.map((expression: Expression) => analyseExpression( expression, graph, @@ -368,11 +390,11 @@ case object AliasAnalysis extends IRPass { ) ) .updateMetadata(this -->> Info.Scope.Child(graph, currentScope)) - case binding @ IR.Expression.Binding(name, expression, _, _, _) => + case binding @ Expression.Binding(name, expression, _, _, _) => if (!parentScope.hasSymbolOccurrenceAs[Occurrence.Def](name.name)) { val isSuspended = expression match { - case IR.Expression.Block(_, _, _, isSuspended, _, _) => isSuspended - case _ => false + case Expression.Block(_, _, _, isSuspended, _, _) => isSuspended + case _ => false } val occurrenceId = graph.nextId() val occurrence = @@ -397,13 +419,13 @@ case object AliasAnalysis extends IRPass { ) .updateMetadata(this -->> Info.Occurrence(graph, occurrenceId)) } else { - IR.Error.Redefined.Binding(binding) + errors.Redefined.Binding(binding) } - case app: IR.Application => + case app: Application => analyseApplication(app, graph, parentScope) - case tpe: IR.Type => analyseType(tpe, graph, parentScope) + case tpe: Type => analyseType(tpe, graph, parentScope) case x => - x.mapExpressions((expression: IR.Expression) => + x.mapExpressions((expression: Expression) => analyseExpression( expression, graph, @@ -420,17 +442,17 @@ case object AliasAnalysis extends IRPass { * @param parentScope the parent scope in which `value` occurs * @return `value`, annotated with aliasing information */ - def analyseType(value: IR.Type, graph: Graph, parentScope: Scope): IR.Type = { + def analyseType(value: Type, graph: Graph, parentScope: Scope): Type = { value match { - case member @ IR.Type.Set.Member(label, memberType, value, _, _, _) => + case member @ `type`.Set.Member(label, memberType, value, _, _, _) => val memberTypeScope = memberType match { - case _: IR.Literal => parentScope - case _ => parentScope.addChild() + case _: Literal => parentScope + case _ => parentScope.addChild() } val valueScope = value match { - case _: IR.Literal => parentScope - case _ => parentScope.addChild() + case _: Literal => parentScope + case _ => parentScope.addChild() } val labelId = graph.nextId() @@ -467,13 +489,13 @@ case object AliasAnalysis extends IRPass { * @return `args`, potentially */ private def analyseArgumentDefs( - args: List[IR.DefinitionArgument], + args: List[DefinitionArgument], graph: Graph, scope: Scope - ): List[IR.DefinitionArgument] = { + ): List[DefinitionArgument] = { args.map { - case arg @ IR.DefinitionArgument.Specified( - selfName @ IR.Name.Self(_, true, _, _), + case arg @ DefinitionArgument.Specified( + selfName @ Name.Self(_, true, _, _), _, _, _, @@ -498,7 +520,7 @@ case object AliasAnalysis extends IRPass { arg.ascribedType.map(analyseExpression(_, graph, scope)) ) - case arg @ IR.DefinitionArgument.Specified( + case arg @ DefinitionArgument.Specified( name, _, value, @@ -510,9 +532,8 @@ case object AliasAnalysis extends IRPass { val nameOccursInScope = scope.hasSymbolOccurrenceAs[Occurrence.Def](name.name) if (!nameOccursInScope) { - val newDefault = value.map((ir: IR.Expression) => - analyseExpression(ir, graph, scope) - ) + val newDefault = + value.map((ir: Expression) => analyseExpression(ir, graph, scope)) val occurrenceId = graph.nextId() val definition = Graph.Occurrence.Def( @@ -551,30 +572,30 @@ case object AliasAnalysis extends IRPass { * @return `application`, possibly with aliasing information attached */ def analyseApplication( - application: IR.Application, + application: Application, graph: AliasAnalysis.Graph, scope: AliasAnalysis.Graph.Scope - ): IR.Application = { + ): Application = { application match { - case app @ IR.Application.Prefix(fun, arguments, _, _, _, _) => + case app @ Application.Prefix(fun, arguments, _, _, _, _) => app.copy( function = analyseExpression(fun, graph, scope), arguments = analyseCallArguments(arguments, graph, scope) ) - case app @ IR.Application.Force(expr, _, _, _) => + case app @ Application.Force(expr, _, _, _) => app.copy(target = analyseExpression(expr, graph, scope)) - case app @ IR.Application.Literal.Sequence(items, _, _, _) => + case app @ Application.Sequence(items, _, _, _) => app.copy(items = items.map(analyseExpression(_, graph, scope))) - case tSet @ IR.Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => val newScope = scope.addChild() tSet .copy(expression = expr.map(analyseExpression(_, graph, newScope))) .updateMetadata(this -->> Info.Scope.Child(graph, newScope)) - case _: IR.Application.Operator.Binary => + case _: Operator.Binary => throw new CompilerError( "Binary operator occurred during Alias Analysis." ) - case _: IR.Application.Operator.Section => + case _: Section => throw new CompilerError( "Operator section occurred during Alias Analysis." ) @@ -589,14 +610,14 @@ case object AliasAnalysis extends IRPass { * @return `args`, with aliasing information attached to each argument */ private def analyseCallArguments( - args: List[IR.CallArgument], + args: List[CallArgument], graph: AliasAnalysis.Graph, parentScope: AliasAnalysis.Graph.Scope - ): List[IR.CallArgument] = { - args.map { case arg @ IR.CallArgument.Specified(_, expr, _, _, _) => + ): List[CallArgument] = { + args.map { case arg @ CallArgument.Specified(_, expr, _, _, _) => val currentScope = expr match { - case _: IR.Literal => parentScope - case _ => parentScope.addChild() + case _: Literal => parentScope + case _ => parentScope.addChild() } arg .copy(value = analyseExpression(expr, graph, currentScope)) @@ -614,16 +635,16 @@ case object AliasAnalysis extends IRPass { * @return `function`, with alias analysis information attached */ def analyseFunction( - function: IR.Function, + function: Function, graph: Graph, parentScope: Scope, lambdaReuseScope: Boolean = false - ): IR.Function = { + ): Function = { val currentScope = if (lambdaReuseScope) parentScope else parentScope.addChild() function match { - case lambda @ IR.Function.Lambda(arguments, body, _, _, _, _) => + case lambda @ Function.Lambda(arguments, body, _, _, _, _) => lambda .copy( arguments = analyseArgumentDefs(arguments, graph, currentScope), @@ -634,7 +655,7 @@ case object AliasAnalysis extends IRPass { ) ) .updateMetadata(this -->> Info.Scope.Child(graph, currentScope)) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during alias analysis." ) @@ -653,12 +674,12 @@ case object AliasAnalysis extends IRPass { * @return `name`, with alias analysis information attached */ def analyseName( - name: IR.Name, + name: Name, isInPatternContext: Boolean, isConstructorNameInPatternContext: Boolean, graph: Graph, parentScope: Scope - ): IR.Name = { + ): Name = { val occurrenceId = graph.nextId() if (isInPatternContext && !isConstructorNameInPatternContext) { @@ -687,18 +708,18 @@ case object AliasAnalysis extends IRPass { * @return `ir`, possibly with alias analysis information attached */ def analyseCase( - ir: IR.Case, + ir: Case, graph: Graph, parentScope: Scope - ): IR.Case = { + ): Case = { ir match { - case caseExpr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case caseExpr @ Case.Expr(scrutinee, branches, _, _, _, _) => caseExpr .copy( scrutinee = analyseExpression(scrutinee, graph, parentScope), branches = branches.map(analyseCaseBranch(_, graph, parentScope)) ) - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("Case branch in `analyseCase`.") } } @@ -711,10 +732,10 @@ case object AliasAnalysis extends IRPass { * @return `branch`, possibly with alias analysis information attached */ def analyseCaseBranch( - branch: IR.Case.Branch, + branch: Case.Branch, graph: Graph, parentScope: Scope - ): IR.Case.Branch = { + ): Case.Branch = { val currentScope = parentScope.addChild() branch @@ -737,10 +758,10 @@ case object AliasAnalysis extends IRPass { * @return `pattern`, possibly with alias analysis information attached */ def analysePattern( - pattern: IR.Pattern, + pattern: Pattern, graph: Graph, parentScope: Scope - ): IR.Pattern = { + ): Pattern = { pattern match { case named @ Pattern.Name(name, _, _, _) => named.copy( @@ -793,7 +814,7 @@ case object AliasAnalysis extends IRPass { throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) - case err: IR.Error.Pattern => err + case err: errors.Pattern => err } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala index 51b18bffbb50..94d844ba24d9 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AmbiguousImportsAnalysis.scala @@ -1,9 +1,10 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Import -import org.enso.compiler.core.IR.Module.Scope.Import.Polyglot +import org.enso.compiler.core.ir.{Expression, Module, Warning} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.module.scope.imports import org.enso.compiler.data.BindingsMap import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -45,16 +46,16 @@ case object AmbiguousImportsAnalysis extends IRPass { /** @inheritdoc */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir /** @inheritdoc */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { if (moduleContext.isSynthetic()) { ir } else { @@ -84,14 +85,14 @@ case object AmbiguousImportsAnalysis extends IRPass { * warnings attached. */ private def analyseAmbiguousSymbols( - imp: IR.Module.Scope.Import, + imp: Import, module: ModuleContext, bindingMap: BindingsMap, encounteredSymbols: EncounteredSymbols - ): Either[List[IR.Error.ImportExport], IR.Module.Scope.Import] = { + ): Either[List[errors.ImportExport], Import] = { imp match { // Import multiple symbols - case moduleImport @ IR.Module.Scope.Import.Module( + case moduleImport @ Import.Module( _, _, _, @@ -104,32 +105,31 @@ case object AmbiguousImportsAnalysis extends IRPass { ) => getImportTarget(moduleImport, bindingMap) match { case Some(importTarget) => - val encounteredErrors: ListBuffer[IR.Error.ImportExport] = + val encounteredErrors: ListBuffer[errors.ImportExport] = ListBuffer() val imp = - onlyNames.foldLeft(moduleImport: IR.Module.Scope.Import) { - case (imp, symbol) => - val symbolName = symbol.name - importTarget.resolveExportedSymbol(symbolName) match { - case Right(resolvedName) => - val symbolPath = resolvedName.qualifiedName.toString - tryAddEncounteredSymbol( - module, - encounteredSymbols, - imp, - symbolName, - symbolPath - ) match { - case Left(error) => - encounteredErrors += error - imp - case Right(imp) => imp - } - case Left(resolutionError) => - throw new CompilerError( - s"Unreachable: (should have been resolved in previous passes) $resolutionError" - ) - } + onlyNames.foldLeft(moduleImport: Import) { case (imp, symbol) => + val symbolName = symbol.name + importTarget.resolveExportedSymbol(symbolName) match { + case Right(resolvedName) => + val symbolPath = resolvedName.qualifiedName.toString + tryAddEncounteredSymbol( + module, + encounteredSymbols, + imp, + symbolName, + symbolPath + ) match { + case Left(error) => + encounteredErrors += error + imp + case Right(imp) => imp + } + case Left(resolutionError) => + throw new CompilerError( + s"Unreachable: (should have been resolved in previous passes) $resolutionError" + ) + } } if (encounteredErrors.nonEmpty) { Left(encounteredErrors.toList) @@ -142,7 +142,7 @@ case object AmbiguousImportsAnalysis extends IRPass { } // Import all symbols - case moduleImport @ IR.Module.Scope.Import.Module( + case moduleImport @ Import.Module( _, _, true, @@ -164,10 +164,10 @@ case object AmbiguousImportsAnalysis extends IRPass { val hiddenNames = hiddenNamesLiterals.map(_.name) exportedSymbolNames.filterNot(hiddenNames.contains) } - val encounteredErrors: ListBuffer[IR.Error.ImportExport] = + val encounteredErrors: ListBuffer[errors.ImportExport] = ListBuffer() val imp = - symbolsToIterate.foldLeft(moduleImport: IR.Module.Scope.Import) { + symbolsToIterate.foldLeft(moduleImport: Import) { case (imp, symbolName) => importTarget.resolveExportedSymbol(symbolName) match { case Left(resolutionError) => @@ -200,7 +200,7 @@ case object AmbiguousImportsAnalysis extends IRPass { } // Import a renamed symbol - case moduleImport @ IR.Module.Scope.Import.Module( + case moduleImport @ Import.Module( importPath, Some(rename), _, @@ -224,7 +224,7 @@ case object AmbiguousImportsAnalysis extends IRPass { } // Import one symbol - case moduleImport @ IR.Module.Scope.Import.Module( + case moduleImport @ Import.Module( importPath, _, _, @@ -247,10 +247,10 @@ case object AmbiguousImportsAnalysis extends IRPass { } // Polyglot import - case polyImport @ Import.Polyglot(entity, rename, _, _, _) => + case polyImport @ imports.Polyglot(entity, rename, _, _, _) => val symbolName = rename.getOrElse(entity.getVisibleName) val symbolPath = entity match { - case Polyglot.Java(packageName, className) => + case imports.Polyglot.Java(packageName, className) => packageName + "." + className } tryAddEncounteredSymbol( @@ -269,7 +269,7 @@ case object AmbiguousImportsAnalysis extends IRPass { } private def getImportTarget( - imp: IR.Module.Scope.Import, + imp: Import, bindingMap: BindingsMap ): Option[BindingsMap.ImportTarget] = { bindingMap.resolvedImports.find(_.importDef == imp) match { @@ -282,7 +282,7 @@ case object AmbiguousImportsAnalysis extends IRPass { /** Tries to add the encountered symbol to the encountered symbols map. If it is already contained * in the map, checks whether the underlying entity path is the same as the original entity path. - * Based on that, either attaches a warning for a duplicated import, or returns an [[IR.Error.ImportExport]]. + * Based on that, either attaches a warning for a duplicated import, or returns an [[errors.ImportExport]]. * * @param module Current module * @param encounteredSymbols Encountered symbols in the current module @@ -294,10 +294,10 @@ case object AmbiguousImportsAnalysis extends IRPass { private def tryAddEncounteredSymbol( module: ModuleContext, encounteredSymbols: EncounteredSymbols, - currentImport: IR.Module.Scope.Import, + currentImport: Import, symbolName: String, symbolPath: String - ): Either[IR.Error.ImportExport, IR.Module.Scope.Import] = { + ): Either[errors.ImportExport, Import] = { if (encounteredSymbols.containsSymbol(symbolName)) { val encounteredFullName = encounteredSymbols.getPathForSymbol(symbolName) @@ -332,15 +332,15 @@ case object AmbiguousImportsAnalysis extends IRPass { private def createErrorForAmbiguousImport( module: ModuleContext, - originalImport: IR.Module.Scope.Import, + originalImport: Import, originalSymbolPath: String, - duplicatingImport: IR.Module.Scope.Import, + duplicatingImport: Import, ambiguousSymbol: String, ambiguousSymbolPath: String - ): IR.Error.ImportExport = { - IR.Error.ImportExport( + ): errors.ImportExport = { + errors.ImportExport( duplicatingImport, - IR.Error.ImportExport.AmbiguousImport( + errors.ImportExport.AmbiguousImport( originalImport, originalSymbolPath, ambiguousSymbol, @@ -352,11 +352,11 @@ case object AmbiguousImportsAnalysis extends IRPass { private def createWarningForDuplicatedImport( module: ModuleContext, - originalImport: IR.Module.Scope.Import, - duplicatingImport: IR.Module.Scope.Import, + originalImport: Import, + duplicatingImport: Import, duplicatedSymbol: String - ): IR.Warning = { - IR.Warning.DuplicatedImport( + ): Warning = { + Warning.DuplicatedImport( duplicatingImport.location, originalImport, duplicatedSymbol, @@ -371,7 +371,7 @@ case object AmbiguousImportsAnalysis extends IRPass { private class EncounteredSymbols( private val encounteredSymbols: mutable.Map[ String, - (IR.Module.Scope.Import, String) + (Import, String) ] = mutable.HashMap.empty ) { @@ -382,7 +382,7 @@ case object AmbiguousImportsAnalysis extends IRPass { /** @param imp Import where the symbol is located */ def addSymbol( - imp: IR.Module.Scope.Import, + imp: Import, symbol: String, symbolPath: String ): Unit = { @@ -406,7 +406,7 @@ case object AmbiguousImportsAnalysis extends IRPass { */ def getOriginalImportForSymbol( symbol: String - ): Option[IR.Module.Scope.Import] = { + ): Option[Import] = { encounteredSymbols.get(symbol).map(_._1) } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AutomaticParallelism.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AutomaticParallelism.scala index 42b0fe4bde3e..a12d1a35e780 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AutomaticParallelism.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/AutomaticParallelism.scala @@ -1,10 +1,19 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + Expression, + Function, + Literal, + Module, + Name +} import org.enso.compiler.core.ir.MetadataStorage.ToPair +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedMethod} import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.{Application, Operator} import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.ComplexType import org.enso.compiler.pass.resolve.{ @@ -65,7 +74,7 @@ object AutomaticParallelism extends IRPass { * @param blockAssignment the thread in which this line should run */ private case class Line( - ir: IR.Expression, + ir: Expression, parallelismStatus: ParallelismStatus, id: Int, assignment: Option[AliasAnalysis.Graph.Id], @@ -81,7 +90,7 @@ object AutomaticParallelism extends IRPass { */ private case class ParallelizationSegment( parallelizable: List[Line], - pinned: List[IR.Expression] + pinned: List[Expression] ) /** Computes the transitive closure of the dependency info. @@ -177,7 +186,7 @@ object AutomaticParallelism extends IRPass { */ @tailrec private def splitParallelBlocks( - exprs: List[(IR.Expression, ParallelismStatus)], + exprs: List[(Expression, ParallelismStatus)], acc: List[ParallelizationSegment] = List() ): List[ParallelizationSegment] = exprs match { case Nil => acc.reverse @@ -199,7 +208,7 @@ object AutomaticParallelism extends IRPass { ): ParallelizationSegment = segment.copy(parallelizable = segment.parallelizable.map { line => line.ir match { - case bind: IR.Expression.Binding => + case bind: Expression.Binding => val aaInfo = bind .unsafeGetMetadata( AliasAnalysis, @@ -219,7 +228,7 @@ object AutomaticParallelism extends IRPass { }: _*) val linesWithDeps = segment.parallelizable.map { line => val deps = line.ir.preorder - .collect { case n: IR.Name.Literal => + .collect { case n: Name.Literal => n } .flatMap(_.getMetadata(AliasAnalysis)) @@ -261,7 +270,7 @@ object AutomaticParallelism extends IRPass { private def codeGen( segment: ParallelizationSegment, freshNameSupply: FreshNameSupply - ): List[IR.Expression] = { + ): List[Expression] = { val spawnedThreads = segment.parallelizable.groupBy( _.blockAssignment.getOrElse( throw new CompilerError("unassigned block in auto parallelism") @@ -275,17 +284,17 @@ object AutomaticParallelism extends IRPass { val refVars = threadBlocks.values.flatten .map(_.ir) - .collect { case bind: IR.Expression.Binding => + .collect { case bind: Expression.Binding => bind.name -> freshNameSupply.newName() } .toMap val refAllocations = refVars.values.map( - IR.Expression + Expression .Binding( _, - IR.Application.Prefix( - IR.Name.Special(IR.Name.Special.NewRef, None), + Application.Prefix( + Name.Special(Name.Special.NewRef, None), List(), false, None @@ -298,13 +307,13 @@ object AutomaticParallelism extends IRPass { val threadSpawns = threadBlocks.values.map { exprs => val blockBody = exprs.map(_.ir).flatMap { - case bind: IR.Expression.Binding => - val refWrite = IR.Application.Prefix( - IR.Name.Special(IR.Name.Special.WriteRef, None), + case bind: Expression.Binding => + val refWrite = Application.Prefix( + Name.Special(Name.Special.WriteRef, None), List( - IR.CallArgument + CallArgument .Specified(None, refVars(bind.name).duplicate(), None), - IR.CallArgument.Specified(None, bind.name.duplicate(), None) + CallArgument.Specified(None, bind.name.duplicate(), None) ), false, None @@ -312,39 +321,39 @@ object AutomaticParallelism extends IRPass { List(bind, refWrite) case other => List(other) } - val spawn = IR.Application.Prefix( - IR.Name.Special(IR.Name.Special.RunThread, None), + val spawn = Application.Prefix( + Name.Special(Name.Special.RunThread, None), List( - IR.CallArgument.Specified( + CallArgument.Specified( None, - IR.Expression.Block(blockBody.init, blockBody.last, None), + Expression.Block(blockBody.init, blockBody.last, None), None ) ), false, None ) - IR.Expression + Expression .Binding(freshNameSupply.newName(), spawn, None) .updateMetadata(IgnoredBindings -->> IgnoredBindings.State.Ignored) } val threadJoins = threadSpawns.map { bind => - IR.Application.Prefix( - IR.Name.Special(IR.Name.Special.JoinThread, None), - List(IR.CallArgument.Specified(None, bind.name.duplicate(), None)), + Application.Prefix( + Name.Special(Name.Special.JoinThread, None), + List(CallArgument.Specified(None, bind.name.duplicate(), None)), false, None ) } val varReads = refVars.map { case (name, ref) => - IR.Expression + Expression .Binding( name.duplicate(), - IR.Application.Prefix( - IR.Name.Special(IR.Name.Special.ReadRef, None), - List(IR.CallArgument.Specified(None, ref.duplicate(), None)), + Application.Prefix( + Name.Special(Name.Special.ReadRef, None), + List(CallArgument.Specified(None, ref.duplicate(), None)), false, None ), @@ -372,11 +381,11 @@ object AutomaticParallelism extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, @unused moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val newBindings = ir.bindings.map { - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: definition.Method.Explicit => val newBody = withBodyBlock(method.body) { block => val allExprs = block.expressions :+ block.returnValue val withParallelismStatus = allExprs.map { expr => @@ -444,14 +453,14 @@ object AutomaticParallelism extends IRPass { } @tailrec - private def getMonad(signature: IR.Expression): Option[String] = + private def getMonad(signature: Expression): Option[String] = signature match { - case lam: IR.Function.Lambda => getMonad(lam.body) - case app: IR.Application.Operator.Binary => + case lam: Function.Lambda => getMonad(lam.body) + case app: Operator.Binary => if (app.operator.name == "in") { app.right.value match { - case lit: IR.Name.Literal => Some(lit.name) - case _ => None + case lit: Name.Literal => Some(lit.name) + case _ => None } } else if (app.operator.name == "->") { getMonad(app.right.value) } else None @@ -463,9 +472,9 @@ object AutomaticParallelism extends IRPass { * @param expr the expression to compute status for. * @return the status of `expr`. */ - private def getParallelismStatus(expr: IR.Expression): ParallelismStatus = + private def getParallelismStatus(expr: Expression): ParallelismStatus = expr match { - case app: IR.Application.Prefix => + case app: Application.Prefix => // The base status of an application is computed based on the type of // the called function. It is then sequenced with statuses of the // arguments. @@ -489,22 +498,22 @@ object AutomaticParallelism extends IRPass { ) case _ => Pinned } - case bind: IR.Expression.Binding => getParallelismStatus(bind.expression) - case _: IR.Name => Pure - case _: IR.Literal => Pure - case _: IR.Function.Lambda => Pure - case _ => Pinned + case bind: Expression.Binding => getParallelismStatus(bind.expression) + case _: Name => Pure + case _: Literal => Pure + case _: Function.Lambda => Pure + case _ => Pinned } private def withBodyBlock( - expr: IR.Expression - )(fn: IR.Expression.Block => IR.Expression.Block): IR.Expression = + expr: Expression + )(fn: Expression.Block => Expression.Block): Expression = expr match { - case fun: IR.Function.Binding => + case fun: Function.Binding => fun.copy(body = withBodyBlock(fun.body)(fn)) - case fun: IR.Function.Lambda => + case fun: Function.Lambda => fun.copy(body = withBodyBlock(fun.body)(fn)) - case block: IR.Expression.Block if block.expressions.nonEmpty => + case block: Expression.Block if block.expressions.nonEmpty => fn(block) case _ => expr } @@ -518,8 +527,8 @@ object AutomaticParallelism extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, @unused inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/BindingAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/BindingAnalysis.scala index e5cc7a51b274..cfe22d786bc5 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/BindingAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/BindingAnalysis.scala @@ -1,7 +1,10 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module, Name} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.module.scope.imports import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.Cons @@ -45,42 +48,40 @@ case object BindingAnalysis extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { - val definedSumTypes = ir.bindings.collect { - case sumType: IR.Module.Scope.Definition.Type => - val isBuiltinType = sumType - .getMetadata(ModuleAnnotations) - .exists(_.annotations.exists(_.name == "@Builtin_Type")) - BindingsMap.Type( - sumType.name.name, - sumType.members.map(m => - Cons( - m.name.name, - m.arguments.length, - m.arguments.forall(_.defaultValue.isDefined) - ) - ), - isBuiltinType - ) + ): Module = { + val definedSumTypes = ir.bindings.collect { case sumType: Definition.Type => + val isBuiltinType = sumType + .getMetadata(ModuleAnnotations) + .exists(_.annotations.exists(_.name == "@Builtin_Type")) + BindingsMap.Type( + sumType.name.name, + sumType.members.map(m => + Cons( + m.name.name, + m.arguments.length, + m.arguments.forall(_.defaultValue.isDefined) + ) + ), + isBuiltinType + ) } - val importedPolyglot = ir.imports.collect { - case poly: IR.Module.Scope.Import.Polyglot => - BindingsMap.PolyglotSymbol(poly.getVisibleName) + val importedPolyglot = ir.imports.collect { case poly: imports.Polyglot => + BindingsMap.PolyglotSymbol(poly.getVisibleName) } val moduleMethods = ir.bindings - .collect { case method: IR.Module.Scope.Definition.Method.Explicit => + .collect { case method: definition.Method.Explicit => val ref = method.methodReference ref.typePointer match { - case Some(IR.Name.Qualified(List(), _, _, _)) => + case Some(Name.Qualified(List(), _, _, _)) => Some(ref.methodName.name) - case Some(IR.Name.Qualified(List(n), _, _, _)) => + case Some(Name.Qualified(List(n), _, _, _)) => val shadowed = definedSumTypes.exists(_.name == n.name) if (!shadowed && n.name == moduleContext.getName().item) Some(ref.methodName.name) else None - case Some(IR.Name.Literal(n, _, _, _, _)) => + case Some(Name.Literal(n, _, _, _, _)) => val shadowed = definedSumTypes.exists(_.name == n) if (!shadowed && n == moduleContext.getName().item) Some(ref.methodName.name) @@ -109,7 +110,7 @@ case object BindingAnalysis extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/CachePreferenceAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/CachePreferenceAnalysis.scala index cac94e045427..35f98b7670b2 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/CachePreferenceAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/CachePreferenceAnalysis.scala @@ -2,7 +2,16 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Module, + Name, + Type +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.{Comment, Error} import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -45,9 +54,9 @@ case object CachePreferenceAnalysis extends IRPass { * @return ir annotated with the preference information */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val weights = WeightInfo() ir.copy(bindings = ir.bindings.map(analyseModuleDefinition(_, weights))) .updateMetadata(this -->> weights) @@ -61,9 +70,9 @@ case object CachePreferenceAnalysis extends IRPass { * @return ir annotated with the preference information */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = + ): Expression = analyseExpression(ir, WeightInfo()) // === Pass Internals ======================================================= @@ -75,47 +84,47 @@ case object CachePreferenceAnalysis extends IRPass { * @return `binding`, with attached preference information */ def analyseModuleDefinition( - binding: IR.Module.Scope.Definition, + binding: Definition, weights: WeightInfo - ): IR.Module.Scope.Definition = + ): Definition = binding match { - case _: IR.Module.Scope.Definition.Type => binding - case method: Method.Conversion => + case _: Definition.Type => binding + case method: definition.Method.Conversion => method .copy(body = analyseExpression(method.body, weights)) .updateMetadata(this -->> weights) - case method @ IR.Module.Scope.Definition.Method + case method @ definition.Method .Explicit(_, body, _, _, _) => method .copy(body = analyseExpression(body, weights)) .updateMetadata(this -->> weights) - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Sugared method definitions should not occur during cache " + "preference analysis." ) - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during cache " + "preference analysis." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation should not exist as an entity during cache " + "preference analysis." ) - case _: IR.Type.Ascription => + case _: Type.Ascription => throw new CompilerError( "Type signatures should not exist at the top level during " + "cache preference analysis." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "cache preference analysis." ) - case ann: IR.Name.GenericAnnotation => ann - case err: IR.Error => err + case ann: Name.GenericAnnotation => ann + case err: Error => err } /** Performs preference analysis on an arbitrary expression. @@ -125,11 +134,11 @@ case object CachePreferenceAnalysis extends IRPass { * @return `expression`, with attached preference information */ def analyseExpression( - expression: IR.Expression, + expression: Expression, weights: WeightInfo - ): IR.Expression = { + ): Expression = { expression.transformExpressions { - case binding: IR.Expression.Binding => + case binding: Expression.Binding => binding.getExternalId.foreach(weights.update(_, Weight.Never)) binding.expression.getExternalId .foreach(weights.update(_, Weight.Always)) @@ -139,7 +148,7 @@ case object CachePreferenceAnalysis extends IRPass { expression = analyseExpression(binding.expression, weights) ) .updateMetadata(this -->> weights) - case error: IR.Error => + case error: Error => error case expr => expr.getExternalId.collect { @@ -158,11 +167,11 @@ case object CachePreferenceAnalysis extends IRPass { * @return `argument`, with attached preference information */ def analyseDefinitionArgument( - argument: IR.DefinitionArgument, + argument: DefinitionArgument, weights: WeightInfo - ): IR.DefinitionArgument = { + ): DefinitionArgument = { argument match { - case spec @ IR.DefinitionArgument.Specified(_, _, defValue, _, _, _, _) => + case spec @ DefinitionArgument.Specified(_, _, defValue, _, _, _, _) => spec .copy(defaultValue = defValue.map(analyseExpression(_, weights))) .updateMetadata(this -->> weights) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala index b2fdfdbc39d1..689ccec62bb1 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DataflowAnalysis.scala @@ -2,8 +2,31 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.{ExternalId, Pattern} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.{ + errors, + Application, + Case, + Comment, + Error, + Foreign, + Operator +} +import org.enso.compiler.core.ir.{ + `type`, + CallArgument, + DefinitionArgument, + Empty, + Expression, + Function, + Literal, + Module, + Name, + Pattern, + Type +} +import org.enso.compiler.core.IR.ExternalId import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -21,7 +44,7 @@ import scala.collection.mutable * * - A [[org.enso.interpreter.runtime.scope.LocalScope]], where relevant. * - * It requires that all members of [[IR.IRKind.Primitive]] have been removed + * It requires that all members of [[org.enso.compiler.core.ir.IRKind.Primitive]] have been removed * from the IR by the time it runs. */ //noinspection DuplicatedCode @@ -46,9 +69,9 @@ case object DataflowAnalysis extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val dependencyInfo = new DependencyInfo ir.copy( bindings = ir.bindings.map(analyseModuleDefinition(_, dependencyInfo)) @@ -63,9 +86,9 @@ case object DataflowAnalysis extends IRPass { * @return `ir` */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val localScope = inlineContext.localScope.getOrElse( throw new CompilerError( "A valid local scope is required for the inline flow." @@ -80,7 +103,7 @@ case object DataflowAnalysis extends IRPass { copyOfIr: T ): T = { (sourceIr, copyOfIr) match { - case (sourceIr: IR.Module, copyOfIr: IR.Module) => + case (sourceIr: Module, copyOfIr: Module) => val sourceMeta = sourceIr.unsafeGetMetadata(this, "Dataflow Analysis must have run.") val copyMeta = DependencyInfo( @@ -115,11 +138,11 @@ case object DataflowAnalysis extends IRPass { */ // TODO [AA] Can I abstract the pattern here? def analyseModuleDefinition( - binding: IR.Module.Scope.Definition, + binding: Definition, info: DependencyInfo - ): IR.Module.Scope.Definition = { + ): Definition = { binding match { - case m: Method.Conversion => + case m: definition.Method.Conversion => val bodyDep = asStatic(m.body) val methodDep = asStatic(m) val sourceTypeDep = asStatic(m.sourceTypeName) @@ -131,7 +154,7 @@ case object DataflowAnalysis extends IRPass { body = analyseExpression(m.body, info), sourceTypeName = m.sourceTypeName.updateMetadata(this -->> info) ).updateMetadata(this -->> info) - case method @ IR.Module.Scope.Definition.Method + case method @ definition.Method .Explicit(_, body, _, _, _) => val bodyDep = asStatic(body) val methodDep = asStatic(method) @@ -141,7 +164,7 @@ case object DataflowAnalysis extends IRPass { method .copy(body = analyseExpression(body, info)) .updateMetadata(this -->> info) - case tp @ IR.Module.Scope.Definition.Type(_, params, members, _, _, _) => + case tp @ Definition.Type(_, params, members, _, _, _) => val tpDep = asStatic(tp) val newParams = params.map { param => val paramDep = asStatic(param) @@ -167,35 +190,35 @@ case object DataflowAnalysis extends IRPass { } tp.copy(params = newParams, members = newMembers) .updateMetadata(this -->> info) - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Sugared method definitions should not occur during dataflow " + "analysis." ) - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during " + "dataflow analysis." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation should not exist as an entity during dataflow analysis." ) - case _: IR.Type.Ascription => + case _: Type.Ascription => throw new CompilerError( "Type signatures should not exist at the top level during " + "dataflow analysis." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "dataflow analysis." ) - case ann: IR.Name.GenericAnnotation => + case ann: Name.GenericAnnotation => ann .copy(expression = analyseExpression(ann.expression, info)) .updateMetadata(this -->> info) - case err: IR.Error => err + case err: Error => err } } @@ -209,22 +232,22 @@ case object DataflowAnalysis extends IRPass { * @return `expression`, with attached dependency information */ def analyseExpression( - expression: IR.Expression, + expression: Expression, info: DependencyInfo - ): IR.Expression = { + ): Expression = { expression match { - case empty: IR.Empty => empty.updateMetadata(this -->> info) - case function: IR.Function => analyseFunction(function, info) - case app: IR.Application => analyseApplication(app, info) - case typ: IR.Type => analyseType(typ, info) - case name: IR.Name => analyseName(name, info) - case cse: IR.Case => analyseCase(cse, info) - case literal: IR.Literal => + case empty: Empty => empty.updateMetadata(this -->> info) + case function: Function => analyseFunction(function, info) + case app: Application => analyseApplication(app, info) + case typ: Type => analyseType(typ, info) + case name: Name => analyseName(name, info) + case cse: Case => analyseCase(cse, info) + case literal: Literal => literal.updateMetadata(this -->> info) - case foreign: IR.Foreign => + case foreign: Foreign => foreign.updateMetadata(this -->> info) - case block @ IR.Expression.Block(expressions, returnValue, _, _, _, _) => + case block @ Expression.Block(expressions, returnValue, _, _, _, _) => val retValDep = asStatic(returnValue) val blockDep = asStatic(block) info.dependents.updateAt(retValDep, Set(blockDep)) @@ -236,7 +259,7 @@ case object DataflowAnalysis extends IRPass { returnValue = analyseExpression(returnValue, info) ) .updateMetadata(this -->> info) - case binding @ IR.Expression.Binding(name, expression, _, _, _) => + case binding @ Expression.Binding(name, expression, _, _, _) => val expressionDep = asStatic(expression) val nameDep = asStatic(name) val bindingDep = asStatic(binding) @@ -251,8 +274,8 @@ case object DataflowAnalysis extends IRPass { ) .updateMetadata(this -->> info) - case error: IR.Error => error - case _: IR.Comment => + case error: Error => error + case _: Comment => throw new CompilerError( "Comments should not be present during dataflow analysis." ) @@ -269,11 +292,11 @@ case object DataflowAnalysis extends IRPass { * @return `function`, with attached dependency information */ def analyseFunction( - function: IR.Function, + function: Function, info: DependencyInfo - ): IR.Function = { + ): Function = { function match { - case lam @ IR.Function.Lambda(arguments, body, _, _, _, _) => + case lam @ Function.Lambda(arguments, body, _, _, _, _) => val bodyDep = asStatic(body) val lamDep = asStatic(lam) info.dependents.updateAt(bodyDep, Set(lamDep)) @@ -285,7 +308,7 @@ case object DataflowAnalysis extends IRPass { body = analyseExpression(body, info) ) .updateMetadata(this -->> info) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during dataflow analysis." ) @@ -302,11 +325,11 @@ case object DataflowAnalysis extends IRPass { * @return `application`, with attached dependency information */ def analyseApplication( - application: IR.Application, + application: Application, info: DependencyInfo - ): IR.Application = { + ): Application = { application match { - case prefix @ IR.Application.Prefix(fn, args, _, _, _, _) => + case prefix @ Application.Prefix(fn, args, _, _, _, _) => val fnDep = asStatic(fn) val prefixDep = asStatic(prefix) info.dependents.updateAt(fnDep, Set(prefixDep)) @@ -323,7 +346,7 @@ case object DataflowAnalysis extends IRPass { arguments = args.map(analyseCallArgument(_, info)) ) .updateMetadata(this -->> info) - case force @ IR.Application.Force(target, _, _, _) => + case force @ Application.Force(target, _, _, _) => val targetDep = asStatic(target) val forceDep = asStatic(force) info.dependents.updateAt(targetDep, Set(forceDep)) @@ -332,7 +355,7 @@ case object DataflowAnalysis extends IRPass { force .copy(target = analyseExpression(target, info)) .updateMetadata(this -->> info) - case vector @ IR.Application.Literal.Sequence(items, _, _, _) => + case vector @ Application.Sequence(items, _, _, _) => val vectorDep = asStatic(vector) items.foreach(it => { val itemDep = asStatic(it) @@ -343,7 +366,7 @@ case object DataflowAnalysis extends IRPass { vector .copy(items = items.map(analyseExpression(_, info))) .updateMetadata(this -->> info) - case tSet @ IR.Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => val tSetDep = asStatic(tSet) expr.foreach(exp => { val exprDep = asStatic(exp) @@ -354,7 +377,7 @@ case object DataflowAnalysis extends IRPass { tSet .copy(expression = expr.map(analyseExpression(_, info))) .updateMetadata(this -->> info) - case _: IR.Application.Operator => + case _: Operator => throw new CompilerError("Unexpected operator during Dataflow Analysis.") } } @@ -367,9 +390,9 @@ case object DataflowAnalysis extends IRPass { * @param info the dependency information for the module * @return `typ`, with attached dependency information */ - def analyseType(typ: IR.Type, info: DependencyInfo): IR.Type = { + def analyseType(typ: Type, info: DependencyInfo): Type = { typ match { - case asc @ IR.Type.Ascription(typed, signature, _, _, _) => + case asc @ Type.Ascription(typed, signature, _, _, _) => val ascrDep = asStatic(asc) val typedDep = asStatic(typed) val sigDep = asStatic(signature) @@ -384,7 +407,7 @@ case object DataflowAnalysis extends IRPass { ) .updateMetadata(this -->> info) - case fun @ IR.Type.Function(args, result, _, _, _) => + case fun @ Type.Function(args, result, _, _, _) => val funDep = asStatic(fun) val argDeps = args.map(asStatic) val resDep = asStatic(result) @@ -398,7 +421,7 @@ case object DataflowAnalysis extends IRPass { result = analyseExpression(result, info) ) .updateMetadata(this -->> info) - case ctx @ IR.Type.Context(typed, context, _, _, _) => + case ctx @ Type.Context(typed, context, _, _, _) => val ctxDep = asStatic(ctx) val typedDep = asStatic(typed) val contextDep = asStatic(context) @@ -412,7 +435,7 @@ case object DataflowAnalysis extends IRPass { context = analyseExpression(context, info) ) .updateMetadata(this -->> info) - case err @ IR.Type.Error(typed, error, _, _, _) => + case err @ Type.Error(typed, error, _, _, _) => val errDep = asStatic(err) val typedDep = asStatic(typed) val errorDep = asStatic(error) @@ -426,7 +449,7 @@ case object DataflowAnalysis extends IRPass { error = analyseExpression(error, info) ) .updateMetadata(this -->> info) - case member @ IR.Type.Set.Member(_, memberType, value, _, _, _) => + case member @ `type`.Set.Member(_, memberType, value, _, _, _) => val memberDep = asStatic(member) val memberTypeDep = asStatic(memberType) val valueDep = asStatic(value) @@ -440,7 +463,7 @@ case object DataflowAnalysis extends IRPass { value = analyseExpression(value, info) ) .updateMetadata(this -->> info) - case concat @ IR.Type.Set.Concat(left, right, _, _, _) => + case concat @ `type`.Set.Concat(left, right, _, _, _) => val concatDep = asStatic(concat) val leftDep = asStatic(left) val rightDep = asStatic(right) @@ -454,7 +477,7 @@ case object DataflowAnalysis extends IRPass { right = analyseExpression(right, info) ) .updateMetadata(this -->> info) - case eq @ IR.Type.Set.Equality(left, right, _, _, _) => + case eq @ `type`.Set.Equality(left, right, _, _, _) => val eqDep = asStatic(eq) val leftDep = asStatic(left) val rightDep = asStatic(right) @@ -466,7 +489,7 @@ case object DataflowAnalysis extends IRPass { left = analyseExpression(left, info), right = analyseExpression(right, info) ).updateMetadata(this -->> info) - case intersect @ IR.Type.Set.Intersection(left, right, _, _, _) => + case intersect @ `type`.Set.Intersection(left, right, _, _, _) => val intersectDep = asStatic(intersect) val leftDep = asStatic(left) val rightDep = asStatic(right) @@ -480,7 +503,7 @@ case object DataflowAnalysis extends IRPass { right = analyseExpression(right, info) ) .updateMetadata(this -->> info) - case union @ IR.Type.Set.Union(operands, _, _, _) => + case union @ `type`.Set.Union(operands, _, _, _) => val unionDep = asStatic(union) val opDeps = operands.map(asStatic) opDeps.foreach(info.dependents.updateAt(_, Set(unionDep))) @@ -488,7 +511,7 @@ case object DataflowAnalysis extends IRPass { union .copy(operands = operands.map(analyseExpression(_, info))) .updateMetadata(this -->> info) - case subsumption @ IR.Type.Set.Subsumption(left, right, _, _, _) => + case subsumption @ `type`.Set.Subsumption(left, right, _, _, _) => val subDep = asStatic(subsumption) val leftDep = asStatic(left) val rightDep = asStatic(right) @@ -502,7 +525,7 @@ case object DataflowAnalysis extends IRPass { right = analyseExpression(right, info) ) .updateMetadata(this -->> info) - case subtraction @ IR.Type.Set.Subtraction(left, right, _, _, _) => + case subtraction @ `type`.Set.Subtraction(left, right, _, _, _) => val subDep = asStatic(subtraction) val leftDep = asStatic(left) val rightDep = asStatic(right) @@ -530,7 +553,7 @@ case object DataflowAnalysis extends IRPass { * @param info the dependency information for the module * @return `name`, with attached dependency information */ - def analyseName(name: IR.Name, info: DependencyInfo): IR.Name = { + def analyseName(name: Name, info: DependencyInfo): Name = { val aliasInfo = name.passData .getUnsafe(AliasAnalysis)( "Name occurrence with missing aliasing information." @@ -538,7 +561,7 @@ case object DataflowAnalysis extends IRPass { .unsafeAs[AliasAnalysis.Info.Occurrence] name match { - case _: IR.Name.Blank => + case _: Name.Blank => throw new CompilerError( "Blanks should not be present during dataflow analysis." ) @@ -575,9 +598,9 @@ case object DataflowAnalysis extends IRPass { * @param info the dependency information for the module * @return `cse`, with attached dependency information */ - def analyseCase(cse: IR.Case, info: DependencyInfo): IR.Case = { + def analyseCase(cse: Case, info: DependencyInfo): Case = { cse match { - case expr: IR.Case.Expr => + case expr: Case.Expr => val exprDep = asStatic(expr) val scrutDep = asStatic(expr.scrutinee) info.dependents.updateAt(scrutDep, Set(exprDep)) @@ -594,7 +617,7 @@ case object DataflowAnalysis extends IRPass { branches = expr.branches.map(analyseCaseBranch(_, info)) ) .updateMetadata(this -->> info) - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("Unexpected case branch.") } } @@ -609,9 +632,9 @@ case object DataflowAnalysis extends IRPass { * @return `branch`, with attached dependency information */ def analyseCaseBranch( - branch: IR.Case.Branch, + branch: Case.Branch, info: DependencyInfo - ): IR.Case.Branch = { + ): Case.Branch = { val pattern = branch.pattern val expression = branch.expression @@ -639,9 +662,9 @@ case object DataflowAnalysis extends IRPass { * @return `pattern`, with attached dependency information */ def analysePattern( - pattern: IR.Pattern, + pattern: Pattern, info: DependencyInfo - ): IR.Pattern = { + ): Pattern = { val patternDep = asStatic(pattern) pattern match { case named @ Pattern.Name(name, _, _, _) => @@ -681,7 +704,7 @@ case object DataflowAnalysis extends IRPass { throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) - case err: IR.Error.Pattern => err.updateMetadata(this -->> info) + case err: errors.Pattern => err.updateMetadata(this -->> info) } } @@ -695,11 +718,11 @@ case object DataflowAnalysis extends IRPass { * @return `argument`, with attached dependency information */ def analyseDefinitionArgument( - argument: IR.DefinitionArgument, + argument: DefinitionArgument, info: DependencyInfo - ): IR.DefinitionArgument = { + ): DefinitionArgument = { argument match { - case spec @ IR.DefinitionArgument.Specified(_, _, defValue, _, _, _, _) => + case spec @ DefinitionArgument.Specified(_, _, defValue, _, _, _, _) => val specDep = asStatic(spec) defValue.foreach(expr => { val exprDep = asStatic(expr) @@ -725,11 +748,11 @@ case object DataflowAnalysis extends IRPass { * @return `argument`, with attached dependency information */ def analyseCallArgument( - argument: IR.CallArgument, + argument: CallArgument, info: DependencyInfo - ): IR.CallArgument = { + ): CallArgument = { argument match { - case spec @ IR.CallArgument.Specified(name, value, _, _, _) => + case spec @ CallArgument.Specified(name, value, _, _, _) => val specDep = asStatic(spec) val valueDep = asStatic(value) info.dependents.updateAt(valueDep, Set(specDep)) @@ -1033,7 +1056,7 @@ case object DataflowAnalysis extends IRPass { * @param ir the IR node to create a dependency on * @return a dynamic dependency on `ir` */ - def asDynamic(ir: IR.Name): Dynamic = { + def asDynamic(ir: Name): Dynamic = { Dynamic(ir.name, ir.getExternalId) } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DemandAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DemandAnalysis.scala index b933f2edda78..170dde6fe8df 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DemandAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/DemandAnalysis.scala @@ -1,7 +1,25 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Empty, + Expression, + Function, + Literal, + Module, + Name, + Type +} +import org.enso.compiler.core.ir.expression.{ + Application, + Case, + Comment, + Error, + Foreign, + Operator +} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.optimise.LambdaConsolidate @@ -16,7 +34,7 @@ import org.enso.compiler.pass.resolve.OverloadsResolution * * - Nothing * - * Additionally, all members of [[IR.IRKind.Primitive]] must have been removed + * Additionally, all members of [[org.enso.compiler.core.ir.IRKind.Primitive]] must have been removed * from the IR by the time it runs. */ case object DemandAnalysis extends IRPass { @@ -40,9 +58,9 @@ case object DemandAnalysis extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.copy(bindings = ir.bindings.map(t => t.mapExpressions( @@ -66,9 +84,9 @@ case object DemandAnalysis extends IRPass { * @return `ir`, transformed to correctly force terms */ override def runExpression( - expression: IR.Expression, + expression: Expression, inlineContext: InlineContext - ): IR.Expression = + ): Expression = analyseExpression( expression, isInsideCallArgument = false @@ -83,37 +101,37 @@ case object DemandAnalysis extends IRPass { * @return `expression`, transformed by the demand analysis process */ def analyseExpression( - expression: IR.Expression, + expression: Expression, isInsideCallArgument: Boolean - ): IR.Expression = { + ): Expression = { expression match { - case empty: IR.Empty => empty - case fn: IR.Function => analyseFunction(fn) - case name: IR.Name => analyseName(name, isInsideCallArgument) - case app: IR.Application => + case empty: Empty => empty + case fn: Function => analyseFunction(fn) + case name: Name => analyseName(name, isInsideCallArgument) + case app: Application => analyseApplication(app, isInsideCallArgument) - case typ: IR.Type => + case typ: Type => analyseType(typ, isInsideCallArgument) - case cse: IR.Case => + case cse: Case => analyseCase(cse, isInsideCallArgument) - case block @ IR.Expression.Block(expressions, retVal, _, _, _, _) => + case block @ Expression.Block(expressions, retVal, _, _, _, _) => block.copy( expressions = expressions.map(x => analyseExpression(x, isInsideCallArgument = false) ), returnValue = analyseExpression(retVal, isInsideCallArgument = false) ) - case binding @ IR.Expression.Binding(_, expression, _, _, _) => + case binding @ Expression.Binding(_, expression, _, _, _) => binding.copy(expression = analyseExpression( expression, isInsideCallArgument = false ) ) - case lit: IR.Literal => lit - case err: IR.Error => err - case foreign: IR.Foreign => foreign - case comment: IR.Comment => + case lit: Literal => lit + case err: Error => err + case foreign: Foreign => foreign + case comment: Comment => comment.mapExpressions(x => analyseExpression( x, @@ -129,10 +147,10 @@ case object DemandAnalysis extends IRPass { * @return `function`, transformed by the demand analysis process */ def analyseFunction( - function: IR.Function - ): IR.Function = + function: Function + ): Function = function match { - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => lam.copy( arguments = args.map(analyseDefinitionArgument), body = analyseExpression( @@ -140,7 +158,7 @@ case object DemandAnalysis extends IRPass { isInsideCallArgument = false ) ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during demand analysis." ) @@ -158,24 +176,24 @@ case object DemandAnalysis extends IRPass { * @return `name`, transformed by the demand analysis process */ def analyseName( - name: IR.Name, + name: Name, isInsideCallArgument: Boolean - ): IR.Expression = { + ): Expression = { if (isInsideCallArgument) { name } else { name match { - case lit: IR.Name.Literal if isDefined(lit) => + case lit: Name.Literal if isDefined(lit) => val forceLocation = name.location val newNameLocation = name.location.map(l => l.copy(id = None)) val newName = lit.copy(location = newNameLocation) - IR.Application.Force(newName, forceLocation) + Application.Force(newName, forceLocation) case _ => name } } } - private def isDefined(name: IR.Name): Boolean = { + private def isDefined(name: Name): Boolean = { val aliasInfo = name .unsafeGetMetadata( AliasAnalysis, @@ -194,27 +212,27 @@ case object DemandAnalysis extends IRPass { * @return `application`, transformed by the demand analysis process */ def analyseApplication( - application: IR.Application, + application: Application, isInsideCallArgument: Boolean - ): IR.Application = + ): Application = application match { - case pref @ IR.Application.Prefix(fn, args, _, _, _, _) => + case pref @ Application.Prefix(fn, args, _, _, _, _) => val newFun = fn match { - case n: IR.Name => n - case e => analyseExpression(e, isInsideCallArgument = false) + case n: Name => n + case e => analyseExpression(e, isInsideCallArgument = false) } pref.copy( function = newFun, arguments = args.map(analyseCallArgument) ) - case force @ IR.Application.Force(target, _, _, _) => + case force @ Application.Force(target, _, _, _) => force.copy(target = analyseExpression( target, isInsideCallArgument ) ) - case vec @ IR.Application.Literal.Sequence(items, _, _, _) => + case vec @ Application.Sequence(items, _, _, _) => vec.copy(items = items.map( analyseExpression( @@ -223,12 +241,12 @@ case object DemandAnalysis extends IRPass { ) ) ) - case tSet @ IR.Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => tSet.copy( expression = expr.map(analyseExpression(_, isInsideCallArgument = false)) ) - case _: IR.Application.Operator => + case _: Operator => throw new CompilerError( "Operators should not be present during demand analysis." ) @@ -243,9 +261,9 @@ case object DemandAnalysis extends IRPass { * @param arg the argument to perform demand analysis on * @return `arg`, transformed by the demand analysis process */ - def analyseCallArgument(arg: IR.CallArgument): IR.CallArgument = { + def analyseCallArgument(arg: CallArgument): CallArgument = { arg match { - case spec @ IR.CallArgument.Specified(_, expr, _, _, _) => + case spec @ CallArgument.Specified(_, expr, _, _, _) => spec.copy( value = analyseExpression( expr, @@ -261,10 +279,10 @@ case object DemandAnalysis extends IRPass { * @return `arg`, transformed by the demand analysis process */ def analyseDefinitionArgument( - arg: IR.DefinitionArgument - ): IR.DefinitionArgument = { + arg: DefinitionArgument + ): DefinitionArgument = { arg match { - case spec @ IR.DefinitionArgument.Specified(_, _, default, _, _, _, _) => + case spec @ DefinitionArgument.Specified(_, _, default, _, _, _, _) => spec.copy( defaultValue = default.map(x => analyseExpression( @@ -284,9 +302,9 @@ case object DemandAnalysis extends IRPass { * @return `typ`, transformed by the demand analysis process */ def analyseType( - typ: IR.Type, + typ: Type, isInsideCallArgument: Boolean - ): IR.Type = + ): Type = typ.mapExpressions(x => analyseExpression(x, isInsideCallArgument)) /** Performs demand analysis on a case expression. @@ -297,11 +315,11 @@ case object DemandAnalysis extends IRPass { * @return `cse`, transformed by the demand analysis process */ def analyseCase( - cse: IR.Case, + cse: Case, isInsideCallArgument: Boolean - ): IR.Case = + ): Case = cse match { - case expr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => expr.copy( scrutinee = analyseExpression( scrutinee, @@ -317,7 +335,7 @@ case object DemandAnalysis extends IRPass { * @param branch the case branch to perform demand analysis on * @return `branch`, transformed by the demand analysis process */ - def analyseCaseBranch(branch: IR.Case.Branch): IR.Case.Branch = { + def analyseCaseBranch(branch: Case.Branch): Case.Branch = { branch.copy( expression = analyseExpression( branch.expression, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/GatherDiagnostics.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/GatherDiagnostics.scala index daa801507d17..282186835cc2 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/GatherDiagnostics.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/GatherDiagnostics.scala @@ -2,6 +2,13 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Diagnostic, + Expression, + Module +} +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.resolve.TypeSignatures @@ -30,9 +37,9 @@ case object GatherDiagnostics extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.updateMetadata(this -->> gatherMetadata(ir)) /** Executes the pass on the provided `ir`, and attaches all the encountered @@ -44,9 +51,9 @@ case object GatherDiagnostics extends IRPass { * @return `ir` with all the errors accumulated in pass metadata. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir.updateMetadata(this -->> gatherMetadata(ir)) + ): Expression = ir.updateMetadata(this -->> gatherMetadata(ir)) /** Gathers diagnostics from all children of an IR node. * @@ -55,21 +62,21 @@ case object GatherDiagnostics extends IRPass { */ private def gatherMetadata(ir: IR): DiagnosticsMeta = { val diagnostics = ir.preorder.collect { - case err: IR.Diagnostic => + case err: Diagnostic => List(err) - case arg: IR.DefinitionArgument => + case arg: DefinitionArgument => val typeSignatureDiagnostics = arg .getMetadata(TypeSignatures) - .map(_.signature.preorder.collect { case err: IR.Diagnostic => + .map(_.signature.preorder.collect { case err: Diagnostic => err }) .getOrElse(Nil) typeSignatureDiagnostics ++ arg.diagnostics.toList - case x: IR.Module.Scope.Definition.Method => + case x: definition.Method => val typeSignatureDiagnostics = x.getMetadata(TypeSignatures) - .map(_.signature.preorder.collect { case err: IR.Diagnostic => + .map(_.signature.preorder.collect { case err: Diagnostic => err }) .getOrElse(Nil) @@ -81,7 +88,7 @@ case object GatherDiagnostics extends IRPass { ) } - final private class DiagnosticKeys(private val diagnostic: IR.Diagnostic) { + final private class DiagnosticKeys(private val diagnostic: Diagnostic) { /** Equals is based on type of diagnostic, its location and its diagnostic keys. */ @@ -110,7 +117,7 @@ case object GatherDiagnostics extends IRPass { * * @param diagnostics a list of the errors found in the IR */ - case class DiagnosticsMeta(diagnostics: List[IR.Diagnostic]) + case class DiagnosticsMeta(diagnostics: List[Diagnostic]) extends IRPass.IRMetadata { /** The name of the metadata as a string. */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/ImportSymbolAnalysis.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/ImportSymbolAnalysis.scala index d888935b1605..ab0164e12bb3 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/ImportSymbolAnalysis.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/ImportSymbolAnalysis.scala @@ -1,14 +1,16 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module, Name} +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.data.BindingsMap import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.GenerateMethodBodies /** Performs analysis of `from ... import sym1, sym2, ...` statements - checks that all * the symbols imported from the module can be resolved, i.e., exists. - * In case of unresolved symbols, replaces the IR import with [[IR.Error.ImportExport]]. + * In case of unresolved symbols, replaces the IR import with [[errors.ImportExport]]. * Reports only the first unresolved symbol. */ case object ImportSymbolAnalysis extends IRPass { @@ -26,9 +28,9 @@ case object ImportSymbolAnalysis extends IRPass { /** @inheritdoc */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val bindingMap = ir.unsafeGetMetadata( BindingAnalysis, "BindingMap should already be present" @@ -41,18 +43,18 @@ case object ImportSymbolAnalysis extends IRPass { /** @inheritdoc */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir - /** @return May return multiple [[IR.Error.ImportExport]] in case of multiple unresolved symbols. + /** @return May return multiple [[errors.ImportExport]] in case of multiple unresolved symbols. */ private def analyseSymbolsFromImport( - imp: IR.Module.Scope.Import, + imp: Import, bindingMap: BindingsMap - ): List[IR.Module.Scope.Import] = { + ): List[Import] = { imp match { - case imp @ IR.Module.Scope.Import.Module( + case imp @ Import.Module( _, _, _, @@ -87,23 +89,23 @@ case object ImportSymbolAnalysis extends IRPass { } private def createErrorForUnresolvedSymbol( - imp: IR.Module.Scope.Import, + imp: Import, importTarget: BindingsMap.ImportTarget, - unresolvedSymbol: IR.Name.Literal - ): IR.Error.ImportExport = { + unresolvedSymbol: Name.Literal + ): errors.ImportExport = { importTarget match { case BindingsMap.ResolvedModule(module) => - IR.Error.ImportExport( + errors.ImportExport( imp, - IR.Error.ImportExport.SymbolDoesNotExist( + errors.ImportExport.SymbolDoesNotExist( unresolvedSymbol.name, module.getName.toString ) ) case BindingsMap.ResolvedType(_, tp) => - IR.Error.ImportExport( + errors.ImportExport( imp, - IR.Error.ImportExport.NoSuchConstructor( + errors.ImportExport.NoSuchConstructor( tp.name, unresolvedSymbol.name ) @@ -113,7 +115,7 @@ case object ImportSymbolAnalysis extends IRPass { private def isSymbolResolved( importTarget: BindingsMap.ImportTarget, - symbol: IR.Name.Literal + symbol: Name.Literal ): Boolean = { importTarget.findExportedSymbolsFor(symbol.name).nonEmpty } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/TailCall.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/TailCall.scala index ed97975ee111..5c393019e345 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/TailCall.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/analyse/TailCall.scala @@ -1,9 +1,32 @@ package org.enso.compiler.pass.analyse import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.expression.{ + errors, + Application, + Case, + Comment, + Error, + Foreign, + Operator +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Diagnostic, + Empty, + Expression, + Function, + Literal, + Module, + Name, + Pattern, + Type, + Warning +} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar._ @@ -46,9 +69,9 @@ case object TailCall extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.copy(bindings = ir.bindings.map(analyseModuleBinding)) } @@ -61,9 +84,9 @@ case object TailCall extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = + ): Expression = analyseExpression( ir, inlineContext.isInTailPosition.getOrElse( @@ -80,55 +103,55 @@ case object TailCall extends IRPass { * @return `definition`, annotated with tail call information */ private def analyseModuleBinding( - definition: IR.Module.Scope.Definition - ): IR.Module.Scope.Definition = { - definition match { - case method: IR.Module.Scope.Definition.Method.Conversion => + moduleDefinition: Definition + ): Definition = { + moduleDefinition match { + case method: definition.Method.Conversion => method .copy( body = analyseExpression(method.body, isInTailPosition = true) ) .updateMetadata(this -->> TailPosition.Tail) - case method @ IR.Module.Scope.Definition.Method + case method @ definition.Method .Explicit(_, body, _, _, _) => method .copy( body = analyseExpression(body, isInTailPosition = true) ) .updateMetadata(this -->> TailPosition.Tail) - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Sugared method definitions should not occur during tail call " + "analysis." ) - case _: IR.Module.Scope.Definition.Type => - definition.updateMetadata(this -->> TailPosition.Tail) - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.Type => + moduleDefinition.updateMetadata(this -->> TailPosition.Tail) + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during " + "tail call analysis." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation should not exist as an entity during tail call analysis." ) - case _: IR.Type.Ascription => + case _: Type.Ascription => throw new CompilerError( "Type signatures should not exist at the top level during " + "tail call analysis." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "tail call analysis." ) - case ann: IR.Name.GenericAnnotation => + case ann: Name.GenericAnnotation => ann .copy(expression = analyseExpression(ann.expression, isInTailPosition = true) ) .updateMetadata(this -->> TailPosition.Tail) - case err: IR.Error => err + case err: Error => err } } @@ -140,30 +163,30 @@ case object TailCall extends IRPass { * @return `expression`, annotated with tail position metadata */ def analyseExpression( - expression: IR.Expression, + expression: Expression, isInTailPosition: Boolean - ): IR.Expression = { + ): Expression = { val expressionWithWarning = if (isTailAnnotated(expression) && !isInTailPosition) - expression.addDiagnostic(IR.Warning.WrongTco(expression.location)) + expression.addDiagnostic(Warning.WrongTco(expression.location)) else expression expressionWithWarning match { - case empty: IR.Empty => + case empty: Empty => empty.updateMetadata(this -->> TailPosition.NotTail) - case function: IR.Function => + case function: Function => analyseFunction(function, isInTailPosition) - case caseExpr: IR.Case => analyseCase(caseExpr, isInTailPosition) - case typ: IR.Type => analyseType(typ, isInTailPosition) - case app: IR.Application => analyseApplication(app, isInTailPosition) - case name: IR.Name => analyseName(name, isInTailPosition) - case foreign: IR.Foreign => + case caseExpr: Case => analyseCase(caseExpr, isInTailPosition) + case typ: Type => analyseType(typ, isInTailPosition) + case app: Application => analyseApplication(app, isInTailPosition) + case name: Name => analyseName(name, isInTailPosition) + case foreign: Foreign => foreign.updateMetadata(this -->> TailPosition.NotTail) - case literal: IR.Literal => analyseLiteral(literal, isInTailPosition) - case _: IR.Comment => + case literal: Literal => analyseLiteral(literal, isInTailPosition) + case _: Comment => throw new CompilerError( "Comments should not be present during tail call analysis." ) - case block @ IR.Expression.Block( + case block @ Expression.Block( expressions, returnValue, _, @@ -179,13 +202,13 @@ case object TailCall extends IRPass { returnValue = analyseExpression(returnValue, isInTailPosition) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case binding @ IR.Expression.Binding(_, expression, _, _, _) => + case binding @ Expression.Binding(_, expression, _, _, _) => binding .copy( expression = analyseExpression(expression, isInTailPosition = false) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case err: IR.Diagnostic => + case err: Diagnostic => err.updateMetadata( this -->> TailPosition.fromBool(isInTailPosition) ) @@ -198,7 +221,7 @@ case object TailCall extends IRPass { * @param isInTailPosition whether the name occurs in tail position or not * @return `name`, annotated with tail position metadata */ - def analyseName(name: IR.Name, isInTailPosition: Boolean): IR.Name = { + def analyseName(name: Name, isInTailPosition: Boolean): Name = { name.updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) } @@ -210,9 +233,9 @@ case object TailCall extends IRPass { * @return `literal`, annotated with tail position metdata */ def analyseLiteral( - literal: IR.Literal, + literal: Literal, isInTailPosition: Boolean - ): IR.Literal = { + ): Literal = { literal.updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) } @@ -224,36 +247,36 @@ case object TailCall extends IRPass { * @return `application`, annotated with tail position metadata */ def analyseApplication( - application: IR.Application, + application: Application, isInTailPosition: Boolean - ): IR.Application = { + ): Application = { application match { - case app @ IR.Application.Prefix(fn, args, _, _, _, _) => + case app @ Application.Prefix(fn, args, _, _, _, _) => app .copy( function = analyseExpression(fn, isInTailPosition = false), arguments = args.map(analyseCallArg) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case force @ IR.Application.Force(target, _, _, _) => + case force @ Application.Force(target, _, _, _) => force .copy( target = analyseExpression(target, isInTailPosition) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case vector @ IR.Application.Literal.Sequence(items, _, _, _) => + case vector @ Application.Sequence(items, _, _, _) => vector .copy(items = items.map(analyseExpression(_, isInTailPosition = false)) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case tSet @ IR.Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => tSet .copy(expression = expr.map(analyseExpression(_, isInTailPosition = false)) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case _: IR.Application.Operator => + case _: Operator => throw new CompilerError("Unexpected binary operator.") } } @@ -263,9 +286,9 @@ case object TailCall extends IRPass { * @param argument the argument to analyse * @return `argument`, annotated with tail position metadata */ - def analyseCallArg(argument: IR.CallArgument): IR.CallArgument = { + def analyseCallArg(argument: CallArgument): CallArgument = { argument match { - case arg @ IR.CallArgument.Specified(_, expr, _, _, _) => + case arg @ CallArgument.Specified(_, expr, _, _, _) => arg .copy( // Note [Call Argument Tail Position] @@ -305,7 +328,7 @@ case object TailCall extends IRPass { * call position * @return `value`, annotated with tail position metadata */ - def analyseType(value: IR.Type, isInTailPosition: Boolean): IR.Type = { + def analyseType(value: Type, isInTailPosition: Boolean): Type = { value .mapExpressions(analyseExpression(_, isInTailPosition = false)) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) @@ -318,9 +341,9 @@ case object TailCall extends IRPass { * call position * @return `caseExpr`, annotated with tail position metadata */ - def analyseCase(caseExpr: IR.Case, isInTailPosition: Boolean): IR.Case = { + def analyseCase(caseExpr: Case, isInTailPosition: Boolean): Case = { caseExpr match { - case caseExpr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case caseExpr @ Case.Expr(scrutinee, branches, _, _, _, _) => caseExpr .copy( scrutinee = analyseExpression(scrutinee, isInTailPosition = false), @@ -328,7 +351,7 @@ case object TailCall extends IRPass { branches = branches.map(analyseCaseBranch(_, isInTailPosition)) ) .updateMetadata(this -->> TailPosition.fromBool(isInTailPosition)) - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("Unexpected case branch.") } } @@ -352,9 +375,9 @@ case object TailCall extends IRPass { * @return `branch`, annotated with tail position metadata */ def analyseCaseBranch( - branch: IR.Case.Branch, + branch: Case.Branch, isInTailPosition: Boolean - ): IR.Case.Branch = { + ): Case.Branch = { branch .copy( pattern = analysePattern(branch.pattern), @@ -372,8 +395,8 @@ case object TailCall extends IRPass { * @return `pattern`, annotated with tail position metadata */ def analysePattern( - pattern: IR.Pattern - ): IR.Pattern = { + pattern: Pattern + ): Pattern = { pattern match { case namePat @ Pattern.Name(name, _, _, _) => namePat @@ -397,7 +420,7 @@ case object TailCall extends IRPass { name = analyseName(name, isInTailPosition = false), tpe = analyseName(tpe, isInTailPosition = false) ) - case err: IR.Error.Pattern => + case err: errors.Pattern => err.updateMetadata(this -->> TailPosition.NotTail) case _: Pattern.Documentation => throw new CompilerError( @@ -414,19 +437,19 @@ case object TailCall extends IRPass { * @return `function`, annotated with tail position metadata */ def analyseFunction( - function: IR.Function, + function: Function, isInTailPosition: Boolean - ): IR.Function = { + ): Function = { val canBeTCO = function.canBeTCO val markAsTail = (!canBeTCO && isInTailPosition) || canBeTCO val resultFunction = function match { - case lambda @ IR.Function.Lambda(args, body, _, _, _, _) => + case lambda @ Function.Lambda(args, body, _, _, _, _) => lambda.copy( arguments = args.map(analyseDefArgument), body = analyseExpression(body, isInTailPosition = markAsTail) ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during tail call analysis." ) @@ -442,9 +465,9 @@ case object TailCall extends IRPass { * @param arg the argument definition to analyse * @return `arg`, annotated with tail position metadata */ - def analyseDefArgument(arg: IR.DefinitionArgument): IR.DefinitionArgument = { + def analyseDefArgument(arg: DefinitionArgument): DefinitionArgument = { arg match { - case arg @ IR.DefinitionArgument.Specified(_, _, default, _, _, _, _) => + case arg @ DefinitionArgument.Specified(_, _, default, _, _, _, _) => arg .copy( defaultValue = default.map(x => @@ -525,7 +548,7 @@ case object TailCall extends IRPass { * @return `true` if `expression` is annotated with `@Tail_Call`, otherwise * `false` */ - def isTailAnnotated(expression: IR.Expression): Boolean = { + def isTailAnnotated(expression: Expression): Boolean = { expression .getMetadata(ExpressionAnnotations) .exists(anns => 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 d7ac45b6f127..0e13e3d64263 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 @@ -2,11 +2,20 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.IdentifiedLocation -import org.enso.compiler.core.IR.Module.Scope.Definition -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.Name.MethodReference -import org.enso.compiler.core.ir.{DiagnosticStorage, MetadataStorage} +import org.enso.compiler.core.ir.{ + DefinitionArgument, + DiagnosticStorage, + Expression, + Function, + IdentifiedLocation, + MetadataStorage, + Module, + Name, + Type +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.Error import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -72,9 +81,9 @@ case object ComplexType extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.copy( bindings = ir.bindings.flatMap { case typ: Definition.SugaredType => desugarComplexType(typ) @@ -91,9 +100,9 @@ case object ComplexType extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir // === Pass Internals ======================================================= @@ -103,17 +112,17 @@ case object ComplexType extends IRPass { * @return the top-level definitions corresponding to the desugaring of `typ` */ private def desugarComplexType( - typ: IR.Module.Scope.Definition.SugaredType - ): List[IR.Module.Scope.Definition] = { + typ: Definition.SugaredType + ): List[Definition] = { val annotations = typ.getMetadata(ModuleAnnotations) - var lastAnnotations = Seq.empty[IR.Name.GenericAnnotation] - var seenAnnotations = Set.empty[IR.Name.GenericAnnotation] + var lastAnnotations = Seq.empty[Name.GenericAnnotation] + var seenAnnotations = Set.empty[Name.GenericAnnotation] val atomDefs = typ.body .flatMap { - case ann: IR.Name.GenericAnnotation => + case ann: Name.GenericAnnotation => lastAnnotations :+= ann None - case d: IR.Module.Scope.Definition.Data => + case d: Definition.Data => val res = Some(d.copy(annotations = d.annotations ++ lastAnnotations)) seenAnnotations ++= lastAnnotations lastAnnotations = Seq() @@ -137,12 +146,12 @@ case object ComplexType extends IRPass { ) val remainingEntities = typ.body.filterNot { - case _: IR.Module.Scope.Definition.Data => true - case ann: IR.Name.GenericAnnotation => seenAnnotations.contains(ann) - case _ => false + case _: Definition.Data => true + case ann: Name.GenericAnnotation => seenAnnotations.contains(ann) + case _ => false } - var lastSignature: Option[IR.Type.Ascription] = None + var lastSignature: Option[Type.Ascription] = None /** Pairs up signatures with method definitions, and then generates the * appropriate method definitions for the atoms in scope. @@ -152,14 +161,14 @@ case object ComplexType extends IRPass { * @return a list of method definitions for `name` */ def matchSignaturesAndGenerate( - name: IR.Name, + name: Name, defn: IR - ): List[IR.Module.Scope.Definition] = { - var unusedSig: Option[IR.Type.Ascription] = None + ): List[Definition] = { + var unusedSig: Option[Type.Ascription] = None val sig = lastSignature match { - case Some(IR.Type.Ascription(typed, _, _, _, _)) => + case Some(Type.Ascription(typed, _, _, _, _)) => typed match { - case IR.Name.Literal(nameStr, _, _, _, _) => + case Name.Literal(nameStr, _, _, _, _) => if (name.name == nameStr) { lastSignature } else { @@ -183,22 +192,22 @@ case object ComplexType extends IRPass { } val entityResults: List[Definition] = remainingEntities.flatMap { - case sig: IR.Type.Ascription => + case sig: Type.Ascription => val res = lastSignature lastSignature = Some(sig) res - case binding @ IR.Expression.Binding(name, _, _, _, _) => + case binding @ Expression.Binding(name, _, _, _, _) => matchSignaturesAndGenerate(name, binding) - case funSugar @ IR.Function.Binding(name, _, _, _, _, _, _) => + case funSugar @ Function.Binding(name, _, _, _, _, _, _) => matchSignaturesAndGenerate(name, funSugar) - case err: IR.Error => Seq(err) - case ann: IR.Name.GenericAnnotation => Seq(ann) + case err: Error => Seq(err) + case ann: Name.GenericAnnotation => Seq(ann) case _ => throw new CompilerError("Unexpected IR node in complex type body.") } val allEntities = entityResults ::: lastSignature.toList - val sumType = IR.Module.Scope.Definition.Type( + val sumType = Definition.Type( typ.name, typ.arguments, atomDefs, @@ -230,13 +239,13 @@ case object ComplexType extends IRPass { */ private def genMethodDef( ir: IR, - typeName: IR.Name, - signature: Option[IR.Type.Ascription] - ): List[IR.Module.Scope.Definition] = { + typeName: Name, + signature: Option[Type.Ascription] + ): List[Definition] = { ir match { - case IR.Expression.Binding(name, expr, location, passData, diagnostics) => + case Expression.Binding(name, expr, location, passData, diagnostics) => val realExpr = expr match { - case b @ IR.Expression.Block(_, _, _, suspended, _, _) if suspended => + case b @ Expression.Block(_, _, _, suspended, _, _) if suspended => b.copy(suspended = false) case _ => expr } @@ -251,7 +260,7 @@ case object ComplexType extends IRPass { diagnostics, signature ) - case IR.Function.Binding( + case Function.Binding( name, args, body, @@ -288,25 +297,25 @@ case object ComplexType extends IRPass { * @return a top-level method definition */ private def genForName( - typeName: IR.Name, - name: IR.Name, - args: List[IR.DefinitionArgument], - body: IR.Expression, + typeName: Name, + name: Name, + args: List[DefinitionArgument], + body: Expression, location: Option[IdentifiedLocation], passData: MetadataStorage, diagnostics: DiagnosticStorage, - signature: Option[IR.Type.Ascription] - ): List[IR.Module.Scope.Definition] = { - val methodRef = IR.Name.MethodReference( - Some(IR.Name.Qualified(List(typeName), typeName.location)), + signature: Option[Type.Ascription] + ): List[Definition] = { + val methodRef = Name.MethodReference( + Some(Name.Qualified(List(typeName), typeName.location)), name, - MethodReference.genLocation(List(typeName, name)) + Name.MethodReference.genLocation(List(typeName, name)) ) val newSig = signature.map(sig => sig.copy(typed = methodRef.duplicate()).duplicate()) - val binding = Method.Binding( + val binding = definition.Method.Binding( methodRef.duplicate(), args.map(_.duplicate()), body.duplicate(), diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/FunctionBinding.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/FunctionBinding.scala index 311a98f295cc..2c82b0a85816 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/FunctionBinding.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/FunctionBinding.scala @@ -1,10 +1,17 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.DefinitionArgument -import org.enso.compiler.core.IR.Module.Scope.Definition -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.{errors, Comment, Error} +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name, + Type +} import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -61,9 +68,9 @@ case object FunctionBinding extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir.copy(bindings = ir.bindings.map(desugarModuleSymbol)) + ): Module = ir.copy(bindings = ir.bindings.map(desugarModuleSymbol)) /** Runs desugaring of function bindings on an arbitrary expression. * @@ -74,9 +81,9 @@ case object FunctionBinding extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = desugarExpression(ir) + ): Expression = desugarExpression(ir) // === Pass Internals ======================================================= @@ -85,9 +92,9 @@ case object FunctionBinding extends IRPass { * @param ir the expression to desugar * @return `ir`, with any function definition sugar removed */ - def desugarExpression(ir: IR.Expression): IR.Expression = { + def desugarExpression(ir: Expression): Expression = { ir.transformExpressions { - case IR.Function.Binding( + case Function.Binding( name, args, body, @@ -103,12 +110,12 @@ case object FunctionBinding extends IRPass { val lambda = args .map(_.mapExpressions(desugarExpression)) .foldRight(desugarExpression(body))((arg, body) => - IR.Function.Lambda(List(arg), body, None) + Function.Lambda(List(arg), body, None) ) - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .copy(canBeTCO = canBeTCO, location = location) - IR.Expression.Binding(name, lambda, location, passData, diagnostics) + Expression.Binding(name, lambda, location, passData, diagnostics) } } @@ -118,21 +125,22 @@ case object FunctionBinding extends IRPass { * @return `definition`, with any function definition sugar removed */ def desugarModuleSymbol( - definition: IR.Module.Scope.Definition - ): IR.Module.Scope.Definition = { - definition match { - case _: Definition.Type => definition.mapExpressions(desugarExpression) - case _: Method.Explicit => + moduleDefinition: Definition + ): Definition = { + moduleDefinition match { + case _: Definition.Type => + moduleDefinition.mapExpressions(desugarExpression) + case _: definition.Method.Explicit => throw new CompilerError( "Explicit method definitions should not exist during function " + "binding desugaring." ) - case _: Method.Conversion => + case _: definition.Method.Conversion => throw new CompilerError( "Conversion method nodes should not exist during function binding " + "desugaring." ) - case meth @ Method.Binding( + case meth @ definition.Method.Binding( methRef, args, body, @@ -146,10 +154,10 @@ case object FunctionBinding extends IRPass { val newBody = args .map(_.mapExpressions(desugarExpression)) .foldRight(desugarExpression(body))((arg, body) => - IR.Function.Lambda(List(arg), body, None) + Function.Lambda(List(arg), body, None) ) - Method.Explicit( + definition.Method.Explicit( methRef, newBody, loc, @@ -158,23 +166,23 @@ case object FunctionBinding extends IRPass { ) } else { if (args.isEmpty) - IR.Error.Conversion(meth, IR.Error.Conversion.MissingArgs) + errors.Conversion(meth, errors.Conversion.MissingArgs) else if (args.head.ascribedType.isEmpty) { - IR.Error.Conversion( + errors.Conversion( args.head, - IR.Error.Conversion.MissingSourceType(args.head.name.name) + errors.Conversion.MissingSourceType(args.head.name.name) ) } else { val firstArg :: restArgs = args val firstArgumentType = firstArg.ascribedType.get val firstArgumentName = firstArg.name val newFirstArgument = - if (firstArgumentName.isInstanceOf[IR.Name.Blank]) { + if (firstArgumentName.isInstanceOf[Name.Blank]) { val newName = if (restArgs.nonEmpty) - IR.Name.Self(firstArgumentName.location, synthetic = true) + Name.Self(firstArgumentName.location, synthetic = true) else - IR.Name + Name .Literal( Constants.Names.THAT_ARGUMENT, firstArgumentName.isMethod, @@ -191,8 +199,8 @@ case object FunctionBinding extends IRPass { val (sndArgument, remaining) = restArgs match { case snd :: rest => val sndArgName = snd.name - if (sndArgName.isInstanceOf[IR.Name.Blank]) { - val newName = IR.Name + if (sndArgName.isInstanceOf[Name.Blank]) { + val newName = Name .Literal( Constants.Names.THAT_ARGUMENT, sndArgName.isMethod, @@ -219,15 +227,15 @@ case object FunctionBinding extends IRPass { def transformRemainingArgs( requiredArgs: List[DefinitionArgument], remainingArgs: List[DefinitionArgument] - ): Either[IR.Error, IR.Module.Scope.Definition.Method] = { + ): Either[Error, definition.Method] = { remaining .filter(_.name.name != Constants.Names.SELF_ARGUMENT) .find(_.defaultValue.isEmpty) match { case Some(nonDefaultedArg) => Left( - IR.Error.Conversion( + errors.Conversion( nonDefaultedArg, - IR.Error.Conversion.NonDefaultedArgument( + errors.Conversion.NonDefaultedArgument( nonDefaultedArg.name.name ) ) @@ -236,10 +244,10 @@ case object FunctionBinding extends IRPass { val newBody = (requiredArgs ::: remainingArgs) .map(_.mapExpressions(desugarExpression)) .foldRight(desugarExpression(body))((arg, body) => - IR.Function.Lambda(List(arg), body, None) + Function.Lambda(List(arg), body, None) ) Right( - Method.Conversion( + definition.Method.Conversion( methRef, firstArgumentType, newBody, @@ -257,9 +265,9 @@ case object FunctionBinding extends IRPass { ) { if (newSndArgument.name.name != Constants.Names.THAT_ARGUMENT) Left( - IR.Error.Conversion( + errors.Conversion( newSndArgument, - IR.Error.Conversion.InvalidSourceArgumentName( + errors.Conversion.InvalidSourceArgumentName( newSndArgument.name.name ) ) @@ -269,9 +277,9 @@ case object FunctionBinding extends IRPass { newFirstArgument.name.name != Constants.Names.THAT_ARGUMENT ) { Left( - IR.Error.Conversion( + errors.Conversion( newFirstArgument, - IR.Error.Conversion.InvalidSourceArgumentName( + errors.Conversion.InvalidSourceArgumentName( newFirstArgument.name.name ) ) @@ -282,9 +290,9 @@ case object FunctionBinding extends IRPass { newFirstArgument.name.name != Constants.Names.THAT_ARGUMENT ) { Left( - IR.Error.Conversion( + errors.Conversion( newFirstArgument, - IR.Error.Conversion.InvalidSourceArgumentName( + errors.Conversion.InvalidSourceArgumentName( newFirstArgument.name.name ) ) @@ -301,24 +309,24 @@ case object FunctionBinding extends IRPass { .fold(identity, identity) } } - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during " + "function binding desugaring." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation should not be present during function binding" + "desugaring." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "function binding desugaring." ) - case a: IR.Name.GenericAnnotation => a - case a: IR.Type.Ascription => a - case e: IR.Error => e + case a: Name.GenericAnnotation => a + case a: Type.Ascription => a + case e: Error => e } } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/GenerateMethodBodies.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/GenerateMethodBodies.scala index 6119efbab2f3..0e6d1b755c6b 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/GenerateMethodBodies.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/GenerateMethodBodies.scala @@ -1,9 +1,18 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name, + Warning +} +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.Foreign import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ AliasAnalysis, @@ -14,7 +23,7 @@ import org.enso.compiler.pass.lint.UnusedBindings import org.enso.compiler.pass.optimise.LambdaConsolidate import org.enso.polyglot.ForeignLanguage -import scala.annotation.{tailrec} +import scala.annotation.tailrec /** This pass is responsible for ensuring that method bodies are in the correct * format. @@ -59,13 +68,13 @@ case object GenerateMethodBodies extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.copy( bindings = ir.bindings.map { - case m: IR.Module.Scope.Definition.Method => processMethodDef(m) - case x => x + case m: definition.Method => processMethodDef(m) + case x => x } ) } @@ -77,20 +86,20 @@ case object GenerateMethodBodies extends IRPass { * correct format */ def processMethodDef( - ir: IR.Module.Scope.Definition.Method - ): IR.Module.Scope.Definition.Method = { + ir: definition.Method + ): definition.Method = { ir match { - case ir: IR.Module.Scope.Definition.Method.Explicit => + case ir: definition.Method.Explicit => ir.copy( body = ir.body match { - case fun: IR.Function => processBodyFunction(fun, ir.methodName) - case expression => processBodyExpression(expression, ir.methodName) + case fun: Function => processBodyFunction(fun, ir.methodName) + case expression => processBodyExpression(expression, ir.methodName) } ) - case ir: Method.Conversion => + case ir: definition.Method.Conversion => ir.copy( body = ir.body match { - case fun: IR.Function => + case fun: Function => processBodyFunction(fun, ir.methodName) case _ => throw new CompilerError( @@ -99,7 +108,7 @@ case object GenerateMethodBodies extends IRPass { ) } ) - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Method definition sugar should not be present during method body " + "generation." @@ -118,29 +127,29 @@ case object GenerateMethodBodies extends IRPass { * @return the body function with the `self` argument */ def processBodyFunction( - fun: IR.Function, - funName: IR.Name - ): IR.Expression = { + fun: Function, + funName: Name + ): Expression = { val chainedFunctionArgs = collectChainedFunctionArgs(fun, 0) val selfArgs = chainedFunctionArgs.collect { - case (arg, idx) if arg.name.isInstanceOf[IR.Name.Self] => + case (arg, idx) if arg.name.isInstanceOf[Name.Self] => (arg, idx) } selfArgs match { case _ :: (redefined, _) :: _ => - IR.Error.Redefined.SelfArg(location = redefined.location) + errors.Redefined.SelfArg(location = redefined.location) case (_, parameterPosition) :: Nil => fun match { - case lam @ IR.Function.Lambda(_ :: _, _, _, _, _, _) + case lam @ Function.Lambda(_ :: _, _, _, _, _, _) if parameterPosition == 0 => lam - case lam @ IR.Function.Lambda(_, _, _, _, _, _) => + case lam @ Function.Lambda(_, _, _, _, _, _) => fun.addDiagnostic( - IR.Warning.WrongSelfParameterPos(funName, fun, parameterPosition) + Warning.WrongSelfParameterPos(funName, fun, parameterPosition) ) lam - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function definition sugar should not be present during method " + "body generation." @@ -148,7 +157,7 @@ case object GenerateMethodBodies extends IRPass { } case Nil => fun match { - case lam @ IR.Function.Lambda(_, body, _, _, _, _) + case lam @ Function.Lambda(_, body, _, _, _, _) if findForeignDefinition( body, lang = Some(ForeignLanguage.JS) @@ -162,13 +171,13 @@ case object GenerateMethodBodies extends IRPass { funName, replace = thisArgs.nonEmpty ) - case lam: IR.Function.Lambda => + case lam: Function.Lambda => lam.copy( arguments = if (funName.name == MAIN_FUNCTION_NAME) lam.arguments else genSyntheticSelf() :: lam.arguments ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function definition sugar should not be present during method " + "body generation." @@ -178,18 +187,18 @@ case object GenerateMethodBodies extends IRPass { } private def insertOrReplaceSelfInJSFunction( - lam: IR.Function.Lambda, - funName: IR.Name, + lam: Function.Lambda, + funName: Name, replace: Boolean, argsIdx: Int = 0 - ): IR.Function.Lambda = { + ): Function.Lambda = { val (args, hasSelf) = lam.arguments.zipWithIndex.foldLeft( - (Nil: List[IR.DefinitionArgument], false) + (Nil: List[DefinitionArgument], false) ) { case ((acc, found), (arg, i)) => if (arg.name.name == THIS_ARGUMENT) { if (i + argsIdx != 0) { lam.addDiagnostic( - IR.Warning.WrongSelfParameterPos(funName, lam, argsIdx + i) + Warning.WrongSelfParameterPos(funName, lam, argsIdx + i) ) } (genSyntheticSelf() :: acc, true) @@ -200,14 +209,14 @@ case object GenerateMethodBodies extends IRPass { lam.copy( arguments = args.reverse ) - case _: IR.Foreign.Definition => + case _: Foreign.Definition => val args = if (argsIdx == 0) genSyntheticSelf() :: lam.arguments else lam.arguments lam.copy( arguments = args ) - case body: IR.Function.Lambda => + case body: Function.Lambda => if (replace) { lam.copy( body = insertOrReplaceSelfInJSFunction( @@ -231,10 +240,10 @@ case object GenerateMethodBodies extends IRPass { * @return `expr` converted to a function taking the `self` argument */ def processBodyExpression( - expr: IR.Expression, - funName: IR.Name - ): IR.Expression = { - IR.Function.Lambda( + expr: Expression, + funName: Name + ): Expression = { + Function.Lambda( arguments = if (funName.name == MAIN_FUNCTION_NAME) Nil else genSyntheticSelf() :: Nil, @@ -247,9 +256,9 @@ case object GenerateMethodBodies extends IRPass { * * @return the `self` argument */ - def genSyntheticSelf(): IR.DefinitionArgument.Specified = { - IR.DefinitionArgument.Specified( - IR.Name.Self(None, synthetic = true), + def genSyntheticSelf(): DefinitionArgument.Specified = { + DefinitionArgument.Specified( + Name.Self(None, synthetic = true), None, defaultValue = None, suspended = false, @@ -269,9 +278,9 @@ case object GenerateMethodBodies extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir /** Collects the argument list of a chain of function definitions. * @@ -280,16 +289,16 @@ case object GenerateMethodBodies extends IRPass { * @return the list of arguments for `function` */ private def collectChainedFunctionArgs( - function: IR.Function, + function: Function, idx: Int - ): List[(IR.DefinitionArgument, Int)] = { + ): List[(DefinitionArgument, Int)] = { val argsWithIdx = function.arguments.foldLeft( - (idx, Nil: List[(IR.DefinitionArgument, Int)]) + (idx, Nil: List[(DefinitionArgument, Int)]) ) { case ((i, acc), arg) => (i + 1, (arg, i) :: acc) } val bodyArgs = function.body match { - case f: IR.Function => collectChainedFunctionArgs(f, argsWithIdx._1) - case _ => List() + case f: Function => collectChainedFunctionArgs(f, argsWithIdx._1) + case _ => List() } argsWithIdx._2 ::: bodyArgs @@ -297,17 +306,17 @@ case object GenerateMethodBodies extends IRPass { @tailrec private def findForeignDefinition( - body: IR.Expression, + body: Expression, lang: Option[ForeignLanguage] - ): Option[IR.Foreign.Definition] = { + ): Option[Foreign.Definition] = { body match { - case foreignDef: IR.Foreign.Definition => + case foreignDef: Foreign.Definition => lang match { case None => Some(foreignDef) case Some(l) => Option.when(l == foreignDef.lang)(foreignDef) } - case fun: IR.Function.Lambda => findForeignDefinition(fun.body, lang) - case _ => None + case fun: Function.Lambda => findForeignDefinition(fun.body, lang) + case _ => None } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/Imports.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/Imports.scala index 22b26c0539b2..7533fb3bc540 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/Imports.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/Imports.scala @@ -1,7 +1,10 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.{Expression, Module, Name} +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.module.scope.Export import org.enso.compiler.pass.IRPass /** Desugars shorthand syntaxes in import and export statements. @@ -21,7 +24,7 @@ case object Imports extends IRPass { override val invalidatedPasses: Seq[IRPass] = Seq() val mainModuleName = - IR.Name.Literal( + Name.Literal( "Main", isMethod = false, location = None @@ -37,11 +40,11 @@ case object Imports extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val newImports = ir.imports.map { - case i: IR.Module.Scope.Import.Module => + case i: Import.Module => desugarCurrentProjectAlias(i.name, moduleContext) .map { newName => val parts = newName.parts @@ -51,21 +54,21 @@ case object Imports extends IRPass { rename = computeRename( i.rename, i.onlyNames.nonEmpty || i.isAll, - parts(1).asInstanceOf[IR.Name.Literal] + parts(1).asInstanceOf[Name.Literal] ) ) } else { i.copy(name = newName) } } .getOrElse( - IR.Error.ImportExport( + errors.ImportExport( i, - IR.Error.ImportExport.ProjectKeywordUsedButNotInProject("import") + errors.ImportExport.ProjectKeywordUsedButNotInProject("import") ) ) case other => other } val newExports = ir.exports.map { - case ex: IR.Module.Scope.Export.Module => + case ex: Export.Module => desugarCurrentProjectAlias(ex.name, moduleContext) .map { newName => val parts = newName.parts @@ -75,15 +78,15 @@ case object Imports extends IRPass { rename = computeRename( ex.rename, ex.onlyNames.nonEmpty || ex.isAll, - parts(1).asInstanceOf[IR.Name.Literal] + parts(1).asInstanceOf[Name.Literal] ) ) } else { ex.copy(name = newName) } } .getOrElse( - IR.Error.ImportExport( + errors.ImportExport( ex, - IR.Error.ImportExport.ProjectKeywordUsedButNotInProject("export") + errors.ImportExport.ProjectKeywordUsedButNotInProject("export") ) ) case other => other @@ -101,34 +104,34 @@ case object Imports extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir private def computeRename( - originalRename: Option[IR.Name.Literal], + originalRename: Option[Name.Literal], onlyNamesOrAll: Boolean, - qualName: IR.Name.Literal - ): Option[IR.Name.Literal] = + qualName: Name.Literal + ): Option[Name.Literal] = originalRename.orElse(Option.unless(onlyNamesOrAll)(qualName)) val currentProjectAlias = "project" private def desugarCurrentProjectAlias( - name: IR.Name.Qualified, + name: Name.Qualified, context: ModuleContext - ): Option[IR.Name.Qualified] = { + ): Option[Name.Qualified] = { name.parts match { case head :: _ if head.name == currentProjectAlias => val pkg = Option(context.getPackage()) pkg.map { pkg => - val namespace = IR.Name.Literal( + val namespace = Name.Literal( pkg.namespace, isMethod = false, location = None ) val pkgName = - IR.Name.Literal( + Name.Literal( pkg.normalizedName, isMethod = false, location = None 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 c366bf54a229..b82fe58f356f 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 @@ -2,7 +2,17 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Module, + Name, + Type +} import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.{Application, Case, Operator} import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ AliasAnalysis, @@ -62,11 +72,11 @@ case object LambdaShorthandToLambda extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val new_bindings = ir.bindings.map { - case asc: IR.Type.Ascription => asc + case asc: Type.Ascription => asc case a => a.mapExpressions( runExpression( @@ -91,9 +101,9 @@ case object LambdaShorthandToLambda extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( "Desugaring underscore arguments to lambdas requires a fresh name " + @@ -113,14 +123,14 @@ case object LambdaShorthandToLambda extends IRPass { * @return `ir`, with any lambda shorthand arguments desugared */ def desugarExpression( - ir: IR.Expression, + ir: Expression, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { ir.transformExpressions { - case asc: IR.Type.Ascription => asc - case app: IR.Application => desugarApplication(app, freshNameSupply) - case caseExpr: IR.Case.Expr => desugarCaseExpr(caseExpr, freshNameSupply) - case name: IR.Name => desugarName(name, freshNameSupply) + case asc: Type.Ascription => asc + case app: Application => desugarApplication(app, freshNameSupply) + case caseExpr: Case.Expr => desugarCaseExpr(caseExpr, freshNameSupply) + case name: Name => desugarName(name, freshNameSupply) } } @@ -131,15 +141,15 @@ case object LambdaShorthandToLambda extends IRPass { * @param supply the compiler's fresh name supply * @return `name`, desugared where necessary */ - def desugarName(name: IR.Name, supply: FreshNameSupply): IR.Expression = { + def desugarName(name: Name, supply: FreshNameSupply): Expression = { name match { - case blank: IR.Name.Blank => + case blank: Name.Blank => val newName = supply.newName() - IR.Function.Lambda( + Function.Lambda( List( - IR.DefinitionArgument.Specified( - name = IR.Name.Literal( + DefinitionArgument.Specified( + name = Name.Literal( newName.name, isMethod = false, None @@ -164,11 +174,11 @@ case object LambdaShorthandToLambda extends IRPass { * @return `application`, with any lambda shorthand arguments desugared */ def desugarApplication( - application: IR.Application, + application: Application, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { application match { - case p @ IR.Application.Prefix(fn, args, _, _, _, _) => + case p @ Application.Prefix(fn, args, _, _, _, _) => // Determine which arguments are lambda shorthand val argIsUnderscore = determineLambdaShorthand(args) @@ -177,7 +187,7 @@ case object LambdaShorthandToLambda extends IRPass { args .zip(argIsUnderscore) .map(updateShorthandArg(_, freshNameSupply)) - .map { case s @ IR.CallArgument.Specified(_, value, _, _, _) => + .map { case s @ CallArgument.Specified(_, value, _, _, _) => s.copy(value = desugarExpression(value, freshNameSupply)) } @@ -190,7 +200,7 @@ case object LambdaShorthandToLambda extends IRPass { } // Determine whether or not the function itself is shorthand - val functionIsShorthand = fn.isInstanceOf[IR.Name.Blank] + val functionIsShorthand = fn.isInstanceOf[Name.Blank] val (updatedFn, updatedName) = if (functionIsShorthand) { val newFn = freshNameSupply .newName() @@ -214,16 +224,16 @@ case object LambdaShorthandToLambda extends IRPass { // 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) + actualDefArgs.foldRight(processedApp: Expression)((arg, body) => + Function.Lambda(List(arg), body, None) ) // If the function is shorthand, do the same val resultExpr = if (functionIsShorthand) { - IR.Function.Lambda( + Function.Lambda( List( - IR.DefinitionArgument.Specified( - IR.Name + DefinitionArgument.Specified( + Name .Literal( updatedName.get, isMethod = false, @@ -241,15 +251,15 @@ case object LambdaShorthandToLambda extends IRPass { } else appResult resultExpr match { - case lam: IR.Function.Lambda => lam.copy(location = p.location) - case result => result + case lam: Function.Lambda => lam.copy(location = p.location) + case result => result } - case f @ IR.Application.Force(tgt, _, _, _) => + case f @ Application.Force(tgt, _, _, _) => f.copy(target = desugarExpression(tgt, freshNameSupply)) - case vector @ IR.Application.Literal.Sequence(items, _, _, _) => - var bindings: List[IR.Name] = List() + case vector @ Application.Sequence(items, _, _, _) => + var bindings: List[Name] = List() val newItems = items.map { - case blank: IR.Name.Blank => + case blank: Name.Blank => val name = freshNameSupply .newName() .copy( @@ -263,19 +273,19 @@ case object LambdaShorthandToLambda extends IRPass { } val newVec = vector.copy(newItems) val locWithoutId = newVec.location.map(_.copy(id = None)) - bindings.foldLeft(newVec: IR.Expression) { (body, bindingName) => - val defArg = IR.DefinitionArgument.Specified( + bindings.foldLeft(newVec: Expression) { (body, bindingName) => + val defArg = DefinitionArgument.Specified( bindingName, ascribedType = None, defaultValue = None, suspended = false, location = None ) - IR.Function.Lambda(List(defArg), body, locWithoutId) + Function.Lambda(List(defArg), body, locWithoutId) } - case tSet @ IR.Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => tSet.copy(expression = expr.map(desugarExpression(_, freshNameSupply))) - case _: IR.Application.Operator => + case _: Operator => throw new CompilerError( "Operators should be desugared by the point of underscore " + "to lambda conversion." @@ -290,11 +300,11 @@ case object LambdaShorthandToLambda extends IRPass { * @return a list containing `true` for a given position if the arg in that * position is lambda shorthand, otherwise `false` */ - def determineLambdaShorthand(args: List[IR.CallArgument]): List[Boolean] = { - args.map { case IR.CallArgument.Specified(_, value, _, _, _) => + def determineLambdaShorthand(args: List[CallArgument]): List[Boolean] = { + args.map { case CallArgument.Specified(_, value, _, _, _) => value match { - case _: IR.Name.Blank => true - case _ => false + case _: Name.Blank => true + case _ => false } } } @@ -308,14 +318,14 @@ case object LambdaShorthandToLambda extends IRPass { * a given position is shorthand, otherwise [[None]]. */ def updateShorthandArg( - argAndIsShorthand: (IR.CallArgument, Boolean), + argAndIsShorthand: (CallArgument, Boolean), freshNameSupply: FreshNameSupply - ): IR.CallArgument = { + ): CallArgument = { val arg = argAndIsShorthand._1 val isShorthand = argAndIsShorthand._2 arg match { - case s @ IR.CallArgument.Specified(_, value, _, _, _) => + case s @ CallArgument.Specified(_, value, _, _, _) => if (isShorthand) { val newName = freshNameSupply .newName() @@ -339,22 +349,22 @@ case object LambdaShorthandToLambda extends IRPass { * otherwise [[None]] */ def generateDefinitionArg( - arg: IR.CallArgument, + arg: CallArgument, isShorthand: Boolean - ): Option[IR.DefinitionArgument] = { + ): Option[DefinitionArgument] = { if (isShorthand) { arg match { - case IR.CallArgument.Specified(_, value, _, passData, diagnostics) => - // Note [Safe Casting to IR.Name.Literal] + case CallArgument.Specified(_, value, _, passData, diagnostics) => + // Note [Safe Casting to Name.Literal] val defArgName = - IR.Name.Literal( - value.asInstanceOf[IR.Name.Literal].name, + Name.Literal( + value.asInstanceOf[Name.Literal].name, isMethod = false, None ) Some( - IR.DefinitionArgument.Specified( + DefinitionArgument.Specified( defArgName, None, None, @@ -368,11 +378,11 @@ case object LambdaShorthandToLambda extends IRPass { } else None } - /* Note [Safe Casting to IR.Name.Literal] + /* Note [Safe Casting to Name.Literal] * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * This cast is entirely safe here as, by construction in * `updateShorthandArg`, any arg for which `isShorthand` is true has its - * value as an `IR.Name.Literal`. + * value as an `Name.Literal`. */ /** Performs desugaring of lambda shorthand arguments in a case expression. @@ -385,15 +395,15 @@ case object LambdaShorthandToLambda extends IRPass { * @return `caseExpr`, with any lambda shorthand desugared */ def desugarCaseExpr( - caseExpr: IR.Case.Expr, + caseExpr: Case.Expr, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { val newBranches = caseExpr.branches.map( _.mapExpressions(expr => desugarExpression(expr, freshNameSupply)) ) caseExpr.scrutinee match { - case IR.Name.Blank(loc, passData, diagnostics) => + case Name.Blank(loc, passData, diagnostics) => val scrutineeName = freshNameSupply .newName() @@ -403,7 +413,7 @@ case object LambdaShorthandToLambda extends IRPass { diagnostics = diagnostics ) - val lambdaArg = IR.DefinitionArgument.Specified( + val lambdaArg = DefinitionArgument.Specified( scrutineeName.copy(id = IR.randomId), None, None, @@ -416,7 +426,7 @@ case object LambdaShorthandToLambda extends IRPass { branches = newBranches ) - IR.Function.Lambda( + Function.Lambda( List(lambdaArg), newCaseExpr, caseExpr.location, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/NestedPatternMatch.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/NestedPatternMatch.scala index aeda8357d262..12d69e35b103 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/NestedPatternMatch.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/NestedPatternMatch.scala @@ -1,8 +1,13 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{ + Expression, + IdentifiedLocation, + Module, + Pattern +} +import org.enso.compiler.core.ir.expression.{errors, Case} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -91,9 +96,9 @@ case object NestedPatternMatch extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, @unused moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val freshNameSupply = moduleContext.freshNameSupply.getOrElse( throw new CompilerError( "A fresh name supply is required for nested case desugaring." @@ -112,9 +117,9 @@ case object NestedPatternMatch extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, @unused inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( "A fresh name supply is required for inline nested case desugaring." @@ -135,10 +140,10 @@ case object NestedPatternMatch extends IRPass { * @return `expr`, with any nested pattern matches desugared */ def desugarExpression( - expr: IR.Expression, + expr: Expression, freshNameSupply: FreshNameSupply - ): IR.Expression = { - expr.transformExpressions { case cse: IR.Case => + ): Expression = { + expr.transformExpressions { case cse: Case => desugarCase(cse, freshNameSupply) } } @@ -150,15 +155,15 @@ case object NestedPatternMatch extends IRPass { * @return `expr`, with any nested patterns desugared */ def desugarCase( - expr: IR.Case, + expr: Case, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { expr match { - case expr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => val scrutineeBindingName = freshNameSupply.newName() val scrutineeExpression = desugarExpression(scrutinee, freshNameSupply) val scrutineeBinding = - IR.Expression.Binding(scrutineeBindingName, scrutineeExpression, None) + Expression.Binding(scrutineeBindingName, scrutineeExpression, None) val caseExprScrutinee = scrutineeBindingName.duplicate() @@ -175,8 +180,8 @@ case object NestedPatternMatch extends IRPass { branches = processedBranches ) - IR.Expression.Block(List(scrutineeBinding), desugaredCaseExpr, None) - case _: IR.Case.Branch => + Expression.Block(List(scrutineeBinding), desugaredCaseExpr, None) + case _: Case.Branch => throw new CompilerError( "Unexpected case branch during case desugaring." ) @@ -193,10 +198,10 @@ case object NestedPatternMatch extends IRPass { */ @scala.annotation.tailrec def desugarCaseBranch( - branch: IR.Case.Branch, - topBranchLocation: Option[IR.IdentifiedLocation], + branch: Case.Branch, + topBranchLocation: Option[IdentifiedLocation], freshNameSupply: FreshNameSupply - ): IR.Case.Branch = { + ): Case.Branch = { if (containsNestedPatterns(branch.pattern)) { branch.pattern match { case cons @ Pattern.Constructor(_, fields, _, _, _) => @@ -225,7 +230,7 @@ case object NestedPatternMatch extends IRPass { ) val newPattern1 = newPattern.duplicate() - val partDesugaredBranch = IR.Case.Branch( + val partDesugaredBranch = Case.Branch( pattern = newPattern1, expression = newExpression.duplicate(), terminalBranch = false, @@ -253,7 +258,7 @@ case object NestedPatternMatch extends IRPass { throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) - case _: IR.Error.Pattern => + case _: errors.Pattern => throw new CompilerError( "Error patterns cannot be nested. This should be unreachable." ) @@ -291,20 +296,20 @@ case object NestedPatternMatch extends IRPass { */ def generateNestedCase( pattern: Pattern, - nestedScrutinee: IR.Expression, - currentBranchExpr: IR.Expression - ): IR.Expression = { + nestedScrutinee: Expression, + currentBranchExpr: Expression + ): Expression = { val patternDuplicate = pattern.duplicate() val finalTest = containsNestedPatterns(patternDuplicate) val patternBranch = - IR.Case.Branch( + Case.Branch( patternDuplicate, currentBranchExpr.duplicate(), terminalBranch = !finalTest, location = None ) - IR.Case.Expr( + Case.Expr( nestedScrutinee.duplicate(), List(patternBranch), isNested = true, @@ -326,15 +331,15 @@ case object NestedPatternMatch extends IRPass { case _: Pattern.Name => false case _: Pattern.Type => true case _: Pattern.Literal => true - case _: IR.Error.Pattern => false + case _: errors.Pattern => false case _: Pattern.Documentation => throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) } - case _: Pattern.Literal => false - case _: Pattern.Type => false - case _: IR.Error.Pattern => false + case _: Pattern.Literal => false + case _: Pattern.Type => false + case _: errors.Pattern => false case _: Pattern.Documentation => throw new CompilerError( "Branch documentation should be desugared at an earlier stage." @@ -353,7 +358,7 @@ case object NestedPatternMatch extends IRPass { case _: Pattern.Type => true case _: Pattern.Constructor => true case _: Pattern.Literal => true - case _: IR.Error.Pattern => false + case _: errors.Pattern => false case _: Pattern.Documentation => throw new CompilerError( "Branch documentation should be desugared at an earlier stage." @@ -371,7 +376,7 @@ case object NestedPatternMatch extends IRPass { case _: Pattern.Constructor => false case _: Pattern.Literal => false case _: Pattern.Type => false - case _: IR.Error.Pattern => true + case _: errors.Pattern => true case _: Pattern.Documentation => throw new CompilerError( "Branch documentation should be desugared at an earlier stage." diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/OperatorToFunction.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/OperatorToFunction.scala index ea49d2dd7047..c7f4cf0d34d5 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/OperatorToFunction.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/OperatorToFunction.scala @@ -1,7 +1,8 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.expression.{Application, Operator} +import org.enso.compiler.core.ir.{Expression, Module, Type} import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ AliasAnalysis, @@ -40,9 +41,9 @@ case object OperatorToFunction extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val new_bindings = ir.bindings.map { a => a.mapExpressions( runExpression( @@ -66,14 +67,14 @@ case object OperatorToFunction extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = + ): Expression = ir.transformExpressions { - case asc: IR.Type.Ascription => + case asc: Type.Ascription => asc.copy(typed = runExpression(asc.typed, inlineContext)) - case IR.Application.Operator.Binary(l, op, r, loc, passData, diag) => - IR.Application.Prefix( + case Operator.Binary(l, op, r, loc, passData, diag) => + Application.Prefix( op, List( l.mapExpressions(runExpression(_, inlineContext)), diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/SectionsToBinOp.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/SectionsToBinOp.scala index f7dadb8aaa82..56a17a779a8d 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/SectionsToBinOp.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/desugar/SectionsToBinOp.scala @@ -1,9 +1,16 @@ package org.enso.compiler.pass.desugar import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Application.Operator.Section +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Module, + Name +} import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.{Application, Section} import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse._ import org.enso.compiler.pass.lint.UnusedBindings @@ -41,9 +48,9 @@ case object SectionsToBinOp extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.mapExpressions( runExpression( _, @@ -64,16 +71,16 @@ case object SectionsToBinOp extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( "A fresh name supply is required for sections desugaring." ) ) - ir.transformExpressions { case sec: IR.Application.Operator.Section => + ir.transformExpressions { case sec: Section => desugarSections(sec, freshNameSupply) } } @@ -90,15 +97,15 @@ case object SectionsToBinOp extends IRPass { */ //noinspection DuplicatedCode def desugarSections( - section: IR.Application.Operator.Section, + section: Section, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { section match { case Section.Left(arg, op, loc, passData, diagnostics) => val rightArgName = freshNameSupply.newName() val rightCallArg = - IR.CallArgument.Specified(None, rightArgName, None) - val rightDefArg = IR.DefinitionArgument.Specified( + CallArgument.Specified(None, rightArgName, None) + val rightDefArg = DefinitionArgument.Specified( rightArgName.duplicate(), None, None, @@ -106,18 +113,18 @@ case object SectionsToBinOp extends IRPass { None ) - if (arg.value.isInstanceOf[IR.Name.Blank]) { + if (arg.value.isInstanceOf[Name.Blank]) { val leftArgName = freshNameSupply.newName() val leftCallArg = - IR.CallArgument.Specified(None, leftArgName, None) - val leftDefArg = IR.DefinitionArgument.Specified( + CallArgument.Specified(None, leftArgName, None) + val leftDefArg = DefinitionArgument.Specified( leftArgName.duplicate(), None, None, suspended = false, None ) - val opCall = IR.Application.Prefix( + val opCall = Application.Prefix( function = op, arguments = List(leftCallArg, rightCallArg), hasDefaultsSuspended = false, @@ -126,20 +133,20 @@ case object SectionsToBinOp extends IRPass { diagnostics ) - val rightLam = IR.Function.Lambda( + val rightLam = Function.Lambda( List(rightDefArg), opCall, None ) - IR.Function.Lambda( + Function.Lambda( List(leftDefArg), rightLam, loc ) } else { - val opCall = IR.Application.Prefix( + val opCall = Application.Prefix( function = op, arguments = List(arg, rightCallArg), hasDefaultsSuspended = false, @@ -148,7 +155,7 @@ case object SectionsToBinOp extends IRPass { diagnostics ) - IR.Function.Lambda( + Function.Lambda( List(rightDefArg), opCall, loc @@ -157,8 +164,8 @@ case object SectionsToBinOp extends IRPass { case Section.Sides(op, loc, passData, diagnostics) => val leftArgName = freshNameSupply.newName() val leftCallArg = - IR.CallArgument.Specified(None, leftArgName, None) - val leftDefArg = IR.DefinitionArgument.Specified( + CallArgument.Specified(None, leftArgName, None) + val leftDefArg = DefinitionArgument.Specified( leftArgName.duplicate(), None, None, @@ -168,8 +175,8 @@ case object SectionsToBinOp extends IRPass { val rightArgName = freshNameSupply.newName() val rightCallArg = - IR.CallArgument.Specified(None, rightArgName, None) - val rightDefArg = IR.DefinitionArgument.Specified( + CallArgument.Specified(None, rightArgName, None) + val rightDefArg = DefinitionArgument.Specified( rightArgName.duplicate(), None, None, @@ -177,7 +184,7 @@ case object SectionsToBinOp extends IRPass { None ) - val opCall = IR.Application.Prefix( + val opCall = Application.Prefix( function = op, arguments = List(leftCallArg, rightCallArg), hasDefaultsSuspended = false, @@ -186,13 +193,13 @@ case object SectionsToBinOp extends IRPass { diagnostics ) - val rightLambda = IR.Function.Lambda( + val rightLambda = Function.Lambda( List(rightDefArg), opCall, None ) - IR.Function.Lambda( + Function.Lambda( List(leftDefArg), rightLambda, loc @@ -220,9 +227,9 @@ case object SectionsToBinOp extends IRPass { case Section.Right(op, arg, loc, passData, diagnostics) => val leftArgName = freshNameSupply.newName() val leftCallArg = - IR.CallArgument.Specified(None, leftArgName, None) + CallArgument.Specified(None, leftArgName, None) val leftDefArg = - IR.DefinitionArgument.Specified( + DefinitionArgument.Specified( leftArgName.duplicate(), None, None, @@ -230,12 +237,12 @@ case object SectionsToBinOp extends IRPass { None ) - if (arg.value.isInstanceOf[IR.Name.Blank]) { + if (arg.value.isInstanceOf[Name.Blank]) { // Note [Blanks in Sections] val rightArgName = freshNameSupply.newName() val rightCallArg = - IR.CallArgument.Specified(None, rightArgName, None) - val rightDefArg = IR.DefinitionArgument.Specified( + CallArgument.Specified(None, rightArgName, None) + val rightDefArg = DefinitionArgument.Specified( rightArgName.duplicate(), None, None, @@ -243,7 +250,7 @@ case object SectionsToBinOp extends IRPass { None ) - val opCall = IR.Application.Prefix( + val opCall = Application.Prefix( function = op, arguments = List(leftCallArg, rightCallArg), hasDefaultsSuspended = false, @@ -252,19 +259,19 @@ case object SectionsToBinOp extends IRPass { diagnostics ) - val leftLam = IR.Function.Lambda( + val leftLam = Function.Lambda( List(leftDefArg), opCall, None ) - IR.Function.Lambda( + Function.Lambda( List(rightDefArg), leftLam, loc ) } else { - val opCall = IR.Application.Prefix( + val opCall = Application.Prefix( function = op, arguments = List(leftCallArg, arg), hasDefaultsSuspended = false, @@ -273,7 +280,7 @@ case object SectionsToBinOp extends IRPass { diagnostics ) - IR.Function.Lambda( + Function.Lambda( List(leftDefArg), opCall, loc diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ModuleNameConflicts.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ModuleNameConflicts.scala index b1103d3234c8..c2b4149f35b1 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ModuleNameConflicts.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ModuleNameConflicts.scala @@ -1,7 +1,10 @@ package org.enso.compiler.pass.lint import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.expression.warnings +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.Export import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.ComplexType @@ -27,12 +30,12 @@ case object ModuleNameConflicts extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { if (moduleContext.compilerConfig.warningsEnabled) { val syntheticExports = ir.exports.flatMap { - case mod @ IR.Module.Scope.Export.Module( + case mod @ Export.Module( _, _, false, @@ -44,8 +47,7 @@ case object ModuleNameConflicts extends IRPass { _ ) => Some(mod) - case mod: IR.Module.Scope.Export.Module - if moduleContext.isSynthetic() => + case mod: Export.Module if moduleContext.isSynthetic() => Some(mod) case _ => None @@ -66,9 +68,9 @@ case object ModuleNameConflicts extends IRPass { * @return unchanged ir. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = + ): Expression = ir // === Pass Internals ======================================================= @@ -80,18 +82,17 @@ case object ModuleNameConflicts extends IRPass { * @return `ir`, with any doc comments associated with nodes as metadata */ private def lintBinding( - binding: IR.Module.Scope.Definition, - syntheticExports: List[IR.Module.Scope.Export.Module] - ): IR.Module.Scope.Definition = { + binding: Definition, + syntheticExports: List[Export.Module] + ): Definition = { val exports = syntheticExports.map(e => (e.name.parts.last.name, e)).toMap binding match { - case cons: IR.Module.Scope.Definition.Type - if exports.contains(cons.name.name) => + case cons: Definition.Type if exports.contains(cons.name.name) => val atomName = cons.name.name val `export` = exports(atomName) binding.addDiagnostic( - IR.Warning.Shadowed + warnings.Shadowed .SyntheticModule(atomName, `export`.name, `export`, cons.location) ) case _ => diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/NoSelfInStatic.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/NoSelfInStatic.scala index 3288ff9c9ccf..e1b6ee652749 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/NoSelfInStatic.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/NoSelfInStatic.scala @@ -1,7 +1,16 @@ package org.enso.compiler.pass.lint import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.{CompilerError, IR} +import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.GenerateMethodBodies @@ -20,17 +29,16 @@ object NoSelfInStatic extends IRPass { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.copy( bindings = ir.bindings.map { - case method: IR.Module.Scope.Definition.Method.Explicit - if isStaticMethod(method) => + case method: definition.Method.Explicit if isStaticMethod(method) => method.copy( body = method.body.transformExpressions(transformSelfToError) ) - case method: IR.Module.Scope.Definition.Method.Binding => + case method: definition.Method.Binding => throw new CompilerError( s"unexpected Method.Binding $method present in pass NoSelfInStatic" ) @@ -39,12 +47,11 @@ object NoSelfInStatic extends IRPass { ) } - private def transformSelfToError - : PartialFunction[IR.Expression, IR.Expression] = { - case IR.Name.Self(location, false, passData, diagnostics) => - IR.Error.Syntax( + private def transformSelfToError: PartialFunction[Expression, Expression] = { + case Name.Self(location, false, passData, diagnostics) => + errors.Syntax( location.get, - IR.Error.Syntax.InvalidSelfArgUsage, + errors.Syntax.InvalidSelfArgUsage, passData, diagnostics ) @@ -56,14 +63,14 @@ object NoSelfInStatic extends IRPass { * @return */ private def isStaticMethod( - method: IR.Module.Scope.Definition.Method + method: definition.Method ): Boolean = { def findSelfArgument( - arguments: List[IR.DefinitionArgument] - ): Option[IR.DefinitionArgument] = { + arguments: List[DefinitionArgument] + ): Option[DefinitionArgument] = { arguments.collectFirst { - case arg @ IR.DefinitionArgument.Specified( - IR.Name.Self(_, false, _, _), + case arg @ DefinitionArgument.Specified( + Name.Self(_, false, _, _), _, _, _, @@ -78,7 +85,7 @@ object NoSelfInStatic extends IRPass { method.typeName match { case Some(_) => method.body match { - case IR.Function.Lambda( + case Function.Lambda( arguments, _, _, @@ -97,7 +104,7 @@ object NoSelfInStatic extends IRPass { } override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ShadowedPatternFields.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ShadowedPatternFields.scala index f2016dd1c824..93b2de36e897 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ShadowedPatternFields.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/ShadowedPatternFields.scala @@ -2,7 +2,8 @@ package org.enso.compiler.pass.lint import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{Expression, Module, Name, Pattern} +import org.enso.compiler.core.ir.expression.{errors, warnings, Case} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -53,9 +54,9 @@ case object ShadowedPatternFields extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, @unused moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.mapExpressions(lintExpression) } @@ -68,9 +69,9 @@ case object ShadowedPatternFields extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, @unused inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { ir.transformExpressions { case x => lintExpression(x) } @@ -84,9 +85,9 @@ case object ShadowedPatternFields extends IRPass { * @return `expression`, with warnings for any shadowed pattern variables */ def lintExpression( - expression: IR.Expression - ): IR.Expression = { - expression.transformExpressions { case cse: IR.Case => + expression: Expression + ): Expression = { + expression.transformExpressions { case cse: Case => lintCase(cse) } } @@ -96,14 +97,14 @@ case object ShadowedPatternFields extends IRPass { * @param cse the expression to lint * @return `cse`, with warnings for any shadowed pattern variables */ - def lintCase(cse: IR.Case): IR.Case = { + def lintCase(cse: Case): Case = { cse match { - case expr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => expr.copy( scrutinee = lintExpression(scrutinee), branches = branches.map(lintCaseBranch) ) - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("Unexpected case branch.") } } @@ -114,8 +115,8 @@ case object ShadowedPatternFields extends IRPass { * @return `branch`, with warnings for any shadowed pattern variables */ def lintCaseBranch( - branch: IR.Case.Branch - ): IR.Case.Branch = { + branch: Case.Branch + ): Case.Branch = { branch.copy( pattern = lintPattern(branch.pattern), expression = lintExpression(branch.expression) @@ -139,16 +140,16 @@ case object ShadowedPatternFields extends IRPass { pattern match { case named @ Pattern.Name(name, location, _, _) => if (seenNames.contains(name.name)) { - val warning = IR.Warning.Shadowed + val warning = warnings.Shadowed .PatternBinding(name.name, lastSeen(name.name), location) lastSeen(name.name) = named named .copy( - name = IR.Name.Blank(location = name.location) + name = Name.Blank(location = name.location) ) .addDiagnostic(warning) - } else if (!name.isInstanceOf[IR.Name.Blank]) { + } else if (!name.isInstanceOf[Name.Blank]) { lastSeen(name.name) = named seenNames += name.name named @@ -165,16 +166,16 @@ case object ShadowedPatternFields extends IRPass { literal case typed @ Pattern.Type(name, _, location, _, _) => if (seenNames.contains(name.name)) { - val warning = IR.Warning.Shadowed + val warning = warnings.Shadowed .PatternBinding(name.name, lastSeen(name.name), location) lastSeen(name.name) = typed typed .copy( - name = IR.Name.Blank(location = name.location) + name = Name.Blank(location = name.location) ) .addDiagnostic(warning) - } else if (!name.isInstanceOf[IR.Name.Blank]) { + } else if (!name.isInstanceOf[Name.Blank]) { lastSeen(name.name) = typed seenNames += name.name typed @@ -185,7 +186,7 @@ case object ShadowedPatternFields extends IRPass { throw new CompilerError( "Branch documentation should be desugared at an earlier stage." ) - case err: IR.Error.Pattern => err + case err: errors.Pattern => err } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/UnusedBindings.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/UnusedBindings.scala index c36a26dd0a7b..b6fb0e8b517d 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/UnusedBindings.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/lint/UnusedBindings.scala @@ -1,8 +1,17 @@ package org.enso.compiler.pass.lint import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.{Case, Pattern} +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Literal, + Module, + Name, + Pattern, + Warning +} +import org.enso.compiler.core.ir.expression.{errors, warnings, Case, Foreign} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.AliasAnalysis @@ -42,9 +51,9 @@ case object UnusedBindings extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = if (moduleContext.compilerConfig.warningsEnabled) { + ): Module = if (moduleContext.compilerConfig.warningsEnabled) { ir.mapExpressions( runExpression( _, @@ -65,13 +74,13 @@ case object UnusedBindings extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = if (inlineContext.compilerConfig.warningsEnabled) { + ): Expression = if (inlineContext.compilerConfig.warningsEnabled) { ir.transformExpressions { - case binding: IR.Expression.Binding => lintBinding(binding, inlineContext) - case function: IR.Function => lintFunction(function, inlineContext) - case cse: IR.Case => lintCase(cse, inlineContext) + case binding: Expression.Binding => lintBinding(binding, inlineContext) + case function: Function => lintFunction(function, inlineContext) + case cse: Case => lintCase(cse, inlineContext) } } else ir @@ -84,9 +93,9 @@ case object UnusedBindings extends IRPass { * @return `binding`, with any lints attached */ def lintBinding( - binding: IR.Expression.Binding, + binding: Expression.Binding, context: InlineContext - ): IR.Expression.Binding = { + ): Expression.Binding = { val isIgnored = binding .unsafeGetMetadata( IgnoredBindings, @@ -105,7 +114,7 @@ case object UnusedBindings extends IRPass { if (!isIgnored && !isUsed) { binding .copy(expression = runExpression(binding.expression, context)) - .addDiagnostic(IR.Warning.Unused.Binding(binding.name)) + .addDiagnostic(warnings.Unused.Binding(binding.name)) } else { binding.copy( expression = runExpression(binding.expression, context) @@ -120,13 +129,13 @@ case object UnusedBindings extends IRPass { * @return `function`, with any lints attached */ def lintFunction( - function: IR.Function, + function: Function, context: InlineContext - ): IR.Function = { + ): Function = { function match { - case IR.Function.Lambda(_, _: IR.Foreign.Definition, _, _, _, _) => + case Function.Lambda(_, _: Foreign.Definition, _, _, _, _) => function - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => val isBuiltin = isBuiltinMethod(body) val lintedArgs = if (isBuiltin) args @@ -135,11 +144,11 @@ case object UnusedBindings extends IRPass { val lintedBody = if (isBuiltin) body match { - case _: IR.Literal.Text => + case _: Literal.Text => body1 case _ => body1.addDiagnostic( - IR.Warning.WrongBuiltinMethod(body.location) + Warning.WrongBuiltinMethod(body.location) ) } else body1 @@ -148,7 +157,7 @@ case object UnusedBindings extends IRPass { arguments = lintedArgs, body = lintedBody ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during unused bindings linting." ) @@ -162,9 +171,9 @@ case object UnusedBindings extends IRPass { * @return `argument`, with any lints attached */ def lintFunctionArgument( - argument: IR.DefinitionArgument, + argument: DefinitionArgument, context: InlineContext - ): IR.DefinitionArgument = { + ): DefinitionArgument = { val isIgnored = argument .unsafeGetMetadata( IgnoredBindings, @@ -182,8 +191,8 @@ case object UnusedBindings extends IRPass { val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty argument match { - case s @ IR.DefinitionArgument.Specified( - _: IR.Name.Self, + case s @ DefinitionArgument.Specified( + _: Name.Self, _, _, _, @@ -192,11 +201,11 @@ case object UnusedBindings extends IRPass { _ ) => s - case s @ IR.DefinitionArgument.Specified(name, _, default, _, _, _, _) => + case s @ DefinitionArgument.Specified(name, _, default, _, _, _, _) => if (!isIgnored && !isUsed) { s.copy( defaultValue = default.map(runExpression(_, context)) - ).addDiagnostic(IR.Warning.Unused.FunctionArgument(name)) + ).addDiagnostic(warnings.Unused.FunctionArgument(name)) } else s } } @@ -207,7 +216,7 @@ case object UnusedBindings extends IRPass { * @param context the inline context in which linting is taking place * @return `cse`, with any lints attached */ - def lintCase(cse: IR.Case, context: InlineContext): IR.Case = { + def lintCase(cse: Case, context: InlineContext): Case = { cse match { case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => expr.copy( @@ -239,7 +248,7 @@ case object UnusedBindings extends IRPass { * @param pattern the pattern to lint * @return `pattern`, with any lints attached */ - def lintPattern(pattern: IR.Pattern): IR.Pattern = { + def lintPattern(pattern: Pattern): Pattern = { pattern match { case n @ Pattern.Name(name, _, _, _) => val isIgnored = name @@ -259,7 +268,7 @@ case object UnusedBindings extends IRPass { val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty if (!isIgnored && !isUsed) { - n.addDiagnostic(IR.Warning.Unused.PatternBinding(name)) + n.addDiagnostic(warnings.Unused.PatternBinding(name)) } else pattern case cons @ Pattern.Constructor(_, fields, _, _, _) => if (!cons.isDesugared) { @@ -289,11 +298,11 @@ case object UnusedBindings extends IRPass { val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty if (!isIgnored && !isUsed) { - typed.addDiagnostic(IR.Warning.Unused.PatternBinding(name)) + typed.addDiagnostic(warnings.Unused.PatternBinding(name)) } else pattern case literal: Pattern.Literal => literal - case err: IR.Error.Pattern => err + case err: errors.Pattern => err case _: Pattern.Documentation => throw new CompilerError( @@ -307,7 +316,7 @@ case object UnusedBindings extends IRPass { * @param expression the expression to check * @return 'true' if 'expression' has @Builtin_Method annotation, otherwise 'false' */ - private def isBuiltinMethod(expression: IR.Expression): Boolean = { + private def isBuiltinMethod(expression: Expression): Boolean = { expression .getMetadata(ExpressionAnnotations) .exists( 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 index 01fa7bc67516..47835b5806f6 100644 --- 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 @@ -1,9 +1,10 @@ package org.enso.compiler.pass.optimise import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +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._ @@ -49,9 +50,9 @@ case object ApplicationSaturation extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val passConfig = moduleContext.passConfiguration ir.mapExpressions( runExpression( @@ -74,9 +75,9 @@ case object ApplicationSaturation extends IRPass { */ //noinspection DuplicatedCode override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val knownFunctions = inlineContext.passConfiguration .flatMap(configs => configs.get(this)) @@ -86,9 +87,9 @@ case object ApplicationSaturation extends IRPass { .knownFunctions ir.transformExpressions { - case func @ IR.Application.Prefix(fn, args, _, _, _, _) => + case func @ Application.Prefix(fn, args, _, _, _, _) => fn match { - case name: IR.Name => + case name: Name => val aliasInfo = name .unsafeGetMetadata( @@ -114,7 +115,7 @@ case object ApplicationSaturation extends IRPass { func .copy( arguments = args.map( - _.mapExpressions((ir: IR.Expression) => + _.mapExpressions((ir: Expression) => runExpression(ir, inlineContext) ) ) @@ -125,7 +126,7 @@ case object ApplicationSaturation extends IRPass { func .copy( arguments = args.map( - _.mapExpressions((ir: IR.Expression) => + _.mapExpressions((ir: Expression) => runExpression(ir, inlineContext) ) ) @@ -137,7 +138,7 @@ case object ApplicationSaturation extends IRPass { func .copy( arguments = args.map( - _.mapExpressions((ir: IR.Expression) => + _.mapExpressions((ir: Expression) => runExpression(ir, inlineContext) ) ) @@ -150,7 +151,7 @@ case object ApplicationSaturation extends IRPass { func .copy( arguments = args.map( - _.mapExpressions((ir: IR.Expression) => + _.mapExpressions((ir: Expression) => runExpression(ir, inlineContext) ) ) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/LambdaConsolidate.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/LambdaConsolidate.scala index f01bfa15cb63..8b07c4901470 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/LambdaConsolidate.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/LambdaConsolidate.scala @@ -2,7 +2,17 @@ package org.enso.compiler.pass.optimise import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.DefinitionArgument +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Empty, + Expression, + Function, + IdentifiedLocation, + Module, + Name +} +import org.enso.compiler.core.ir.expression.warnings +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -73,9 +83,9 @@ case object LambdaConsolidate extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.mapExpressions( runExpression( _, @@ -96,15 +106,15 @@ case object LambdaConsolidate extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( "A fresh name supply is required for lambda consolidation." ) ) - ir.transformExpressions { case fn: IR.Function => + ir.transformExpressions { case fn: Function => collapseFunction(fn, inlineContext, freshNameSupply) } } @@ -116,15 +126,15 @@ case object LambdaConsolidate extends IRPass { * lambdas collapsed */ def collapseFunction( - function: IR.Function, + function: Function, inlineContext: InlineContext, freshNameSupply: FreshNameSupply - ): IR.Function = { + ): Function = { function match { - case lam @ IR.Function.Lambda(_, body, _, _, _, _) => + case lam @ Function.Lambda(_, body, _, _, _, _) => val chainedLambdas = lam :: gatherChainedLambdas(body) val chainedArgList = - chainedLambdas.foldLeft(List[IR.DefinitionArgument]())( + chainedLambdas.foldLeft(List[DefinitionArgument]())( _ ::: _.arguments ) val lastBody = chainedLambdas.last.body @@ -132,7 +142,7 @@ case object LambdaConsolidate extends IRPass { val shadowedBindingIds = getShadowedBindingIds(chainedArgList) val argIsShadowed = chainedArgList.map { - case spec: IR.DefinitionArgument.Specified => + case spec: DefinitionArgument.Specified => val aliasInfo = spec .unsafeGetMetadata( AliasAnalysis, @@ -159,7 +169,7 @@ case object LambdaConsolidate extends IRPass { val newLocation = chainedLambdas.head.location match { case Some(location) => Some( - IR.IdentifiedLocation( + IdentifiedLocation( Location( location.start, chainedLambdas.last.location.getOrElse(location).location.end @@ -176,7 +186,7 @@ case object LambdaConsolidate extends IRPass { location = newLocation, canBeTCO = chainedLambdas.last.canBeTCO ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during lambda consolidation." ) @@ -194,8 +204,8 @@ case object LambdaConsolidate extends IRPass { * whether or not they are shadowed */ def attachShadowingWarnings( - argsWithShadowed: List[(IR.DefinitionArgument, Boolean)] - ): List[(IR.DefinitionArgument, Boolean)] = { + argsWithShadowed: List[(DefinitionArgument, Boolean)] + ): List[(DefinitionArgument, Boolean)] = { val args = argsWithShadowed.map(_._1) val argsWithIndex = argsWithShadowed.zipWithIndex.map(t => (t._1._1, t._1._2, t._2)) @@ -206,15 +216,15 @@ case object LambdaConsolidate extends IRPass { arg match { case spec @ DefinitionArgument.Specified(argName, _, _, _, _, _, _) => val mShadower = restArgs.collectFirst { - case s @ IR.DefinitionArgument.Specified(sName, _, _, _, _, _, _) + case s @ DefinitionArgument.Specified(sName, _, _, _, _, _, _) if sName.name == argName.name => s } - val shadower: IR = mShadower.getOrElse(IR.Empty(spec.location)) + val shadower: IR = mShadower.getOrElse(Empty(spec.location)) spec.diagnostics.add( - IR.Warning.Shadowed + warnings.Shadowed .FunctionParam(argName.name, shadower, spec.location) ) @@ -232,12 +242,12 @@ case object LambdaConsolidate extends IRPass { * @param body the function body to optimise * @return the directly chained lambdas in `body` */ - def gatherChainedLambdas(body: IR.Expression): List[IR.Function.Lambda] = { + def gatherChainedLambdas(body: Expression): List[Function.Lambda] = { body match { - case IR.Expression.Block(expressions, lam: IR.Function.Lambda, _, _, _, _) + case Expression.Block(expressions, lam: Function.Lambda, _, _, _, _) if expressions.isEmpty => lam :: gatherChainedLambdas(lam.body) - case l @ IR.Function.Lambda(_, body, _, _, _, _) => + case l @ Function.Lambda(_, body, _, _, _, _) => l :: gatherChainedLambdas(body) case _ => List() } @@ -255,11 +265,11 @@ case object LambdaConsolidate extends IRPass { * by the new name */ def replaceUsages( - body: IR.Expression, - defaults: List[Option[IR.Expression]], - argument: IR.DefinitionArgument, + body: Expression, + defaults: List[Option[Expression]], + argument: DefinitionArgument, toReplaceExpressionIds: Set[IR.Identifier] - ): (IR.Expression, List[Option[IR.Expression]]) = { + ): (Expression, List[Option[Expression]]) = { ( replaceInExpression(body, argument, toReplaceExpressionIds), defaults.map( @@ -270,7 +280,7 @@ case object LambdaConsolidate extends IRPass { /** Replaces usages of a name in an expression. * - * As usages of a name can only be an [[IR.Name]], we can safely use the + * As usages of a name can only be an [[Name]], we can safely use the * expression transformation mechanism to do this. * * @param expr the expression to replace usages in @@ -280,11 +290,11 @@ case object LambdaConsolidate extends IRPass { * @return `expr`, with occurrences of the symbol for `argument` replaced */ def replaceInExpression( - expr: IR.Expression, - argument: IR.DefinitionArgument, + expr: Expression, + argument: DefinitionArgument, toReplaceExpressionIds: Set[IR.Identifier] - ): IR.Expression = { - expr.transformExpressions { case name: IR.Name => + ): Expression = { + expr.transformExpressions { case name: Name => replaceInName(name, argument, toReplaceExpressionIds) } } @@ -298,27 +308,27 @@ case object LambdaConsolidate extends IRPass { * @return `name`, with the symbol replaced by `argument.name` */ def replaceInName( - name: IR.Name, - argument: IR.DefinitionArgument, + name: Name, + argument: DefinitionArgument, toReplaceExpressionIds: Set[IR.Identifier] - ): IR.Name = { + ): Name = { if (toReplaceExpressionIds.contains(name.getId)) { name match { - case spec: IR.Name.Literal => + case spec: Name.Literal => spec.copy( name = argument match { - case defSpec: IR.DefinitionArgument.Specified => defSpec.name.name + case defSpec: DefinitionArgument.Specified => defSpec.name.name } ) - case self: IR.Name.Self => self - case selfType: IR.Name.SelfType => selfType - case special: IR.Name.Special => special - case blank: IR.Name.Blank => blank - case ref: IR.Name.MethodReference => ref - case qual: IR.Name.Qualified => qual - case err: IR.Error.Resolution => err - case err: IR.Error.Conversion => err - case annotation: IR.Name.Annotation => annotation + case self: Name.Self => self + case selfType: Name.SelfType => selfType + case special: Name.Special => special + case blank: Name.Blank => blank + case ref: Name.MethodReference => ref + case qual: Name.Qualified => qual + case err: errors.Resolution => err + case err: errors.Conversion => err + case annotation: Name.Annotation => annotation } } else { name @@ -332,10 +342,10 @@ case object LambdaConsolidate extends IRPass { * @return the set of aliasing identifiers shadowed by `args` */ def getShadowedBindingIds( - args: List[IR.DefinitionArgument] + args: List[DefinitionArgument] ): Set[AliasAnalysis.Graph.Id] = { args - .map { case spec: IR.DefinitionArgument.Specified => + .map { case spec: DefinitionArgument.Specified => val aliasInfo = spec .unsafeGetMetadata( @@ -360,10 +370,10 @@ case object LambdaConsolidate extends IRPass { * an empty set represents a non-shadowed argument */ def usageIdsForShadowedArgs( - argsWithShadowed: List[(IR.DefinitionArgument, Boolean)] + argsWithShadowed: List[(DefinitionArgument, Boolean)] ): List[Set[IR.Identifier]] = { argsWithShadowed.map { - case (spec: IR.DefinitionArgument.Specified, isShadowed) => + case (spec: DefinitionArgument.Specified, isShadowed) => val aliasInfo = spec .unsafeGetMetadata( @@ -397,12 +407,12 @@ case object LambdaConsolidate extends IRPass { * @return a set of argument names, with shadowed arguments replaced */ def generateNewNames( - argsWithShadowed: List[(IR.DefinitionArgument, Boolean)], + argsWithShadowed: List[(DefinitionArgument, Boolean)], freshNameSupply: FreshNameSupply - ): List[IR.DefinitionArgument] = { + ): List[DefinitionArgument] = { argsWithShadowed.map { case ( - spec @ IR.DefinitionArgument.Specified(name, _, _, _, _, _, _), + spec @ DefinitionArgument.Specified(name, _, _, _, _, _, _), isShadowed ) => val newName = @@ -430,10 +440,10 @@ case object LambdaConsolidate extends IRPass { * @return `args` and `body`, with any usages of shadowed symbols replaced */ def computeReplacedExpressions( - args: List[IR.DefinitionArgument], - body: IR.Expression, + args: List[DefinitionArgument], + body: Expression, usageIdsForShadowed: List[Set[IR.Identifier]] - ): (List[IR.DefinitionArgument], IR.Expression) = { + ): (List[DefinitionArgument], Expression) = { var newBody = body var newDefaults = args.map(_.defaultValue) @@ -449,7 +459,7 @@ case object LambdaConsolidate extends IRPass { } val processedArgList = args.zip(newDefaults).map { - case (spec: IR.DefinitionArgument.Specified, default) => + case (spec: DefinitionArgument.Specified, default) => spec.copy(defaultValue = default) } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/UnreachableMatchBranches.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/UnreachableMatchBranches.scala index 438ea7d5ae6c..a8dbe1774c5e 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/UnreachableMatchBranches.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/optimise/UnreachableMatchBranches.scala @@ -1,8 +1,13 @@ package org.enso.compiler.pass.optimise import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.{IdentifiedLocation, Pattern} +import org.enso.compiler.core.ir.{ + Expression, + IdentifiedLocation, + Module, + Pattern +} +import org.enso.compiler.core.ir.expression.{errors, warnings, Case} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -20,7 +25,7 @@ import scala.annotation.unused /** This pass discovers and optimised away unreachable case branches. * * It removes these unreachable expressions from the IR, and attaches a - * [[IR.Warning]] diagnostic to the case expression itself. + * [[org.enso.compiler.core.ir.Warning]] diagnostic to the case expression itself. * * Currently, a branch is considered 'unreachable' by this pass if: * @@ -66,9 +71,9 @@ case object UnreachableMatchBranches extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, @unused moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.mapExpressions(optimizeExpression) } @@ -81,9 +86,9 @@ case object UnreachableMatchBranches extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, @unused inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { ir.transformExpressions { case x => optimizeExpression(x) } @@ -97,8 +102,8 @@ case object UnreachableMatchBranches extends IRPass { * @param expression the expression to optimize * @return `expression` with unreachable case branches removed */ - def optimizeExpression(expression: IR.Expression): IR.Expression = { - expression.transformExpressions { case cse: IR.Case => + def optimizeExpression(expression: Expression): Expression = { + expression.transformExpressions { case cse: Case => optimizeCase(cse) } } @@ -112,9 +117,9 @@ case object UnreachableMatchBranches extends IRPass { * @return `cse` with unreachable branches removed */ //noinspection DuplicatedCode - def optimizeCase(cse: IR.Case): IR.Case = { + def optimizeCase(cse: Case): Case = { cse match { - case expr @ IR.Case.Expr(scrutinee, branches, _, _, _, _) => + case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => val reachableNonCatchAllBranches = branches.takeWhile(!isCatchAll(_)) val firstCatchAll = branches.find(isCatchAll) val unreachableBranches = @@ -152,7 +157,7 @@ case object UnreachableMatchBranches extends IRPass { } ) - val diagnostic = IR.Warning.Unreachable.Branches(unreachableLocation) + val diagnostic = warnings.Unreachable.Branches(unreachableLocation) expr .copy( @@ -162,7 +167,7 @@ case object UnreachableMatchBranches extends IRPass { ) .addDiagnostic(diagnostic) } - case _: IR.Case.Branch => + case _: Case.Branch => throw new CompilerError("Unexpected case branch.") } } @@ -172,14 +177,14 @@ case object UnreachableMatchBranches extends IRPass { * @param branch the branch to check * @return `true` if `branch` is catch-all, otherwise `false` */ - def isCatchAll(branch: IR.Case.Branch): Boolean = { + def isCatchAll(branch: Case.Branch): Boolean = { branch.pattern match { case _: Pattern.Name => true case _: Pattern.Constructor => false case _: Pattern.Literal => false case _: Pattern.Type => false case _: Pattern.Documentation => false - case _: IR.Error.Pattern => true + case _: errors.Pattern => true } } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/DocumentationComments.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/DocumentationComments.scala index 1ba169f2eb33..33a9e8a3b7c9 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/DocumentationComments.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/DocumentationComments.scala @@ -2,7 +2,20 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Case.Branch +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Module, + Name, + Pattern, + Type +} +import org.enso.compiler.core.ir.expression.{Case, Comment, Error} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.module.scope.Export +import org.enso.compiler.core.ir.module.scope.Import import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass @@ -39,9 +52,9 @@ case object DocumentationComments extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = resolveModule(ir) + ): Module = resolveModule(ir) /** Collects comments for an expression. * @@ -52,9 +65,9 @@ case object DocumentationComments extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = resolveExpression(ir) + ): Expression = resolveExpression(ir) /** @inheritdoc */ @@ -65,14 +78,14 @@ case object DocumentationComments extends IRPass { * @param ir the IR node to resolve comments in * @return `ir`, with any doc comments associated with nodes as metadata */ - private def resolveExpression(ir: IR.Expression): IR.Expression = + private def resolveExpression(ir: Expression): Expression = ir.transformExpressions({ - case block: IR.Expression.Block => + case block: Expression.Block => val newLines = resolveList(block.expressions :+ block.returnValue) val newExpressions = newLines.init.map(resolveExpression) val newReturn = resolveExpression(newLines.last) block.copy(expressions = newExpressions, returnValue = newReturn) - case caseExpr: IR.Case.Expr => + case caseExpr: Case.Expr => val newScrutinee = resolveExpression(caseExpr.scrutinee) val newBranches = resolveBranches(caseExpr.branches) caseExpr.copy(scrutinee = newScrutinee, branches = newBranches) @@ -85,11 +98,11 @@ case object DocumentationComments extends IRPass { * @return `items`, with any doc comments associated with nodes as metadata */ private def resolveList[T <: IR](items: List[T]): List[T] = { - var lastDoc: Option[IR.Comment.Documentation] = None + var lastDoc: Option[Comment.Documentation] = None items.flatMap { - case annotation: IR.Name.Annotation => + case annotation: Name.Annotation => Some(annotation.asInstanceOf[T]) - case doc: IR.Comment.Documentation => + case doc: Comment.Documentation => lastDoc = Some(doc) None case other => @@ -108,13 +121,13 @@ case object DocumentationComments extends IRPass { * @param items the list of branches * @return `items`, with any doc comments associated with nodes as metadata */ - private def resolveBranches(items: Seq[Branch]): Seq[Branch] = { + private def resolveBranches(items: Seq[Case.Branch]): Seq[Case.Branch] = { var lastDoc: Option[String] = None items.flatMap { - case Branch(IR.Pattern.Documentation(doc, _, _, _), _, _, _, _, _) => + case Case.Branch(Pattern.Documentation(doc, _, _, _), _, _, _, _, _) => lastDoc = Some(doc) None - case branch @ Branch(pattern, expression, _, _, _, _) => + case branch @ Case.Branch(pattern, expression, _, _, _, _) => val resolved = branch.copy( pattern = pattern.mapExpressions(resolveExpression), @@ -135,29 +148,29 @@ case object DocumentationComments extends IRPass { * @return `ir`, with any doc comments associated with nodes as metadata */ private def resolveDefinition( - ir: IR.Module.Scope.Definition - ): IR.Module.Scope.Definition = + ir: Definition + ): Definition = ir match { - case _: IR.Module.Scope.Definition.Method.Conversion => + case _: definition.Method.Conversion => throw new CompilerError( "Conversion methods should not yet be present in the compiler " + "pipeline." ) - case _: IR.Module.Scope.Definition.Type => + case _: Definition.Type => throw new CompilerError( "Union types should not yet be present in the compiler pipeline." ) - case method: IR.Module.Scope.Definition.Method.Binding => + case method: definition.Method.Binding => method.copy(body = resolveExpression(method.body)) - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: definition.Method.Explicit => method.copy(body = resolveExpression(method.body)) - case tpe: IR.Module.Scope.Definition.SugaredType => + case tpe: Definition.SugaredType => tpe.copy(body = resolveList(tpe.body).map(resolveIr)) - case doc: IR.Comment.Documentation => doc - case tySig: IR.Type.Ascription => tySig - case err: IR.Error => err - case ann: IR.Name.GenericAnnotation => ann - case _: IR.Name.BuiltinAnnotation => + case doc: Comment.Documentation => doc + case tySig: Type.Ascription => tySig + case err: Error => err + case ann: Name.GenericAnnotation => ann + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "documentation comment resolution." @@ -169,7 +182,7 @@ case object DocumentationComments extends IRPass { * @param ir the module to resolve comments in * @return `ir`, with any doc comments associated with nodes as metadata */ - private def resolveModule(ir: IR.Module): IR.Module = { + private def resolveModule(ir: Module): Module = { // All entities that came from source (the only ones we care about). val allModuleEntities: List[IR] = (ir.imports ++ ir.exports ++ ir.bindings) @@ -188,7 +201,7 @@ case object DocumentationComments extends IRPass { leftLocation.start < rightLocation.start } val newBindings = (allModuleEntities.headOption match { - case Some(doc: IR.Comment.Documentation) => + case Some(doc: Comment.Documentation) => ir.updateMetadata(this -->> Doc(doc.doc)) resolveList(ir.bindings.drop(1)) case _ => resolveList(ir.bindings) @@ -203,15 +216,15 @@ case object DocumentationComments extends IRPass { */ private def resolveIr(ir: IR): IR = ir match { - case module: IR.Module => resolveModule(module) - case expr: IR.Expression => resolveExpression(expr) - case df: IR.Module.Scope.Definition => resolveDefinition(df) - case data: IR.Module.Scope.Definition.Data => data - case imp: IR.Module.Scope.Import => imp - case exp: IR.Module.Scope.Export.Module => exp - case arg: IR.CallArgument => arg - case arg: IR.DefinitionArgument => arg - case pat: IR.Pattern => pat + case module: Module => resolveModule(module) + case expr: Expression => resolveExpression(expr) + case df: Definition => resolveDefinition(df) + case data: Definition.Data => data + case imp: Import => imp + case exp: Export.Module => exp + case arg: CallArgument => arg + case arg: DefinitionArgument => arg + case pat: Pattern => pat } // === Metadata ============================================================= diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala index 72e240b10c81..3937fe4293e5 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ExpressionAnnotations.scala @@ -1,8 +1,11 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.Name import org.enso.compiler.core.ir.MetadataStorage.ToPair +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.AliasAnalysis import org.enso.compiler.pass.resolve.ModuleAnnotations.Annotations @@ -35,9 +38,9 @@ case object ExpressionAnnotations extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.mapExpressions(doExpression) } @@ -51,20 +54,20 @@ case object ExpressionAnnotations extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { doExpression(ir) } /** @inheritdoc */ private def doExpression( - ir: IR.Expression - ): IR.Expression = + ir: Expression + ): Expression = ir.transformExpressions { - case app @ IR.Application.Prefix( - ann: IR.Name.BuiltinAnnotation, + case app @ Application.Prefix( + ann: Name.BuiltinAnnotation, arguments, _, _, @@ -74,9 +77,9 @@ case object ExpressionAnnotations extends IRPass { if (isKnownAnnotation(ann.name)) { arguments match { case List() => - IR.Error.Resolution( + errors.Resolution( ann, - IR.Error.Resolution.UnexpectedAnnotation + errors.Resolution.UnexpectedAnnotation ) case List(arg) => doExpression(arg.value) @@ -84,7 +87,7 @@ case object ExpressionAnnotations extends IRPass { case realFun :: args => val recurFun = doExpression(realFun.value) val (finalFun, preArgs) = recurFun match { - case IR.Application.Prefix(nextFun, moreArgs, _, _, _, _) => + case Application.Prefix(nextFun, moreArgs, _, _, _, _) => (nextFun, moreArgs) case _ => (recurFun, List()) } @@ -95,17 +98,17 @@ case object ExpressionAnnotations extends IRPass { } } else { val err = - IR.Error.Resolution(ann, IR.Error.Resolution.UnknownAnnotation) + errors.Resolution(ann, errors.Resolution.UnknownAnnotation) app.copy(function = err) } - case ann: IR.Name.BuiltinAnnotation => + case ann: Name.BuiltinAnnotation => if (isKnownAnnotation(ann.name)) { - IR.Error.Resolution( + errors.Resolution( ann, - IR.Error.Resolution.UnexpectedAnnotation + errors.Resolution.UnexpectedAnnotation ) } else { - IR.Error.Resolution(ann, IR.Error.Resolution.UnknownAnnotation) + errors.Resolution(ann, errors.Resolution.UnknownAnnotation) } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyAppliedFunctionUses.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyAppliedFunctionUses.scala index 6261d5b11e1c..ada09a2f1dbf 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyAppliedFunctionUses.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyAppliedFunctionUses.scala @@ -1,7 +1,9 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.expression.Application import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedConstructor} import org.enso.compiler.pass.IRPass @@ -28,9 +30,9 @@ object FullyAppliedFunctionUses extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir.mapExpressions(doExpression) + ): Module = ir.mapExpressions(doExpression) /** Executes the pass on the provided `ir`, and returns a possibly transformed * or annotated version of `ir` in an inline context. @@ -42,20 +44,20 @@ object FullyAppliedFunctionUses extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = doExpression(ir) + ): Expression = doExpression(ir) - private def doExpression(expr: IR.Expression): IR.Expression = { + private def doExpression(expr: Expression): Expression = { expr.transformExpressions { - case app: IR.Application.Prefix => + case app: Application.Prefix => app.copy(arguments = app.arguments.map(_.mapExpressions(doExpression))) - case name: IR.Name.Literal => + case name: Name.Literal => val meta = name.getMetadata(GlobalNames) meta match { case Some(Resolution(ResolvedConstructor(_, cons))) if cons.allFieldsDefaulted && cons.arity > 0 => - IR.Application.Prefix(name, List(), false, None); + Application.Prefix(name, List(), false, None); case _ => name } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyQualifiedNames.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyQualifiedNames.scala index fee1d7fa2a4c..160c34b85e4a 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyQualifiedNames.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/FullyQualifiedNames.scala @@ -2,8 +2,12 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.{Compiler, PackageRepository} import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Error.Resolution.MissingLibraryImportInFQNError +import org.enso.compiler.core.ir.{Expression, Module, Name, Type} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.Export +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.expression.warnings import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{ @@ -13,6 +17,7 @@ import org.enso.compiler.data.BindingsMap.{ ResolvedType } 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, BindingAnalysis} import org.enso.compiler.pass.desugar.Imports @@ -49,9 +54,9 @@ case object FullyQualifiedNames extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val scopeMap = ir.unsafeGetMetadata( BindingAnalysis, "No binding analysis on the module" @@ -104,10 +109,10 @@ case object FullyQualifiedNames extends IRPass { if (allStarting.nonEmpty) { ir.exports.foreach { export => export match { - case m: IR.Module.Scope.Export.Module + case m: Export.Module if m.name.name == resolution.qualifiedName.toString => m.addDiagnostic( - IR.Warning.Shadowed.TypeInModuleNameConflicts( + warnings.Shadowed.TypeInModuleNameConflicts( exportedModule.getName.toString, tpeName, allStarting.head.getName.toString, @@ -142,9 +147,9 @@ case object FullyQualifiedNames extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val scopeMap = inlineContext.bindingsAnalysis() val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( @@ -162,21 +167,21 @@ case object FullyQualifiedNames extends IRPass { } private def processModuleDefinition( - definition: IR.Module.Scope.Definition, + moduleDefinition: Definition, bindings: BindingsMap, freshNameSupply: FreshNameSupply, pkgRepo: Option[PackageRepository] - ): IR.Module.Scope.Definition = { - definition match { - case asc: IR.Type.Ascription => asc - case method: IR.Module.Scope.Definition.Method => + ): Definition = { + moduleDefinition match { + case asc: Type.Ascription => asc + case method: definition.Method => val resolution = method.methodReference.typePointer.flatMap( _.getMetadata(MethodDefinitions) ) method.mapExpressions( processExpression(_, bindings, freshNameSupply, resolution, pkgRepo) ) - case tp: IR.Module.Scope.Definition.Type => + case tp: Definition.Type => tp.copy(members = tp.members.map( _.mapExpressions( @@ -199,14 +204,14 @@ case object FullyQualifiedNames extends IRPass { } private def processExpression( - ir: IR.Expression, + ir: Expression, bindings: BindingsMap, freshNameSupply: FreshNameSupply, selfTypeResolution: Option[Resolution], pkgRepo: Option[PackageRepository] - ): IR.Expression = + ): Expression = ir.transformExpressions { - case lit: IR.Name.Literal => + case lit: Name.Literal => if (!lit.isMethod && !isLocalVar(lit)) { val resolution = bindings.resolveName(lit.name) resolution match { @@ -228,9 +233,9 @@ case object FullyQualifiedNames extends IRPass { } else { lit } - case app @ IR.Application.Prefix(_, List(_), _, _, _, _) => + case app @ Application.Prefix(_, List(_), _, _, _, _) => app.function match { - case lit: IR.Name.Literal => + case lit: Name.Literal => if (lit.isMethod) resolveLocalApplication( app, @@ -265,12 +270,12 @@ case object FullyQualifiedNames extends IRPass { } private def resolveLocalApplication( - app: IR.Application.Prefix, + app: Application.Prefix, bindings: BindingsMap, freshNameSupply: FreshNameSupply, pkgRepo: Option[PackageRepository], selfTypeResolution: Option[Resolution] - ): IR.Expression = { + ): Expression = { val processedFun = processExpression( app.function, @@ -295,7 +300,7 @@ case object FullyQualifiedNames extends IRPass { val processedApp = processedArgs match { case List(thisArg) => (thisArg.value.getMetadata(this).map(_.target), processedFun) match { - case (Some(resolved @ ResolvedLibrary(_)), name: IR.Name.Literal) => + case (Some(resolved @ ResolvedLibrary(_)), name: Name.Literal) => resolveQualName(resolved, name, pkgRepo).fold( err => Some(err), _.map(resolvedMod => @@ -319,9 +324,9 @@ case object FullyQualifiedNames extends IRPass { private def resolveQualName( thisResolution: ResolvedLibrary, - consName: IR.Name.Literal, + consName: Name.Literal, optPkgRepo: Option[PackageRepository] - ): Either[IR.Expression, Option[FQNResolution]] = { + ): Either[Expression, Option[FQNResolution]] = { optPkgRepo .flatMap { pkgRepo => val libName = LibraryName(thisResolution.namespace, consName.name) @@ -337,9 +342,10 @@ case object FullyQualifiedNames extends IRPass { // IR for it. Triggering a full compilation at this stage may have // undesired consequences and is therefore prohibited on purpose. Left( - IR.Error.Resolution( + errors.Resolution( consName, - MissingLibraryImportInFQNError(thisResolution.namespace) + errors.Resolution + .MissingLibraryImportInFQNError(thisResolution.namespace) ) ) } else { @@ -353,9 +359,10 @@ case object FullyQualifiedNames extends IRPass { } else { Some( Left( - IR.Error.Resolution( + errors.Resolution( consName, - MissingLibraryImportInFQNError(thisResolution.namespace) + errors.Resolution + .MissingLibraryImportInFQNError(thisResolution.namespace) ) ) ) @@ -364,7 +371,7 @@ case object FullyQualifiedNames extends IRPass { .getOrElse(Right(None)) } - private def isLocalVar(name: IR.Name.Literal): Boolean = { + private def isLocalVar(name: Name.Literal): Boolean = { val aliasInfo = name .unsafeGetMetadata( AliasAnalysis, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GenericAnnotations.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GenericAnnotations.scala index f7112ab9fcad..abbb3932e8cd 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GenericAnnotations.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GenericAnnotations.scala @@ -1,13 +1,15 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.module.scope.Definition import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.Comment import org.enso.compiler.pass.IRPass -/** A pass responsible for the discovery of [[IR.Name.GenericAnnotation]] +/** A pass responsible for the discovery of [[Name.GenericAnnotation]] * annotations, and for associating them with the corresponding construct. * * Compilation pipeline of generic annotations: @@ -34,12 +36,12 @@ case object GenericAnnotations extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { - var lastAnnotations: Seq[IR.Name.GenericAnnotation] = Seq() + ): Module = { + var lastAnnotations: Seq[Name.GenericAnnotation] = Seq() val newBindings = ir.bindings.map { - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( s"Builtin annotations should not be present at generic annotations pass." ) @@ -47,11 +49,11 @@ case object GenericAnnotations extends IRPass { throw new CompilerError( s"Sugared types should not be present at generic annotations pass." ) - case _: IR.Comment => + case _: Comment => throw new CompilerError( "Comments should not be present at generic annotations pass." ) - case ann: IR.Name.GenericAnnotation => + case ann: Name.GenericAnnotation => lastAnnotations :+= ann None case entity => @@ -77,9 +79,9 @@ case object GenericAnnotations extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir /** @inheritdoc */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GlobalNames.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GlobalNames.scala index a2c55d07ec06..fcd92924afd6 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GlobalNames.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/GlobalNames.scala @@ -2,7 +2,18 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Module, + Name, + Type +} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.ir.MetadataStorage.ToPair +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{ Resolution, @@ -11,6 +22,7 @@ import org.enso.compiler.data.BindingsMap.{ ResolvedModule } 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, BindingAnalysis} import org.enso.interpreter.Constants @@ -50,9 +62,9 @@ case object GlobalNames extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val scopeMap = ir.unsafeGetMetadata( BindingAnalysis, "No binding analysis on the module" @@ -77,9 +89,9 @@ case object GlobalNames extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val scopeMap = inlineContext.bindingsAnalysis() val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( @@ -92,20 +104,20 @@ case object GlobalNames extends IRPass { /** @inheritdoc */ private def processModuleDefinition( - definition: IR.Module.Scope.Definition, + moduleDefinition: Definition, bindings: BindingsMap, freshNameSupply: FreshNameSupply - ): IR.Module.Scope.Definition = { - definition match { - case asc: IR.Type.Ascription => asc - case method: IR.Module.Scope.Definition.Method => + ): Definition = { + moduleDefinition match { + case asc: Type.Ascription => asc + case method: definition.Method => val resolution = method.methodReference.typePointer.flatMap( _.getMetadata(MethodDefinitions) ) method.mapExpressions( processExpression(_, bindings, List(), freshNameSupply, resolution) ) - case tp: IR.Module.Scope.Definition.Type => + case tp: Definition.Type => tp.copy(members = tp.members.map( _.mapExpressions( @@ -128,24 +140,24 @@ case object GlobalNames extends IRPass { } private def processExpression( - ir: IR.Expression, + ir: Expression, bindings: BindingsMap, - params: List[IR.DefinitionArgument], + params: List[DefinitionArgument], freshNameSupply: FreshNameSupply, selfTypeResolution: Option[Resolution], isInsideApplication: Boolean = false - ): IR.Expression = { + ): Expression = { ir.transformExpressions { - case selfTp: IR.Name.SelfType => + case selfTp: Name.SelfType => selfTypeResolution .map(res => selfTp.updateMetadata(this -->> res)) .getOrElse( - IR.Error.Resolution( + errors.Resolution( selfTp, - IR.Error.Resolution.ResolverError(ResolutionNotFound) + errors.Resolution.ResolverError(ResolutionNotFound) ) ) - case lit: IR.Name.Literal => + case lit: Name.Literal => if (params.exists(p => p.name.name == lit.name)) { lit } else { @@ -161,9 +173,9 @@ case object GlobalNames extends IRPass { val resolution = bindings.resolveName(lit.name) resolution match { case Left(error) => - IR.Error.Resolution( + errors.Resolution( lit, - IR.Error.Resolution.ResolverError(error) + errors.Resolution.ResolverError(error) ) case Right(r @ BindingsMap.ResolvedMethod(mod, method)) => if (isInsideApplication) { @@ -182,9 +194,9 @@ case object GlobalNames extends IRPass { name = method.name, location = None ) - val app = IR.Application.Prefix( + val app = Application.Prefix( fun, - List(IR.CallArgument.Specified(None, self, None)), + List(CallArgument.Specified(None, self, None)), hasDefaultsSuspended = false, lit.location ) @@ -207,9 +219,9 @@ case object GlobalNames extends IRPass { } } } - case app: IR.Application.Prefix => + case app: Application.Prefix => app.function match { - case lit: IR.Name.Literal => + case lit: Name.Literal => if (!lit.isMethod) resolveReferantApplication( app, @@ -244,13 +256,13 @@ case object GlobalNames extends IRPass { } private def resolveReferantApplication( - app: IR.Application.Prefix, - fun: IR.Name.Literal, + app: Application.Prefix, + fun: Name.Literal, bindingsMap: BindingsMap, - params: List[IR.DefinitionArgument], + params: List[DefinitionArgument], freshNameSupply: FreshNameSupply, selfTypeResolution: Option[Resolution] - ): IR.Expression = { + ): Expression = { val processedFun = processExpression( app.function, bindingsMap, @@ -279,7 +291,7 @@ case object GlobalNames extends IRPass { BindingsMap.ResolvedModule(mod) ) ) - val selfArg = IR.CallArgument.Specified(None, self, None) + val selfArg = CallArgument.Specified(None, self, None) processedFun.passData.remove(this) // Necessary for IrToTruffle app.copy(function = processedFun, arguments = selfArg :: processedArgs) case _ => @@ -288,12 +300,12 @@ case object GlobalNames extends IRPass { } private def resolveLocalApplication( - app: IR.Application.Prefix, + app: Application.Prefix, bindings: BindingsMap, - params: List[IR.DefinitionArgument], + params: List[DefinitionArgument], freshNameSupply: FreshNameSupply, selfTypeResolution: Option[Resolution] - ): IR.Expression = { + ): Expression = { val processedFun = processExpression( app.function, @@ -341,11 +353,11 @@ case object GlobalNames extends IRPass { } private def buildConsApplication( - originalApp: IR.Application.Prefix, + originalApp: Application.Prefix, calledCons: BindingsMap.Cons, - newFun: IR.Expression, - newArgs: List[IR.CallArgument] - ): IR.Expression = { + newFun: Expression, + newArgs: List[CallArgument] + ): Expression = { if ( newArgs.isEmpty && (!originalApp.hasDefaultsSuspended || calledCons.arity == 0) ) { @@ -358,7 +370,7 @@ case object GlobalNames extends IRPass { private def buildSymbolFor( cons: BindingsMap.ResolvedConstructor, freshNameSupply: FreshNameSupply - ): IR.Expression = { + ): Expression = { freshNameSupply .newName() .updateMetadata(this -->> BindingsMap.Resolution(cons)) @@ -366,7 +378,7 @@ case object GlobalNames extends IRPass { private def resolveQualName( thisResolution: BindingsMap.Resolution, - consName: IR.Name.Literal + consName: Name.Literal ): Option[BindingsMap.ResolvedName] = thisResolution.target match { case BindingsMap.ResolvedModule(module) => @@ -385,7 +397,7 @@ case object GlobalNames extends IRPass { case _ => None } - private def findThisPosition(args: List[IR.CallArgument]): Option[Int] = { + private def findThisPosition(args: List[CallArgument]): Option[Int] = { val ix = args.indexWhere(arg => arg.name.exists( _.name == Constants.Names.SELF_ARGUMENT @@ -394,14 +406,14 @@ case object GlobalNames extends IRPass { if (ix == -1) None else Some(ix) } - private def asGlobalVar(ir: IR): Option[IR.Name.Literal] = + private def asGlobalVar(ir: IR): Option[Name.Literal] = ir match { - case name: IR.Name.Literal => + case name: Name.Literal => if (isLocalVar(name)) None else Some(name) case _ => None } - private def isLocalVar(name: IR.Name.Literal): Boolean = { + private def isLocalVar(name: Name.Literal): Boolean = { val aliasInfo = name .unsafeGetMetadata( AliasAnalysis, diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/IgnoredBindings.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/IgnoredBindings.scala index 774ca41c8908..167c5daf4737 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/IgnoredBindings.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/IgnoredBindings.scala @@ -2,8 +2,16 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.{Case, Pattern} +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name, + Pattern +} import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.expression.{errors, Case} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ @@ -55,9 +63,9 @@ case object IgnoredBindings extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.mapExpressions( runExpression( _, @@ -78,9 +86,9 @@ case object IgnoredBindings extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val freshNameSupply = inlineContext.freshNameSupply.getOrElse( throw new CompilerError( "Desugaring underscore arguments to lambdas requires a fresh name " + @@ -110,13 +118,13 @@ case object IgnoredBindings extends IRPass { * @return `expression`, with any ignored bidings desugared */ private def resolveExpression( - expression: IR.Expression, + expression: Expression, supply: FreshNameSupply - ): IR.Expression = { + ): Expression = { expression.transformExpressions { - case binding: IR.Expression.Binding => resolveBinding(binding, supply) - case function: IR.Function => resolveFunction(function, supply) - case cse: IR.Case => resolveCase(cse, supply) + case binding: Expression.Binding => resolveBinding(binding, supply) + case function: Function => resolveFunction(function, supply) + case cse: Case => resolveCase(cse, supply) } } @@ -127,9 +135,9 @@ case object IgnoredBindings extends IRPass { * @return `binding`, with any ignored bindings desugared */ def resolveBinding( - binding: IR.Expression.Binding, + binding: Expression.Binding, supply: FreshNameSupply - ): IR.Expression.Binding = { + ): Expression.Binding = { if (isIgnore(binding.name)) { val newName = supply .newName() @@ -162,11 +170,11 @@ case object IgnoredBindings extends IRPass { * @return `function`, with any ignores desugared */ def resolveFunction( - function: IR.Function, + function: Function, supply: FreshNameSupply - ): IR.Function = { + ): Function = { function match { - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => val argIsIgnore = args.map(isIgnoreArg) val newArgs = args.zip(argIsIgnore).map { case (arg, isIgnore) => genNewArg(arg, isIgnore, supply) @@ -176,7 +184,7 @@ case object IgnoredBindings extends IRPass { arguments = newArgs, body = resolveExpression(body, supply) ) - case _: IR.Function.Binding => + case _: Function.Binding => throw new CompilerError( "Function sugar should not be present during ignored " + "bindings desugaring." @@ -195,13 +203,13 @@ case object IgnoredBindings extends IRPass { * @return `arg`, if `isIgnored` is `false`, otherwise `arg` with a new name */ def genNewArg( - arg: IR.DefinitionArgument, + arg: DefinitionArgument, isIgnored: Boolean, freshNameSupply: FreshNameSupply - ): IR.DefinitionArgument = { + ): DefinitionArgument = { arg match { - case spec @ IR.DefinitionArgument.Specified( - IR.Name.Self(_, _, _, _), + case spec @ DefinitionArgument.Specified( + Name.Self(_, _, _, _), _, _, _, @@ -215,7 +223,7 @@ case object IgnoredBindings extends IRPass { spec.defaultValue.map(resolveExpression(_, freshNameSupply)) ) .updateMetadata(this -->> State.Ignored) - case spec: IR.DefinitionArgument.Specified => + case spec: DefinitionArgument.Specified => if (isIgnored) { val newName = freshNameSupply .newName() @@ -249,9 +257,9 @@ case object IgnoredBindings extends IRPass { * @param ir the definition argument to check * @return `true` if `ir` represents an ignore, otherwise `false` */ - def isIgnoreArg(ir: IR.DefinitionArgument): Boolean = { + def isIgnoreArg(ir: DefinitionArgument): Boolean = { ir match { - case IR.DefinitionArgument.Specified(name, _, _, _, _, _, _) => + case DefinitionArgument.Specified(name, _, _, _, _, _, _) => isIgnore(name) } } @@ -261,11 +269,11 @@ case object IgnoredBindings extends IRPass { * @param ir the name to check * @return `true` if `ir` represents an ignore, otherwise `false` */ - def isIgnore(ir: IR.Name): Boolean = { + def isIgnore(ir: Name): Boolean = { ir match { - case _: IR.Name.Blank => true - case IR.Name.Literal(name, _, _, _, _) => name == "_" - case _ => false + case _: Name.Blank => true + case Name.Literal(name, _, _, _, _) => name == "_" + case _ => false } } @@ -275,7 +283,7 @@ case object IgnoredBindings extends IRPass { * @param supply the compiler's fresh name supply * @return `cse`, with any ignored bindings resolved */ - def resolveCase(cse: IR.Case, supply: FreshNameSupply): IR.Case = { + def resolveCase(cse: Case, supply: FreshNameSupply): Case = { cse match { case expr @ Case.Expr(scrutinee, branches, _, _, _, _) => expr.copy( @@ -312,9 +320,9 @@ case object IgnoredBindings extends IRPass { * @return `pattern`, with any ignored bindings resolved */ def resolvePattern( - pattern: IR.Pattern, + pattern: Pattern, supply: FreshNameSupply - ): IR.Pattern = { + ): Pattern = { pattern match { case named @ Pattern.Name(name, _, _, _) => if (isIgnore(name)) { @@ -359,7 +367,7 @@ case object IgnoredBindings extends IRPass { name = setNotIgnored(name) ) } - case err: IR.Error.Pattern => err + case err: errors.Pattern => err case _: Pattern.Documentation => throw new CompilerError( "Branch documentation should be desugared at an earlier stage." diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodCalls.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodCalls.scala index e26550a7b63d..658044ecc263 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodCalls.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodCalls.scala @@ -1,8 +1,10 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.Name import org.enso.compiler.core.ir.MetadataStorage.ToPair +import org.enso.compiler.core.ir.expression.Application import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedModule} import org.enso.compiler.pass.IRPass @@ -30,9 +32,9 @@ object MethodCalls extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { ir.mapExpressions(doExpression) } @@ -46,19 +48,19 @@ object MethodCalls extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { doExpression(ir) } private def doExpression( - expr: IR.Expression - ): IR.Expression = { - expr.transformExpressions { case app: IR.Application.Prefix => + expr: Expression + ): Expression = { + expr.transformExpressions { case app: Application.Prefix => def fallback = app.mapExpressions(doExpression(_)) app.function match { - case name: IR.Name if name.isMethod => + case name: Name if name.isMethod => app.arguments match { case first :: _ => val targetBindings = diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala index 5ab2063471ca..39051dadd9d7 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/MethodDefinitions.scala @@ -1,7 +1,15 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedType, Type} @@ -38,34 +46,34 @@ case object MethodDefinitions extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val availableSymbolsMap = ir.unsafeGetMetadata( BindingAnalysis, "MethodDefinitionResolution is being run before BindingResolution" ) val newDefs = ir.bindings.map { - case method: IR.Module.Scope.Definition.Method => + case method: definition.Method => val methodRef = method.methodReference val resolvedTypeRef = methodRef.typePointer.map(resolveType(_, availableSymbolsMap)) val resolvedMethodRef = methodRef.copy(typePointer = resolvedTypeRef) method match { - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: definition.Method.Explicit => val resolvedMethod = method.copy(methodReference = resolvedMethodRef) resolvedMethod - case method: IR.Module.Scope.Definition.Method.Conversion => + case method: definition.Method.Conversion => val sourceTypeExpr = method.sourceTypeName - val resolvedName: IR.Name = sourceTypeExpr match { - case name: IR.Name => resolveType(name, availableSymbolsMap) + val resolvedName: Name = sourceTypeExpr match { + case name: Name => resolveType(name, availableSymbolsMap) case _ => - IR.Error.Conversion( + errors.Conversion( sourceTypeExpr, - IR.Error.Conversion.UnsupportedSourceType + errors.Conversion.UnsupportedSourceType ) } @@ -84,8 +92,7 @@ case object MethodDefinitions extends IRPass { } val withStaticAliases = newDefs.flatMap { - case method: IR.Module.Scope.Definition.Method.Explicit - if !method.isStatic => + case method: definition.Method.Explicit if !method.isStatic => method.methodReference.typePointer.flatMap( _.getMetadata(this) ) match { @@ -93,11 +100,11 @@ case object MethodDefinitions extends IRPass { if canGenerateStaticWrappers(tp) => val dup = method.duplicate() val static = dup.copy(body = - IR.Function.Lambda( + Function.Lambda( List( - IR.DefinitionArgument + DefinitionArgument .Specified( - IR.Name.Self(None, true), + Name.Self(None, true), None, None, false, @@ -128,27 +135,27 @@ case object MethodDefinitions extends IRPass { tp.members.nonEmpty || (tp.builtinType && (tp.name != "Nothing")) private def resolveType( - typePointer: IR.Name, + typePointer: Name, availableSymbolsMap: BindingsMap - ): IR.Name = { + ): Name = { typePointer match { - case _: IR.Name.Qualified | _: IR.Name.Literal => + case _: Name.Qualified | _: Name.Literal => val items = typePointer match { - case IR.Name.Qualified(names, _, _, _) => names.map(_.name) - case IR.Name.Literal(name, _, _, _, _) => List(name) + case Name.Qualified(names, _, _, _) => names.map(_.name) + case Name.Literal(name, _, _, _, _) => List(name) case _ => throw new CompilerError("Impossible to reach.") } availableSymbolsMap.resolveQualifiedName(items) match { case Left(err) => - IR.Error.Resolution( + errors.Resolution( typePointer, - IR.Error.Resolution.ResolverError(err) + errors.Resolution.ResolverError(err) ) case Right(_: BindingsMap.ResolvedConstructor) => - IR.Error.Resolution( + errors.Resolution( typePointer, - IR.Error.Resolution.UnexpectedConstructor( + errors.Resolution.UnexpectedConstructor( "a method definition target" ) ) @@ -159,29 +166,29 @@ case object MethodDefinitions extends IRPass { case Right(value: BindingsMap.ResolvedType) => typePointer.updateMetadata(this -->> BindingsMap.Resolution(value)) case Right(_: BindingsMap.ResolvedPolyglotSymbol) => - IR.Error.Resolution( + errors.Resolution( typePointer, - IR.Error.Resolution.UnexpectedPolyglot( + errors.Resolution.UnexpectedPolyglot( "a method definition target" ) ) case Right(_: BindingsMap.ResolvedPolyglotField) => - IR.Error.Resolution( + errors.Resolution( typePointer, - IR.Error.Resolution.UnexpectedPolyglot( + errors.Resolution.UnexpectedPolyglot( "a method definition target" ) ) case Right(_: BindingsMap.ResolvedMethod) => - IR.Error.Resolution( + errors.Resolution( typePointer, - IR.Error.Resolution.UnexpectedMethod( + errors.Resolution.UnexpectedMethod( "a method definition target" ) ) } - case tp: IR.Error.Resolution => tp + case tp: errors.Resolution => tp case _ => throw new CompilerError( "Unexpected kind of name for method reference" @@ -199,8 +206,8 @@ case object MethodDefinitions extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ModuleAnnotations.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ModuleAnnotations.scala index 28a3aa553f7f..6e5e56acf659 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ModuleAnnotations.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/ModuleAnnotations.scala @@ -1,10 +1,11 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition -import org.enso.compiler.core.IR.Name +import org.enso.compiler.core.ir.{Expression, Module} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.Name import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.expression.Comment import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.{ ComplexType, @@ -35,17 +36,17 @@ case object ModuleAnnotations extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { - var lastAnnotations: Seq[IR.Name.Annotation] = Seq() + ): Module = { + var lastAnnotations: Seq[Name.Annotation] = Seq() val newBindings = ir.bindings.map { case ann: Name.BuiltinAnnotation => lastAnnotations :+= ann None case ann: Name.GenericAnnotation => Some(ann) - case comment: IR.Comment => Some(comment) + case comment: Comment => Some(comment) case typ: Definition.SugaredType => val res = Some( resolveComplexType(typ).updateMetadata( @@ -72,14 +73,14 @@ case object ModuleAnnotations extends IRPass { private def resolveComplexType( typ: Definition.SugaredType ): Definition.SugaredType = { - var lastAnnotations: Seq[IR.Name.Annotation] = Seq() + var lastAnnotations: Seq[Name.Annotation] = Seq() val newBodyElems = typ.body.flatMap { case ann: Name.BuiltinAnnotation => lastAnnotations :+= ann None case ann: Name.GenericAnnotation => Some(ann) - case comment: IR.Comment => Some(comment) + case comment: Comment => Some(comment) case entity => val res = Some( entity.updateMetadata(this -->> Annotations(lastAnnotations)) @@ -101,9 +102,9 @@ case object ModuleAnnotations extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir /** @inheritdoc */ @@ -111,7 +112,7 @@ case object ModuleAnnotations extends IRPass { * * @param annotations the initial annotations for the container */ - case class Annotations(annotations: Seq[IR.Name.Annotation]) + case class Annotations(annotations: Seq[Name.Annotation]) extends IRPass.IRMetadata { override val metadataName: String = "Annotations" override def duplicate(): Option[IRPass.IRMetadata] = Some(this.copy()) @@ -121,7 +122,7 @@ case object ModuleAnnotations extends IRPass { * @param annotation the annotation to add * @return `this`, with `annotation` added to it */ - def addAnnotation(annotation: IR.Name.Annotation): Annotations = + def addAnnotation(annotation: Name.Annotation): Annotations = this.copy(annotations = this.annotations :+ annotation) /** @inheritdoc */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/OverloadsResolution.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/OverloadsResolution.scala index 7ca5b8e2c7aa..e0edd1d61a89 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/OverloadsResolution.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/OverloadsResolution.scala @@ -1,7 +1,10 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Diagnostic, Expression, Module, Name, Type} +import org.enso.compiler.core.ir.expression.{errors, Comment} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.desugar.{ComplexType, GenerateMethodBodies} @@ -44,44 +47,42 @@ case object OverloadsResolution extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { var seenTypes: Set[String] = Set() var seenMethods: Map[Option[String], Set[(String, Boolean)]] = Map() - val types = ir.bindings.collect { - case tp: IR.Module.Scope.Definition.Type => - tp + val types = ir.bindings.collect { case tp: Definition.Type => + tp } - ir.bindings.collect { - case meth: IR.Module.Scope.Definition.Method.Explicit => - seenMethods += meth.typeName.map(_.name) -> Set() - meth + ir.bindings.collect { case meth: definition.Method.Explicit => + seenMethods += meth.typeName.map(_.name) -> Set() + meth } val conversionsForType: mutable.Map[Option[String], Set[String]] = mutable.Map() val newBindings = ir.bindings.map { - case tp: IR.Module.Scope.Definition.Type => + case tp: Definition.Type => if (seenTypes.contains(tp.name.name)) { - IR.Error.Redefined.Type(tp.name, tp.location) + errors.Redefined.Type(tp.name, tp.location) } else { seenTypes += tp.name.name tp } - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: definition.Method.Explicit => if ( seenMethods(method.typeName.map(_.name)) .contains((method.methodName.name, method.isStatic)) ) { - IR.Error.Redefined + errors.Redefined .Method(method.typeName, method.methodName, method.location) } else { types.find(_.name.name.equals(method.methodName.name)) match { case Some(clashedAtom) if method.typeName.isEmpty => - IR.Error.Redefined.MethodClashWithAtom( + errors.Redefined.MethodClashWithAtom( clashedAtom.name, method.methodName, method.location @@ -95,12 +96,12 @@ case object OverloadsResolution extends IRPass { } } - case m: IR.Module.Scope.Definition.Method.Conversion => - val fromName = m.sourceTypeName.asInstanceOf[IR.Name] + case m: definition.Method.Conversion => + val fromName = m.sourceTypeName.asInstanceOf[Name] conversionsForType.get(m.typeName.map(_.name)) match { case Some(elems) => if (elems.contains(fromName.name)) { - IR.Error.Redefined.Conversion(m.typeName, fromName, m.location) + errors.Redefined.Conversion(m.typeName, fromName, m.location) } else { conversionsForType.update( m.typeName.map(_.name), @@ -113,25 +114,25 @@ case object OverloadsResolution extends IRPass { m } - case diagnostic: IR.Diagnostic => diagnostic - case ann: IR.Name.GenericAnnotation => ann - case _: IR.Type.Ascription => + case diagnostic: Diagnostic => diagnostic + case ann: Name.GenericAnnotation => ann + case _: Type.Ascription => throw new CompilerError( "Type ascriptions should not be present during the overloads resolution." ) - case _: IR.Module.Scope.Definition.Method.Binding => + case _: definition.Method.Binding => throw new CompilerError( "Method bindings should not be present during the overloads resolution." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Builtin annotations should not be present during the overloads resolution." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation comments should not be present during the overloads resolution." ) - case _: IR.Module.Scope.Definition.SugaredType => + case _: Definition.SugaredType => throw new CompilerError( "Sugared types should not be present during the overloads resolution." ) @@ -149,9 +150,9 @@ case object OverloadsResolution extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir /** @inheritdoc */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/Patterns.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/Patterns.scala index 6e633480ce76..b90893311b7b 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/Patterns.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/Patterns.scala @@ -1,7 +1,10 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module, Name, Pattern} +import org.enso.compiler.core.ir.expression.{errors, Case} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.data.BindingsMap import org.enso.compiler.core.CompilerError @@ -30,9 +33,9 @@ object Patterns extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val bindings = ir.unsafeGetMetadata( BindingAnalysis, "Binding resolution was not run before pattern resolution" @@ -50,19 +53,19 @@ object Patterns extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { val bindings = inlineContext.bindingsAnalysis() doExpression(ir, bindings, None) } private def doDefinition( - ir: IR.Module.Scope.Definition, + ir: Definition, bindings: BindingsMap - ): IR.Module.Scope.Definition = { + ): Definition = { ir match { - case method: IR.Module.Scope.Definition.Method.Explicit => + case method: definition.Method.Explicit => val resolution = method.methodReference.typePointer .flatMap( _.getMetadata(MethodDefinitions) @@ -75,19 +78,19 @@ object Patterns extends IRPass { } private def doExpression( - expr: IR.Expression, + expr: Expression, bindings: BindingsMap, selfTypeResolution: Option[BindingsMap.ResolvedName] - ): IR.Expression = { - expr.transformExpressions { case caseExpr: IR.Case.Expr => + ): Expression = { + expr.transformExpressions { case caseExpr: Case.Expr => val newBranches = caseExpr.branches.map { branch => val resolvedPattern = branch.pattern match { - case consPat: IR.Pattern.Constructor => + case consPat: Pattern.Constructor => val consName = consPat.constructor val resolution = consName match { - case qual: IR.Name.Qualified => + case qual: Name.Qualified => qual.parts match { - case (_: IR.Name.SelfType) :: (others :+ item) => + case (_: Name.SelfType) :: (others :+ item) => selfTypeResolution.map( bindings.resolveQualifiedNameIn( _, @@ -101,18 +104,18 @@ object Patterns extends IRPass { bindings.resolveQualifiedName(parts) ) } - case lit: IR.Name.Literal => + case lit: Name.Literal => Some(bindings.resolveName(lit.name)) - case _: IR.Name.SelfType => + case _: Name.SelfType => selfTypeResolution.map(Right(_)) case _ => None } val resolvedName = resolution .map { case Left(err) => - IR.Error.Resolution( + errors.Resolution( consPat.constructor, - IR.Error.Resolution.ResolverError(err) + errors.Resolution.ResolverError(err) ) case Right(value: BindingsMap.ResolvedConstructor) => consName.updateMetadata( @@ -136,9 +139,9 @@ object Patterns extends IRPass { ) case Right(_: BindingsMap.ResolvedMethod) => - IR.Error.Resolution( + errors.Resolution( consName, - IR.Error.Resolution.UnexpectedMethod( + errors.Resolution.UnexpectedMethod( "a pattern match" ) ) @@ -162,9 +165,9 @@ object Patterns extends IRPass { expectedArity match { case Some(arity) => if (consPat.fields.length != arity) { - IR.Error.Pattern( + errors.Pattern( consPat, - IR.Error.Pattern.WrongArity( + errors.Pattern.WrongArity( consPat.constructor.name, arity, consPat.fields.length @@ -175,34 +178,34 @@ object Patterns extends IRPass { } case None => consPat.copy(constructor = resolvedName) } - case tpePattern @ IR.Pattern.Type(_, tpeName, _, _, _) => + case tpePattern @ Pattern.Type(_, tpeName, _, _, _) => val resolution = tpeName match { - case qual: IR.Name.Qualified => + case qual: Name.Qualified => val parts = qual.parts.map(_.name) Some( bindings.resolveQualifiedName(parts) ) - case lit: IR.Name.Literal => + case lit: Name.Literal => Some(bindings.resolveName(lit.name)) - case _: IR.Name.SelfType => + case _: Name.SelfType => selfTypeResolution.map(Right(_)) case _ => None } val resolvedTpeName = resolution .map { case Left(err) => - IR.Error.Resolution( + errors.Resolution( tpePattern.tpe, - IR.Error.Resolution.ResolverError(err) + errors.Resolution.ResolverError(err) ) case Right(value: BindingsMap.ResolvedType) => tpeName.updateMetadata( this -->> BindingsMap.Resolution(value) ) case Right(_: BindingsMap.ResolvedConstructor) => - IR.Error.Resolution( + errors.Resolution( tpeName, - IR.Error.Resolution + errors.Resolution .UnexpectedConstructor(s"type pattern case") ) case Right(value: BindingsMap.ResolvedPolyglotSymbol) => @@ -213,19 +216,19 @@ object Patterns extends IRPass { tpeName.updateMetadata( this -->> BindingsMap.Resolution(value) ) - /*IR.Error.Resolution( + /*errors.Resolution( tpeName, - IR.Error.Resolution.UnexpectedPolyglot(s"type pattern case") + errors.Resolution.UnexpectedPolyglot(s"type pattern case") )*/ case Right(_: BindingsMap.ResolvedMethod) => - IR.Error.Resolution( + errors.Resolution( tpeName, - IR.Error.Resolution.UnexpectedMethod(s"type pattern case") + errors.Resolution.UnexpectedMethod(s"type pattern case") ) case Right(_: BindingsMap.ResolvedModule) => - IR.Error.Resolution( + errors.Resolution( tpeName, - IR.Error.Resolution.UnexpectedModule(s"type pattern case") + errors.Resolution.UnexpectedModule(s"type pattern case") ) } .getOrElse(tpeName) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala index 101a6ee0be07..534dd37779b6 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/SuspendedArguments.scala @@ -1,10 +1,18 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.Type +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Empty, + Expression, + Function, + Module, + Name, + Type +} +import org.enso.compiler.core.ir.expression.{errors, Comment, Error} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse._ @@ -66,9 +74,9 @@ case object SuspendedArguments extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = + ): Module = ir.copy( bindings = ir.bindings.map(resolveModuleBinding) ) @@ -82,9 +90,9 @@ case object SuspendedArguments extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = resolveExpression(ir) + ): Expression = resolveExpression(ir) /** @inheritdoc */ @@ -99,19 +107,19 @@ case object SuspendedArguments extends IRPass { * @return `binding`, with any suspended arguments resolved */ private def resolveModuleBinding( - binding: IR.Module.Scope.Definition - ): IR.Module.Scope.Definition = { + binding: Definition + ): Definition = { binding match { - case method: Method.Conversion => + case method: definition.Method.Conversion => method.body match { - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => method.getMetadata(TypeSignatures) match { case Some(Signature(signature)) => val newArgs = computeSuspensions(args.drop(1), signature) if (newArgs.head.suspended) { - IR.Error.Conversion( + errors.Conversion( method, - IR.Error.Conversion.SuspendedSourceArgument( + errors.Conversion.SuspendedSourceArgument( newArgs.head.name.name ) ) @@ -126,16 +134,16 @@ case object SuspendedArguments extends IRPass { case None => args match { case _ :: Nil => - IR.Error.Conversion( + errors.Conversion( method, - IR.Error.Conversion.SuspendedSourceArgument( + errors.Conversion.SuspendedSourceArgument( "unknown" ) ) case _ :: sourceArg :: _ if sourceArg.suspended => - IR.Error.Conversion( + errors.Conversion( method, - IR.Error.Conversion.SuspendedSourceArgument( + errors.Conversion.SuspendedSourceArgument( sourceArg.name.name ) ) @@ -150,9 +158,9 @@ case object SuspendedArguments extends IRPass { "Method bodies must be lambdas at this point." ) } - case explicit @ Method.Explicit(_, body, _, _, _) => + case explicit @ definition.Method.Explicit(_, body, _, _, _) => body match { - case lam @ IR.Function.Lambda(args, lamBody, _, _, _, _) => + case lam @ Function.Lambda(args, lamBody, _, _, _, _) => explicit.getMetadata(TypeSignatures) match { case Some(Signature(signature)) => val newArgs = computeSuspensions( @@ -176,23 +184,23 @@ case object SuspendedArguments extends IRPass { "Method bodies must be lambdas at this point." ) } - case _: Method.Binding => throw new CompilerError("") - case _: Definition.Type => binding - case err: IR.Error => err + case _: definition.Method.Binding => throw new CompilerError("") + case _: Definition.Type => binding + case err: Error => err case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present." ) case _: Type.Ascription => throw new CompilerError("Type ascriptions should not be present.") - case _: IR.Comment => + case _: Comment => throw new CompilerError("Comments should not be present.") - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "suspended arguments analysis." ) - case ann: IR.Name.GenericAnnotation => ann + case ann: Name.GenericAnnotation => ann } } @@ -201,13 +209,13 @@ case object SuspendedArguments extends IRPass { * @param expression the expression to perform resolution in * @return `expression`, with any suspended arguments resolved */ - private def resolveExpression(expression: IR.Expression): IR.Expression = { + private def resolveExpression(expression: Expression): Expression = { expression.transformExpressions { - case bind @ IR.Expression.Binding(_, expr, _, _, _) => + case bind @ Expression.Binding(_, expr, _, _, _) => val newExpr = bind.getMetadata(TypeSignatures) match { case Some(Signature(signature)) => expr match { - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => lam.copy( arguments = computeSuspensions(args, signature), body = resolveExpression(body) @@ -218,7 +226,7 @@ case object SuspendedArguments extends IRPass { } bind.copy(expression = newExpr) - case lam @ IR.Function.Lambda(args, body, _, _, _, _) => + case lam @ Function.Lambda(args, body, _, _, _, _) => lam.getMetadata(TypeSignatures) match { case Some(Signature(signature)) => lam.copy( @@ -239,10 +247,10 @@ case object SuspendedArguments extends IRPass { * @param signature the type signature to split * @return the segments of `signature` */ - private def toSegments(signature: IR.Expression): List[IR.Expression] = { + private def toSegments(signature: Expression): List[Expression] = { signature match { - case IR.Type.Function(args, ret, _, _, _) => args :+ ret - case _ => List(signature) + case Type.Function(args, ret, _, _, _) => args :+ ret + case _ => List(signature) } } @@ -252,10 +260,10 @@ case object SuspendedArguments extends IRPass { * @return `true` if `value` represents a suspended argument, otherwise * `false` */ - def representsSuspended(value: IR.Expression): Boolean = { + def representsSuspended(value: Expression): Boolean = { value match { - case IR.Name.Literal("Suspended", _, _, _, _) => true - case _ => false + case Name.Literal("Suspended", _, _, _, _) => true + case _ => false } } @@ -266,12 +274,12 @@ case object SuspendedArguments extends IRPass { * @return the argument from `pair`, with its suspension marked appropriately */ private def markSuspended( - pair: (IR.DefinitionArgument, IR.Expression) - ): IR.DefinitionArgument = + pair: (DefinitionArgument, Expression) + ): DefinitionArgument = pair match { case (arg, typ) => arg match { - case spec: IR.DefinitionArgument.Specified => + case spec: DefinitionArgument.Specified => if (representsSuspended(typ) || spec.suspended) { spec.copy(suspended = true) } else spec.copy(suspended = false) @@ -285,9 +293,9 @@ case object SuspendedArguments extends IRPass { * @return `args`, appropriately marked as suspended or not */ private def computeSuspensions( - args: List[IR.DefinitionArgument], - signature: IR.Expression - ): List[IR.DefinitionArgument] = { + args: List[DefinitionArgument], + signature: Expression + ): List[DefinitionArgument] = { val signatureSegments = toSegments(signature) val toComputeArgs = @@ -296,7 +304,7 @@ case object SuspendedArguments extends IRPass { } else if (args.length > signatureSegments.length) { val additionalSegments = signatureSegments ::: List.fill( args.length - signatureSegments.length - )(IR.Empty(None)) + )(Empty(None)) args.zip(additionalSegments) } else { diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala index 9d98007107a4..2acd01d109b8 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeFunctions.scala @@ -2,9 +2,19 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.{Application, IdentifiedLocation} +import org.enso.compiler.core.ir.{ + `type`, + CallArgument, + Expression, + IdentifiedLocation, + Module, + Name, + Type +} import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.expression.Error import org.enso.compiler.core.CompilerError +import org.enso.compiler.core.ir.expression.{Application, Operator} import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse._ import org.enso.compiler.pass.desugar.{ @@ -52,9 +62,9 @@ case object TypeFunctions extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, @unused moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val new_bindings = ir.bindings.map(_.mapExpressions(resolveExpression)) ir.copy(bindings = new_bindings) } @@ -68,9 +78,9 @@ case object TypeFunctions extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, @unused inlineContext: InlineContext - ): IR.Expression = + ): Expression = ir.transformExpressions { case a => resolveExpression(a) } @@ -79,15 +89,15 @@ case object TypeFunctions extends IRPass { /** The names of the known typing functions. */ val knownTypingFunctions: Set[String] = Set( - IR.Type.Ascription.name, - IR.Type.Context.name, - IR.Type.Error.name, - IR.Type.Set.Concat.name, - IR.Type.Set.Subsumption.name, - IR.Type.Set.Equality.name, - IR.Type.Set.Union.name, - IR.Type.Set.Intersection.name, - IR.Type.Set.Subtraction.name + Type.Ascription.name, + Type.Context.name, + Type.Error.name, + `type`.Set.Concat.name, + `type`.Set.Subsumption.name, + `type`.Set.Equality.name, + `type`.Set.Union.name, + `type`.Set.Intersection.name, + `type`.Set.Subtraction.name ) /** Performs resolution of typing functions in an arbitrary expression. @@ -95,10 +105,10 @@ case object TypeFunctions extends IRPass { * @param expr the expression to perform resolution in * @return `expr`, with any typing functions resolved */ - def resolveExpression(expr: IR.Expression): IR.Expression = { + def resolveExpression(expr: Expression): Expression = { expr.transformExpressions { - case asc: IR.Type.Ascription => asc - case app: IR.Application => + case asc: Type.Ascription => asc + case app: Application => val result = resolveApplication(app) app .getMetadata(DocumentationComments) @@ -112,14 +122,14 @@ case object TypeFunctions extends IRPass { * @param app the application to perform resolution in * @return `app`, with any typing functions resolved */ - def resolveApplication(app: IR.Application): IR.Expression = { + def resolveApplication(app: Application): Expression = { app match { case pre @ Application.Prefix(fn, arguments, _, _, _, _) => fn match { - case name: IR.Name if name.name == IR.Type.Set.Union.name => + case name: Name if name.name == `type`.Set.Union.name => val members = flattenUnion(app).map(resolveExpression) - IR.Type.Set.Union(members, app.location) - case name: IR.Name if knownTypingFunctions.contains(name.name) => + `type`.Set.Union(members, app.location) + case name: Name if knownTypingFunctions.contains(name.name) => resolveKnownFunction(name, pre.arguments, pre.location, pre) case _ => pre.copy( @@ -129,25 +139,25 @@ case object TypeFunctions extends IRPass { } case force @ Application.Force(target, _, _, _) => force.copy(target = resolveExpression(target)) - case seq @ Application.Literal.Sequence(items, _, _, _) => + case seq @ Application.Sequence(items, _, _, _) => seq.copy( items = items.map(resolveExpression) ) - case tSet @ Application.Literal.Typeset(expr, _, _, _) => + case tSet @ Application.Typeset(expr, _, _, _) => tSet.copy( expression = expr.map(resolveExpression) ) - case _: Application.Operator => + case _: Operator => throw new CompilerError( "Operators should not be present during typing functions lifting." ) } } - def flattenUnion(expr: IR.Expression): List[IR.Expression] = { + def flattenUnion(expr: Expression): List[Expression] = { expr match { - case Application.Prefix(n: IR.Name, args, _, _, _, _) - if n.name == IR.Type.Set.Union.name => + case Application.Prefix(n: Name, args, _, _, _, _) + if n.name == `type`.Set.Union.name => args.flatMap(arg => flattenUnion(arg.value)) case _ => List(expr) } @@ -159,11 +169,11 @@ case object TypeFunctions extends IRPass { * @return the IR node representing `prefix` */ def resolveKnownFunction( - name: IR.Name, - arguments: List[IR.CallArgument], + name: Name, + arguments: List[CallArgument], location: Option[IdentifiedLocation], originalIR: IR - ): IR.Expression = { + ): Expression = { val expectedNumArgs = 2 val lengthIsValid = arguments.length == expectedNumArgs val argsAreValid = arguments.forall(isValidCallArg) @@ -173,25 +183,25 @@ case object TypeFunctions extends IRPass { val rightArg = resolveExpression(arguments.last.value) name.name match { - case IR.Type.Ascription.name => - IR.Type.Ascription(leftArg, rightArg, location) - case IR.Type.Context.name => - IR.Type.Context(leftArg, rightArg, location) - case IR.Type.Error.name => - IR.Type.Error(leftArg, rightArg, location) - case IR.Type.Set.Concat.name => - IR.Type.Set.Concat(leftArg, rightArg, location) - case IR.Type.Set.Subsumption.name => - IR.Type.Set.Subsumption(leftArg, rightArg, location) - case IR.Type.Set.Equality.name => - IR.Type.Set.Equality(leftArg, rightArg, location) - case IR.Type.Set.Intersection.name => - IR.Type.Set.Intersection(leftArg, rightArg, location) - case IR.Type.Set.Subtraction.name => - IR.Type.Set.Subtraction(leftArg, rightArg, location) + case Type.Ascription.name => + Type.Ascription(leftArg, rightArg, location) + case Type.Context.name => + Type.Context(leftArg, rightArg, location) + case Type.Error.name => + Type.Error(leftArg, rightArg, location) + case `type`.Set.Concat.name => + `type`.Set.Concat(leftArg, rightArg, location) + case `type`.Set.Subsumption.name => + `type`.Set.Subsumption(leftArg, rightArg, location) + case `type`.Set.Equality.name => + `type`.Set.Equality(leftArg, rightArg, location) + case `type`.Set.Intersection.name => + `type`.Set.Intersection(leftArg, rightArg, location) + case `type`.Set.Subtraction.name => + `type`.Set.Subtraction(leftArg, rightArg, location) } } else { - IR.Error.InvalidIR(originalIR) + Error.InvalidIR(originalIR) } } @@ -200,9 +210,9 @@ case object TypeFunctions extends IRPass { * @param arg the argument to perform resolution in * @return `arg`, with any call arguments resolved */ - def resolveCallArgument(arg: IR.CallArgument): IR.CallArgument = { + def resolveCallArgument(arg: CallArgument): CallArgument = { arg match { - case spec @ IR.CallArgument.Specified(_, value, _, _, _) => + case spec @ CallArgument.Specified(_, value, _, _, _) => spec.copy( value = resolveExpression(value) ) @@ -222,9 +232,9 @@ case object TypeFunctions extends IRPass { * @param arg the argument to check * @return `true` if `arg` is valid, otherwise `false` */ - def isValidCallArg(arg: IR.CallArgument): Boolean = { + def isValidCallArg(arg: CallArgument): Boolean = { arg match { - case IR.CallArgument.Specified(name, _, _, _, _) => + case CallArgument.Specified(name, _, _, _, _) => name.isEmpty } } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala index 295af20e2cb5..078c5a0d9fb7 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeNames.scala @@ -2,7 +2,11 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Function, Module, Name} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Definition import org.enso.compiler.core.ir.MetadataStorage.ToPair +import org.enso.compiler.core.ir.`type` import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedModule} import org.enso.compiler.pass.IRPass @@ -35,9 +39,9 @@ case object TypeNames extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { val bindingsMap = ir.unsafeGetMetadata(BindingAnalysis, "bindings analysis did not run") ir.copy(bindings = ir.bindings.map { d => @@ -46,7 +50,7 @@ case object TypeNames extends IRPass { Nil, bindingsMap, mapped match { - case typ: IR.Module.Scope.Definition.Type => + case typ: Definition.Type => typ.members.foreach(m => m.arguments.foreach(a => doResolveType(typ.params.map(_.name), bindingsMap, a) @@ -61,11 +65,11 @@ case object TypeNames extends IRPass { private def resolveExpression( bindingsMap: BindingsMap, - ir: IR.Expression - ): IR.Expression = { - def go(ir: IR.Expression): IR.Expression = { + ir: Expression + ): Expression = { + def go(ir: Expression): Expression = { val processedIr = ir match { - case fn: IR.Function.Lambda => + case fn: Function.Lambda => fn.copy(arguments = fn.arguments.map(doResolveType(Nil, bindingsMap, _)) ) @@ -77,7 +81,7 @@ case object TypeNames extends IRPass { } private def doResolveType[T <: IR]( - typeParams: List[IR.Name], + typeParams: List[Name], bindingsMap: BindingsMap, ir: T ): T = { @@ -93,42 +97,42 @@ case object TypeNames extends IRPass { } private def resolveSignature( - typeParams: List[IR.Name], + typeParams: List[Name], bindingsMap: BindingsMap, - expression: IR.Expression - ): IR.Expression = + expression: Expression + ): Expression = expression.transformExpressions { case expr if SuspendedArguments.representsSuspended(expr) => expr - case n: IR.Name.Literal => + case n: Name.Literal => if (typeParams.exists(_.name == n.name)) { n } else { processResolvedName(n, bindingsMap.resolveName(n.name)) } - case n: IR.Name.Qualified => + case n: Name.Qualified => processResolvedName( n, bindingsMap.resolveQualifiedName(n.parts.map(_.name)) ) - case s: IR.Type.Set => + case s: `type`.Set => s.mapExpressions(resolveSignature(typeParams, bindingsMap, _)) } private def processResolvedName( - name: IR.Name, + name: Name, resolvedName: Either[BindingsMap.ResolutionError, BindingsMap.ResolvedName] - ): IR.Name = + ): Name = resolvedName .map(res => name.updateMetadata(this -->> Resolution(res))) .fold( error => - IR.Error.Resolution(name, IR.Error.Resolution.ResolverError(error)), + errors.Resolution(name, errors.Resolution.ResolverError(error)), n => n.getMetadata(this).get.target match { case _: ResolvedModule => - IR.Error.Resolution( + errors.Resolution( n, - IR.Error.Resolution.UnexpectedModule("type signature") + errors.Resolution.UnexpectedModule("type signature") ) case _ => n } @@ -144,9 +148,9 @@ case object TypeNames extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { ir } diff --git a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala index f68e1bfb58ae..6c88743eebea 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/pass/resolve/TypeSignatures.scala @@ -1,8 +1,18 @@ package org.enso.compiler.pass.resolve import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name, + Type +} import org.enso.compiler.core.ir.MetadataStorage._ +import org.enso.compiler.core.ir.expression.{errors, Comment, Error} import org.enso.compiler.core.CompilerError import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse._ @@ -45,9 +55,9 @@ case object TypeSignatures extends IRPass { * IR. */ override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = resolveModule(ir) + ): Module = resolveModule(ir) /** Resolves type signatures in an expression. * @@ -58,9 +68,9 @@ case object TypeSignatures extends IRPass { * IR. */ override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = resolveExpression(ir) + ): Expression = resolveExpression(ir) /** @inheritdoc */ @@ -71,22 +81,22 @@ case object TypeSignatures extends IRPass { * @param mod the module to resolve signatures in * @return `mod`, with type signatures resolved */ - private def resolveModule(mod: IR.Module): IR.Module = { - var lastSignature: Option[IR.Type.Ascription] = None + private def resolveModule(mod: Module): Module = { + var lastSignature: Option[Type.Ascription] = None - val newBindings: List[IR.Module.Scope.Definition] = mod.bindings.flatMap { - case sig: IR.Type.Ascription => - val res = lastSignature.map(IR.Error.Unexpected.TypeSignature(_)) + val newBindings: List[Definition] = mod.bindings.flatMap { + case sig: Type.Ascription => + val res = lastSignature.map(errors.Unexpected.TypeSignature(_)) lastSignature = Some(sig) res - case meth: IR.Module.Scope.Definition.Method => + case meth: definition.Method => val newMethod = meth.mapExpressions(resolveExpression) newMethod.body.preorder.foreach { - case fn: IR.Function => verifyAscribedArguments(fn.arguments) - case _ => + case fn: Function => verifyAscribedArguments(fn.arguments) + case _ => } val res = lastSignature match { - case Some(asc @ IR.Type.Ascription(typed, sig, _, _, _)) => + case Some(asc @ Type.Ascription(typed, sig, _, _, _)) => val methodRef = meth.methodReference val newMethodWithDoc = asc .getMetadata(DocumentationComments) @@ -104,7 +114,7 @@ case object TypeSignatures extends IRPass { .getOrElse(newMethodWithDoc) typed match { - case ref: IR.Name.MethodReference => + case ref: Name.MethodReference => if (ref isSameReferenceAs methodRef) { Some( newMethodWithAnnotations.updateMetadata( @@ -113,13 +123,13 @@ case object TypeSignatures extends IRPass { ) } else { List( - IR.Error.Unexpected.TypeSignature(asc), + errors.Unexpected.TypeSignature(asc), newMethodWithAnnotations ) } case _ => List( - IR.Error.Unexpected.TypeSignature(asc), + errors.Unexpected.TypeSignature(asc), newMethodWithAnnotations ) } @@ -128,7 +138,7 @@ case object TypeSignatures extends IRPass { lastSignature = None res - case ut: IR.Module.Scope.Definition.Type => + case ut: Definition.Type => ut.members.foreach(d => verifyAscribedArguments(d.arguments)) Some( ut @@ -138,25 +148,25 @@ case object TypeSignatures extends IRPass { ) .mapExpressions(resolveExpression) ) - case err: IR.Error => Some(err) - case ann: IR.Name.GenericAnnotation => Some(ann) - case _: IR.Module.Scope.Definition.SugaredType => + case err: Error => Some(err) + case ann: Name.GenericAnnotation => Some(ann) + case _: Definition.SugaredType => throw new CompilerError( "Complex type definitions should not be present during type " + "signature resolution." ) - case _: IR.Name.BuiltinAnnotation => + case _: Name.BuiltinAnnotation => throw new CompilerError( "Annotations should already be associated by the point of " + "type signature resolution." ) - case _: IR.Comment.Documentation => + case _: Comment.Documentation => throw new CompilerError( "Documentation comments should not be present during type " + "signature resolution." ) } ::: lastSignature - .map(asc => IR.Error.Unexpected.TypeSignature(asc)) + .map(asc => errors.Unexpected.TypeSignature(asc)) .toList mod.copy( @@ -171,7 +181,7 @@ case object TypeSignatures extends IRPass { * @param fn the function to check arguments for */ private def verifyAscribedArguments( - arguments: List[IR.DefinitionArgument] + arguments: List[DefinitionArgument] ): Unit = { arguments.foreach(arg => arg.ascribedType.map(t => arg.updateMetadata(this -->> Signature(t))) @@ -183,26 +193,26 @@ case object TypeSignatures extends IRPass { * @param expr the expression to resolve signatures in * @return `expr`, with any type signatures resolved */ - private def resolveExpression(expr: IR.Expression): IR.Expression = { + private def resolveExpression(expr: Expression): Expression = { expr.transformExpressions { - case block: IR.Expression.Block => resolveBlock(block) - case sig: IR.Type.Ascription => resolveAscription(sig) + case block: Expression.Block => resolveBlock(block) + case sig: Type.Ascription => resolveAscription(sig) } } private def resolveDefinitionData( - data: IR.Module.Scope.Definition.Data - ): IR.Module.Scope.Definition.Data = { + data: Definition.Data + ): Definition.Data = { data.copy( arguments = data.arguments.map(resolveArgument) ) } private def resolveArgument( - argument: IR.DefinitionArgument - ): IR.DefinitionArgument = + argument: DefinitionArgument + ): DefinitionArgument = argument match { - case specified @ IR.DefinitionArgument.Specified( + case specified @ DefinitionArgument.Specified( _, Some(ascribedType), _, @@ -225,7 +235,7 @@ case object TypeSignatures extends IRPass { * @param sig the signature to convert * @return the typed expression in `sig`, with `signature` attached */ - private def resolveAscription(sig: IR.Type.Ascription): IR.Expression = { + private def resolveAscription(sig: Type.Ascription): Expression = { val newTyped = sig.typed.mapExpressions(resolveExpression) val newSig = sig.signature.mapExpressions(resolveExpression) newTyped.updateMetadata(this -->> Signature(newSig)) @@ -236,24 +246,24 @@ case object TypeSignatures extends IRPass { * @param block the block to resolve signatures in * @return `block`, with any type signatures resolved */ - private def resolveBlock(block: IR.Expression.Block): IR.Expression.Block = { - var lastSignature: Option[IR.Type.Ascription] = None + private def resolveBlock(block: Expression.Block): Expression.Block = { + var lastSignature: Option[Type.Ascription] = None val allBlockExpressions = block.expressions :+ block.returnValue val newExpressions = allBlockExpressions.flatMap { - case sig: IR.Type.Ascription => + case sig: Type.Ascription => val res = lastSignature match { - case Some(oldSig) => Some(IR.Error.Unexpected.TypeSignature(oldSig)) + case Some(oldSig) => Some(errors.Unexpected.TypeSignature(oldSig)) case None => None } lastSignature = Some(sig) res - case binding: IR.Expression.Binding => + case binding: Expression.Binding => val newBinding = binding.mapExpressions(resolveExpression) val res = lastSignature match { - case Some(asc @ IR.Type.Ascription(typed, sig, _, _, _)) => + case Some(asc @ Type.Ascription(typed, sig, _, _, _)) => val name = binding.name val newBindingWithDoc = asc .getMetadata(DocumentationComments) @@ -263,20 +273,20 @@ case object TypeSignatures extends IRPass { .getOrElse(newBinding) typed match { - case typedName: IR.Name => + case typedName: Name => if (typedName.name == name.name) { Some( newBindingWithDoc.updateMetadata(this -->> Signature(sig)) ) } else { List( - IR.Error.Unexpected.TypeSignature(asc), + errors.Unexpected.TypeSignature(asc), newBindingWithDoc ) } case _ => List( - IR.Error.Unexpected.TypeSignature(asc), + errors.Unexpected.TypeSignature(asc), newBindingWithDoc ) } @@ -286,7 +296,7 @@ case object TypeSignatures extends IRPass { lastSignature = None res case a => Some(resolveExpression(a)) - } ::: lastSignature.map(IR.Error.Unexpected.TypeSignature(_)).toList + } ::: lastSignature.map(errors.Unexpected.TypeSignature(_)).toList block.copy( expressions = newExpressions.init, @@ -300,7 +310,7 @@ case object TypeSignatures extends IRPass { * * @param signature the expression for the type signature */ - case class Signature(signature: IR.Expression) extends IRPass.IRMetadata { + case class Signature(signature: Expression) extends IRPass.IRMetadata { override val metadataName: String = "TypeSignatures.Signature" /** @inheritdoc */ diff --git a/engine/runtime/src/main/scala/org/enso/compiler/phase/ImportResolver.scala b/engine/runtime/src/main/scala/org/enso/compiler/phase/ImportResolver.scala index ffcfcfede475..c4a5358491c3 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/phase/ImportResolver.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/phase/ImportResolver.scala @@ -1,8 +1,12 @@ package org.enso.compiler.phase import org.enso.compiler.Compiler -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.{Export, Import} +import org.enso.compiler.core.IR.AsMetadata +import org.enso.compiler.core.ir.{Module => IRModule} +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Import +import org.enso.compiler.core.ir.module.scope.Export import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{ ModuleReference, @@ -57,10 +61,10 @@ class ImportResolver(compiler: Compiler) { ) || !current.hasCrossModuleLinks ) { val importedModules: List[ - (IR.Module.Scope.Import, Option[BindingsMap.ResolvedImport]) + (Import, Option[BindingsMap.ResolvedImport]) ] = ir.imports.map { - case imp: IR.Module.Scope.Import.Module => + case imp: Import.Module => tryResolveImport(ir, imp) case other => (other, None) } @@ -140,7 +144,7 @@ class ImportResolver(compiler: Compiler) { } private def tryResolveAsType( - name: IR.Name.Qualified + name: Name.Qualified ): Option[ResolvedType] = { val tp = name.parts.last.name val mod = name.parts.dropRight(1).map(_.name).mkString(".") @@ -160,9 +164,9 @@ class ImportResolver(compiler: Compiler) { } private def tryResolveImport( - module: IR.Module, + module: IRModule, imp: Import.Module - ): (IR.Module.Scope.Import, Option[BindingsMap.ResolvedImport]) = { + ): (Import, Option[BindingsMap.ResolvedImport]) = { val impName = imp.name.name val exp = module.exports .collect { case ex: Export.Module if ex.name.name == impName => ex } @@ -174,7 +178,7 @@ class ImportResolver(compiler: Compiler) { case e if e.onlyNames.isEmpty => e } val qualifiedImports = fromAllExports.collect { - case IR.Module.Scope.Export.Module( + case Export.Module( _, _, _, @@ -188,7 +192,7 @@ class ImportResolver(compiler: Compiler) { onlyNames.map(_.name) } val importsWithHiddenNames = fromAllExports.collect { - case e @ IR.Module.Scope.Export.Module( + case e @ Export.Module( _, _, _, @@ -254,9 +258,9 @@ class ImportResolver(compiler: Compiler) { (imp, Some(BindingsMap.ResolvedImport(imp, exp, tp))) case None => ( - IR.Error.ImportExport( + errors.ImportExport( imp, - IR.Error.ImportExport.ModuleDoesNotExist(impName) + errors.ImportExport.ModuleDoesNotExist(impName) ), None ) @@ -264,9 +268,9 @@ class ImportResolver(compiler: Compiler) { } case Left(loadingError) => ( - IR.Error.ImportExport( + errors.ImportExport( imp, - IR.Error.ImportExport.PackageCouldNotBeLoaded( + errors.ImportExport.PackageCouldNotBeLoaded( impName, loadingError.toString ) diff --git a/engine/runtime/src/main/scala/org/enso/compiler/refactoring/IRUtils.scala b/engine/runtime/src/main/scala/org/enso/compiler/refactoring/IRUtils.scala index 66f0b778711d..04124f0c2b2f 100644 --- a/engine/runtime/src/main/scala/org/enso/compiler/refactoring/IRUtils.scala +++ b/engine/runtime/src/main/scala/org/enso/compiler/refactoring/IRUtils.scala @@ -1,6 +1,7 @@ package org.enso.compiler.refactoring import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Name import org.enso.compiler.data.BindingsMap import org.enso.compiler.pass.analyse.DataflowAnalysis import org.enso.compiler.pass.resolve.MethodCalls @@ -26,13 +27,13 @@ trait IRUtils { */ def findLocalUsages( ir: IR, - literal: IR.Name.Literal - ): Option[Set[IR.Name.Literal]] = { + literal: Name.Literal + ): Option[Set[Name.Literal]] = { for { usages <- findStaticUsages(ir, literal) } yield { usages.collect { - case usage: IR.Name.Literal if usage.name == literal.name => usage + case usage: Name.Literal if usage.name == literal.name => usage } } } @@ -47,14 +48,14 @@ trait IRUtils { def findModuleMethodUsages( moduleName: QualifiedName, ir: IR, - node: IR.Name - ): Option[Set[IR.Name.Literal]] = + node: Name + ): Option[Set[Name.Literal]] = for { usages <- findDynamicUsages(ir, node) } yield { usages .collect { - case usage: IR.Name.Literal + case usage: Name.Literal if usage.isMethod && usage.name == node.name => usage } @@ -79,7 +80,7 @@ trait IRUtils { */ private def findStaticUsages( ir: IR, - literal: IR.Name.Literal + literal: Name.Literal ): Option[Set[IR]] = { for { metadata <- ir.getMetadata(DataflowAnalysis) @@ -105,7 +106,7 @@ trait IRUtils { */ private def findDynamicUsages( ir: IR, - node: IR.Name + node: Name ): Option[Set[IR]] = { for { metadata <- ir.getMetadata(DataflowAnalysis) diff --git a/engine/runtime/src/test/java/org/enso/compiler/AnnotationsCompilerTest.java b/engine/runtime/src/test/java/org/enso/compiler/AnnotationsCompilerTest.java index 9ee12724e01c..2f67460d227b 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/AnnotationsCompilerTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/AnnotationsCompilerTest.java @@ -1,11 +1,9 @@ package org.enso.compiler; -import org.enso.compiler.core.IR$Error$Syntax; -import org.enso.compiler.core.IR$Error$Syntax$UnexpectedDeclarationInType$; -import org.enso.compiler.core.IR$Function$Binding; -import org.enso.compiler.core.IR$Module$Scope$Definition$Data; -import org.enso.compiler.core.IR$Module$Scope$Definition$SugaredType; -import org.enso.compiler.core.IR$Name$Annotation; +import org.enso.compiler.core.ir.expression.errors.Syntax; +import org.enso.compiler.core.ir.Function; +import org.enso.compiler.core.ir.Name; +import org.enso.compiler.core.ir.module.scope.Definition; import org.junit.Test; import static org.junit.Assert.assertEquals; @@ -21,8 +19,8 @@ public void testModuleMethod() throws Exception { foo a b = a b """); - var annotation1 = (IR$Name$Annotation) ir.bindings().apply(0); - var annotation2 = (IR$Name$Annotation) ir.bindings().apply(1); + var annotation1 = (Name.Annotation) ir.bindings().apply(0); + var annotation2 = (Name.Annotation) ir.bindings().apply(1); assertEquals(annotation1.name(), "a"); assertEquals(annotation2.name(), "b"); @@ -36,8 +34,8 @@ public void testExtensionMethod() throws Exception { Foo.foo a b = a b """); - var annotation1 = (IR$Name$Annotation) ir.bindings().apply(0); - var annotation2 = (IR$Name$Annotation) ir.bindings().apply(1); + var annotation1 = (Name.Annotation) ir.bindings().apply(0); + var annotation2 = (Name.Annotation) ir.bindings().apply(1); assertEquals(annotation1.name(), "a"); assertEquals(annotation2.name(), "b"); @@ -52,11 +50,11 @@ public void testTypeMethod() throws Exception { method a b = a b """); - var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0); + var typeDefinition = (Definition.SugaredType) ir.bindings().apply(0); - var annotation1 = (IR$Name$Annotation) typeDefinition.body().apply(0); - var annotation2 = (IR$Name$Annotation) typeDefinition.body().apply(1); - var function = (IR$Function$Binding) typeDefinition.body().apply(2); + var annotation1 = (Name.Annotation) typeDefinition.body().apply(0); + var annotation2 = (Name.Annotation) typeDefinition.body().apply(1); + var function = (Function.Binding) typeDefinition.body().apply(2); assertEquals(annotation1.name(), "a"); assertEquals(annotation2.name(), "b"); @@ -72,11 +70,11 @@ public void testConstructor() throws Exception { Cons a b = a b """); - var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0); + var typeDefinition = (Definition.SugaredType) ir.bindings().apply(0); - var annotation1 = (IR$Name$Annotation) typeDefinition.body().apply(0); - var annotation2 = (IR$Name$Annotation) typeDefinition.body().apply(1); - var constructor = (IR$Module$Scope$Definition$Data) typeDefinition.body().apply(2); + var annotation1 = (Name.Annotation) typeDefinition.body().apply(0); + var annotation2 = (Name.Annotation) typeDefinition.body().apply(1); + var constructor = (Definition.Data) typeDefinition.body().apply(2); assertEquals(annotation1.name(), "a"); assertEquals(annotation2.name(), "b"); @@ -90,11 +88,11 @@ public void testInvalidComplexType() throws Exception { bar a = """); - var typeDefinition = (IR$Module$Scope$Definition$SugaredType) ir.bindings().apply(0); + var typeDefinition = (Definition.SugaredType) ir.bindings().apply(0); var methodOrError = typeDefinition.body().apply(0); - if (methodOrError instanceof IR$Error$Syntax error) { - assertEquals(error.reason(), IR$Error$Syntax$UnexpectedDeclarationInType$.MODULE$); + if (methodOrError instanceof Syntax error) { + assertEquals(error.reason(), Syntax.UnexpectedDeclarationInType$.MODULE$); } else { fail("Expecting error instead of bar function: " + methodOrError); } diff --git a/engine/runtime/src/test/java/org/enso/compiler/CompilerTest.java b/engine/runtime/src/test/java/org/enso/compiler/CompilerTest.java index ca6ee7686e92..5ecf5c7301a6 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/CompilerTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/CompilerTest.java @@ -8,6 +8,7 @@ import java.util.function.Function; import org.enso.compiler.core.EnsoParser; import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Module; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -27,16 +28,16 @@ public static void closeEnsoParser() throws Exception { ensoCompiler.close(); } - protected static IR.Module parse(String code) throws IOException { + protected static Module parse(String code) throws IOException { var src = Source.newBuilder("enso", code, "test-" + Integer.toHexString(code.hashCode()) + ".enso") .build(); - IR.Module ir = ensoCompiler.compile(src.getCharacters()); + Module ir = ensoCompiler.compile(src.getCharacters()); assertNotNull("IR was generated", ir); return ir; } - static void assertIR(String msg, IR.Module old, IR.Module now) throws IOException { + static void assertIR(String msg, Module old, Module now) throws IOException { Function filter = f -> simplifyIR(f, true, true, false); String ir1 = filter.apply(old); String ir2 = filter.apply(now); @@ -100,32 +101,32 @@ private static String simplifyIR(IR ir, boolean noIds, boolean noLocations, bool } if (lessDocs) { for (;;) { - final String pref = "IR.Comment.Documentation("; + final String pref = "Comment.Documentation("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("location =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Comment.Doc(" + txt.substring(to); + txt = txt.substring(0, at) + "Comment.Doc(" + txt.substring(to); } for (;;) { - final String pref = "IR.Case.Pattern.Doc("; + final String pref = "Case.Pattern.Doc("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("location =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Comment.CaseDoc(" + txt.substring(to); + txt = txt.substring(0, at) + "Comment.CaseDoc(" + txt.substring(to); } } for (;;) { - final String pref = "IR.Error.Syntax("; + final String pref = "errors.Syntax("; int at = txt.indexOf(pref); if (at == -1) { break; } int to = txt.indexOf("reason =", at + pref.length()); - txt = txt.substring(0, at) + "IR.Error.Syntax (" + txt.substring(to); + txt = txt.substring(0, at) + "errors.Syntax (" + txt.substring(to); } return txt; } diff --git a/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java b/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java index a58cb731bd10..259aabad3b3b 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/ErrorCompilerTest.java @@ -1,16 +1,7 @@ package org.enso.compiler; -import org.enso.compiler.core.IR; -import org.enso.compiler.core.IR$Error$Syntax; -import org.enso.compiler.core.IR$Error$Syntax$InvalidEscapeSequence$; -import org.enso.compiler.core.IR$Error$Syntax$InvalidExport; -import org.enso.compiler.core.IR$Error$Syntax$InvalidImport; -import org.enso.compiler.core.IR$Error$Syntax$InvalidUnderscore$; -import org.enso.compiler.core.IR$Error$Syntax$Reason; -import org.enso.compiler.core.IR$Error$Syntax$UnclosedTextLiteral$; -import org.enso.compiler.core.IR$Error$Syntax$UnexpectedExpression$; -import org.enso.compiler.core.IR$Error$Syntax$UnrecognizedToken$; -import org.enso.compiler.core.IR$Error$Syntax$UnsupportedSyntax; +import org.enso.compiler.core.ir.Module; +import org.enso.compiler.core.ir.expression.errors.Syntax; import org.enso.syntax.text.Location; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -26,7 +17,7 @@ public void unfinishedLiteral1() throws Exception { foo = "unfinished literal... """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 28); + assertSingleSyntaxError(ir, Syntax.UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 28); } @Test @@ -36,7 +27,7 @@ public void dotUnderscore() throws Exception { op._ """); - assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidUnderscore$.MODULE$, "Invalid use of _", 14, 15); + assertSingleSyntaxError(ir, Syntax.InvalidUnderscore$.MODULE$, "Invalid use of _", 14, 15); } @Test @@ -46,7 +37,7 @@ public void dotUnderscore2() throws Exception { op._.something """); - assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidUnderscore$.MODULE$, "Invalid use of _", 14, 15); + assertSingleSyntaxError(ir, Syntax.InvalidUnderscore$.MODULE$, "Invalid use of _", 14, 15); } @Test @@ -54,7 +45,7 @@ public void unfinishedLiteral2() throws Exception { var ir = parse(""" foo = 'unfinished literal... """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 28); + assertSingleSyntaxError(ir, Syntax.UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 28); } @Test @@ -62,7 +53,7 @@ public void unpairedLiteral1() throws Exception { var ir = parse(""" foo = "unpaired literal' """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 24); + assertSingleSyntaxError(ir, Syntax.UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 24); } @Test @@ -70,19 +61,19 @@ public void unpairedLiteral2() throws Exception { var ir = parse(""" foo = 'unpaired literal" """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 24); + assertSingleSyntaxError(ir, Syntax.UnclosedTextLiteral$.MODULE$, "Unclosed text literal", 6, 24); } @Test public void spaceRequired() throws Exception { var ir = parse("foo = if cond.x else.y"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 8); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 8); } @Test public void incompleteTypeDefinition() throws Exception { var ir = parse("type"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 4); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 4); } @Test @@ -91,7 +82,7 @@ public void badCase1() throws Exception { foo = case x of 4 """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 18); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 18); } @Test @@ -100,7 +91,7 @@ public void badCase2() throws Exception { foo = case x of 4 -> """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 21); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 21); } @Test @@ -109,7 +100,7 @@ public void badCase3() throws Exception { foo = case x of 4-> """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 20); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 20); } @Test @@ -119,94 +110,94 @@ public void badCase4() throws Exception { case value of -1 ->"minus one" """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 32, 45); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 32, 45); } @Test public void malformedSequence1() throws Exception { var ir = parse("(1, )"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 5); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 5); } @Test public void malformedSequence2() throws Exception { var ir = parse("foo = (1, )"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 7, 9); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 7, 9); } @Test public void unmatchedDemiliter1() throws Exception { var ir = parse("("); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); } @Test public void unmatchedDemiliter2() throws Exception { var ir = parse(")"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); } @Test public void unmatchedDemiliter3() throws Exception { var ir = parse("["); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); } @Test public void unmatchedDemiliter4() throws Exception { var ir = parse("["); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); } @Test public void unmatchedDemiliter5() throws Exception { var ir = parse("foo = ("); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); } @Test public void unmatchedDemiliter6() throws Exception { var ir = parse("foo = )"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); } @Test public void unmatchedDemiliter7() throws Exception { var ir = parse("foo = ["); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); } @Test public void unmatchedDemiliter8() throws Exception { var ir = parse("foo = ]"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 7); } @Test public void unexpectedSpecialOperator() throws Exception { var ir = parse("foo = 1, 2"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 10); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 6, 10); } @Test public void malformedImport1() throws Exception { var ir = parse("import"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 6); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 6); } @Test public void malformedImport2() throws Exception { var ir = parse("import as Foo"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); } - private IR$Error$Syntax$InvalidImport invalidImport(String msg) { - return new IR$Error$Syntax$InvalidImport(msg); + private Syntax.InvalidImport invalidImport(String msg) { + return new Syntax.InvalidImport(msg); } - private IR$Error$Syntax$InvalidExport invalidExport(String msg) { - return new IR$Error$Syntax$InvalidExport(msg); + private Syntax.InvalidExport invalidExport(String msg) { + return new Syntax.InvalidExport(msg); } @Test @@ -248,13 +239,13 @@ public void malformedImport8() throws Exception { @Test public void malformedImport9() throws Exception { var ir = parse("polyglot import Foo"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnrecognizedToken$.MODULE$, "Unrecognized token", 0, 19); + assertSingleSyntaxError(ir, Syntax.UnrecognizedToken$.MODULE$, "Unrecognized token", 0, 19); } @Test public void malformedImport10() throws Exception { var ir = parse("polyglot java import"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 20); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 20); } @Test @@ -262,7 +253,7 @@ public void malformedTypeException() throws Exception { var ir = parse(""" fan_out_to_columns : Table -> Text | Integer -> (Any -> Vector Any) -> | Nothing -> Problem_Behavior -> Table | Nothing """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 48, 119); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 48, 119); } @Test @@ -292,13 +283,13 @@ public void malformedImport14() throws Exception { @Test public void malformedExport1() throws Exception { var ir = parse("export"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 6); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 6); } @Test public void malformedExport2() throws Exception { var ir = parse("export as Foo"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); } @Test @@ -358,37 +349,37 @@ public void malformedExport11() throws Exception { @Test public void invalidToken1() throws Exception { var ir = parse("`"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 1); } @Test public void invalidToken2() throws Exception { var ir = parse("splice_outside_text = `"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 22, 23); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 22, 23); } @Test public void illegalForeignBody1() throws Exception { var ir = parse("foreign 4"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 9); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 9); } @Test public void illegalForeignBody2() throws Exception { var ir = parse("foreign 4 * 4"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 13); } @Test public void illegalForeignBody3() throws Exception { var ir = parse("foreign foo = \"4\""); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 17); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 17); } @Test public void illegalForeignBody4() throws Exception { var ir = parse("foreign js foo = 4"); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 18); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 0, 18); } @Test @@ -396,7 +387,7 @@ public void illegalEscapeSequence() throws Exception { var ir = parse(""" escape = 'wrong \\c sequence' """); - assertSingleSyntaxError(ir, IR$Error$Syntax$InvalidEscapeSequence$.MODULE$.apply("wrong sequence"), "Invalid escape sequence wrong sequence", 9, 28); + assertSingleSyntaxError(ir, new Syntax.InvalidEscapeSequence("wrong sequence"), "Invalid escape sequence wrong sequence", 9, 28); } @Test @@ -409,7 +400,7 @@ public void testNPE183814303() throws Exception { z = x. length IO.println z """); - assertSingleSyntaxError(ir, IR$Error$Syntax$UnexpectedExpression$.MODULE$, "Unexpected expression", 60, 62); + assertSingleSyntaxError(ir, Syntax.UnexpectedExpression$.MODULE$, "Unexpected expression", 60, 62); } @Test @@ -419,18 +410,18 @@ public void testNPE183863754() throws Exception { # meh 42 """); - var errors = ir.preorder().filter(IR$Error$Syntax.class::isInstance).map(IR$Error$Syntax.class::cast); + var errors = ir.preorder().filter(Syntax.class::isInstance).map(Syntax.class::cast); assertEquals("Two errors", 2, errors.size()); - assertTrue(errors.head().reason() instanceof IR$Error$Syntax$UnsupportedSyntax); + assertTrue(errors.head().reason() instanceof Syntax.UnsupportedSyntax); assertEquals(errors.head().location().get().start(), 0); assertEquals(errors.head().location().get().length(), 6); } private void assertSingleSyntaxError( - IR.Module ir, IR$Error$Syntax$Reason type, + Module ir, Syntax.Reason type, String msg, int start, int end ) { - var errors = assertIR(ir, IR$Error$Syntax.class, 1); + var errors = assertIR(ir, Syntax.class, 1); assertEquals(type, errors.head().reason()); if (msg != null) { assertEquals(msg, errors.head().message()); @@ -438,7 +429,7 @@ private void assertSingleSyntaxError( assertEquals(new Location(start, end), errors.head().location().get().location()); } - private List assertIR(IR.Module ir, Class type, int count) { + private List assertIR(Module ir, Class type, int count) { var errors = ir.preorder().filter(type::isInstance).map(type::cast); assertEquals("Expecting errors: " + errors, count, errors.size()); return errors; diff --git a/engine/runtime/src/test/java/org/enso/compiler/SerdeCompilerTest.java b/engine/runtime/src/test/java/org/enso/compiler/SerdeCompilerTest.java index 65816025914b..d4589615059d 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/SerdeCompilerTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/SerdeCompilerTest.java @@ -16,7 +16,7 @@ import java.util.logging.Handler; import java.util.logging.LogRecord; import java.util.logging.SimpleFormatter; -import org.enso.compiler.core.IR; +import org.enso.compiler.core.ir.Module; import org.enso.interpreter.runtime.EnsoContext; import org.enso.pkg.PackageManager; import org.enso.polyglot.LanguageInfo; @@ -38,7 +38,7 @@ public void testFibTest() throws Exception { private void parseSerializedModule(String projectName, String forbiddenMessage) throws InterruptedException, ExecutionException, IOException, TimeoutException { - IR.Module old; + Module old; var pkgPath = new File(getClass().getClassLoader().getResource(projectName).getPath()); var pkg = PackageManager.Default().fromDirectory(pkgPath).get(); try (org.graalvm.polyglot.Context ctx = ensoContextForPackage(projectName, pkgPath, true)) { @@ -73,7 +73,7 @@ private void parseSerializedModule(String projectName, String forbiddenMessage) ctx.leave(); } - IR.Module now; + Module now; mockHandler.failOnMessage(forbiddenMessage); try (org.graalvm.polyglot.Context ctx = ensoContextForPackage(projectName, pkgPath, false)) { diff --git a/engine/runtime/src/test/java/org/enso/compiler/VectorArraySignatureTest.java b/engine/runtime/src/test/java/org/enso/compiler/VectorArraySignatureTest.java index f0cd339ed33f..d1cbfbe0e0e6 100644 --- a/engine/runtime/src/test/java/org/enso/compiler/VectorArraySignatureTest.java +++ b/engine/runtime/src/test/java/org/enso/compiler/VectorArraySignatureTest.java @@ -10,10 +10,10 @@ import java.util.HashMap; import org.enso.compiler.core.EnsoParser; import org.enso.compiler.core.IR; -import org.enso.compiler.core.IR$Comment$Documentation; -import org.enso.compiler.core.IR$Function$Binding; -import org.enso.compiler.core.IR$Module$Scope$Definition$SugaredType; -import org.enso.compiler.core.IR$Name$Self; +import org.enso.compiler.core.ir.expression.Comment; +import org.enso.compiler.core.ir.Function; +import org.enso.compiler.core.ir.Name; +import org.enso.compiler.core.ir.module.scope.Definition; import org.junit.AfterClass; import static org.junit.Assert.assertEquals; import org.junit.BeforeClass; @@ -76,7 +76,7 @@ public FileVisitResult postVisitDirectory(Path t, IOException ioe) throws IOExce var vectorSrc = Files.readString(vectorAndArray[1]); var arrayIR = ensoCompiler.compile(arraySrc).preorder().filter((v) -> { - if (v instanceof IR$Module$Scope$Definition$SugaredType t) { + if (v instanceof Definition.SugaredType t) { if ("Array".equals(t.name().name())) { return true; } @@ -84,7 +84,7 @@ public FileVisitResult postVisitDirectory(Path t, IOException ioe) throws IOExce return false; }).head(); var vectorIR = ensoCompiler.compile(vectorSrc).preorder().filter((v) -> { - if (v instanceof IR$Module$Scope$Definition$SugaredType t) { + if (v instanceof Definition.SugaredType t) { if ("Vector".equals(t.name().name())) { return true; } @@ -92,40 +92,40 @@ public FileVisitResult postVisitDirectory(Path t, IOException ioe) throws IOExce return false; }).head(); - var documentation = new HashMap(); - var lastDoc = new IR$Comment$Documentation[1]; + var documentation = new HashMap(); + var lastDoc = new Comment.Documentation[1]; final Function1 filter = (v) -> { - if (v instanceof IR$Comment$Documentation d) { + if (v instanceof Comment.Documentation d) { lastDoc[0] = d; } - if (v instanceof IR$Function$Binding b && b.arguments().head().name() instanceof IR$Name$Self) { + if (v instanceof Function.Binding b && b.arguments().head().name() instanceof Name.Self) { documentation.put(b, lastDoc[0]); lastDoc[0] = null; } - return v instanceof IR$Function$Binding b && b.arguments().head().name() instanceof IR$Name$Self; + return v instanceof Function.Binding b && b.arguments().head().name() instanceof Name.Self; }; var arrayFns = arrayIR.preorder().filter(filter); var vectorFns = vectorIR.preorder().filter(filter); - var arrayNames = arrayFns.map((v) -> v instanceof IR$Function$Binding b ? b.name().name() : null); - var vectorNames = vectorFns.map((v) -> v instanceof IR$Function$Binding b ? b.name().name() : null); + var arrayNames = arrayFns.map((v) -> v instanceof Function.Binding b ? b.name().name() : null); + var vectorNames = vectorFns.map((v) -> v instanceof Function.Binding b ? b.name().name() : null); - var missingInArray = vectorFns.filter((v) -> v instanceof IR$Function$Binding b && !arrayNames.contains(b.name().name())); - var missingNamesInArray = missingInArray.map((v) -> v instanceof IR$Function$Binding b ? b.name().name() : null); + var missingInArray = vectorFns.filter((v) -> v instanceof Function.Binding b && !arrayNames.contains(b.name().name())); + var missingNamesInArray = missingInArray.map((v) -> v instanceof Function.Binding b ? b.name().name() : null); - var missingInVector = arrayFns.filter((v) -> v instanceof IR$Function$Binding b && !vectorNames.contains(b.name().name())); - var missingNamesInVector = missingInVector.map((v) -> v instanceof IR$Function$Binding b ? b.name().name() : null); + var missingInVector = arrayFns.filter((v) -> v instanceof Function.Binding b && !vectorNames.contains(b.name().name())); + var missingNamesInVector = missingInVector.map((v) -> v instanceof Function.Binding b ? b.name().name() : null); assertTrue("Nothing is missing in vector: " + missingNamesInVector, missingNamesInVector.isEmpty()); assertTrue("Nothing is missing in array: " + missingNamesInArray, missingNamesInArray.isEmpty()); vectorFns.foreach((v) -> { - if (v instanceof IR$Function$Binding b) { + if (v instanceof Function.Binding b) { var name = b.name().name(); var d = documentation.get(b); if (!d.doc().contains("PRIVATE")) { assertNotNull("Documentation for " + name, d); - var head = arrayFns.filter((av) -> av instanceof IR$Function$Binding ab && ab.name().name().equals(b.name().name())).head(); + var head = arrayFns.filter((av) -> av instanceof Function.Binding ab && ab.name().name().equals(b.name().name())).head(); var ad = documentation.get(head); assertNotNull("No documentation for Array." + name, ad); var exp = d.doc() diff --git a/engine/runtime/src/test/java/org/enso/interpreter/runtime/ModuleTestUtils.java b/engine/runtime/src/test/java/org/enso/interpreter/runtime/ModuleTestUtils.java index e68df2aa0eee..5e6c24f59cdb 100644 --- a/engine/runtime/src/test/java/org/enso/interpreter/runtime/ModuleTestUtils.java +++ b/engine/runtime/src/test/java/org/enso/interpreter/runtime/ModuleTestUtils.java @@ -1,12 +1,11 @@ package org.enso.interpreter.runtime; -import org.enso.compiler.core.IR; import org.enso.polyglot.CompilationStage; public final class ModuleTestUtils { private ModuleTestUtils() {} - public static void unsafeSetIr(Module m, IR.Module ir) { + public static void unsafeSetIr(Module m, org.enso.compiler.core.ir.Module ir) { m.unsafeSetIr(ir); } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/refactoring/IRUtilsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/refactoring/IRUtilsTest.scala index 768caeca3d04..7cad16d66e52 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/refactoring/IRUtilsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/refactoring/IRUtilsTest.scala @@ -1,6 +1,8 @@ package org.enso.compiler.refactoring import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Name import org.enso.interpreter.runtime import org.enso.interpreter.runtime.EnsoContext import org.enso.interpreter.test.InterpreterContext @@ -23,7 +25,7 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { private val Module = QualifiedName(List("Unnamed"), "Test") - def preprocessModule(name: QualifiedName): IR.Module = { + def preprocessModule(name: QualifiedName): Module = { val module = new runtime.Module( name, null, @@ -33,17 +35,17 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { module.getIr } - def preprocessModule: IR.Module = + def preprocessModule: Module = preprocessModule(Module) } private def findUsagesOfLiteral( - module: IR.Module, + module: Module, ir: IR - ): Option[Set[IR.Name.Literal]] = { + ): Option[Set[Name.Literal]] = { ir match { - case literal: IR.Name.Literal => + case literal: Name.Literal => IRUtils.findLocalUsages(module, literal) case _ => fail(s"Trying to find literal usages of [${ir.getClass}]: [$ir]") @@ -52,12 +54,11 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { private def findUsagesOfStaticMethod( moduleName: QualifiedName, - module: IR.Module, + module: Module, ir: IR - ): Option[Set[IR.Name.Literal]] = { + ): Option[Set[Name.Literal]] = { ir match { - case methodRef: IR.Name.MethodReference - if methodRef.typePointer.isEmpty => + case methodRef: Name.MethodReference if methodRef.typePointer.isEmpty => IRUtils.findModuleMethodUsages( moduleName, module, @@ -90,8 +91,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 1 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -115,8 +116,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 2 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -140,8 +141,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 1 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -168,8 +169,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 1 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -196,8 +197,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 2 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -224,8 +225,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 1 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } @@ -255,8 +256,8 @@ class IRUtilsTest extends AnyWordSpecLike with Matchers with OptionValues { usages.value.size shouldEqual 1 usages.value.foreach { - case _: IR.Name.Literal => succeed - case ir => fail(s"Not a literal: $ir") + case _: Name.Literal => succeed + case ir => fail(s"Not a literal: $ir") } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala index 51d56cb5d844..c4fd6abf4e2a 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/CompilerTest.scala @@ -3,6 +3,9 @@ package org.enso.compiler.test import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.EnsoParser import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{DefinitionArgument, Expression, Module, Name} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.core.ir.MetadataStorage.ToPair import org.enso.compiler.data.BindingsMap.ModuleReference import org.enso.compiler.data.{BindingsMap, CompilerConfig} @@ -10,7 +13,7 @@ import org.enso.compiler.pass.analyse.BindingAnalysis import org.enso.compiler.pass.{PassConfiguration, PassManager} import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike -import org.enso.interpreter.runtime.Module +import org.enso.interpreter.runtime import org.enso.interpreter.runtime.ModuleTestUtils import org.enso.interpreter.runtime.scope.LocalScope import org.enso.pkg.QualifiedName @@ -31,7 +34,7 @@ trait CompilerRunner { * * @return the [[IR]] representing [[source]] */ - def toIrModule: IR.Module = { + def toIrModule: Module = { val compiler = new EnsoParser() try compiler.compile(source) finally compiler.close() @@ -49,7 +52,7 @@ trait CompilerRunner { * * @return the [[IR]] representing [[source]], if it is a valid expression */ - def toIrExpression: Option[IR.Expression] = { + def toIrExpression: Option[Expression] = { val compiler = new EnsoParser() try compiler.generateIRInline(compiler.parse(source)) finally compiler.close() @@ -61,7 +64,7 @@ trait CompilerRunner { * * @param ir the IR to run the passes on */ - implicit class RunPassesOnModule(ir: IR.Module) { + implicit class RunPassesOnModule(ir: Module) { /** Executes the passes using `passManager` on the input [[ir]]. * @@ -72,7 +75,7 @@ trait CompilerRunner { def runPasses( passManager: PassManager, moduleContext: ModuleContext - ): IR.Module = { + ): Module = { passManager.runPassesOnModule(ir, moduleContext) } } @@ -82,7 +85,7 @@ trait CompilerRunner { * * @param ir the IR to run the passes on */ - implicit class RunPassesOnExpression(ir: IR.Expression) { + implicit class RunPassesOnExpression(ir: Expression) { /** Executes the passes using `passManager` on the input [[ir]]. * @@ -93,7 +96,7 @@ trait CompilerRunner { def runPasses( passManager: PassManager, inlineContext: InlineContext - ): IR.Expression = { + ): Expression = { passManager.runPassesInline(ir, inlineContext) } } @@ -110,7 +113,7 @@ trait CompilerRunner { * * @return IR appropriate for testing the alias analysis pass as a module */ - def preprocessModule(implicit moduleContext: ModuleContext): IR.Module = { + def preprocessModule(implicit moduleContext: ModuleContext): Module = { source.toIrModule.runPasses(passManager, moduleContext) } @@ -121,7 +124,7 @@ trait CompilerRunner { */ def preprocessExpression(implicit inlineContext: InlineContext - ): Option[IR.Expression] = { + ): Option[Expression] = { source.toIrExpression.map(_.runPasses(passManager, inlineContext)) } } @@ -138,25 +141,25 @@ trait CompilerRunner { * * @param ir the expression to add extension methods to */ - implicit class ExpressionAs(ir: IR.Expression) { + implicit class ExpressionAs(ir: Expression) { /** Hoists the provided expression into the body of a method. * * @return a method containing `ir` as its body */ - def asMethod: IR.Module.Scope.Definition.Method = { - IR.Module.Scope.Definition.Method.Explicit( - IR.Name.MethodReference( + def asMethod: definition.Method = { + definition.Method.Explicit( + Name.MethodReference( Some( - IR.Name.Qualified( + Name.Qualified( List( - IR.Name + Name .Literal("TestType", isMethod = false, None) ), None ) ), - IR.Name + Name .Literal("testMethod", isMethod = false, None), None ), @@ -169,13 +172,13 @@ trait CompilerRunner { * * @return an atom with one argument `arg` with default value `ir` */ - def asAtomDefaultArg: IR.Module.Scope.Definition.Data = { - IR.Module.Scope.Definition.Data( - IR.Name.Literal("TestAtom", isMethod = false, None), + def asAtomDefaultArg: Definition.Data = { + Definition.Data( + Name.Literal("TestAtom", isMethod = false, None), List( - IR.DefinitionArgument + DefinitionArgument .Specified( - IR.Name + Name .Literal("arg", isMethod = false, None), None, Some(ir), @@ -223,8 +226,8 @@ trait CompilerRunner { passConfiguration: Option[PassConfiguration] = None, compilerConfig: CompilerConfig = defaultConfig, isGeneratingDocs: Boolean = false - ): (ModuleContext, Module) = { - val mod = Module.empty(moduleName, null) + ): (ModuleContext, runtime.Module) = { + val mod = runtime.Module.empty(moduleName, null) val ctx = ModuleContext( module = mod, freshNameSupply = freshNameSupply, @@ -251,10 +254,11 @@ trait CompilerRunner { passConfiguration: Option[PassConfiguration] = None, compilerConfig: CompilerConfig = defaultConfig ): InlineContext = { - val mod = Module.empty(QualifiedName.simpleName("Test_Module"), null) + val mod = + runtime.Module.empty(QualifiedName.simpleName("Test_Module"), null) ModuleTestUtils.unsafeSetIr( mod, - IR.Module(List(), List(), List(), None) + Module(List(), List(), List(), None) .updateMetadata( BindingAnalysis -->> BindingsMap( List(), diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/PassesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/PassesTest.scala index ac18776bca4c..d4bdc9e887bf 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/PassesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/PassesTest.scala @@ -2,7 +2,8 @@ package org.enso.compiler.test import org.enso.compiler.Passes import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Module import org.enso.compiler.pass.IRPass import org.enso.compiler.pass.analyse.{ AliasAnalysis, @@ -27,14 +28,14 @@ class PassesTest extends CompilerTest { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir + ): Module = ir override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir } // === The Tests ============================================================ diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/context/FreshNameSupplyTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/context/FreshNameSupplyTest.scala index d46925aad092..1acd86054946 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/context/FreshNameSupplyTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/context/FreshNameSupplyTest.scala @@ -1,7 +1,7 @@ package org.enso.compiler.test.context import org.enso.compiler.context.FreshNameSupply -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Name import org.enso.compiler.test.CompilerTest import scala.collection.mutable @@ -12,7 +12,7 @@ class FreshNameSupplyTest extends CompilerTest { val fns = new FreshNameSupply "generate unique identifiers" in { - val seenNames: mutable.Set[IR.Name] = mutable.Set() + val seenNames: mutable.Set[Name] = mutable.Set() for (_ <- 1 to 100000) { val newName = fns.newName() diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala index 3286b46b8964..11d617691c6c 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/context/SuggestionBuilderTest.scala @@ -1,7 +1,7 @@ package org.enso.compiler.test.context import org.enso.compiler.context.SuggestionBuilder -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Module import org.enso.interpreter.runtime import org.enso.interpreter.runtime.EnsoContext import org.enso.interpreter.test.InterpreterContext @@ -22,7 +22,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { implicit private class PreprocessModule(code: String) { - def preprocessModule(name: QualifiedName): IR.Module = { + def preprocessModule(name: QualifiedName): Module = { val module = new runtime.Module( name, null, @@ -32,7 +32,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { module.getIr } - def preprocessModule: IR.Module = + def preprocessModule: Module = preprocessModule(Module) } @@ -3227,7 +3227,7 @@ class SuggestionBuilderTest extends AnyWordSpecLike with Matchers { private def build( source: String, - ir: IR.Module, + ir: Module, module: QualifiedName = Module ): Tree.Root[Suggestion] = SuggestionBuilder(source, langCtx.getCompiler).build(module, ir) diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/DiagnosticStorageTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/DiagnosticStorageTest.scala index a9a68154e8ae..29ddddcc753e 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/DiagnosticStorageTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/DiagnosticStorageTest.scala @@ -1,7 +1,8 @@ package org.enso.compiler.test.core.ir -import org.enso.compiler.core.IR -import org.enso.compiler.core.ir.DiagnosticStorage +import org.enso.compiler.core.ir.{Diagnostic, DiagnosticStorage, Empty} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.expression.warnings import org.enso.compiler.test.CompilerTest class DiagnosticStorageTest extends CompilerTest { @@ -13,8 +14,8 @@ class DiagnosticStorageTest extends CompilerTest { * @param name the name to give the internal diagnostic * @return a new diagnostic */ - def mkDiagnostic(name: String): IR.Diagnostic = { - IR.Warning.Shadowed.FunctionParam(name, IR.Empty(None), None) + def mkDiagnostic(name: String): Diagnostic = { + warnings.Shadowed.FunctionParam(name, Empty(None), None) } // === The Tests ============================================================ @@ -70,7 +71,7 @@ class DiagnosticStorageTest extends CompilerTest { ) diagnostics.mapInPlace { - case s: IR.Warning.Shadowed.FunctionParam => + case s: warnings.Shadowed.FunctionParam => s.copy(shadowedName = "aaa") case x => x } @@ -79,7 +80,7 @@ class DiagnosticStorageTest extends CompilerTest { } "collecting across the diagnostics to produce a new sequence" in { - val err = IR.Error.Syntax(null, IR.Error.Syntax.UnsupportedSyntax("aa")) + val err = errors.Syntax(null, errors.Syntax.UnsupportedSyntax("aa")) val diagnostics = new DiagnosticStorage( List( @@ -90,7 +91,7 @@ class DiagnosticStorageTest extends CompilerTest { ) ) - diagnostics.collect { case e: IR.Error.Syntax => + diagnostics.collect { case e: errors.Syntax => e } shouldEqual Seq(err) } @@ -109,7 +110,7 @@ class DiagnosticStorageTest extends CompilerTest { ) diagnostics.filter { - case s: IR.Warning.Shadowed.FunctionParam => + case s: warnings.Shadowed.FunctionParam => s.shadowedName.contains("a") case _ => false } shouldEqual result @@ -127,7 +128,7 @@ class DiagnosticStorageTest extends CompilerTest { val result = List(mkDiagnostic("aa"), mkDiagnostic("ba")) diagnostics.filterInPlace { - case s: IR.Warning.Shadowed.FunctionParam => + case s: warnings.Shadowed.FunctionParam => s.shadowedName.contains("a") case _ => false } @@ -146,8 +147,8 @@ class DiagnosticStorageTest extends CompilerTest { diagnostics.foldLeft("")((str, d) => d match { - case f: IR.Warning.Shadowed.FunctionParam => str + f.shadowedName - case _ => str + case f: warnings.Shadowed.FunctionParam => str + f.shadowedName + case _ => str } ) shouldEqual "abcd" } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/MetadataStorageTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/MetadataStorageTest.scala index 8c0d072a530e..4f8299109ded 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/MetadataStorageTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/core/ir/MetadataStorageTest.scala @@ -1,7 +1,8 @@ package org.enso.compiler.test.core.ir import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Module import org.enso.compiler.core.ir.MetadataStorage import org.enso.compiler.core.ir.MetadataStorage._ import org.enso.compiler.core.CompilerError @@ -21,14 +22,14 @@ class MetadataStorageTest extends CompilerTest { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir + ): Module = ir override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir sealed case class Metadata1() extends IRPass.IRMetadata { override val metadataName: String = "TestPass1.Metadata1" @@ -53,14 +54,14 @@ class MetadataStorageTest extends CompilerTest { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir + ): Module = ir override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir sealed case class Metadata2() extends IRPass.IRMetadata { override val metadataName: String = "TestPass2.Metadata2" diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassConfigurationTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassConfigurationTest.scala index aba6e1300092..daa53194c0c4 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassConfigurationTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/PassConfigurationTest.scala @@ -1,7 +1,8 @@ package org.enso.compiler.test.pass import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Module import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.{IRPass, PassConfiguration} import org.enso.compiler.test.CompilerTest @@ -19,14 +20,14 @@ class PassConfigurationTest extends CompilerTest { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir + ): Module = ir override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir sealed case class Configuration1() extends IRPass.Configuration { override var shouldWriteToContext: Boolean = false @@ -41,14 +42,14 @@ class PassConfigurationTest extends CompilerTest { override val invalidatedPasses: Seq[IRPass] = List() override def runModule( - ir: IR.Module, + ir: Module, moduleContext: ModuleContext - ): IR.Module = ir + ): Module = ir override def runExpression( - ir: IR.Expression, + ir: Expression, inlineContext: InlineContext - ): IR.Expression = ir + ): Expression = ir sealed case class Configuration2() extends IRPass.Configuration { override var shouldWriteToContext: Boolean = true diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/AliasAnalysisTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/AliasAnalysisTest.scala index 64caba00d002..31a6042ab7ff 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/AliasAnalysisTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/AliasAnalysisTest.scala @@ -2,9 +2,17 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{ + CallArgument, + Expression, + Function, + Module, + Name, + Pattern +} +import org.enso.compiler.core.ir.expression.{errors, Application, Case} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse.AliasAnalysis import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{Link, Occurrence} @@ -28,17 +36,17 @@ class AliasAnalysisTest extends CompilerTest { implicit val passManager: PassManager = new PassManager(List(precursorPasses), passConfig) - /** Adds an extension method to run alias analysis on an [[IR.Module]]. + /** Adds an extension method to run alias analysis on an [[Module]]. * * @param ir the module to run alias analysis on */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Runs alias analysis on a module. * * @return [[ir]], with attached aliasing information */ - def analyse: IR.Module = { + def analyse: Module = { AliasAnalysis.runModule( ir, buildModuleContext(passConfiguration = Some(passConfig)) @@ -46,11 +54,11 @@ class AliasAnalysisTest extends CompilerTest { } } - /** Adds an extension method to run alias analysis on an [[IR.Expression]]. + /** Adds an extension method to run alias analysis on an [[Expression]]. * * @param ir the expression to run alias analysis on */ - implicit class AnalyseExpression(ir: IR.Expression) { + implicit class AnalyseExpression(ir: Expression) { /** Runs alias analysis on an expression. * @@ -58,7 +66,7 @@ class AliasAnalysisTest extends CompilerTest { * expression * @return [[ir]], with attached aliasing information */ - def analyse(inlineContext: InlineContext): IR.Expression = { + def analyse(inlineContext: InlineContext): Expression = { AliasAnalysis.runExpression(ir, inlineContext) } } @@ -400,7 +408,7 @@ class AliasAnalysisTest extends CompilerTest { |type M | MyAtom a b (c=a) |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Type] + .asInstanceOf[Definition.Type] .members .head val goodMeta = goodAtom.getMetadata(AliasAnalysis) @@ -411,7 +419,7 @@ class AliasAnalysisTest extends CompilerTest { |type M | MyAtom a=b b |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Type] + .asInstanceOf[Definition.Type] .members .head val badMeta = badAtom.getMetadata(AliasAnalysis) @@ -467,7 +475,7 @@ class AliasAnalysisTest extends CompilerTest { | 1 + 1 | d c (a + b) |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val methodWithLambdaGraph = methodWithLambda .getMetadata(AliasAnalysis) @@ -477,22 +485,22 @@ class AliasAnalysisTest extends CompilerTest { val graphLinks = methodWithLambdaGraph.links - val topLambda = methodWithLambda.body.asInstanceOf[IR.Function.Lambda] + val topLambda = methodWithLambda.body.asInstanceOf[Function.Lambda] val topLambdaBody = topLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val childLambda = topLambdaBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val childLambdaBody = childLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] "assign Info.Scope.Root metadata to the method" in { val meta = methodWithLambda.getMetadata(AliasAnalysis) @@ -503,23 +511,23 @@ class AliasAnalysisTest extends CompilerTest { "assign Info.Scope.Child to all child scopes" in { methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] @@ -528,7 +536,7 @@ class AliasAnalysisTest extends CompilerTest { .get shouldBe an[Info.Scope.Child] childLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] } @@ -540,11 +548,11 @@ class AliasAnalysisTest extends CompilerTest { // TODO [AA] the method function's scope should be the block scope val cLamScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -552,13 +560,13 @@ class AliasAnalysisTest extends CompilerTest { val cLamBlockScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -567,7 +575,7 @@ class AliasAnalysisTest extends CompilerTest { cLamScope shouldEqual cLamBlockScope val aLamScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -579,27 +587,27 @@ class AliasAnalysisTest extends CompilerTest { "allocate new scopes where necessary" in { val topScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] .scope val bLambdaScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] .scope val cLambdaScope = methodWithLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -612,9 +620,9 @@ class AliasAnalysisTest extends CompilerTest { .scope val dALambdaScope = topLambdaBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -622,19 +630,19 @@ class AliasAnalysisTest extends CompilerTest { val gScope = topLambdaBody .expressions(1) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] .scope val cUseScope = topLambdaBody.returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -653,7 +661,7 @@ class AliasAnalysisTest extends CompilerTest { ) topLambdaBody.expressions.foreach( - _.asInstanceOf[IR.Expression.Binding] + _.asInstanceOf[Expression.Binding] .getMetadata(AliasAnalysis) .get .as[Info.Occurrence] shouldBe defined @@ -676,9 +684,9 @@ class AliasAnalysisTest extends CompilerTest { "create the correct usage links for resolvable entities" in { val topLambdaCDefId = topLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head .getMetadata(AliasAnalysis) @@ -694,7 +702,7 @@ class AliasAnalysisTest extends CompilerTest { .id val nestedLambdaBDefId = childLambda.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head .getMetadata(AliasAnalysis) @@ -703,7 +711,7 @@ class AliasAnalysisTest extends CompilerTest { .id val nestedLambdaAUseId = childLambdaBody - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .function .getMetadata(AliasAnalysis) .get @@ -711,10 +719,10 @@ class AliasAnalysisTest extends CompilerTest { .id val nestedLambdaBUseId = childLambdaBody - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value .getMetadata(AliasAnalysis) .get @@ -722,23 +730,23 @@ class AliasAnalysisTest extends CompilerTest { .id val dDefId = topLambdaBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Occurrence] .id val dUseId = topLambdaBody.returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .function .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Occurrence] .id val dDefCUseId = topLambdaBody.returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value .getMetadata(AliasAnalysis) .get @@ -755,11 +763,11 @@ class AliasAnalysisTest extends CompilerTest { "not resolve links for unknown symbols" in { val unknownPlusId = topLambdaBody .expressions(1) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .function .getMetadata(AliasAnalysis) .get @@ -784,7 +792,7 @@ class AliasAnalysisTest extends CompilerTest { | | IO.println b |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val methodWithBlockGraph = methodWithBlock .getMetadata(AliasAnalysis) @@ -801,14 +809,14 @@ class AliasAnalysisTest extends CompilerTest { "assign Info.Scope.Child to all child scopes" in { methodWithBlock.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] methodWithBlock.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .getMetadata(AliasAnalysis) .get shouldBe an[Info.Scope.Child] } @@ -819,16 +827,16 @@ class AliasAnalysisTest extends CompilerTest { val blockChildLambdaScope = methodWithBlock.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] .scope val blockChildBlockScope = methodWithBlock.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .getMetadata(AliasAnalysis) .get .unsafeAs[Info.Scope.Child] @@ -848,7 +856,7 @@ class AliasAnalysisTest extends CompilerTest { | add x = self.a + x |""".stripMargin.preprocessModule.analyse .bindings(2) - .asInstanceOf[Method.Explicit] + .asInstanceOf[definition.Method.Explicit] val graph = addMethod .unsafeGetMetadata(AliasAnalysis, "Missing aliasing info") @@ -856,7 +864,7 @@ class AliasAnalysisTest extends CompilerTest { .graph val graphLinks = graph.links - val lambda = addMethod.body.asInstanceOf[IR.Function.Lambda] + val lambda = addMethod.body.asInstanceOf[Function.Lambda] "assign Info.Scope.Root metadata to the method" in { val meta = addMethod.getMetadata(AliasAnalysis) @@ -865,7 +873,7 @@ class AliasAnalysisTest extends CompilerTest { "not add self to the scope" in { lambda.arguments.length shouldEqual 2 - lambda.arguments(0).name shouldBe a[IR.Name.Self] + lambda.arguments(0).name shouldBe a[Name.Self] val topScope = graph.rootScope val lambdaScope = lambda .getMetadata(AliasAnalysis) @@ -882,8 +890,8 @@ class AliasAnalysisTest extends CompilerTest { .get .unsafeAs[Info.Occurrence] .id - lambda.body shouldBe an[IR.Application.Prefix] - val app = lambda.body.asInstanceOf[IR.Application.Prefix] + lambda.body shouldBe an[Application.Prefix] + val app = lambda.body.asInstanceOf[Application.Prefix] val valueUseId = app .arguments(1) .value @@ -897,7 +905,7 @@ class AliasAnalysisTest extends CompilerTest { "add self as a definition" in { lambda.arguments.length shouldEqual 2 - lambda.arguments(0).name shouldBe a[IR.Name.Self] + lambda.arguments(0).name shouldBe a[Name.Self] val lambdaScope = lambda .getMetadata(AliasAnalysis) .get @@ -918,7 +926,7 @@ class AliasAnalysisTest extends CompilerTest { """Bar.from (that : Foo) = | Bar that.get_thing meh |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method.Conversion] + .asInstanceOf[definition.Method.Conversion] val graph = conversionMethod .unsafeGetMetadata(AliasAnalysis, "Missing aliasing info") @@ -926,9 +934,9 @@ class AliasAnalysisTest extends CompilerTest { .graph val graphLinks = graph.links - val lambda = conversionMethod.body.asInstanceOf[IR.Function.Lambda] - val lambdaBody = lambda.body.asInstanceOf[IR.Expression.Block] - val app = lambdaBody.returnValue.asInstanceOf[IR.Application.Prefix] + val lambda = conversionMethod.body.asInstanceOf[Function.Lambda] + val lambdaBody = lambda.body.asInstanceOf[Expression.Block] + val app = lambdaBody.returnValue.asInstanceOf[Application.Prefix] "assign Info.Scope.Root metatata to the method" in { val meta = conversionMethod.getMetadata(AliasAnalysis) @@ -985,7 +993,7 @@ class AliasAnalysisTest extends CompilerTest { arg.getMetadata(AliasAnalysis).get.as[Info.Occurrence] shouldBe defined ) val firstAppArg = - app.arguments.head.value.asInstanceOf[IR.Application.Prefix] + app.arguments.head.value.asInstanceOf[Application.Prefix] val innerAppArg = firstAppArg.arguments.head.value innerAppArg .getMetadata(AliasAnalysis) @@ -1001,7 +1009,7 @@ class AliasAnalysisTest extends CompilerTest { .unsafeAs[Info.Occurrence] .id val valueUseId = app.arguments.head.value - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head .value @@ -1038,13 +1046,13 @@ class AliasAnalysisTest extends CompilerTest { | num : Integer -> process num Integer | _ -> 0 |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] - val lambda = methodWithCase.body.asInstanceOf[IR.Function.Lambda] - val caseBlock = lambda.body.asInstanceOf[IR.Expression.Block] + .asInstanceOf[definition.Method] + val lambda = methodWithCase.body.asInstanceOf[Function.Lambda] + val caseBlock = lambda.body.asInstanceOf[Expression.Block] val scrutBinding = - caseBlock.expressions.head.asInstanceOf[IR.Expression.Binding] - val scrutBindingExpr = scrutBinding.expression.asInstanceOf[IR.Name.Literal] - val caseExpr = caseBlock.returnValue.asInstanceOf[IR.Case.Expr] + caseBlock.expressions.head.asInstanceOf[Expression.Binding] + val scrutBindingExpr = scrutBinding.expression.asInstanceOf[Name.Literal] + val caseExpr = caseBlock.returnValue.asInstanceOf[Case.Expr] val graph = methodWithCase .getMetadata(AliasAnalysis) @@ -1140,7 +1148,7 @@ class AliasAnalysisTest extends CompilerTest { "correctly link to pattern variables" in { val consBranch = caseExpr.branches.head val pattern = consBranch.pattern.asInstanceOf[Pattern.Constructor] - val body = consBranch.expression.asInstanceOf[IR.Application.Prefix] + val body = consBranch.expression.asInstanceOf[Application.Prefix] val consBranchADef = pattern.fields.head .asInstanceOf[Pattern.Name] @@ -1160,17 +1168,17 @@ class AliasAnalysisTest extends CompilerTest { .id val aUse = body.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val aUseId = aUse.getMetadata(AliasAnalysis).get.unsafeAs[Info.Occurrence].id val bUse = body .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val bUseId = bUse.getMetadata(AliasAnalysis).get.unsafeAs[Info.Occurrence].id @@ -1181,7 +1189,7 @@ class AliasAnalysisTest extends CompilerTest { "correctly link to pattern variables in type patterns" in { val tpeBranch = caseExpr.branches(2) val pattern = tpeBranch.pattern.asInstanceOf[Pattern.Type] - val body = tpeBranch.expression.asInstanceOf[IR.Application.Prefix] + val body = tpeBranch.expression.asInstanceOf[Application.Prefix] val tpeBranchNameDef = pattern.name val tpeTpeBranchTpeDef = pattern.tpe @@ -1200,17 +1208,17 @@ class AliasAnalysisTest extends CompilerTest { val numUse = body .arguments(0) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val numUseId = numUse.getMetadata(AliasAnalysis).get.unsafeAs[Info.Occurrence].id val integerUse = body .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val integerUseId = integerUse.getMetadata(AliasAnalysis).get.unsafeAs[Info.Occurrence].id @@ -1227,20 +1235,20 @@ class AliasAnalysisTest extends CompilerTest { |main = | { x := 1, b := 2 } |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val block = method.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val blockScope = block.unsafeGetMetadata(AliasAnalysis, "").unsafeAs[Info.Scope.Child] "create a new scope for the literal" in { - if (!block.returnValue.isInstanceOf[IR.Error.Syntax]) { + if (!block.returnValue.isInstanceOf[errors.Syntax]) { val literal = - block.returnValue.asInstanceOf[IR.Application.Literal.Typeset] + block.returnValue.asInstanceOf[Application.Typeset] val literalScope = literal .unsafeGetMetadata(AliasAnalysis, "") @@ -1263,15 +1271,15 @@ class AliasAnalysisTest extends CompilerTest { | | IO.println a |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val block = method.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] - block.expressions(2) shouldBe an[IR.Error.Redefined.Binding] - atLeast(1, block.expressions) shouldBe an[IR.Error.Redefined.Binding] + block.expressions(2) shouldBe an[errors.Redefined.Binding] + atLeast(1, block.expressions) shouldBe an[errors.Redefined.Binding] } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/BindingAnalysisTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/BindingAnalysisTest.scala index 10a4797d1e4b..487190a5fbb1 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/BindingAnalysisTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/BindingAnalysisTest.scala @@ -2,7 +2,7 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Module import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.{ Cons, @@ -36,14 +36,14 @@ class BindingAnalysisTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * * @param context the module context in which analysis takes place * @return [[ir]], with tail call analysis metadata attached */ - def analyse(implicit context: ModuleContext): IR.Module = { + def analyse(implicit context: ModuleContext): Module = { BindingAnalysis.runModule(ir, context) } } 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 fd6e6afa270f..1e984dffd12a 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 @@ -3,8 +3,18 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Literal, + Module, + Name, + Pattern +} +import org.enso.compiler.core.ir.expression.{errors, Application, Case} +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.data.CompilerConfig import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse.DataflowAnalysis.DependencyInfo.Type.asStatic @@ -90,17 +100,17 @@ class DataflowAnalysisTest extends CompilerTest { DependencyInfo.Type.Dynamic(str, extId) } - /** Adds an extension method to run dataflow analysis on an [[IR.Module]]. + /** Adds an extension method to run dataflow analysis on an [[Module]]. * * @param ir the module to run dataflow analysis on. */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Runs dataflow analysis on a module. * * @return [[ir]], with attached data dependency information */ - def analyse: IR.Module = { + def analyse: Module = { DataflowAnalysis.runModule( ir, buildModuleContext(freshNameSupply = Some(new FreshNameSupply)) @@ -108,11 +118,11 @@ class DataflowAnalysisTest extends CompilerTest { } } - /** Adds an extension method to run dataflow analysis on an [[IR.Expression]]. + /** Adds an extension method to run dataflow analysis on an [[Expression]]. * * @param ir the expression to run dataflow analysis on */ - implicit class AnalyseExpresion(ir: IR.Expression) { + implicit class AnalyseExpresion(ir: Expression) { /** Runs dataflow analysis on an expression. * @@ -120,7 +130,7 @@ class DataflowAnalysisTest extends CompilerTest { * expression * @return [[ir]], with attached data dependency information */ - def analyse(implicit inlineContext: InlineContext): IR.Expression = { + def analyse(implicit inlineContext: InlineContext): Expression = { DataflowAnalysis.runExpression(ir, inlineContext) } } @@ -294,46 +304,46 @@ class DataflowAnalysisTest extends CompilerTest { // The method and body val method = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method] - val fn = method.body.asInstanceOf[IR.Function.Lambda] + ir.bindings.head.asInstanceOf[definition.Method] + val fn = method.body.asInstanceOf[Function.Lambda] val fnArgThis = - fn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] - val fnArgA = fn.arguments(1).asInstanceOf[IR.DefinitionArgument.Specified] - val fnArgB = fn.arguments(2).asInstanceOf[IR.DefinitionArgument.Specified] - val fnBody = fn.body.asInstanceOf[IR.Expression.Block] + fn.arguments.head.asInstanceOf[DefinitionArgument.Specified] + val fnArgA = fn.arguments(1).asInstanceOf[DefinitionArgument.Specified] + val fnArgB = fn.arguments(2).asInstanceOf[DefinitionArgument.Specified] + val fnBody = fn.body.asInstanceOf[Expression.Block] // The `IO.println` expression val printlnExpr = - fnBody.expressions.head.asInstanceOf[IR.Application.Prefix] - val printlnFn = printlnExpr.function.asInstanceOf[IR.Name.Literal] + fnBody.expressions.head.asInstanceOf[Application.Prefix] + val printlnFn = printlnExpr.function.asInstanceOf[Name.Literal] val printlnArgIO = - printlnExpr.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val printlnArgIOExpr = printlnArgIO.value.asInstanceOf[IR.Error.Resolution] + printlnExpr.arguments.head.asInstanceOf[CallArgument.Specified] + val printlnArgIOExpr = printlnArgIO.value.asInstanceOf[errors.Resolution] val printlnArgB = - printlnExpr.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val printlnArgBExpr = printlnArgB.value.asInstanceOf[IR.Name.Literal] + printlnExpr.arguments(1).asInstanceOf[CallArgument.Specified] + val printlnArgBExpr = printlnArgB.value.asInstanceOf[Name.Literal] // The `c =` expression - val cBindExpr = fnBody.expressions(1).asInstanceOf[IR.Expression.Binding] - val cBindName = cBindExpr.name.asInstanceOf[IR.Name.Literal] - val plusExpr = cBindExpr.expression.asInstanceOf[IR.Application.Prefix] - val plusExprFn = plusExpr.function.asInstanceOf[IR.Name.Literal] + val cBindExpr = fnBody.expressions(1).asInstanceOf[Expression.Binding] + val cBindName = cBindExpr.name.asInstanceOf[Name.Literal] + val plusExpr = cBindExpr.expression.asInstanceOf[Application.Prefix] + val plusExprFn = plusExpr.function.asInstanceOf[Name.Literal] val plusExprArgA = - plusExpr.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val plusExprArgAExpr = plusExprArgA.value.asInstanceOf[IR.Name.Literal] + plusExpr.arguments.head.asInstanceOf[CallArgument.Specified] + val plusExprArgAExpr = plusExprArgA.value.asInstanceOf[Name.Literal] val plusExprArgB = - plusExpr.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val plusExprArgBExpr = plusExprArgB.value.asInstanceOf[IR.Name.Literal] + plusExpr.arguments(1).asInstanceOf[CallArgument.Specified] + val plusExprArgBExpr = plusExprArgB.value.asInstanceOf[Name.Literal] // The `frobnicate` return expression - val frobExpr = fnBody.returnValue.asInstanceOf[IR.Application.Prefix] - val frobFn = frobExpr.function.asInstanceOf[IR.Error.Resolution] + val frobExpr = fnBody.returnValue.asInstanceOf[Application.Prefix] + val frobFn = frobExpr.function.asInstanceOf[errors.Resolution] val frobArgA = - frobExpr.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val frobArgAExpr = frobArgA.value.asInstanceOf[IR.Name.Literal] + frobExpr.arguments.head.asInstanceOf[CallArgument.Specified] + val frobArgAExpr = frobArgA.value.asInstanceOf[Name.Literal] val frobArgC = - frobExpr.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val frobArgCExpr = frobArgC.value.asInstanceOf[IR.Name.Literal] + frobExpr.arguments(1).asInstanceOf[CallArgument.Specified] + val frobArgCExpr = frobArgC.value.asInstanceOf[Name.Literal] // The global symbols val frobnicateSymbol = mkDynamicDep("frobnicate") @@ -931,19 +941,19 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val fn = ir.asInstanceOf[IR.Function.Lambda] + val fn = ir.asInstanceOf[Function.Lambda] val fnArgX = - fn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + fn.arguments.head.asInstanceOf[DefinitionArgument.Specified] val fnArgY = - fn.arguments(1).asInstanceOf[IR.DefinitionArgument.Specified] - val fnBody = fn.body.asInstanceOf[IR.Application.Prefix] - val plusFn = fnBody.function.asInstanceOf[IR.Name.Literal] + fn.arguments(1).asInstanceOf[DefinitionArgument.Specified] + val fnBody = fn.body.asInstanceOf[Application.Prefix] + val plusFn = fnBody.function.asInstanceOf[Name.Literal] val plusArgX = - fnBody.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val plusArgXExpr = plusArgX.value.asInstanceOf[IR.Name.Literal] + fnBody.arguments.head.asInstanceOf[CallArgument.Specified] + val plusArgXExpr = plusArgX.value.asInstanceOf[Name.Literal] val plusArgY = - fnBody.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val plusArgYExpr = plusArgY.value.asInstanceOf[IR.Name.Literal] + fnBody.arguments(1).asInstanceOf[CallArgument.Specified] + val plusArgYExpr = plusArgY.value.asInstanceOf[Name.Literal] // Identifiers val fnId = mkStaticDep(fn.getId) @@ -995,24 +1005,24 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val app = ir.asInstanceOf[IR.Application.Prefix] - val appFn = app.function.asInstanceOf[IR.Error.Resolution] + val app = ir.asInstanceOf[Application.Prefix] + val appFn = app.function.asInstanceOf[errors.Resolution] val appArg10 = - app.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val appArg10Expr = appArg10.value.asInstanceOf[IR.Literal.Number] - val appArg10Name = appArg10.name.get.asInstanceOf[IR.Name.Literal] + app.arguments.head.asInstanceOf[CallArgument.Specified] + val appArg10Expr = appArg10.value.asInstanceOf[Literal.Number] + val appArg10Name = appArg10.name.get.asInstanceOf[Name.Literal] val appArgFn = - app.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val lam = appArgFn.value.asInstanceOf[IR.Function.Lambda] + app.arguments(1).asInstanceOf[CallArgument.Specified] + val lam = appArgFn.value.asInstanceOf[Function.Lambda] val lamArgX = - lam.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] - val mul = lam.body.asInstanceOf[IR.Application.Prefix] - val mulFn = mul.function.asInstanceOf[IR.Name.Literal] + lam.arguments.head.asInstanceOf[DefinitionArgument.Specified] + val mul = lam.body.asInstanceOf[Application.Prefix] + val mulFn = mul.function.asInstanceOf[Name.Literal] val mulArg1 = - mul.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val mulArg1Expr = mulArg1.value.asInstanceOf[IR.Name.Literal] - val mulArg2 = mul.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val mulArg2Expr = mulArg2.value.asInstanceOf[IR.Name.Literal] + mul.arguments.head.asInstanceOf[CallArgument.Specified] + val mulArg1Expr = mulArg1.value.asInstanceOf[Name.Literal] + val mulArg2 = mul.arguments(1).asInstanceOf[CallArgument.Specified] + val mulArg2Expr = mulArg2.value.asInstanceOf[Name.Literal] // Identifiers val appId = mkStaticDep(app.getId) @@ -1089,9 +1099,9 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val lam = ir.asInstanceOf[IR.Function.Lambda] + val lam = ir.asInstanceOf[Function.Lambda] val argX = - lam.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + lam.arguments.head.asInstanceOf[DefinitionArgument.Specified] // The IDs val argXId = mkStaticDep(argX.getId) @@ -1114,10 +1124,10 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val block = ir.asInstanceOf[IR.Expression.Block] - val xBind = block.expressions.head.asInstanceOf[IR.Expression.Binding] - val xBindName = xBind.name.asInstanceOf[IR.Name.Literal] - val xBindExpr = xBind.expression.asInstanceOf[IR.Literal.Number] + val block = ir.asInstanceOf[Expression.Block] + val xBind = block.expressions.head.asInstanceOf[Expression.Binding] + val xBindName = xBind.name.asInstanceOf[Name.Literal] + val xBindExpr = xBind.expression.asInstanceOf[Literal.Number] // The IDs val blockId = mkStaticDep(block.getId) @@ -1152,9 +1162,9 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val binding = ir.asInstanceOf[IR.Expression.Binding] - val bindingName = binding.name.asInstanceOf[IR.Name.Literal] - val bindingExpr = binding.expression.asInstanceOf[IR.Literal.Number] + val binding = ir.asInstanceOf[Expression.Binding] + val bindingName = binding.name.asInstanceOf[Name.Literal] + val bindingExpr = binding.expression.asInstanceOf[Literal.Number] // The IDs val bindingId = mkStaticDep(binding.getId) @@ -1188,18 +1198,18 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val binding = ir.asInstanceOf[IR.Expression.Binding] - val bindingName = binding.name.asInstanceOf[IR.Name.Literal] - val bindingExpr = binding.expression.asInstanceOf[IR.Application.Prefix] - val plusFn = bindingExpr.function.asInstanceOf[IR.Name.Literal] + val binding = ir.asInstanceOf[Expression.Binding] + val bindingName = binding.name.asInstanceOf[Name.Literal] + val bindingExpr = binding.expression.asInstanceOf[Application.Prefix] + val plusFn = bindingExpr.function.asInstanceOf[Name.Literal] val numArg = - bindingExpr.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val numArgExpr = numArg.value.asInstanceOf[IR.Literal.Number] + bindingExpr.arguments.head.asInstanceOf[CallArgument.Specified] + val numArgExpr = numArg.value.asInstanceOf[Literal.Number] val undefinedArg = bindingExpr .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] - val undefinedExpr = undefinedArg.value.asInstanceOf[IR.Error.Resolution] + .asInstanceOf[CallArgument.Specified] + val undefinedExpr = undefinedArg.value.asInstanceOf[errors.Resolution] val undefinedName = undefinedExpr.originalName // The IDs @@ -1256,12 +1266,12 @@ class DataflowAnalysisTest extends CompilerTest { """ |x -> [x, y * z + 1, 123] |""".stripMargin.preprocessExpression.get.analyse - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val depInfo = ir.getMetadata(DataflowAnalysis).get val vector = ir.body - .asInstanceOf[IR.Application.Literal.Sequence] + .asInstanceOf[Application.Sequence] val xUseId = mkStaticDep(vector.items(0).getId) val yId = mkStaticDep(vector.items(1).getId) @@ -1293,10 +1303,10 @@ class DataflowAnalysisTest extends CompilerTest { |{ x := a ; y := b } |""".stripMargin.preprocessExpression.get.analyse - if (!ir.isInstanceOf[IR.Error.Syntax]) { + if (!ir.isInstanceOf[errors.Syntax]) { val depInfo = ir.getMetadata(DataflowAnalysis).get - val literal = ir.asInstanceOf[IR.Application.Literal.Typeset] + val literal = ir.asInstanceOf[Application.Typeset] val literalExpression = literal.expression.get val literalId = mkStaticDep(literal.getId) @@ -1320,13 +1330,13 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get - val caseBlock = ir.asInstanceOf[IR.Expression.Block] + val caseBlock = ir.asInstanceOf[Expression.Block] val caseBinding = - caseBlock.expressions.head.asInstanceOf[IR.Expression.Binding] + caseBlock.expressions.head.asInstanceOf[Expression.Binding] val caseBindingExpr = - caseBinding.expression.asInstanceOf[IR.Application.Prefix] - val caseBindingName = caseBinding.name.asInstanceOf[IR.Name.Literal] - val caseExpr = caseBlock.returnValue.asInstanceOf[IR.Case.Expr] + caseBinding.expression.asInstanceOf[Application.Prefix] + val caseBindingName = caseBinding.name.asInstanceOf[Name.Literal] + val caseExpr = caseBlock.returnValue.asInstanceOf[Case.Expr] val consBranch = caseExpr.branches.head val consBranchPattern = @@ -1340,16 +1350,16 @@ class DataflowAnalysisTest extends CompilerTest { val consBranchBDef = consBranchBPattern.name val consBranchExpression = - consBranch.expression.asInstanceOf[IR.Application.Prefix] + consBranch.expression.asInstanceOf[Application.Prefix] val consBranchFn = - consBranchExpression.function.asInstanceOf[IR.Name.Literal] + consBranchExpression.function.asInstanceOf[Name.Literal] val aArg = consBranchExpression.arguments.head - .asInstanceOf[IR.CallArgument.Specified] - val aUse = aArg.value.asInstanceOf[IR.Name.Literal] + .asInstanceOf[CallArgument.Specified] + val aUse = aArg.value.asInstanceOf[Name.Literal] val bArg = consBranchExpression .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] - val bUse = bArg.value.asInstanceOf[IR.Name.Literal] + .asInstanceOf[CallArgument.Specified] + val bUse = bArg.value.asInstanceOf[Name.Literal] val consSym = mkDynamicDep("Cons") val plusSym = mkDynamicDep("+") @@ -1454,7 +1464,7 @@ class DataflowAnalysisTest extends CompilerTest { implicit val inlineContext: InlineContext = mkInlineContext "10".preprocessExpression.get.analyse - .asInstanceOf[IR.Literal] + .asInstanceOf[Literal] .hasDependencyInfo } } @@ -1483,13 +1493,13 @@ class DataflowAnalysisTest extends CompilerTest { meta.assertInCode(aBindId, codeWithMeta, "a = x + 1") val ir = codeWithMeta.preprocessExpression.get.analyse - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val metadata = ir.getMetadata(DataflowAnalysis).get - val blockBody = ir.body.asInstanceOf[IR.Expression.Block] + val blockBody = ir.body.asInstanceOf[Expression.Block] val aBind = blockBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val aBindExpr = aBind.expression "store a mapping between internal and external identifiers" in { @@ -1530,22 +1540,22 @@ class DataflowAnalysisTest extends CompilerTest { val depInfo = ir.getMetadata(DataflowAnalysis).get // The method and its body - val conversion = ir.bindings.head.asInstanceOf[Method.Conversion] - val sourceType = conversion.sourceTypeName.asInstanceOf[IR.Name] - val lambda = conversion.body.asInstanceOf[IR.Function.Lambda] + val conversion = ir.bindings.head.asInstanceOf[definition.Method.Conversion] + val sourceType = conversion.sourceTypeName.asInstanceOf[Name] + val lambda = conversion.body.asInstanceOf[Function.Lambda] val fnArgThis = - lambda.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + lambda.arguments.head.asInstanceOf[DefinitionArgument.Specified] val fnArgValue = - lambda.arguments(1).asInstanceOf[IR.DefinitionArgument.Specified] - val fnBody = lambda.body.asInstanceOf[IR.Expression.Block] + lambda.arguments(1).asInstanceOf[DefinitionArgument.Specified] + val fnBody = lambda.body.asInstanceOf[Expression.Block] // The `Foo` application - val fooExpr = fnBody.returnValue.asInstanceOf[IR.Application.Prefix] - val fooFunction = fooExpr.function.asInstanceOf[IR.Name] - val fooArg1 = fooExpr.arguments.head.asInstanceOf[IR.CallArgument.Specified] - val fooArg1Expr = fooArg1.value.asInstanceOf[IR.Name] - val fooArg2 = fooExpr.arguments(1).asInstanceOf[IR.CallArgument.Specified] - val fooArg2Expr = fooArg2.value.asInstanceOf[IR.Literal.Number] + val fooExpr = fnBody.returnValue.asInstanceOf[Application.Prefix] + val fooFunction = fooExpr.function.asInstanceOf[Name] + val fooArg1 = fooExpr.arguments.head.asInstanceOf[CallArgument.Specified] + val fooArg1Expr = fooArg1.value.asInstanceOf[Name] + val fooArg2 = fooExpr.arguments(1).asInstanceOf[CallArgument.Specified] + val fooArg2Expr = fooArg2.value.asInstanceOf[Literal.Number] // The global symbols val fooSymbol = mkDynamicDep("Foo") diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DemandAnalysisTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DemandAnalysisTest.scala index ec1831fa3b69..56ccaad06f1f 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DemandAnalysisTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/DemandAnalysisTest.scala @@ -2,7 +2,15 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + Expression, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse.{AliasAnalysis, DemandAnalysis} import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} @@ -25,26 +33,26 @@ class DemandAnalysisTest extends CompilerTest { implicit val passManager: PassManager = new PassManager(List(precursorPasses), passConfig) - /** Adds an extension method to run alias analysis on an [[IR.Module]]. + /** Adds an extension method to run alias analysis on an [[Module]]. * * @param ir the module to run alias analysis on */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Runs demand analysis on a module. * * @return [[ir]], transformed by the demand analysis pass */ - def analyse: IR.Module = { + def analyse: Module = { DemandAnalysis.runModule(ir, buildModuleContext()) } } - /** Adds an extension method to run alias analysis on an [[IR.Expression]]. + /** Adds an extension method to run alias analysis on an [[Expression]]. * * @param ir the expression to run alias analysis on */ - implicit class AnalyseExpression(ir: IR.Expression) { + implicit class AnalyseExpression(ir: Expression) { /** Runs demand analysis on an expression. * @@ -52,7 +60,7 @@ class DemandAnalysisTest extends CompilerTest { * expression * @return [[ir]], transformed by the demand analysis pass */ - def analyse(implicit inlineContext: InlineContext): IR.Expression = { + def analyse(implicit inlineContext: InlineContext): Expression = { DemandAnalysis.runExpression(ir, inlineContext) } } @@ -88,16 +96,16 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.analyse val boundX = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .expressions .head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - boundX shouldBe an[IR.Application.Force] - boundX.asInstanceOf[IR.Application.Force].target shouldBe an[IR.Name] + boundX shouldBe an[Application.Force] + boundX.asInstanceOf[Application.Force].target shouldBe an[Name] } "work correctly when deeply nested" in { @@ -109,11 +117,11 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.analyse val xUsage = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - xUsage shouldBe an[IR.Application.Force] - xUsage.asInstanceOf[IR.Application.Force].target shouldBe an[IR.Name] + xUsage shouldBe an[Application.Force] + xUsage.asInstanceOf[Application.Force].target shouldBe an[Name] } "not be forced when passed to functions" in { @@ -125,18 +133,18 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.analyse val app = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] app.arguments.head - .asInstanceOf[IR.CallArgument.Specified] - .value shouldBe an[IR.Name] + .asInstanceOf[CallArgument.Specified] + .value shouldBe an[Name] app .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] - .value shouldBe an[IR.Name] + .asInstanceOf[CallArgument.Specified] + .value shouldBe an[Name] } "be forced when used in vector literals" in { @@ -148,13 +156,13 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.analyse val vec = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Literal.Sequence] + .asInstanceOf[Application.Sequence] - vec.items(0) shouldBe an[IR.Application.Force] - vec.items(1) shouldBe an[IR.Application.Force] - vec.items(2) shouldBe an[IR.Application.Force] + vec.items(0) shouldBe an[Application.Force] + vec.items(1) shouldBe an[Application.Force] + vec.items(2) shouldBe an[Application.Force] } } @@ -173,16 +181,16 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.analyse val irBody = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] irBody .expressions(1) - .asInstanceOf[IR.Expression.Binding] - .expression shouldBe an[IR.Application.Force] + .asInstanceOf[Expression.Binding] + .expression shouldBe an[Application.Force] - irBody.returnValue shouldBe an[IR.Application.Force] + irBody.returnValue shouldBe an[Application.Force] } "not be forced when passed to a function" in { @@ -196,15 +204,15 @@ class DemandAnalysisTest extends CompilerTest { | bar blck |""".stripMargin.preprocessExpression.get.analyse - ir.asInstanceOf[IR.Function.Lambda] + ir.asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] - .value shouldBe an[IR.Name] + .asInstanceOf[CallArgument.Specified] + .value shouldBe an[Name] } "force terms in blocks passed directly as arguments" in { @@ -217,21 +225,21 @@ class DemandAnalysisTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val barFunc = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] val oprCall = barFunc.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - oprCall.function.asInstanceOf[IR.Name].name shouldEqual "<|" + oprCall.function.asInstanceOf[Name].name shouldEqual "<|" oprCall.arguments.length shouldEqual 2 - val xArg = oprCall.arguments(1).asInstanceOf[IR.CallArgument.Specified] + val xArg = oprCall.arguments(1).asInstanceOf[CallArgument.Specified] - xArg.value shouldBe an[IR.Expression.Block] + xArg.value shouldBe an[Expression.Block] xArg.value - .asInstanceOf[IR.Expression.Block] - .returnValue shouldBe an[IR.Application.Force] + .asInstanceOf[Expression.Block] + .returnValue shouldBe an[Application.Force] } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala index 946ab789dd95..e7bad033d6b0 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/analyse/GatherDiagnosticsTest.scala @@ -2,8 +2,17 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.CallArgument +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.Application import org.enso.compiler.pass.PassManager import org.enso.compiler.pass.analyse.GatherDiagnostics import org.enso.compiler.test.CompilerTest @@ -11,9 +20,9 @@ import org.enso.compiler.test.CompilerTest class GatherDiagnosticsTest extends CompilerTest { "Error Gathering" should { - val error1 = IR.Error.Syntax(null, IR.Error.Syntax.UnrecognizedToken) - val plusOp = IR.Name.Literal("+", isMethod = true, None) - val plusApp = IR.Application.Prefix( + val error1 = errors.Syntax(null, errors.Syntax.UnrecognizedToken) + val plusOp = Name.Literal("+", isMethod = true, None) + val plusApp = Application.Prefix( plusOp, List( CallArgument.Specified(None, error1, None) @@ -21,11 +30,11 @@ class GatherDiagnosticsTest extends CompilerTest { hasDefaultsSuspended = false, None ) - val lam = IR.Function.Lambda( + val lam = Function.Lambda( List( - IR.DefinitionArgument + DefinitionArgument .Specified( - IR.Name.Literal("bar", isMethod = false, None), + Name.Literal("bar", isMethod = false, None), None, None, suspended = false, @@ -46,58 +55,58 @@ class GatherDiagnosticsTest extends CompilerTest { } "work with module flow" in { - val error2 = IR.Error.Syntax(null, IR.Error.Syntax.UnexpectedExpression) - val error3 = IR.Error.Syntax(null, IR.Error.Syntax.AmbiguousExpression) + val error2 = errors.Syntax(null, errors.Syntax.UnexpectedExpression) + val error3 = errors.Syntax(null, errors.Syntax.AmbiguousExpression) val typeName = - IR.Name.Literal("Foo", isMethod = false, None) + Name.Literal("Foo", isMethod = false, None) val method1Name = - IR.Name.Literal("bar", isMethod = false, None) + Name.Literal("bar", isMethod = false, None) val method2Name = - IR.Name.Literal("baz", isMethod = false, None) + Name.Literal("baz", isMethod = false, None) val fooName = - IR.Name.Literal("foo", isMethod = false, None) + Name.Literal("foo", isMethod = false, None) val method1Ref = - IR.Name.MethodReference( - Some(IR.Name.Qualified(List(typeName), None)), + Name.MethodReference( + Some(Name.Qualified(List(typeName), None)), method1Name, None ) val method2Ref = - IR.Name.MethodReference( - Some(IR.Name.Qualified(List(typeName), None)), + Name.MethodReference( + Some(Name.Qualified(List(typeName), None)), method2Name, None ) - val module = IR.Module( + val module = Module( List(), List(), List( - IR.Module.Scope.Definition.Type( + Definition.Type( typeName, List( - IR.DefinitionArgument + DefinitionArgument .Specified(fooName, None, Some(error2), suspended = false, None) ), List(), None ), - IR.Module.Scope.Definition.Method + definition.Method .Explicit(method1Ref, lam, None), - IR.Module.Scope.Definition.Method + definition.Method .Explicit(method2Ref, error3, None) ), None ) val result = GatherDiagnostics.runModule(module, buildModuleContext()) - val errors = result + val gatheredErrros = result .unsafeGetMetadata(GatherDiagnostics, "Impossible") .diagnostics - errors.toSet shouldEqual Set(error1, error2, error3) + gatheredErrros.toSet shouldEqual Set(error1, error2, error3) } "avoid duplication" in { 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 cb8cd3177d2e..68acdc1f8327 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 @@ -2,9 +2,16 @@ package org.enso.compiler.test.pass.analyse import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{ + Expression, + Function, + Module, + Pattern, + Warning +} +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.Application +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} @@ -52,7 +59,7 @@ class TailCallTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * @@ -68,14 +75,14 @@ class TailCallTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseExpresion(ir: IR.Expression) { + implicit class AnalyseExpresion(ir: Expression) { /** Performs tail call analysis on [[ir]]. * * @param context the inline context in which analysis takes place * @return [[ir]], with tail call analysis metadata attached */ - def analyse(implicit context: InlineContext): IR.Expression = { + def analyse(implicit context: InlineContext): Expression = { TailCall.runExpression(ir, context) } } @@ -138,7 +145,7 @@ class TailCallTest extends CompilerTest { """ |foo = a b |""".stripMargin.preprocessExpression.get.analyse - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] binding.getMetadata(TailCall) shouldEqual Some(TailPosition.Tail) binding.expression.getMetadata(TailCall) shouldEqual Some( TailPosition.NotTail @@ -157,9 +164,9 @@ class TailCallTest extends CompilerTest { | e = a * c | @Tail_Call (d + e) |""".stripMargin.preprocessExpression.get.analyse - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] - val fnBody = ir.body.asInstanceOf[IR.Expression.Block] + val fnBody = ir.body.asInstanceOf[Expression.Block] "mark the last expression of the function as tail" in { fnBody.returnValue.getMetadata(TailCall) shouldEqual Some( @@ -178,15 +185,15 @@ class TailCallTest extends CompilerTest { "warn about misplaced @TailCall annotations" in { fnBody .expressions(0) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression .diagnostics - .filter(_.isInstanceOf[IR.Warning.WrongTco]) + .filter(_.isInstanceOf[Warning.WrongTco]) .toList .length shouldEqual 1 fnBody.returnValue.diagnostics - .filter(_.isInstanceOf[IR.Warning.WrongTco]) + .filter(_.isInstanceOf[Warning.WrongTco]) .toList .length shouldEqual 0 } @@ -203,24 +210,24 @@ class TailCallTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val fnBody = ir.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body "handle application involving local functions" in { fnBody - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments(2) .value - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .function .diagnostics - .filter(_.isInstanceOf[IR.Warning.WrongTco]) + .filter(_.isInstanceOf[Warning.WrongTco]) .toList .length shouldEqual 0 } @@ -241,25 +248,25 @@ class TailCallTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val caseExpr = ir.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .expressions .head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] caseExpr.getMetadata(TailCall) shouldEqual Some( TailPosition.NotTail ) caseExpr.branches.foreach(branch => { val branchExpression = - branch.expression.asInstanceOf[IR.Application.Prefix] + branch.expression.asInstanceOf[Application.Prefix] branchExpression.getMetadata(TailCall) shouldEqual Some( TailPosition.NotTail @@ -278,22 +285,22 @@ class TailCallTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val caseExpr = ir.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] caseExpr.getMetadata(TailCall) shouldEqual Some( TailPosition.Tail ) caseExpr.branches.foreach(branch => { val branchExpression = - branch.expression.asInstanceOf[IR.Application.Prefix] + branch.expression.asInstanceOf[Application.Prefix] branchExpression.getMetadata(TailCall) shouldEqual Some( TailPosition.Tail @@ -309,9 +316,9 @@ class TailCallTest extends CompilerTest { |case x of | Cons a b -> a + b |""".stripMargin.preprocessExpression.get.analyse - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val caseBranch = ir.branches.head val pattern = caseBranch.pattern.asInstanceOf[Pattern.Constructor] @@ -339,11 +346,11 @@ class TailCallTest extends CompilerTest { |Foo.bar = | IO.println "AAAAA" |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val tailCallBody = tailCall.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val nonTailCall = """ @@ -351,17 +358,17 @@ class TailCallTest extends CompilerTest { | a = b c d | a |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val nonTailCallBody = nonTailCall.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] "mark the arguments as tail" in { nonTailCallBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .foreach(arg => arg.getMetadata(TailCall) shouldEqual Some( @@ -370,7 +377,7 @@ class TailCallTest extends CompilerTest { ) tailCallBody.returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .foreach(arg => arg.getMetadata(TailCall) shouldEqual Some( @@ -387,7 +394,7 @@ class TailCallTest extends CompilerTest { "mark the function call as not tail if it is in a tail position" in { nonTailCallBody.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression .getMetadata(TailCall) shouldEqual Some(TailPosition.NotTail) } @@ -403,19 +410,19 @@ class TailCallTest extends CompilerTest { | mul = a -> b -> a * b | mul c d |""".stripMargin.preprocessModule.analyse.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val block = ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] "mark the bodies of bound functions as tail properly" in { block .expressions(1) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body .getMetadata(TailCall) shouldEqual Some(TailPosition.Tail) } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala index 426493566306..f0e50df5bfba 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ComplexTypeTest.scala @@ -2,8 +2,10 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.ModuleContext -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition +import org.enso.compiler.core.ir.{Module, Name, Type} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.desugar.ComplexType import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -22,11 +24,11 @@ class ComplexTypeTest extends CompilerTest { new PassManager(List(precursorPasses), passConfig) /** Adds an extension method to run complex type desugaring on an - * [[IR.Module]]. + * [[Module]]. * * @param ir the module to run desugaring on */ - implicit class DesugarModule(ir: IR.Module) { + implicit class DesugarModule(ir: Module) { /** Runs desugaring on a module. * @@ -34,7 +36,7 @@ class ComplexTypeTest extends CompilerTest { * place * @return [[ir]], with any complex type definitions desugared */ - def desugar(implicit moduleContext: ModuleContext): IR.Module = { + def desugar(implicit moduleContext: ModuleContext): Module = { ComplexType.runModule(ir, moduleContext) } } @@ -85,29 +87,29 @@ class ComplexTypeTest extends CompilerTest { } "have their methods desugared to binding methods" in { - ir.bindings(3) shouldBe an[Definition.Method.Binding] - val isJust = ir.bindings(3).asInstanceOf[Definition.Method.Binding] + ir.bindings(3) shouldBe an[definition.Method.Binding] + val isJust = ir.bindings(3).asInstanceOf[definition.Method.Binding] isJust.methodName.name shouldEqual "is_just" isJust.typeName.get.name shouldEqual "Maybe" - ir.bindings(5) shouldBe an[Definition.Method.Binding] - val f = ir.bindings(5).asInstanceOf[Definition.Method.Binding] + ir.bindings(5) shouldBe an[definition.Method.Binding] + val f = ir.bindings(5).asInstanceOf[definition.Method.Binding] f.methodName.name shouldEqual "f" f.typeName.get.name shouldEqual "Maybe" } "have type signatures copied to above each method" in { - ir.bindings(2) shouldBe an[IR.Type.Ascription] - ir.bindings(4) shouldBe an[IR.Type.Ascription] + ir.bindings(2) shouldBe an[Type.Ascription] + ir.bindings(4) shouldBe an[Type.Ascription] val isJustSigName = ir .bindings(2) - .asInstanceOf[IR.Type.Ascription] + .asInstanceOf[Type.Ascription] .typed - .asInstanceOf[IR.Name.MethodReference] + .asInstanceOf[Name.MethodReference] val isJustMethodName = ir .bindings(3) - .asInstanceOf[Definition.Method.Binding] + .asInstanceOf[definition.Method.Binding] .methodReference assert( @@ -117,12 +119,12 @@ class ComplexTypeTest extends CompilerTest { val fSigName = ir .bindings(4) - .asInstanceOf[IR.Type.Ascription] + .asInstanceOf[Type.Ascription] .typed - .asInstanceOf[IR.Name.MethodReference] + .asInstanceOf[Name.MethodReference] val fMethodName = ir .bindings(5) - .asInstanceOf[Definition.Method.Binding] + .asInstanceOf[definition.Method.Binding] .methodReference assert( @@ -132,18 +134,18 @@ class ComplexTypeTest extends CompilerTest { } "leave un-associated signatures intact" in { - ir.bindings(1) shouldBe an[IR.Type.Ascription] + ir.bindings(1) shouldBe an[Type.Ascription] ir.bindings(1) - .asInstanceOf[IR.Type.Ascription] + .asInstanceOf[Type.Ascription] .typed - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "invalid_sig" - ir.bindings(6) shouldBe an[IR.Type.Ascription] + ir.bindings(6) shouldBe an[Type.Ascription] ir.bindings(6) - .asInstanceOf[IR.Type.Ascription] + .asInstanceOf[Type.Ascription] .typed - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "bad_trailing_sig" } } @@ -169,14 +171,14 @@ class ComplexTypeTest extends CompilerTest { } "have their errors translated untouched" in { - ir.bindings.last shouldBe an[IR.Error.Syntax] - val err = ir.bindings.last.asInstanceOf[IR.Error.Syntax] - err.reason shouldBe an[IR.Error.Syntax.UnexpectedDeclarationInType.type] + ir.bindings.last shouldBe an[errors.Syntax] + val err = ir.bindings.last.asInstanceOf[errors.Syntax] + err.reason shouldBe an[errors.Syntax.UnexpectedDeclarationInType.type] } "have their valid methods desugared" in { - ir.bindings(1) shouldBe a[Definition.Method.Binding] - val method = ir.bindings(1).asInstanceOf[Definition.Method.Binding] + ir.bindings(1) shouldBe a[definition.Method.Binding] + val method = ir.bindings(1).asInstanceOf[definition.Method.Binding] method.typeName.get.name shouldEqual "Foo" method.methodName.name shouldEqual "g" } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/FunctionBindingTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/FunctionBindingTest.scala index a86adc9c7194..c3676f3a3859 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/FunctionBindingTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/FunctionBindingTest.scala @@ -2,7 +2,17 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.expression.{Application, Operator} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.expression.Error +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.desugar.FunctionBinding import org.enso.compiler.pass.resolve.{DocumentationComments, ModuleAnnotations} import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} @@ -21,11 +31,11 @@ class FunctionBindingTest extends CompilerTest { new PassManager(List(precursorPasses), passConfig) /** Adds an extension method to run method and function desugaring on an - * [[IR.Module]]. + * [[Module]]. * * @param ir the module to run desugaring on */ - implicit class DesugarModule(ir: IR.Module) { + implicit class DesugarModule(ir: Module) { /** Runs desugaring on a module. * @@ -34,7 +44,7 @@ class FunctionBindingTest extends CompilerTest { * @return [[ir]], with any sugared function and method definitions * desugared */ - def desugar(implicit moduleContext: ModuleContext): IR.Module = { + def desugar(implicit moduleContext: ModuleContext): Module = { FunctionBinding.runModule(ir, moduleContext) } } @@ -44,7 +54,7 @@ class FunctionBindingTest extends CompilerTest { * * @param ir the expression to desugar */ - implicit class DesugarExpression(ir: IR.Expression) { + implicit class DesugarExpression(ir: Expression) { /** Runs desgaring on an expression. * @@ -52,7 +62,7 @@ class FunctionBindingTest extends CompilerTest { * taking place * @return [[ir]], with any sugared function definitions desugared */ - def desugar(implicit inlineContext: InlineContext): IR.Expression = { + def desugar(implicit inlineContext: InlineContext): Expression = { FunctionBinding.runExpression(ir, inlineContext) } } @@ -84,26 +94,26 @@ class FunctionBindingTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar "desugar to standard method definitions" in { - ir.bindings.head shouldBe an[IR.Module.Scope.Definition.Method.Explicit] + ir.bindings.head shouldBe an[definition.Method.Explicit] } val explicitMethod = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + ir.bindings.head.asInstanceOf[definition.Method.Explicit] "have the function arguments in the body functions" in { - val lambda1 = explicitMethod.body.asInstanceOf[IR.Function.Lambda] - val lambda2 = lambda1.body.asInstanceOf[IR.Function.Lambda] - val lambda3 = lambda2.body.asInstanceOf[IR.Function.Lambda] + val lambda1 = explicitMethod.body.asInstanceOf[Function.Lambda] + val lambda2 = lambda1.body.asInstanceOf[Function.Lambda] + val lambda3 = lambda2.body.asInstanceOf[Function.Lambda] val cArg = - lambda3.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + lambda3.arguments.head.asInstanceOf[DefinitionArgument.Specified] lambda1.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .suspended shouldEqual true lambda1.arguments.head.name.name shouldEqual "a" lambda2.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] - .name shouldBe an[IR.Name.Blank] + .asInstanceOf[DefinitionArgument.Specified] + .name shouldBe an[Name.Blank] cArg.name.name shouldEqual "c" cArg.defaultValue shouldBe defined } @@ -117,16 +127,16 @@ class FunctionBindingTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val body = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] - body.expressions.head shouldBe an[IR.Expression.Binding] - val binding = body.expressions.head.asInstanceOf[IR.Expression.Binding] + body.expressions.head shouldBe an[Expression.Binding] + val binding = body.expressions.head.asInstanceOf[Expression.Binding] - binding.expression shouldBe an[IR.Function.Lambda] + binding.expression shouldBe an[Function.Lambda] } "desugar module-level methods" in { @@ -136,7 +146,7 @@ class FunctionBindingTest extends CompilerTest { | y -> x + y |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Module.Scope.Definition.Method.Explicit] + ir.bindings.head shouldBe an[definition.Method.Explicit] } } @@ -150,11 +160,11 @@ class FunctionBindingTest extends CompilerTest { s"""My_Type.$from (that : Other) ~config=Nothing = My_Type value.a |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Module.Scope.Definition.Method.Conversion] + ir.bindings.head shouldBe an[definition.Method.Conversion] val conversion = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Conversion] - conversion.sourceTypeName.asInstanceOf[IR.Name].name shouldEqual "Other" - val arguments = conversion.body.asInstanceOf[IR.Function.Lambda].arguments + .asInstanceOf[definition.Method.Conversion] + conversion.sourceTypeName.asInstanceOf[Name].name shouldEqual "Other" + val arguments = conversion.body.asInstanceOf[Function.Lambda].arguments arguments.length shouldEqual 1 arguments.head.name.name shouldEqual "that" arguments.head.ascribedType shouldBe defined @@ -162,9 +172,9 @@ class FunctionBindingTest extends CompilerTest { arguments.head.suspended shouldBe false val subLambda = conversion.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val subArguments = subLambda.arguments subArguments.length shouldEqual 1 subArguments.head.name.name shouldEqual "config" @@ -182,9 +192,9 @@ class FunctionBindingTest extends CompilerTest { |My_Type.$from (that : Value) = that |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Module.Scope.Definition.Method.Conversion] + ir.bindings.head shouldBe an[definition.Method.Conversion] val conversion = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Conversion] + .asInstanceOf[definition.Method.Conversion] val annotations = conversion.unsafeGetMetadata(ModuleAnnotations, "Should be present.") @@ -203,9 +213,9 @@ class FunctionBindingTest extends CompilerTest { s"""My_Type.$from = a + b |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Error.Conversion] - val err = ir.bindings.head.asInstanceOf[IR.Error.Conversion] - err.reason shouldBe an[IR.Error.Conversion.MissingArgs.type] + ir.bindings.head shouldBe an[errors.Conversion] + val err = ir.bindings.head.asInstanceOf[errors.Conversion] + err.reason shouldBe an[errors.Conversion.MissingArgs.type] } "return an error if the conversion does not have a source type" in { @@ -213,9 +223,9 @@ class FunctionBindingTest extends CompilerTest { s"""My_Type.$from that = that + that |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Error.Conversion] - val err = ir.bindings.head.asInstanceOf[IR.Error.Conversion] - err.reason shouldBe an[IR.Error.Conversion.MissingSourceType] + ir.bindings.head shouldBe an[errors.Conversion] + val err = ir.bindings.head.asInstanceOf[errors.Conversion] + err.reason shouldBe an[errors.Conversion.MissingSourceType] } "return an error if the additional arguments don't have defaults" in { @@ -223,9 +233,9 @@ class FunctionBindingTest extends CompilerTest { s"""My_Type.$from (that : Other) config = that + that |""".stripMargin.preprocessModule.desugar - ir.bindings.head shouldBe an[IR.Error.Conversion] - val err = ir.bindings.head.asInstanceOf[IR.Error.Conversion] - err.reason shouldBe an[IR.Error.Conversion.NonDefaultedArgument] + ir.bindings.head shouldBe an[errors.Conversion] + val err = ir.bindings.head.asInstanceOf[errors.Conversion] + err.reason shouldBe an[errors.Conversion.NonDefaultedArgument] } "not return an error if the additional arguments don't have defaults and is not a self parameter" in { @@ -233,7 +243,7 @@ class FunctionBindingTest extends CompilerTest { s"""My_Type.$from (that : Other) config=1 self = that + that |""".stripMargin.preprocessModule.desugar - ir.bindings.head should not be an[IR.Error] + ir.bindings.head should not be an[Error] } } @@ -246,29 +256,29 @@ class FunctionBindingTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.desugar "desugar to a binding with a lambda" in { - ir shouldBe an[IR.Expression.Binding] - val binding = ir.asInstanceOf[IR.Expression.Binding] + ir shouldBe an[Expression.Binding] + val binding = ir.asInstanceOf[Expression.Binding] binding.name.name shouldEqual "f" - binding.expression shouldBe an[IR.Function.Lambda] + binding.expression shouldBe an[Function.Lambda] } "work properly for complex argument definition types" in { val lambda1 = ir - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] - val lambda2 = lambda1.body.asInstanceOf[IR.Function.Lambda] - val lambda3 = lambda2.body.asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] + val lambda2 = lambda1.body.asInstanceOf[Function.Lambda] + val lambda3 = lambda2.body.asInstanceOf[Function.Lambda] val cArg = - lambda3.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + lambda3.arguments.head.asInstanceOf[DefinitionArgument.Specified] lambda1.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .suspended shouldEqual true lambda2.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] - .name shouldBe an[IR.Name.Blank] + .asInstanceOf[DefinitionArgument.Specified] + .name shouldBe an[Name.Blank] cArg.name.name shouldEqual "c" cArg.defaultValue shouldBe defined } @@ -280,32 +290,32 @@ class FunctionBindingTest extends CompilerTest { | g b = b | g 1 |""".stripMargin.preprocessExpression.get.desugar - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val aArg = ir.expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] aArg.name.name shouldEqual "a" aArg.defaultValue.get - .asInstanceOf[IR.Application.Operator.Binary] + .asInstanceOf[Operator.Binary] .left .value - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .function - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "f" val body = ir.expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] - body.expressions.head shouldBe an[IR.Expression.Binding] + .asInstanceOf[Expression.Block] + body.expressions.head shouldBe an[Expression.Binding] - val gBinding = body.expressions.head.asInstanceOf[IR.Expression.Binding] + val gBinding = body.expressions.head.asInstanceOf[Expression.Binding] gBinding.name.name shouldEqual "g" - gBinding.expression shouldBe an[IR.Function.Lambda] + gBinding.expression shouldBe an[Function.Lambda] } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/GenerateMethodBodiesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/GenerateMethodBodiesTest.scala index 89a83563b2bd..1e754ba9564e 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/GenerateMethodBodiesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/GenerateMethodBodiesTest.scala @@ -2,8 +2,16 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.ModuleContext -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Function, + Module, + Name, + Warning +} +import org.enso.compiler.core.ir.expression.Operator +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.desugar.{FunctionBinding, GenerateMethodBodies} import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -25,11 +33,11 @@ class GenerateMethodBodiesTest extends CompilerTest { new PassManager(List(precursorPasses), passConfig) /** Adds an extension method to run method and method body generation on an - * [[IR.Module]]. + * [[Module]]. * * @param ir the module to run desugaring on */ - implicit class DesugarModule(ir: IR.Module) { + implicit class DesugarModule(ir: Module) { /** Runs desugaring on a module. * @@ -37,7 +45,7 @@ class GenerateMethodBodiesTest extends CompilerTest { * place * @return [[ir]], with any method bodies desugared */ - def desugar(implicit moduleContext: ModuleContext): IR.Module = { + def desugar(implicit moduleContext: ModuleContext): Module = { GenerateMethodBodies.runModule(ir, moduleContext) } } @@ -49,30 +57,30 @@ class GenerateMethodBodiesTest extends CompilerTest { """ |Unit.method = a -> b -> c -> a + b + c |""".stripMargin.preprocessModule - val irMethod = ir.bindings.head.asInstanceOf[Method] + val irMethod = ir.bindings.head.asInstanceOf[definition.Method] val irResult = ir.desugar - val irResultMethod = irResult.bindings.head.asInstanceOf[Method] + val irResultMethod = irResult.bindings.head.asInstanceOf[definition.Method] "still have the `self` argument prepended to the argument list" in { val resultArgs = - irResultMethod.body.asInstanceOf[IR.Function.Lambda].arguments + irResultMethod.body.asInstanceOf[Function.Lambda].arguments val firstArg :: restArgs = resultArgs val self = firstArg - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - self shouldBe a[IR.Name.Self] - self.asInstanceOf[IR.Name.Self].synthetic shouldBe true + self shouldBe a[Name.Self] + self.asInstanceOf[Name.Self].synthetic shouldBe true restArgs shouldEqual irMethod.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments } "have the body of the function remain untouched" in { - val inputBody = irMethod.body.asInstanceOf[IR.Function.Lambda].body - val resultBody = irResultMethod.body.asInstanceOf[IR.Function.Lambda].body + val inputBody = irMethod.body.asInstanceOf[Function.Lambda].body + val resultBody = irResultMethod.body.asInstanceOf[Function.Lambda].body inputBody shouldEqual resultBody } @@ -83,25 +91,25 @@ class GenerateMethodBodiesTest extends CompilerTest { """ |Unit.method = 1 |""".stripMargin.preprocessModule - val irMethod = ir.bindings.head.asInstanceOf[Method] + val irMethod = ir.bindings.head.asInstanceOf[definition.Method] val irResult = ir.desugar - val irResultMethod = irResult.bindings.head.asInstanceOf[Method] + val irResultMethod = irResult.bindings.head.asInstanceOf[definition.Method] "have the expression converted into a function" in { - irResultMethod.body shouldBe an[IR.Function.Lambda] + irResultMethod.body shouldBe an[Function.Lambda] } "have the resultant function take the `self` argument" in { // TODO old semantics val bodyArgs = - irResultMethod.body.asInstanceOf[IR.Function.Lambda].arguments + irResultMethod.body.asInstanceOf[Function.Lambda].arguments bodyArgs.length shouldEqual 1 } "have the body of the function be equivalent to the expression" in { irResultMethod.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body shouldEqual irMethod.body } @@ -115,31 +123,31 @@ class GenerateMethodBodiesTest extends CompilerTest { """ |Unit.method self = 1 |""".stripMargin.preprocessModule - val irMethod = ir.bindings.head.asInstanceOf[Method] + val irMethod = ir.bindings.head.asInstanceOf[definition.Method] val irResult = ir.desugar - val irResultMethod = irResult.bindings.head.asInstanceOf[Method] + val irResultMethod = irResult.bindings.head.asInstanceOf[definition.Method] "have the expression converted into a function" in { - irResultMethod.body shouldBe an[IR.Function.Lambda] + irResultMethod.body shouldBe an[Function.Lambda] } "have the resultant function take the `self` argument" in { // TODO old semantics val bodyArgs = - irResultMethod.body.asInstanceOf[IR.Function.Lambda].arguments + irResultMethod.body.asInstanceOf[Function.Lambda].arguments bodyArgs.length shouldEqual 1 val self = bodyArgs.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - self shouldBe a[IR.Name.Self] - self.asInstanceOf[IR.Name.Self].synthetic shouldBe false + self shouldBe a[Name.Self] + self.asInstanceOf[Name.Self].synthetic shouldBe false } "have the body of the function be equivalent to the expression" in { irResultMethod.body - .asInstanceOf[IR.Function.Lambda] - .body shouldEqual irMethod.body.asInstanceOf[IR.Function.Lambda].body + .asInstanceOf[Function.Lambda] + .body shouldEqual irMethod.body.asInstanceOf[Function.Lambda].body } "have the body function's location equivalent to the original body" in { @@ -158,41 +166,41 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule val irMethod = - ir.bindings.head.asInstanceOf[Method] + ir.bindings.head.asInstanceOf[definition.Method] val irMethodSelfArg = - irMethod.body.asInstanceOf[IR.Function.Lambda].arguments.head + irMethod.body.asInstanceOf[Function.Lambda].arguments.head val irFoo = - ir.bindings(1).asInstanceOf[Method] + ir.bindings(1).asInstanceOf[definition.Method] val irFooFirstArg = - irFoo.body.asInstanceOf[IR.Function.Lambda].arguments.head + irFoo.body.asInstanceOf[Function.Lambda].arguments.head val irBar = - ir.bindings(2).asInstanceOf[Method] + ir.bindings(2).asInstanceOf[definition.Method] val irBarFirstArg = - irBar.body.asInstanceOf[IR.Function.Lambda].arguments.head + irBar.body.asInstanceOf[Function.Lambda].arguments.head val irBaz = - ir.bindings(3).asInstanceOf[Method] + ir.bindings(3).asInstanceOf[definition.Method] val irBazSndArg = irBaz.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head val irResult = ir.desugar - val irResultMethod = irResult.bindings.head.asInstanceOf[Method] - val irResultFoo = irResult.bindings(1).asInstanceOf[Method] - val irResultBar = irResult.bindings(2).asInstanceOf[Method] - val irResultBaz = irResult.bindings(3).asInstanceOf[Method] - val irResultQux = irResult.bindings(4).asInstanceOf[Method] + val irResultMethod = irResult.bindings.head.asInstanceOf[definition.Method] + val irResultFoo = irResult.bindings(1).asInstanceOf[definition.Method] + val irResultBar = irResult.bindings(2).asInstanceOf[definition.Method] + val irResultBaz = irResult.bindings(3).asInstanceOf[definition.Method] + val irResultQux = irResult.bindings(4).asInstanceOf[definition.Method] "not generate an auxiliary self parameter" in { val resultArgs = irResultMethod.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments resultArgs.size shouldEqual 1 val selfArg = resultArgs.head.name - selfArg shouldEqual IR.Name.Self( + selfArg shouldEqual Name.Self( location = irMethodSelfArg.name.location, synthetic = false ) @@ -200,47 +208,47 @@ class GenerateMethodBodiesTest extends CompilerTest { "generate a warning about self parameter not being in the first position" in { val resultLambda = irResultFoo.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val resultArgs = resultLambda.arguments resultArgs.size shouldEqual 1 val selfArg = resultArgs.head.name - selfArg should not be an[IR.Name.Self] + selfArg should not be an[Name.Self] selfArg shouldEqual irFooFirstArg.name } "not generate an auxiliary self parameter for the already present one" in { val resultLambda = irResultBar.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val resultArgs = resultLambda.arguments resultArgs.size shouldEqual 1 val selfArg = resultArgs.head.name - selfArg shouldBe an[IR.Name.Self] - resultLambda.body shouldBe an[IR.Application.Operator.Binary] - selfArg shouldEqual IR.Name.Self(location = irBarFirstArg.location) + selfArg shouldBe an[Name.Self] + resultLambda.body shouldBe an[Operator.Binary] + selfArg shouldEqual Name.Self(location = irBarFirstArg.location) } "not generate an auxiliary self parameter for the already present one but in a wrong position" in { val resultLambda = irResultBaz.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val resultArgs = resultLambda.arguments resultArgs.size shouldEqual 1 val firstArg = resultArgs.head.name - firstArg should not be an[IR.Name.Self] + firstArg should not be an[Name.Self] - val bodyLambda = resultLambda.body.asInstanceOf[IR.Function.Lambda] + val bodyLambda = resultLambda.body.asInstanceOf[Function.Lambda] bodyLambda.arguments.size shouldEqual 1 val selfArg = bodyLambda.arguments.head.name - selfArg shouldEqual IR.Name.Self(location = irBazSndArg.location) - resultLambda.diagnostics.collect { case w: IR.Warning => + selfArg shouldEqual Name.Self(location = irBazSndArg.location) + resultLambda.diagnostics.collect { case w: Warning => w - }.head shouldBe an[IR.Warning.WrongSelfParameterPos] + }.head shouldBe an[Warning.WrongSelfParameterPos] } "return an error when redefining `self` parameter" in { - irResultQux.body shouldBe an[IR.Error.Redefined.SelfArg] + irResultQux.body shouldBe an[errors.Redefined.SelfArg] } } @@ -257,45 +265,45 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val irMethodAdd = - ir.bindings(2).asInstanceOf[Method] + ir.bindings(2).asInstanceOf[definition.Method] val irMethodAddSelfArg = - irMethodAdd.body.asInstanceOf[IR.Function.Lambda].arguments + irMethodAdd.body.asInstanceOf[Function.Lambda].arguments val irResult = ir.desugar - val irResultMethodAdd = irResult.bindings(2).asInstanceOf[Method] + val irResultMethodAdd = irResult.bindings(2).asInstanceOf[definition.Method] - val irResultMethodSum = irResult.bindings(3).asInstanceOf[Method] + val irResultMethodSum = irResult.bindings(3).asInstanceOf[definition.Method] "not add new argument" in { val resultLambda = irResultMethodAdd.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val resultArgs = resultLambda.arguments resultArgs.size shouldEqual 1 val selfArg = resultArgs.head.name - selfArg shouldEqual IR.Name.Self(location = + selfArg shouldEqual Name.Self(location = irMethodAddSelfArg.head.name.location ) - resultLambda.diagnostics.collect { case w: IR.Warning => + resultLambda.diagnostics.collect { case w: Warning => w } shouldBe empty } "generate a warning when the parameter is not first" in { val resultLambda = irResultMethodSum.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val resultArgs = resultLambda.arguments resultArgs.size shouldEqual 1 val selfArg = resultArgs(0).name - selfArg should not be an[IR.Name.Self] - resultLambda.diagnostics.collect { case w: IR.Warning => + selfArg should not be an[Name.Self] + resultLambda.diagnostics.collect { case w: Warning => w - }.head shouldBe an[IR.Warning.WrongSelfParameterPos] + }.head shouldBe an[Warning.WrongSelfParameterPos] - val nestedLmabda = resultLambda.body.asInstanceOf[IR.Function.Lambda] + val nestedLmabda = resultLambda.body.asInstanceOf[Function.Lambda] nestedLmabda.arguments.size shouldEqual 1 - nestedLmabda.arguments(0).name shouldBe an[IR.Name.Self] + nestedLmabda.arguments(0).name shouldBe an[Name.Self] } } @@ -308,11 +316,11 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val conversion = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method] - conversion.body shouldBe an[IR.Function.Lambda] - val body = conversion.body.asInstanceOf[IR.Function.Lambda] + ir.bindings.head.asInstanceOf[definition.Method] + conversion.body shouldBe an[Function.Lambda] + val body = conversion.body.asInstanceOf[Function.Lambda] body.arguments.length shouldEqual 2 - body.arguments.head.name shouldBe a[IR.Name.Self] + body.arguments.head.name shouldBe a[Name.Self] } // FIXME: This should probably be prohibited @@ -322,14 +330,14 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val conversion = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method] - conversion.body shouldBe an[IR.Function.Lambda] - val body = conversion.body.asInstanceOf[IR.Function.Lambda] + ir.bindings.head.asInstanceOf[definition.Method] + conversion.body shouldBe an[Function.Lambda] + val body = conversion.body.asInstanceOf[Function.Lambda] body.arguments.length shouldEqual 1 - body.arguments.head.name shouldBe an[IR.Name.Self] - val nestedBody = body.body.asInstanceOf[IR.Function.Lambda] + body.arguments.head.name shouldBe an[Name.Self] + val nestedBody = body.body.asInstanceOf[Function.Lambda] nestedBody.arguments.length shouldEqual 1 - nestedBody.arguments.head.name shouldBe an[IR.Name.Literal] + nestedBody.arguments.head.name shouldBe an[Name.Literal] nestedBody.arguments.head.name.name shouldEqual Constants.Names.THAT_ARGUMENT } @@ -339,16 +347,16 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val conversion = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method] - conversion.body shouldBe an[IR.Function.Lambda] - val body = conversion.body.asInstanceOf[IR.Function.Lambda] + ir.bindings.head.asInstanceOf[definition.Method] + conversion.body shouldBe an[Function.Lambda] + val body = conversion.body.asInstanceOf[Function.Lambda] body.arguments.length shouldEqual 1 - body.arguments.head.name shouldBe an[IR.Name.Literal] + body.arguments.head.name shouldBe an[Name.Literal] body.arguments.head.name.name shouldBe Constants.Names.THAT_ARGUMENT - conversion.body.diagnostics.collect { case w: IR.Warning => + conversion.body.diagnostics.collect { case w: Warning => w - }.head shouldBe an[IR.Warning.WrongSelfParameterPos] + }.head shouldBe an[Warning.WrongSelfParameterPos] } "have report a warning when defining default `self` at a wrong position" in { @@ -357,16 +365,16 @@ class GenerateMethodBodiesTest extends CompilerTest { |""".stripMargin.preprocessModule.desugar val conversion = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.Method] - conversion.body shouldBe an[IR.Function.Lambda] - val body = conversion.body.asInstanceOf[IR.Function.Lambda] + ir.bindings.head.asInstanceOf[definition.Method] + conversion.body shouldBe an[Function.Lambda] + val body = conversion.body.asInstanceOf[Function.Lambda] body.arguments.length shouldEqual 1 - body.arguments.head.name shouldBe an[IR.Name.Literal] + body.arguments.head.name shouldBe an[Name.Literal] body.arguments.head.name.name shouldBe Constants.Names.THAT_ARGUMENT - conversion.body.diagnostics.collect { case w: IR.Warning => + conversion.body.diagnostics.collect { case w: Warning => w - }.head shouldBe an[IR.Warning.WrongSelfParameterPos] + }.head shouldBe an[Warning.WrongSelfParameterPos] } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ImportsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ImportsTest.scala index 468e8f1fbceb..8d7064cd993e 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ImportsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/ImportsTest.scala @@ -2,7 +2,7 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Module import org.enso.compiler.pass.desugar.Imports import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -30,7 +30,7 @@ class ImportsTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * 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 e5e3a375ee19..ef9eefe41416 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 @@ -2,7 +2,15 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Literal, + Name +} +import org.enso.compiler.core.ir.expression.{Application, Case} import org.enso.compiler.pass.desugar.LambdaShorthandToLambda import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -25,7 +33,7 @@ class LambdaShorthandToLambdaTest extends CompilerTest { * * @param ir the IR to desugar */ - implicit class DesugarExpression(ir: IR.Expression) { + implicit class DesugarExpression(ir: Expression) { /** Runs lambda shorthand desugaring on [[ir]]. * @@ -33,7 +41,7 @@ class LambdaShorthandToLambdaTest extends CompilerTest { * place * @return [[ir]], with all lambda shorthand desugared */ - def desugar(implicit inlineContext: InlineContext): IR.Expression = { + def desugar(implicit inlineContext: InlineContext): Expression = { LambdaShorthandToLambda.runExpression(ir, inlineContext) } } @@ -57,34 +65,34 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |foo a _ b _ |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val irFnArgName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn.body shouldBe an[IR.Function.Lambda] - val irFnNested = irFn.body.asInstanceOf[IR.Function.Lambda] + irFn.body shouldBe an[Function.Lambda] + val irFnNested = irFn.body.asInstanceOf[Function.Lambda] val irFnNestedArgName = irFnNested.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - irFnNested.body shouldBe an[IR.Application.Prefix] + irFnNested.body shouldBe an[Application.Prefix] val body = irFn.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] val arg2Name = body .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val arg4Name = body .arguments(3) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] irFnArgName.name shouldEqual arg2Name.name irFnNestedArgName.name shouldEqual arg4Name.name @@ -98,32 +106,32 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |foo (a = _) b _ |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val irFnArgName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn.body shouldBe an[IR.Function.Lambda] - val irFnNested = irFn.body.asInstanceOf[IR.Function.Lambda] + irFn.body shouldBe an[Function.Lambda] + val irFnNested = irFn.body.asInstanceOf[Function.Lambda] val irFnNestedArgName = irFnNested.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - irFnNested.body shouldBe an[IR.Application.Prefix] - val app = irFnNested.body.asInstanceOf[IR.Application.Prefix] + irFnNested.body shouldBe an[Application.Prefix] + val app = irFnNested.body.asInstanceOf[Application.Prefix] val arg1Name = app.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val arg3Name = app .arguments(2) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] irFnArgName.name shouldEqual arg1Name.name irFnNestedArgName.name shouldEqual arg3Name.name @@ -137,16 +145,16 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |_ a b |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val irFnArgName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn.body shouldBe an[IR.Application.Prefix] - val app = irFn.body.asInstanceOf[IR.Application.Prefix] + irFn.body shouldBe an[Application.Prefix] + val app = irFn.body.asInstanceOf[Application.Prefix] - val fnName = app.function.asInstanceOf[IR.Name.Literal] + val fnName = app.function.asInstanceOf[Name.Literal] irFnArgName.name shouldEqual fnName.name } @@ -159,18 +167,18 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |if _ then a |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val irFnArgName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn.body shouldBe an[IR.Application.Prefix] - val app = irFn.body.asInstanceOf[IR.Application.Prefix] + irFn.body shouldBe an[Application.Prefix] + val app = irFn.body.asInstanceOf[Application.Prefix] val arg1Name = app.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] irFnArgName.name shouldEqual arg1Name.name } @@ -184,20 +192,20 @@ class LambdaShorthandToLambdaTest extends CompilerTest { | Nil -> 0 |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irLam = ir.asInstanceOf[IR.Function.Lambda] + val irLam = ir.asInstanceOf[Function.Lambda] irLam.arguments.length shouldEqual 1 val lamArgName = - irLam.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irLam.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - val lamBody = irLam.body.asInstanceOf[IR.Case.Expr] + val lamBody = irLam.body.asInstanceOf[Case.Expr] - lamBody.scrutinee shouldBe an[IR.Name.Literal] + lamBody.scrutinee shouldBe an[Name.Literal] lamBody.scrutinee - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual lamArgName.name } @@ -209,15 +217,15 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |(10 + _) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val argName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - val body = irFn.body.asInstanceOf[IR.Application.Prefix] - val rightArg = body.arguments(1).value.asInstanceOf[IR.Name.Literal] + val body = irFn.body.asInstanceOf[Application.Prefix] + val rightArg = body.arguments(1).value.asInstanceOf[Name.Literal] argName.name shouldEqual rightArg.name } @@ -230,22 +238,22 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |(_ +) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val underscoreFn = ir.asInstanceOf[IR.Function.Lambda] + val underscoreFn = ir.asInstanceOf[Function.Lambda] val underscoreArgName = underscoreFn.arguments.head.name - val rightArgLambda = underscoreFn.body.asInstanceOf[IR.Function.Lambda] + val rightArgLambda = underscoreFn.body.asInstanceOf[Function.Lambda] rightArgLambda.arguments.length shouldEqual 1 val rightArgLambdaArgName = rightArgLambda.arguments.head.name - val body = rightArgLambda.body.asInstanceOf[IR.Application.Prefix] + val body = rightArgLambda.body.asInstanceOf[Application.Prefix] body.arguments.length shouldEqual 2 val leftCallArgName = - body.arguments.head.value.asInstanceOf[IR.Name.Literal] + body.arguments.head.value.asInstanceOf[Name.Literal] val rightCallArgName = - body.arguments(1).value.asInstanceOf[IR.Name.Literal] + body.arguments(1).value.asInstanceOf[Name.Literal] underscoreArgName.name shouldEqual leftCallArgName.name rightArgLambdaArgName.name shouldEqual rightCallArgName.name @@ -259,19 +267,19 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |(_ + _) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val arg1Name = irFn.arguments.head.name - val irFn2 = irFn.body.asInstanceOf[IR.Function.Lambda] + val irFn2 = irFn.body.asInstanceOf[Function.Lambda] val arg2Name = irFn2.arguments.head.name - val app = irFn2.body.asInstanceOf[IR.Application.Prefix] + val app = irFn2.body.asInstanceOf[Application.Prefix] app.arguments.length shouldEqual 2 - val leftArg = app.arguments.head.value.asInstanceOf[IR.Name.Literal] - val rightArg = app.arguments(1).value.asInstanceOf[IR.Name.Literal] + val leftArg = app.arguments.head.value.asInstanceOf[Name.Literal] + val rightArg = app.arguments(1).value.asInstanceOf[Name.Literal] arg1Name.name shouldEqual leftArg.name arg2Name.name shouldEqual rightArg.name @@ -285,22 +293,22 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |(+ _) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val rightArgName = irFn.arguments.head.name - irFn.body shouldBe an[IR.Function.Lambda] - val irFn2 = irFn.body.asInstanceOf[IR.Function.Lambda] + irFn.body shouldBe an[Function.Lambda] + val irFn2 = irFn.body.asInstanceOf[Function.Lambda] val leftArgName = irFn2.arguments.head.name - irFn2.body shouldBe an[IR.Application.Prefix] - val app = irFn2.body.asInstanceOf[IR.Application.Prefix] + irFn2.body shouldBe an[Application.Prefix] + val app = irFn2.body.asInstanceOf[Application.Prefix] app.arguments.length shouldEqual 2 - val appLeftName = app.arguments.head.value.asInstanceOf[IR.Name.Literal] - val appRightName = app.arguments(1).value.asInstanceOf[IR.Name.Literal] + val appLeftName = app.arguments.head.value.asInstanceOf[Name.Literal] + val appRightName = app.arguments(1).value.asInstanceOf[Name.Literal] leftArgName.name shouldEqual appLeftName.name rightArgName.name shouldEqual appRightName.name @@ -314,14 +322,14 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |[1, _, (3 + 4), _] |""".stripMargin.preprocessExpression.get.desugar - val fun1 = ir.asInstanceOf[IR.Function.Lambda] - val fun2 = fun1.body.asInstanceOf[IR.Function.Lambda] - val vec = fun2.body.asInstanceOf[IR.Application.Literal.Sequence] + val fun1 = ir.asInstanceOf[Function.Lambda] + val fun2 = fun1.body.asInstanceOf[Function.Lambda] + val vec = fun2.body.asInstanceOf[Application.Sequence] fun1.arguments(0).name shouldEqual vec.items(1) fun2.arguments(0).name shouldEqual vec.items(3) - vec.items(0) shouldBe an[IR.Literal.Number] - vec.items(2) shouldBe an[IR.Application.Prefix] + vec.items(0) shouldBe an[Literal.Number] + vec.items(2) shouldBe an[Application.Prefix] } } @@ -334,32 +342,31 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |a _ (fn _ c) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] - ir.asInstanceOf[IR.Function.Lambda] - .body shouldBe an[IR.Application.Prefix] + ir shouldBe an[Function.Lambda] + ir.asInstanceOf[Function.Lambda].body shouldBe an[Application.Prefix] val irBody = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] irBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] - .value shouldBe an[IR.Function.Lambda] + .asInstanceOf[CallArgument.Specified] + .value shouldBe an[Function.Lambda] val lamArg = irBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val lamArgArgName = - lamArg.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + lamArg.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - lamArg.body shouldBe an[IR.Application.Prefix] - val lamArgBody = lamArg.body.asInstanceOf[IR.Application.Prefix] + lamArg.body shouldBe an[Application.Prefix] + val lamArgBody = lamArg.body.asInstanceOf[Application.Prefix] val lamArgBodyArg1Name = lamArgBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] lamArgArgName.name shouldEqual lamArgBodyArg1Name.name } @@ -372,32 +379,31 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |a _ (fn (t = _) c) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] - ir.asInstanceOf[IR.Function.Lambda] - .body shouldBe an[IR.Application.Prefix] + ir shouldBe an[Function.Lambda] + ir.asInstanceOf[Function.Lambda].body shouldBe an[Application.Prefix] val irBody = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] irBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] - .value shouldBe an[IR.Function.Lambda] + .asInstanceOf[CallArgument.Specified] + .value shouldBe an[Function.Lambda] val lamArg = irBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val lamArgArgName = - lamArg.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + lamArg.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - lamArg.body shouldBe an[IR.Application.Prefix] - val lamArgBody = lamArg.body.asInstanceOf[IR.Application.Prefix] + lamArg.body shouldBe an[Application.Prefix] + val lamArgBody = lamArg.body.asInstanceOf[Application.Prefix] val lamArgBodyArg1Name = lamArgBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] lamArgArgName.name shouldEqual lamArgBodyArg1Name.name } @@ -410,27 +416,27 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |a -> (b = f _ 1) -> f a |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] val bArgFn = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val bArg1 = - bArgFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + bArgFn.arguments.head.asInstanceOf[DefinitionArgument.Specified] bArg1.defaultValue shouldBe defined - bArg1.defaultValue.get shouldBe an[IR.Function.Lambda] - val default = bArg1.defaultValue.get.asInstanceOf[IR.Function.Lambda] + bArg1.defaultValue.get shouldBe an[Function.Lambda] + val default = bArg1.defaultValue.get.asInstanceOf[Function.Lambda] val defaultArgName = default.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - default.body shouldBe an[IR.Application.Prefix] - val defBody = default.body.asInstanceOf[IR.Application.Prefix] + default.body shouldBe an[Application.Prefix] + val defBody = default.body.asInstanceOf[Application.Prefix] val defBodyArg1Name = defBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] defaultArgName.name shouldEqual defBodyArg1Name.name } @@ -444,29 +450,29 @@ class LambdaShorthandToLambdaTest extends CompilerTest { | Nil -> f _ b |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] val nilBranch = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] .branches .head - .asInstanceOf[IR.Case.Branch] + .asInstanceOf[Case.Branch] - nilBranch.expression shouldBe an[IR.Function.Lambda] - val nilBody = nilBranch.expression.asInstanceOf[IR.Function.Lambda] + nilBranch.expression shouldBe an[Function.Lambda] + val nilBody = nilBranch.expression.asInstanceOf[Function.Lambda] val nilBodyArgName = nilBody.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - nilBody.body shouldBe an[IR.Application.Prefix] - val nilBodyBody = nilBody.body.asInstanceOf[IR.Application.Prefix] + nilBody.body shouldBe an[Application.Prefix] + val nilBodyBody = nilBody.body.asInstanceOf[Application.Prefix] val nilBodyBodyArg1Name = nilBodyBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] nilBodyArgName.name shouldEqual nilBodyBodyArg1Name.name } @@ -481,10 +487,10 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |x = _ |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Expression.Binding] - val expr = ir.asInstanceOf[IR.Expression.Binding].expression + ir shouldBe an[Expression.Binding] + val expr = ir.asInstanceOf[Expression.Binding].expression - expr shouldBe an[IR.Function.Lambda] + expr shouldBe an[Function.Lambda] } "translate to an `id` in argument defaults" in { @@ -495,15 +501,15 @@ class LambdaShorthandToLambdaTest extends CompilerTest { |(x = _) -> x |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] - val irFn = ir.asInstanceOf[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] - irFn.arguments.head shouldBe an[IR.DefinitionArgument.Specified] + irFn.arguments.head shouldBe an[DefinitionArgument.Specified] val arg = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified] arg.defaultValue shouldBe defined - arg.defaultValue.get shouldBe an[IR.Function.Lambda] + arg.defaultValue.get shouldBe an[Function.Lambda] } } @@ -515,21 +521,21 @@ class LambdaShorthandToLambdaTest extends CompilerTest { """(_ + 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] + ir shouldBe an[Application.Prefix] + val app = ir.asInstanceOf[Application.Prefix] + app.function shouldBe an[Function.Lambda] + val lam = app.function.asInstanceOf[Function.Lambda] lam.arguments.length shouldEqual 1 val lamArg1Name = lam.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name - val lamBody = lam.body.asInstanceOf[IR.Application.Prefix] + val lamBody = lam.body.asInstanceOf[Application.Prefix] lamBody.arguments.length shouldEqual 2 val appArg1Name = lamBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name lamArg1Name shouldEqual appArg1Name } @@ -541,32 +547,32 @@ class LambdaShorthandToLambdaTest extends CompilerTest { """(f _ _ b) b |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Application.Prefix] - val irFn = ir.asInstanceOf[IR.Application.Prefix].function - irFn shouldBe an[IR.Function.Lambda] - val firstLam = irFn.asInstanceOf[IR.Function.Lambda] + ir shouldBe an[Application.Prefix] + val irFn = ir.asInstanceOf[Application.Prefix].function + irFn shouldBe an[Function.Lambda] + val firstLam = irFn.asInstanceOf[Function.Lambda] firstLam.arguments.length shouldEqual 1 val firstLamArgName = firstLam.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name - val secondLam = firstLam.body.asInstanceOf[IR.Function.Lambda] + val secondLam = firstLam.body.asInstanceOf[Function.Lambda] val secondLamArgName = secondLam.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name - val app = secondLam.body.asInstanceOf[IR.Application.Prefix] + val app = secondLam.body.asInstanceOf[Application.Prefix] app.arguments.length shouldEqual 3 val appArg1Name = app.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name] + .asInstanceOf[Name] .name val appArg2Name = app .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name] + .asInstanceOf[Name] .name firstLamArgName shouldEqual appArg1Name secondLamArgName shouldEqual appArg2Name diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala index 7de04f2c5aa2..8afc10b451eb 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/NestedPatternMatchTest.scala @@ -2,8 +2,8 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.expression.Case +import org.enso.compiler.core.ir.{Expression, Literal, Module, Name, Pattern} import org.enso.compiler.pass.desugar.NestedPatternMatch import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -22,11 +22,11 @@ class NestedPatternMatchTest extends CompilerTest { new PassManager(List(precursorPasses), passConfig) /** Adds an extension method to run nested pattern desugaring on an - * [[IR.Module]]. + * [[Module]]. * * @param ir the module to run desugaring on */ - implicit class DesugarModule(ir: IR.Module) { + implicit class DesugarModule(ir: Module) { /** Runs desugaring on a module. * @@ -34,7 +34,7 @@ class NestedPatternMatchTest extends CompilerTest { * place * @return [[ir]], with any nested patterns desugared */ - def desugar(implicit moduleContext: ModuleContext): IR.Module = { + def desugar(implicit moduleContext: ModuleContext): Module = { NestedPatternMatch.runModule(ir, moduleContext) } } @@ -44,7 +44,7 @@ class NestedPatternMatchTest extends CompilerTest { * * @param ir the expression to desugar */ - implicit class DesugarExpression(ir: IR.Expression) { + implicit class DesugarExpression(ir: Expression) { /** Runs desgaring on an expression. * @@ -52,7 +52,7 @@ class NestedPatternMatchTest extends CompilerTest { * taking place * @return [[ir]], with nested patterns desugared */ - def desugar(implicit inlineContext: InlineContext): IR.Expression = { + def desugar(implicit inlineContext: InlineContext): Expression = { NestedPatternMatch.runExpression(ir, inlineContext) } } @@ -84,7 +84,7 @@ class NestedPatternMatchTest extends CompilerTest { |case x of | a -> a | _ -> 0 - |""".stripMargin.preprocessExpression.get.asInstanceOf[IR.Case.Expr] + |""".stripMargin.preprocessExpression.get.asInstanceOf[Case.Expr] val pattern1 = ir.branches.head.pattern @@ -96,7 +96,7 @@ class NestedPatternMatchTest extends CompilerTest { """ |case x of | Cons a b -> a + b - |""".stripMargin.preprocessExpression.get.asInstanceOf[IR.Case.Expr] + |""".stripMargin.preprocessExpression.get.asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern @@ -108,7 +108,7 @@ class NestedPatternMatchTest extends CompilerTest { """ |case x of | Cons (Cons a b) c -> a + b - |""".stripMargin.preprocessExpression.get.asInstanceOf[IR.Case.Expr] + |""".stripMargin.preprocessExpression.get.asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern @@ -119,7 +119,7 @@ class NestedPatternMatchTest extends CompilerTest { val ir = """case x of | Cons a Nil -> a - |""".stripMargin.preprocessExpression.get.asInstanceOf[IR.Case.Expr] + |""".stripMargin.preprocessExpression.get.asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern @@ -141,9 +141,9 @@ class NestedPatternMatchTest extends CompilerTest { | Cons a Nil -> a | _ -> 0 |""".stripMargin.preprocessExpression.get.desugar - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val consConsNilBranch = ir.branches(0) val consConsOneNilBranch = ir.branches(1) @@ -154,18 +154,18 @@ class NestedPatternMatchTest extends CompilerTest { "desugar nested constructors to simple patterns" in { ir.isNested shouldBe false - consANilBranch.expression shouldBe an[IR.Expression.Block] - consANilBranch.pattern shouldBe an[IR.Pattern.Constructor] + consANilBranch.expression shouldBe an[Expression.Block] + consANilBranch.pattern shouldBe an[Pattern.Constructor] NestedPatternMatch .containsNestedPatterns(consANilBranch.pattern) shouldEqual false consANilBranch.terminalBranch shouldBe false val nestedCase = consANilBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] - nestedCase.scrutinee shouldBe an[IR.Name.Literal] + nestedCase.scrutinee shouldBe an[Name.Literal] nestedCase.branches.length shouldEqual 1 nestedCase.isNested shouldBe true @@ -176,38 +176,38 @@ class NestedPatternMatchTest extends CompilerTest { .asInstanceOf[Pattern.Constructor] .constructor .name shouldEqual "Nil" - nilBranch.expression shouldBe an[IR.Name.Literal] - nilBranch.expression.asInstanceOf[IR.Name].name shouldEqual "a" + nilBranch.expression shouldBe an[Name.Literal] + nilBranch.expression.asInstanceOf[Name].name shouldEqual "a" nilBranch.terminalBranch shouldBe true } "desugar deeply nested patterns to simple patterns" in { - consConsNilBranch.expression shouldBe an[IR.Expression.Block] - consConsNilBranch.pattern shouldBe an[IR.Pattern.Constructor] + consConsNilBranch.expression shouldBe an[Expression.Block] + consConsNilBranch.pattern shouldBe an[Pattern.Constructor] NestedPatternMatch .containsNestedPatterns(consConsNilBranch.pattern) shouldEqual false consConsNilBranch.terminalBranch shouldBe false val nestedCase = consConsNilBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] - nestedCase.scrutinee shouldBe an[IR.Name.Literal] + nestedCase.scrutinee shouldBe an[Name.Literal] nestedCase.branches.length shouldEqual 1 nestedCase.isNested shouldBe true val consBranch = nestedCase.branches(0) - consBranch.expression shouldBe an[IR.Expression.Block] + consBranch.expression shouldBe an[Expression.Block] val consBranchBody = consBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consBranchBody.branches.length shouldEqual 1 - consBranchBody.branches.head.expression shouldBe an[IR.Expression.Block] + consBranchBody.branches.head.expression shouldBe an[Expression.Block] consBranchBody.branches.head.pattern .asInstanceOf[Pattern.Constructor] .constructor @@ -218,37 +218,37 @@ class NestedPatternMatchTest extends CompilerTest { } "desugar deeply nested patterns with literals to simple patterns" in { - consConsOneNilBranch.expression shouldBe an[IR.Expression.Block] - consConsOneNilBranch.pattern shouldBe an[IR.Pattern.Constructor] + consConsOneNilBranch.expression shouldBe an[Expression.Block] + consConsOneNilBranch.pattern shouldBe an[Pattern.Constructor] NestedPatternMatch .containsNestedPatterns(consConsOneNilBranch.pattern) shouldEqual false consConsOneNilBranch.terminalBranch shouldBe false val nestedCase = consConsOneNilBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] - nestedCase.scrutinee shouldBe an[IR.Name.Literal] + nestedCase.scrutinee shouldBe an[Name.Literal] nestedCase.branches.length shouldEqual 1 nestedCase.isNested shouldBe true val consBranch = nestedCase.branches(0) - consBranch.expression shouldBe an[IR.Expression.Block] + consBranch.expression shouldBe an[Expression.Block] consBranch.terminalBranch shouldBe false val consBranchBody = consBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consBranchBody.branches.length shouldEqual 1 - consBranchBody.branches.head.expression shouldBe an[IR.Expression.Block] + consBranchBody.branches.head.expression shouldBe an[Expression.Block] consBranchBody.branches.head.pattern .asInstanceOf[Pattern.Literal] .literal - .asInstanceOf[IR.Literal.Number] + .asInstanceOf[Literal.Number] .numericValue shouldEqual 1 NestedPatternMatch.containsNestedPatterns( consBranchBody.branches.head.pattern @@ -258,8 +258,8 @@ class NestedPatternMatchTest extends CompilerTest { } "desugar deeply nested patterns with type pattern to simple patterns" in { - consConsIntegerNilBranch.expression shouldBe an[IR.Expression.Block] - consConsIntegerNilBranch.pattern shouldBe an[IR.Pattern.Constructor] + consConsIntegerNilBranch.expression shouldBe an[Expression.Block] + consConsIntegerNilBranch.pattern shouldBe an[Pattern.Constructor] NestedPatternMatch .containsNestedPatterns( consConsIntegerNilBranch.pattern @@ -267,32 +267,32 @@ class NestedPatternMatchTest extends CompilerTest { consConsIntegerNilBranch.terminalBranch shouldBe false val nestedCase = consConsIntegerNilBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] - nestedCase.scrutinee shouldBe an[IR.Name.Literal] + nestedCase.scrutinee shouldBe an[Name.Literal] nestedCase.branches.length shouldEqual 1 nestedCase.isNested shouldBe true val consBranch = nestedCase.branches(0) - consBranch.expression shouldBe an[IR.Expression.Block] + consBranch.expression shouldBe an[Expression.Block] consBranch.terminalBranch shouldBe false val consBranchBody = consBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consBranchBody.branches.length shouldEqual 1 - consBranchBody.branches.head.expression shouldBe an[IR.Expression.Block] + consBranchBody.branches.head.expression shouldBe an[Expression.Block] val tpePattern = consBranchBody.branches.head.pattern .asInstanceOf[Pattern.Type] consBranchBody.branches.head.terminalBranch shouldBe true tpePattern.name - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "num" tpePattern.tpe.name shouldEqual "Integer" @@ -301,21 +301,21 @@ class NestedPatternMatchTest extends CompilerTest { ) shouldEqual false val consTpeBranchBody = consBranchBody.branches.head.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consTpeBranchBody.branches.length shouldEqual 1 consTpeBranchBody.branches.head.pattern shouldBe an[Pattern.Constructor] } "work recursively" in { - catchAllBranch.expression shouldBe an[IR.Expression.Block] + catchAllBranch.expression shouldBe an[Expression.Block] catchAllBranch.terminalBranch shouldBe true val consANilCase = catchAllBranch.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consANilCase.isNested shouldBe false @@ -326,12 +326,12 @@ class NestedPatternMatchTest extends CompilerTest { consANilBranch2.pattern ) shouldEqual false consANilBranch2.terminalBranch shouldBe false - consANilBranch2.expression shouldBe an[IR.Expression.Block] + consANilBranch2.expression shouldBe an[Expression.Block] val consANilBranch2Expr = consANilBranch2.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] consANilBranch2Expr.isNested shouldBe true consANilBranch2Expr.branches.length shouldEqual 1 diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/OperatorToFunctionTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/OperatorToFunctionTest.scala index 5f03deda2f26..c0928178f546 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/OperatorToFunctionTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/OperatorToFunctionTest.scala @@ -1,7 +1,13 @@ package org.enso.compiler.test.pass.desugar -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.IdentifiedLocation +import org.enso.compiler.core.ir.{ + CallArgument, + Empty, + Expression, + IdentifiedLocation, + Name +} +import org.enso.compiler.core.ir.expression.{Application, Operator} import org.enso.compiler.pass.desugar.OperatorToFunction import org.enso.compiler.test.CompilerTest import org.enso.syntax.text.Location @@ -21,18 +27,18 @@ class OperatorToFunctionTest extends CompilerTest { * @return an operator `name` and its corresponding function */ def genOprAndFn( - name: IR.Name, - left: IR.Expression, - right: IR.Expression - ): (IR.Application.Operator.Binary, IR.Application.Prefix) = { + name: Name, + left: Expression, + right: Expression + ): (Operator.Binary, Application.Prefix) = { val loc = IdentifiedLocation(Location(1, 33)) - val leftArg = IR.CallArgument.Specified(None, left, left.location) - val rightArg = IR.CallArgument.Specified(None, right, right.location) + val leftArg = CallArgument.Specified(None, left, left.location) + val rightArg = CallArgument.Specified(None, right, right.location) val binOp = - IR.Application.Operator.Binary(leftArg, name, rightArg, Some(loc)) - val opFn = IR.Application.Prefix( + Operator.Binary(leftArg, name, rightArg, Some(loc)) + val opFn = Application.Prefix( name, List(leftArg, rightArg), hasDefaultsSuspended = false, @@ -46,15 +52,15 @@ class OperatorToFunctionTest extends CompilerTest { "Operators" should { val opName = - IR.Name.Literal("=:=", isMethod = true, None) - val left = IR.Empty(None) - val right = IR.Empty(None) - val rightArg = IR.CallArgument.Specified(None, IR.Empty(None), None) + Name.Literal("=:=", isMethod = true, None) + val left = Empty(None) + val right = Empty(None) + val rightArg = CallArgument.Specified(None, Empty(None), None) val (operator, operatorFn) = genOprAndFn(opName, left, right) - val oprArg = IR.CallArgument.Specified(None, operator, None) - val oprFnArg = IR.CallArgument.Specified(None, operatorFn, None) + val oprArg = CallArgument.Specified(None, operator, None) + val oprFnArg = CallArgument.Specified(None, operatorFn, None) "be translated to functions" in { OperatorToFunction.runExpression(operator, ctx) shouldEqual operatorFn @@ -69,8 +75,8 @@ class OperatorToFunctionTest extends CompilerTest { "be translated recursively" in { val recursiveIR = - IR.Application.Operator.Binary(oprArg, opName, rightArg, None) - val recursiveIRResult = IR.Application.Prefix( + Operator.Binary(oprArg, opName, rightArg, None) + val recursiveIRResult = Application.Prefix( opName, List(oprFnArg, rightArg), hasDefaultsSuspended = false, diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/SectionsToBinOpTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/SectionsToBinOpTest.scala index 778cae59952d..a5a9ede0096d 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/SectionsToBinOpTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/desugar/SectionsToBinOpTest.scala @@ -2,7 +2,14 @@ package org.enso.compiler.test.pass.desugar import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Name +} +import org.enso.compiler.core.ir.expression.Application import org.enso.compiler.pass.desugar.SectionsToBinOp import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -24,7 +31,7 @@ class SectionsToBinOpTest extends CompilerTest { * * @param ir the IR to desugar */ - implicit class DesugarExpression(ir: IR.Expression) { + implicit class DesugarExpression(ir: Expression) { /** Runs section desugaring on [[ir]]. * @@ -32,7 +39,7 @@ class SectionsToBinOpTest extends CompilerTest { * place * @return [[ir]], with all sections desugared */ - def desugar(implicit inlineContext: InlineContext): IR.Expression = { + def desugar(implicit inlineContext: InlineContext): Expression = { SectionsToBinOp.runExpression(ir, inlineContext) } } @@ -56,23 +63,23 @@ class SectionsToBinOpTest extends CompilerTest { |(1 +) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irLam = ir.asInstanceOf[IR.Function.Lambda] + val irLam = ir.asInstanceOf[Function.Lambda] irLam.arguments.length shouldEqual 1 val lamArgName = - irLam.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irLam.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - val lamBody = irLam.body.asInstanceOf[IR.Application.Prefix] + val lamBody = irLam.body.asInstanceOf[Application.Prefix] lamBody.arguments.length shouldEqual 2 val lamBodyFirstArg = lamBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] lamBodyFirstArg.name shouldEqual lamArgName.name lamBodyFirstArg.getId should not equal lamArgName.getId @@ -86,34 +93,34 @@ class SectionsToBinOpTest extends CompilerTest { |(+) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] // TODO[DB] Section.Sides location is not parsed //ir.location shouldBe defined - val leftLam = ir.asInstanceOf[IR.Function.Lambda] + val leftLam = ir.asInstanceOf[Function.Lambda] leftLam.arguments.length shouldEqual 1 val leftLamArgName = leftLam.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - val rightLam = leftLam.body.asInstanceOf[IR.Function.Lambda] + val rightLam = leftLam.body.asInstanceOf[Function.Lambda] rightLam.arguments.length shouldEqual 1 val rightLamArgName = rightLam.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name - val lamBody = rightLam.body.asInstanceOf[IR.Application.Prefix] + val lamBody = rightLam.body.asInstanceOf[Application.Prefix] lamBody.arguments.length shouldEqual 2 val lamBodyFirstArg = lamBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val lamBodySecondArg = lamBody .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] lamBodyFirstArg.name shouldEqual leftLamArgName.name lamBodySecondArg.name shouldEqual rightLamArgName.name @@ -129,22 +136,22 @@ class SectionsToBinOpTest extends CompilerTest { |(+ 1) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irLam = ir.asInstanceOf[IR.Function.Lambda] + val irLam = ir.asInstanceOf[Function.Lambda] irLam.arguments.length shouldEqual 1 val lamArgName = - irLam.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irLam.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - val lamBody = irLam.body.asInstanceOf[IR.Application.Prefix] + val lamBody = irLam.body.asInstanceOf[Application.Prefix] lamBody.arguments.length shouldEqual 2 val lamBodyFirstArg = lamBody.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] lamBodyFirstArg.name shouldEqual lamArgName.name lamBodyFirstArg.getId should not equal lamArgName.getId @@ -157,15 +164,15 @@ class SectionsToBinOpTest extends CompilerTest { """ |x -> (x +) |""".stripMargin.preprocessExpression.get.desugar - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.body - .asInstanceOf[IR.Function.Lambda] - .body shouldBe an[IR.Application.Prefix] + .asInstanceOf[Function.Lambda] + .body shouldBe an[Application.Prefix] ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .length shouldEqual 2 } @@ -178,30 +185,30 @@ class SectionsToBinOpTest extends CompilerTest { |(+ _) |""".stripMargin.preprocessExpression.get.desugar - ir shouldBe an[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] ir.location shouldBe defined - val irFn = ir.asInstanceOf[IR.Function.Lambda] + val irFn = ir.asInstanceOf[Function.Lambda] val rightArgName = - irFn.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn.body shouldBe an[IR.Function.Lambda] - val irFn2 = irFn.body.asInstanceOf[IR.Function.Lambda] + irFn.body shouldBe an[Function.Lambda] + val irFn2 = irFn.body.asInstanceOf[Function.Lambda] val leftArgName = - irFn2.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified].name + irFn2.arguments.head.asInstanceOf[DefinitionArgument.Specified].name - irFn2.body shouldBe an[IR.Application.Prefix] - val app = irFn2.body.asInstanceOf[IR.Application.Prefix] + irFn2.body shouldBe an[Application.Prefix] + val app = irFn2.body.asInstanceOf[Application.Prefix] val appLeftName = app.arguments.head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] val appRightName = app .arguments(1) .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] leftArgName.name shouldEqual appLeftName.name rightArgName.name shouldEqual appRightName.name diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/NoSelfInStaticTests.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/NoSelfInStaticTests.scala index 92bf86229477..574ccabd4a3f 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/NoSelfInStaticTests.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/NoSelfInStaticTests.scala @@ -2,7 +2,8 @@ package org.enso.compiler.test.pass.lint import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.Module import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.pass.lint.NoSelfInStatic import org.enso.compiler.test.CompilerTest @@ -21,7 +22,7 @@ class NoSelfInStaticTests extends CompilerTest { * * @param ir the IR to lint */ - implicit class LintModule(ir: IR.Module) { + implicit class LintModule(ir: Module) { /** Runs unused name linting on [[ir]]. * @@ -29,7 +30,7 @@ class NoSelfInStaticTests extends CompilerTest { * place * @return [[ir]], with all unused names linted */ - def lint(implicit moduleContext: ModuleContext): IR.Module = { + def lint(implicit moduleContext: ModuleContext): Module = { NoSelfInStatic.runModule(ir, moduleContext) } } @@ -54,8 +55,7 @@ class NoSelfInStaticTests extends CompilerTest { | bar = self.x + self.x |""".stripMargin.preprocessModule.lint val errs = ir.bindings.flatMap(_.preorder).collect { - case err @ IR.Error - .Syntax(_, IR.Error.Syntax.InvalidSelfArgUsage, _, _) => + case err @ errors.Syntax(_, errors.Syntax.InvalidSelfArgUsage, _, _) => err } errs should have size 2 @@ -68,8 +68,7 @@ class NoSelfInStaticTests extends CompilerTest { |static_method x y = x + y + self.data |""".stripMargin.preprocessModule.lint val errs = ir.bindings.flatMap(_.preorder).collect { - case err @ IR.Error - .Syntax(_, IR.Error.Syntax.InvalidSelfArgUsage, _, _) => + case err @ errors.Syntax(_, errors.Syntax.InvalidSelfArgUsage, _, _) => err } errs should have size 1 @@ -86,8 +85,7 @@ class NoSelfInStaticTests extends CompilerTest { | nested_method (x + y) |""".stripMargin.preprocessModule.lint val errs = ir.bindings.flatMap(_.preorder).collect { - case err @ IR.Error - .Syntax(_, IR.Error.Syntax.InvalidSelfArgUsage, _, _) => + case err @ errors.Syntax(_, errors.Syntax.InvalidSelfArgUsage, _, _) => err } errs should have size 1 @@ -105,8 +103,7 @@ class NoSelfInStaticTests extends CompilerTest { | nested_method 42 |""".stripMargin.preprocessModule.lint val errs = ir.bindings.flatMap(_.preorder).collect { - case err @ IR.Error - .Syntax(_, IR.Error.Syntax.InvalidSelfArgUsage, _, _) => + case err @ errors.Syntax(_, errors.Syntax.InvalidSelfArgUsage, _, _) => err } errs should be(empty) @@ -122,8 +119,7 @@ class NoSelfInStaticTests extends CompilerTest { |My_Type.extension_method = self.value + 1 |""".stripMargin.preprocessModule.lint val errs = ir.bindings.flatMap(_.preorder).collect { - case err @ IR.Error - .Syntax(_, IR.Error.Syntax.InvalidSelfArgUsage, _, _) => + case err @ errors.Syntax(_, errors.Syntax.InvalidSelfArgUsage, _, _) => err } errs should have size 1 diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/ShadowedPatternFieldsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/ShadowedPatternFieldsTest.scala index 5341cdbb0a51..f5b9ea3d5d93 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/ShadowedPatternFieldsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/lint/ShadowedPatternFieldsTest.scala @@ -2,8 +2,8 @@ package org.enso.compiler.test.pass.lint import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.{Pattern, Warning} +import org.enso.compiler.core.ir.{Expression, Name, Pattern} +import org.enso.compiler.core.ir.expression.{warnings, Case} import org.enso.compiler.pass.lint.ShadowedPatternFields import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -26,14 +26,14 @@ class ShadowedPatternFieldsTest extends CompilerTest { * * @param ir the expression to lint */ - implicit class LintExxpression(ir: IR.Expression) { + implicit class LintExxpression(ir: Expression) { /** Lints [[ir]] for shadowed pattern variables. * * @param inlineContext the context in which linting is taking place * @return [[ir]], with shadowed pattern variables linted */ - def lint(implicit inlineContext: InlineContext): IR.Expression = { + def lint(implicit inlineContext: InlineContext): Expression = { ShadowedPatternFields.runExpression(ir, inlineContext) } } @@ -56,7 +56,7 @@ class ShadowedPatternFieldsTest extends CompilerTest { |case f of | Foo a b a -> a + a |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern.asInstanceOf[Pattern.Constructor] @@ -65,20 +65,20 @@ class ShadowedPatternFieldsTest extends CompilerTest { pattern.fields.head .asInstanceOf[Pattern.Name] - .name shouldBe an[IR.Name.Blank] + .name shouldBe an[Name.Blank] pattern .fields(1) .asInstanceOf[Pattern.Name] - .name shouldBe an[IR.Name.Literal] + .name shouldBe an[Name.Literal] } "attach a shadowing warning to each shadowed field" in { atLeast(1, pattern.fields.head.diagnostics.toList) shouldBe a[ - Warning.Shadowed.PatternBinding + warnings.Shadowed.PatternBinding ] val warning = pattern.fields.head.diagnostics.collect { - case w: Warning.Shadowed.PatternBinding => w + case w: warnings.Shadowed.PatternBinding => w }.head warning.shadowedName shouldEqual "a" 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 042f559d6f3a..fbfb709bd173 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 @@ -2,8 +2,9 @@ package org.enso.compiler.test.pass.lint import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.{Expression, Function, Module, Pattern} +import org.enso.compiler.core.ir.module.scope.definition +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 @@ -33,7 +34,7 @@ class UnusedBindingsTest extends CompilerTest with Inside { * * @param ir the IR to lint */ - implicit class LintExpression(ir: IR.Expression) { + implicit class LintExpression(ir: Expression) { /** Runs unused name linting on [[ir]]. * @@ -41,7 +42,7 @@ class UnusedBindingsTest extends CompilerTest with Inside { * place * @return [[ir]], with all unused names linted */ - def lint(implicit inlineContext: InlineContext): IR.Expression = { + def lint(implicit inlineContext: InlineContext): Expression = { UnusedBindings.runExpression(ir, inlineContext) } } @@ -62,7 +63,7 @@ class UnusedBindingsTest extends CompilerTest with Inside { * * @param ir the IR to lint */ - implicit class LintModule(ir: IR.Module) { + implicit class LintModule(ir: Module) { /** Runs unused name linting on [[ir]]. * @@ -70,7 +71,7 @@ class UnusedBindingsTest extends CompilerTest with Inside { * place * @return [[ir]], with all unused names linted */ - def lint(implicit moduleContext: ModuleContext): IR.Module = { + def lint(implicit moduleContext: ModuleContext): Module = { UnusedBindings.runModule(ir, moduleContext) } } @@ -93,14 +94,14 @@ class UnusedBindingsTest extends CompilerTest with Inside { """ |x -> 10 |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val lintMeta = ir.arguments.head.diagnostics.collect { - case u: IR.Warning.Unused.FunctionArgument => u + case u: warnings.Unused.FunctionArgument => u } lintMeta should not be empty - lintMeta.head shouldBe an[IR.Warning.Unused.FunctionArgument] + lintMeta.head shouldBe an[warnings.Unused.FunctionArgument] lintMeta.head.name.name shouldEqual "x" } @@ -114,17 +115,16 @@ class UnusedBindingsTest extends CompilerTest with Inside { | f 0 |""".stripMargin.preprocessModule.lint - inside(ir.bindings.head) { - case definition: IR.Module.Scope.Definition.Method.Explicit => - inside(definition.body) { case f: IR.Function.Lambda => - val lintMeta = f.arguments(1).diagnostics.collect { - case u: IR.Warning.Unused.FunctionArgument => u - } - - lintMeta should not be empty - lintMeta.head shouldBe an[IR.Warning.Unused.FunctionArgument] - lintMeta.head.name.name shouldEqual "x" + inside(ir.bindings.head) { case definition: definition.Method.Explicit => + inside(definition.body) { case f: Function.Lambda => + val lintMeta = f.arguments(1).diagnostics.collect { + case u: warnings.Unused.FunctionArgument => u } + + lintMeta should not be empty + lintMeta.head shouldBe an[warnings.Unused.FunctionArgument] + lintMeta.head.name.name shouldEqual "x" + } } } @@ -135,10 +135,10 @@ class UnusedBindingsTest extends CompilerTest with Inside { """ |_ -> 10 |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val lintMeta = ir.arguments.head.diagnostics.collect { - case u: IR.Warning.Unused => u + case u: warnings.Unused => u } lintMeta shouldBe empty @@ -151,14 +151,14 @@ class UnusedBindingsTest extends CompilerTest with Inside { """ |a = 10 |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] - val lintMeta = ir.diagnostics.collect { case u: IR.Warning.Unused => + val lintMeta = ir.diagnostics.collect { case u: warnings.Unused => u } lintMeta should not be empty - lintMeta.head shouldBe an[IR.Warning.Unused.Binding] + lintMeta.head shouldBe an[warnings.Unused.Binding] lintMeta.head.name.name shouldEqual "a" } @@ -169,9 +169,9 @@ class UnusedBindingsTest extends CompilerTest with Inside { """ |_ = 10 |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] - val lintMeta = ir.diagnostics.collect { case u: IR.Warning.Unused => + val lintMeta = ir.diagnostics.collect { case u: warnings.Unused => u } @@ -186,23 +186,23 @@ class UnusedBindingsTest extends CompilerTest with Inside { |case x of | Cons a _ -> 10 |""".stripMargin.preprocessExpression.get.lint - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern.asInstanceOf[Pattern.Constructor] val field1 = pattern.fields.head.asInstanceOf[Pattern.Name] val field2 = pattern.fields(1).asInstanceOf[Pattern.Name] - val lintMeta1 = field1.diagnostics.collect { case u: IR.Warning.Unused => + val lintMeta1 = field1.diagnostics.collect { case u: warnings.Unused => u } - val lintMeta2 = field2.diagnostics.collect { case u: IR.Warning.Unused => + val lintMeta2 = field2.diagnostics.collect { case u: warnings.Unused => u } lintMeta1 should not be empty - lintMeta1.head shouldBe an[IR.Warning.Unused.PatternBinding] + lintMeta1.head shouldBe an[warnings.Unused.PatternBinding] lintMeta1.head.name.name shouldEqual "a" lintMeta2 shouldBe empty 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 index 43f444e82e15..e2d1332136bf 100644 --- 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 @@ -2,7 +2,8 @@ package org.enso.compiler.test.pass.optimise import org.enso.compiler.Passes import org.enso.compiler.context.FreshNameSupply -import org.enso.compiler.core.IR +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 @@ -14,8 +15,8 @@ import org.enso.compiler.pass.optimise.ApplicationSaturation.{ import org.enso.compiler.pass.{PassConfiguration, PassManager} import org.enso.compiler.test.CompilerTest import org.enso.interpreter.node.ExpressionNode -import org.enso.interpreter.runtime.callable.argument.CallArgument import org.enso.interpreter.runtime.scope.{LocalScope, ModuleScope} +import org.enso.interpreter.runtime.callable import scala.annotation.unused @@ -31,21 +32,21 @@ class ApplicationSaturationTest extends CompilerTest { * or positionally * @return a list containing `n` arguments */ - def genNArgs(n: Int, positional: Boolean = true): List[IR.CallArgument] = { + def genNArgs(n: Int, positional: Boolean = true): List[CallArgument] = { val name = if (positional) { None } else { - Some(IR.Name.Literal("a", isMethod = false, None)) + Some(Name.Literal("a", isMethod = false, None)) } - List.fill(n)(IR.CallArgument.Specified(name, IR.Empty(None), 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[CallArgument] + @unused args: List[callable.argument.CallArgument] ): ExpressionNode = ??? val knownFunctions: ApplicationSaturation.Configuration = @@ -83,45 +84,45 @@ class ApplicationSaturationTest extends CompilerTest { // === The Tests ============================================================ "Known applications" should { - val plusFn = IR.Application + val plusFn = Application .Prefix( - IR.Name.Literal("+", isMethod = true, None), + Name.Literal("+", isMethod = true, None), genNArgs(2), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - val bazFn = IR.Application + val bazFn = Application .Prefix( - IR.Name.Literal("baz", isMethod = false, None), + Name.Literal("baz", isMethod = false, None), genNArgs(2), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - val fooFn = IR.Application + val fooFn = Application .Prefix( - IR.Name.Literal("foo", isMethod = false, None), + Name.Literal("foo", isMethod = false, None), genNArgs(5), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - val fooFnByName = IR.Application + val fooFnByName = Application .Prefix( - IR.Name.Literal("foo", isMethod = false, None), - genNArgs(4, positional = false), + Name.Literal("foo", isMethod = false, None), + genNArgs(4, positional = false), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] "be tagged with full saturation where possible" in { val resultIR = @@ -159,15 +160,15 @@ class ApplicationSaturationTest extends CompilerTest { } "Unknown applications" should { - val unknownFn = IR.Application + val unknownFn = Application .Prefix( - IR.Name.Literal("unknown", isMethod = false, None), + Name.Literal("unknown", isMethod = false, None), genNArgs(10), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] "be tagged with unknown saturation" in { val resultIR = @@ -179,61 +180,61 @@ class ApplicationSaturationTest extends CompilerTest { } "Known applications containing known applications" should { - val empty = IR.Empty(None) - val knownPlus = IR.Application + val empty = Empty(None) + val knownPlus = Application .Prefix( - IR.Name.Literal("+", isMethod = true, None), + Name.Literal("+", isMethod = true, None), genNArgs(2), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - val undersaturatedPlus = IR.Application + val undersaturatedPlus = Application .Prefix( - IR.Name.Literal("+", isMethod = true, None), + Name.Literal("+", isMethod = true, None), genNArgs(1), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - val oversaturatedPlus = IR.Application + val oversaturatedPlus = Application .Prefix( - IR.Name.Literal("+", isMethod = true, None), + Name.Literal("+", isMethod = true, None), genNArgs(3), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] - implicit class InnerMeta(ir: IR.Expression) { + implicit class InnerMeta(ir: Expression) { def getInnerMetadata: Option[Metadata] = { - ir.asInstanceOf[IR.Application.Prefix] + ir.asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value .getMetadata(ApplicationSaturation) } } - def outerPlus(argExpr: IR.Expression): IR.Application.Prefix = { - IR.Application + def outerPlus(argExpr: Expression): Application.Prefix = { + Application .Prefix( - IR.Name.Literal("+", isMethod = true, None), + Name.Literal("+", isMethod = true, None), List( - IR.CallArgument.Specified(None, argExpr, None), - IR.CallArgument.Specified(None, empty, None) + CallArgument.Specified(None, argExpr, None), + CallArgument.Specified(None, empty, None) ), hasDefaultsSuspended = false, None ) .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] } "have fully saturated applications tagged correctly" in { @@ -303,16 +304,16 @@ class ApplicationSaturationTest extends CompilerTest { val inputIR = rawIR.get .runPasses(passManagerKnown, knownCtx) - .asInstanceOf[IR.Expression] + .asInstanceOf[Expression] val result = ApplicationSaturation .runExpression(inputIR, knownCtx) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] "be tagged as unknown even if their name is known" in { // Needs alias analysis to work result.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue .getMetadata(ApplicationSaturation) .foreach { diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/LambdaConsolidateTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/LambdaConsolidateTest.scala index 56d8a1d6e3f3..8e03e5a45bb3 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/LambdaConsolidateTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/LambdaConsolidateTest.scala @@ -2,13 +2,23 @@ package org.enso.compiler.test.pass.optimise import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{ + CallArgument, + DefinitionArgument, + Expression, + Function, + Module, + Name +} +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.warnings import org.enso.compiler.pass.PassConfiguration._ import org.enso.compiler.pass.analyse.AliasAnalysis import org.enso.compiler.pass.optimise.LambdaConsolidate import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest import org.enso.interpreter.runtime.scope.LocalScope + class LambdaConsolidateTest extends CompilerTest { // === Test Setup =========================================================== @@ -25,17 +35,17 @@ class LambdaConsolidateTest extends CompilerTest { implicit val passManager: PassManager = new PassManager(List(precursorPasses), passConfiguration) - /** Adds an extension method to run lambda consolidation on an [[IR.Module]]. + /** Adds an extension method to run lambda consolidation on an [[Module]]. * * @param ir the module to run lambda consolidation on */ - implicit class OptimiseModule(ir: IR.Module) { + implicit class OptimiseModule(ir: Module) { /** Runs lambda consolidation on a module. * * @return [[ir]], with chained lambdas consolidated */ - def optimise: IR.Module = { + def optimise: Module = { LambdaConsolidate.runModule( ir, buildModuleContext(passConfiguration = Some(passConfiguration)) @@ -44,11 +54,11 @@ class LambdaConsolidateTest extends CompilerTest { } /** Adds an extension method to run lambda consolidation on an - * [[IR.Expression]]. + * [[Expression]]. * * @param ir the expression to run lambda consolidation on */ - implicit class OptimiseExpression(ir: IR.Expression) { + implicit class OptimiseExpression(ir: Expression) { /** Runs lambda consolidation on an expression. * @@ -56,7 +66,7 @@ class LambdaConsolidateTest extends CompilerTest { * expression * @return [[ir]], with chained lambdas consolidated */ - def optimise(implicit inlineContext: InlineContext): IR.Expression = { + def optimise(implicit inlineContext: InlineContext): Expression = { LambdaConsolidate.runExpression(ir, inlineContext) } } @@ -84,10 +94,10 @@ class LambdaConsolidateTest extends CompilerTest { """ |x -> y -> z -> x + y + z |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 3 - ir.body shouldBe an[IR.Application] + ir.body shouldBe an[Application] } "rename shadowed parameters" in { @@ -97,19 +107,19 @@ class LambdaConsolidateTest extends CompilerTest { """ |x -> z -> y -> x -> y -> x + y |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name should not equal "x" ir.body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name] + .asInstanceOf[Name] .name shouldEqual "x" } @@ -120,7 +130,7 @@ class LambdaConsolidateTest extends CompilerTest { """ |x -> y -> (z = x) -> x + y + z |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 3 ir.arguments(2).defaultValue shouldBe defined @@ -133,28 +143,28 @@ class LambdaConsolidateTest extends CompilerTest { """ |x -> (y = x) -> (x = x + 1) -> x + y |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] // Usages of `x` and `y` should be untouched ir.body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "x" ir.body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments(1) - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual "y" // The first argument `x` should be renamed val newXName = ir.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name @@ -162,21 +172,21 @@ class LambdaConsolidateTest extends CompilerTest { // Usages of the first argument `x` should be replaced by the new name ir.arguments(1) - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .defaultValue .get - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual newXName ir.arguments(2) - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .defaultValue .get - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments .head - .asInstanceOf[IR.CallArgument.Specified] + .asInstanceOf[CallArgument.Specified] .value - .asInstanceOf[IR.Name.Literal] + .asInstanceOf[Name.Literal] .name shouldEqual newXName } @@ -187,14 +197,14 @@ class LambdaConsolidateTest extends CompilerTest { """ |~x -> ~y -> x + y |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 2 ir.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .suspended shouldEqual true ir.arguments(1) - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .suspended shouldEqual true } @@ -203,12 +213,12 @@ class LambdaConsolidateTest extends CompilerTest { val ir = """ |x -> (y = x->y->z) -> y x |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 2 val defaultExpr = ir.arguments(1).defaultValue.get - defaultExpr shouldBe a[IR.Function.Lambda] + defaultExpr shouldBe a[Function.Lambda] defaultExpr - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .length shouldEqual 2 } @@ -216,30 +226,30 @@ class LambdaConsolidateTest extends CompilerTest { "collapse lambdas with multiple parameters" in { implicit val inlineContext: InlineContext = mkContext - val ir: IR.Function.Lambda = IR.Function + val ir: Function.Lambda = Function .Lambda( List( - IR.DefinitionArgument + DefinitionArgument .Specified( - IR.Name + Name .Literal("a", isMethod = false, None), None, None, suspended = false, None ), - IR.DefinitionArgument.Specified( - IR.Name.Literal("b", isMethod = false, None), + DefinitionArgument.Specified( + Name.Literal("b", isMethod = false, None), None, None, suspended = false, None ) ), - IR.Function.Lambda( + Function.Lambda( List( - IR.DefinitionArgument.Specified( - IR.Name + DefinitionArgument.Specified( + Name .Literal("c", isMethod = false, None), None, None, @@ -247,26 +257,26 @@ class LambdaConsolidateTest extends CompilerTest { None ) ), - IR.Name.Literal("c", isMethod = false, None), + Name.Literal("c", isMethod = false, None), None ), None ) .runPasses(passManager, inlineContext) .optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 3 ir.arguments.head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name shouldEqual "a" ir.arguments(1) - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name shouldEqual "b" ir.arguments(2) - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] .name .name shouldEqual "c" } @@ -278,15 +288,15 @@ class LambdaConsolidateTest extends CompilerTest { """ |x -> x -> x |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] - val warnings = ir.arguments.head.diagnostics.toList.collect { - case w: IR.Warning.Shadowed.FunctionParam => w + val ws = ir.arguments.head.diagnostics.toList.collect { + case w: warnings.Shadowed.FunctionParam => w } - warnings should not be empty - warnings.head.shadowedName shouldEqual "x" - warnings.head.shadower shouldBe ir.arguments(1) + ws should not be empty + ws.head.shadowedName shouldEqual "x" + ws.head.shadower shouldBe ir.arguments(1) } "consolidate chained lambdas if the chaining occurs via a single-lined block" in { @@ -297,7 +307,7 @@ class LambdaConsolidateTest extends CompilerTest { |x -> | y -> x + y |""".stripMargin.preprocessExpression.get.optimise - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] ir.arguments.length shouldEqual 2 } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/UnreachableMatchBranchesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/UnreachableMatchBranchesTest.scala index 251eabf2ad4b..617ef04a1b15 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/UnreachableMatchBranchesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/optimise/UnreachableMatchBranchesTest.scala @@ -2,8 +2,8 @@ package org.enso.compiler.test.pass.optimise import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Warning +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.expression.{warnings, Case} import org.enso.compiler.pass.optimise.UnreachableMatchBranches import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -26,14 +26,14 @@ class UnreachableMatchBranchesTest extends CompilerTest { * * @param ir the ir to optimise */ - implicit class OptimizeExpression(ir: IR.Expression) { + implicit class OptimizeExpression(ir: Expression) { /** Optimises [[ir]] by removing unreachable case branches. * * @param inlineContext the context in which optimization is taking place * @return [[ir]] with unreachable case branches removed */ - def optimize(implicit inlineContext: InlineContext): IR.Expression = { + def optimize(implicit inlineContext: InlineContext): Expression = { UnreachableMatchBranches.runExpression(ir, inlineContext) } } @@ -60,10 +60,12 @@ class UnreachableMatchBranchesTest extends CompilerTest { | _ -> 100 | a -> 30 |""".stripMargin.preprocessExpression.get.optimize - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] "associate a warning with the case expression" in { - atLeast(1, ir.diagnostics.toList) shouldBe a[Warning.Unreachable.Branches] + atLeast(1, ir.diagnostics.toList) shouldBe a[ + warnings.Unreachable.Branches + ] } "remove unreachable branches" in { @@ -71,7 +73,7 @@ class UnreachableMatchBranchesTest extends CompilerTest { } "work recursively" in { - val nestedCase = ir.branches.head.expression.asInstanceOf[IR.Case.Expr] + val nestedCase = ir.branches.head.expression.asInstanceOf[Case.Expr] nestedCase.branches.length shouldEqual 2 } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/DocumentationCommentsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/DocumentationCommentsTest.scala index 316790c628cc..99c773e20fdd 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/DocumentationCommentsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/DocumentationCommentsTest.scala @@ -3,6 +3,12 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.expression.{Case, Operator} +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.resolve.DocumentationComments import org.enso.compiler.pass.{PassConfiguration, PassManager} import org.enso.compiler.test.CompilerTest @@ -21,14 +27,14 @@ class DocumentationCommentsTest extends CompilerTest with Inside { * * @param ir the module */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { /** Resolves documentation comments for [[ir]]. * * @param moduleContext the context in which to resolve * @return [[ir]], with documentation resolved */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { DocumentationComments.runModule(ir, moduleContext) } } @@ -37,14 +43,14 @@ class DocumentationCommentsTest extends CompilerTest with Inside { * * @param ir the expression */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Resolves documentation comments for [[ir]]. * * @param inlineContext the context in which to resolve * @return [[ir]], with documentation resolved */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { DocumentationComments.runExpression(ir, inlineContext) } } @@ -95,8 +101,8 @@ class DocumentationCommentsTest extends CompilerTest with Inside { "be associated with atoms and methods" in { ir.bindings.length shouldEqual 2 - ir.bindings.head shouldBe an[IR.Module.Scope.Definition.SugaredType] - ir.bindings(1) shouldBe an[IR.Module.Scope.Definition.Method] + ir.bindings.head shouldBe an[Definition.SugaredType] + ir.bindings(1) shouldBe an[definition.Method] getDoc(ir.bindings.head) shouldEqual " This is doc for My_Atom" getDoc(ir.bindings(1)) shouldEqual " This is doc for my_method" @@ -203,11 +209,11 @@ class DocumentationCommentsTest extends CompilerTest with Inside { | z = x * y |""".stripMargin.preprocessExpression.get.resolve val body = ir - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] body.expressions.length shouldEqual 1 getDoc(body.expressions.head) shouldEqual " Do thing" @@ -225,9 +231,9 @@ class DocumentationCommentsTest extends CompilerTest with Inside { | z = x * y |""".stripMargin.preprocessModule.resolve val body = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Binding] + .asInstanceOf[definition.Method.Binding] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] body.expressions.length shouldEqual 1 getDoc(body.expressions.head) shouldEqual " Do thing" @@ -247,12 +253,12 @@ class DocumentationCommentsTest extends CompilerTest with Inside { | f 1 |""".stripMargin.preprocessModule.resolve val body = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Binding] + .asInstanceOf[definition.Method.Binding] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] body.expressions.length shouldEqual 2 - body.expressions.head shouldBe an[IR.Application.Operator.Binary] + body.expressions.head shouldBe an[Operator.Binary] getDoc(body.expressions.head) shouldEqual " Id" getDoc(body.returnValue) shouldEqual " Return thing" } @@ -280,15 +286,15 @@ class DocumentationCommentsTest extends CompilerTest with Inside { | 0 |""".stripMargin.preprocessModule.resolve val tp = - ir.bindings.head.asInstanceOf[IR.Module.Scope.Definition.SugaredType] + ir.bindings.head.asInstanceOf[Definition.SugaredType] getDoc(tp) shouldEqual " the type Foo" val t1 = tp.body.head getDoc(t1) shouldEqual " the constructor Bar" val t2 = tp.body(1) getDoc(t2) shouldEqual " the included Unit" - val method = tp.body(2).asInstanceOf[IR.Function.Binding] + val method = tp.body(2).asInstanceOf[Function.Binding] getDoc(method) shouldEqual " a method" - val block = method.body.asInstanceOf[IR.Expression.Block] + val block = method.body.asInstanceOf[Expression.Block] getDoc(block.expressions.head) shouldEqual " a statement" getDoc(block.returnValue) shouldEqual " the return" } @@ -343,28 +349,26 @@ class DocumentationCommentsTest extends CompilerTest with Inside { val t1 = ir.bindings.head getDoc(t1) shouldEqual " the type Foo" - inside(ir.bindings(1)) { - case method: IR.Module.Scope.Definition.Method.Explicit => - getDoc(method) shouldEqual " a method" - inside(method.body) { case lambda: IR.Function.Lambda => - inside(lambda.body) { case block: IR.Expression.Block => - getDoc(block.expressions.head) shouldEqual " a statement" - getDoc(block.returnValue) shouldEqual " the return" - } + inside(ir.bindings(1)) { case method: definition.Method.Explicit => + getDoc(method) shouldEqual " a method" + inside(method.body) { case lambda: Function.Lambda => + inside(lambda.body) { case block: Expression.Block => + getDoc(block.expressions.head) shouldEqual " a statement" + getDoc(block.returnValue) shouldEqual " the return" } + } } - inside(ir.bindings(2)) { - case method: IR.Module.Scope.Definition.Method.Explicit => - inside(method.body) { case lambda: IR.Function.Lambda => - inside(lambda.body) { case block: IR.Expression.Block => - inside(block.returnValue) { case caseExpr: IR.Case.Expr => - caseExpr.branches should have length 2 - getDoc(caseExpr.branches.head) shouldEqual " case 1" - getDoc(caseExpr.branches(1)) shouldEqual " catchall" - } + inside(ir.bindings(2)) { case method: definition.Method.Explicit => + inside(method.body) { case lambda: Function.Lambda => + inside(lambda.body) { case block: Expression.Block => + inside(block.returnValue) { case caseExpr: Case.Expr => + caseExpr.branches should have length 2 + getDoc(caseExpr.branches.head) shouldEqual " case 1" + getDoc(caseExpr.branches(1)) shouldEqual " catchall" } } + } } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ExpressionAnnotationsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ExpressionAnnotationsTest.scala index cbea06854a62..c49bfffdd2e5 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ExpressionAnnotationsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ExpressionAnnotationsTest.scala @@ -2,8 +2,14 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Name +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Literal +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.pass.resolve.ExpressionAnnotations import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -36,20 +42,20 @@ class ExpressionAnnotationsTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * * @param context the module context in which analysis takes place * @return [[ir]], with tail call analysis metadata attached */ - def analyse(implicit context: ModuleContext): IR.Module = { + def analyse(implicit context: ModuleContext): Module = { ExpressionAnnotations.runModule(ir, context) } } - implicit class AnalyseExpression(ir: IR.Expression) { - def analyse(implicit context: InlineContext): IR.Expression = { + implicit class AnalyseExpression(ir: Expression) { + def analyse(implicit context: InlineContext): Expression = { ExpressionAnnotations.runExpression(ir, context) } } @@ -71,23 +77,23 @@ class ExpressionAnnotationsTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val items = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] "create an error when discovering an unknown annotation" in { val unknown = - items.expressions(1).asInstanceOf[IR.Application.Prefix].function - unknown shouldBe an[IR.Error.Resolution] + items.expressions(1).asInstanceOf[Application.Prefix].function + unknown shouldBe an[errors.Resolution] unknown - .asInstanceOf[IR.Error.Resolution] - .reason shouldEqual IR.Error.Resolution.UnknownAnnotation + .asInstanceOf[errors.Resolution] + .reason shouldEqual errors.Resolution.UnknownAnnotation } "associate the annotation with the annotated definition" in { - val builtinDef = items.expressions(2).asInstanceOf[IR.Literal.Text] + val builtinDef = items.expressions(2).asInstanceOf[Literal.Text] builtinDef.text shouldEqual "myBuiltin" builtinDef .unsafeGetMetadata(ExpressionAnnotations, "") @@ -95,7 +101,7 @@ class ExpressionAnnotationsTest extends CompilerTest { .head .name shouldEqual ExpressionAnnotations.builtinMethodName - val parallelDef = items.expressions(3).asInstanceOf[IR.Application.Prefix] + val parallelDef = items.expressions(3).asInstanceOf[Application.Prefix] parallelDef.function shouldBe a[Name.Literal] val fn = parallelDef.function.asInstanceOf[Name.Literal] fn.name shouldEqual "f" @@ -107,11 +113,11 @@ class ExpressionAnnotationsTest extends CompilerTest { .name shouldEqual ExpressionAnnotations.autoParallelName val correct = items.returnValue - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments(0) .value - .asInstanceOf[IR.Application.Prefix] - correct.function.asInstanceOf[IR.Name].name shouldEqual "bar" + .asInstanceOf[Application.Prefix] + correct.function.asInstanceOf[Name].name shouldEqual "bar" correct.arguments.length shouldEqual 1 correct .getMetadata(ExpressionAnnotations) @@ -124,13 +130,13 @@ class ExpressionAnnotationsTest extends CompilerTest { "create an error on a misplaced annotation" in { val misplaced = items .expressions(4) - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] .arguments(0) .value - misplaced shouldBe an[IR.Error.Resolution] + misplaced shouldBe an[errors.Resolution] misplaced - .asInstanceOf[IR.Error.Resolution] - .reason shouldEqual IR.Error.Resolution.UnexpectedAnnotation + .asInstanceOf[errors.Resolution] + .reason shouldEqual errors.Resolution.UnexpectedAnnotation } } @@ -144,19 +150,19 @@ class ExpressionAnnotationsTest extends CompilerTest { |""".stripMargin.preprocessModule.analyse val items = ir.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] "create an error when discovering an unexpected annotation" in { items.expressions.size shouldBe 0 - items.returnValue shouldBe an[IR.Error.Resolution] - val err = items.returnValue.asInstanceOf[IR.Error.Resolution] + items.returnValue shouldBe an[errors.Resolution] + val err = items.returnValue.asInstanceOf[errors.Resolution] err - .asInstanceOf[IR.Error.Resolution] - .reason shouldEqual IR.Error.Resolution.UnexpectedAnnotation + .asInstanceOf[errors.Resolution] + .reason shouldEqual errors.Resolution.UnexpectedAnnotation } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/GlobalNamesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/GlobalNamesTest.scala index c66d7f5fe3be..e79da01cfa98 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/GlobalNamesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/GlobalNamesTest.scala @@ -2,25 +2,26 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.data.BindingsMap.{ -// Cons, - Resolution, -// ResolvedConstructor, - ResolvedModule -} +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.data.BindingsMap.{Resolution, ResolvedModule} import org.enso.compiler.pass.resolve.GlobalNames import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.phase.ExportsResolution import org.enso.compiler.test.CompilerTest -import org.enso.interpreter.runtime.Module +import org.enso.interpreter.runtime import org.enso.interpreter.runtime.ModuleTestUtils class GlobalNamesTest extends CompilerTest { // === Test Setup =========================================================== - def mkModuleContext: (ModuleContext, Module) = + def mkModuleContext: (ModuleContext, runtime.Module) = buildModuleContextModule( freshNameSupply = Some(new FreshNameSupply) ) @@ -42,7 +43,7 @@ class GlobalNamesTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * @@ -57,8 +58,8 @@ class GlobalNamesTest extends CompilerTest { // === The Tests ============================================================ "Method definition resolution" should { - val both: (ModuleContext, Module) = mkModuleContext - implicit val ctx: ModuleContext = both._1 + val both: (ModuleContext, runtime.Module) = mkModuleContext + implicit val ctx: ModuleContext = both._1 val code = """ |main = @@ -91,24 +92,24 @@ class GlobalNamesTest extends CompilerTest { val bodyExprs = ir .bindings(0) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .expressions - .map(expr => expr.asInstanceOf[IR.Expression.Binding].expression) + .map(expr => expr.asInstanceOf[Expression.Binding].expression) "not resolve uppercase method names to applications with no arguments" in { val expr = bodyExprs(1) - expr shouldBe an[IR.Error.Resolution] + expr shouldBe an[errors.Resolution] } "resolve method names to applications" in { val expr = bodyExprs(2) - expr shouldBe an[IR.Application.Prefix] - val app = expr.asInstanceOf[IR.Application.Prefix] - app.function.asInstanceOf[IR.Name.Literal].name shouldEqual "constant" + expr shouldBe an[Application.Prefix] + val app = expr.asInstanceOf[Application.Prefix] + app.function.asInstanceOf[Name.Literal].name shouldEqual "constant" app.arguments.length shouldEqual 1 app.arguments(0).value.getMetadata(GlobalNames) shouldEqual Some( Resolution(ResolvedModule(ctx.moduleReference())) @@ -117,16 +118,16 @@ class GlobalNamesTest extends CompilerTest { "not resolve uppercase method names to applications with arguments" in { val expr = bodyExprs(3) - expr shouldBe an[IR.Application.Prefix] - val app = expr.asInstanceOf[IR.Application.Prefix] - app.function shouldBe an[IR.Error.Resolution] + expr shouldBe an[Application.Prefix] + val app = expr.asInstanceOf[Application.Prefix] + app.function shouldBe an[errors.Resolution] } "resolve method names in applications by adding the self argument" in { val expr = bodyExprs(4) - expr shouldBe an[IR.Application.Prefix] - val app = expr.asInstanceOf[IR.Application.Prefix] - app.function.asInstanceOf[IR.Name.Literal].name shouldEqual "add_one" + expr shouldBe an[Application.Prefix] + val app = expr.asInstanceOf[Application.Prefix] + app.function.asInstanceOf[Name.Literal].name shouldEqual "add_one" app.arguments.length shouldEqual 2 app.arguments(0).value.getMetadata(GlobalNames) shouldEqual Some( Resolution(ResolvedModule(ctx.moduleReference())) @@ -135,9 +136,9 @@ class GlobalNamesTest extends CompilerTest { "resolve method names in partial applications by adding the self argument" in { val expr = bodyExprs(5) - expr shouldBe an[IR.Application.Prefix] - val app = expr.asInstanceOf[IR.Application.Prefix] - app.function.asInstanceOf[IR.Name.Literal].name shouldEqual "add_one" + expr shouldBe an[Application.Prefix] + val app = expr.asInstanceOf[Application.Prefix] + app.function.asInstanceOf[Name.Literal].name shouldEqual "add_one" app.arguments.length shouldEqual 1 app.arguments(0).value.getMetadata(GlobalNames) shouldEqual Some( Resolution(ResolvedModule(ctx.moduleReference())) @@ -145,8 +146,8 @@ class GlobalNamesTest extends CompilerTest { } "indicate resolution failures" in { - val app = bodyExprs(8).asInstanceOf[IR.Application.Prefix] - app.function shouldBe an[IR.Error.Resolution] + val app = bodyExprs(8).asInstanceOf[Application.Prefix] + app.function shouldBe an[errors.Resolution] } } @@ -163,9 +164,9 @@ class GlobalNamesTest extends CompilerTest { | x + z |""".stripMargin.preprocessModule.analyse val unresolved = ir.preorder.collect { - case IR.Error.Resolution( + case errors.Resolution( name, - _: IR.Error.Resolution.ResolverError, + _: errors.Resolution.ResolverError, _, _ ) => @@ -185,9 +186,9 @@ class GlobalNamesTest extends CompilerTest { | here.my_func 1 |""".stripMargin.preprocessModule.analyse val unresolved = ir.preorder.collect { - case IR.Error.Resolution( + case errors.Resolution( name, - _: IR.Error.Resolution.ResolverError, + _: errors.Resolution.ResolverError, _, _ ) => diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/IgnoredBindingsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/IgnoredBindingsTest.scala index 1f62559c5c74..1358d33d9b4f 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/IgnoredBindingsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/IgnoredBindingsTest.scala @@ -2,8 +2,14 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Pattern +import org.enso.compiler.core.ir.expression.Case +import org.enso.compiler.core.ir.{ + DefinitionArgument, + Expression, + Function, + Name, + Pattern +} import org.enso.compiler.pass.resolve.IgnoredBindings import org.enso.compiler.pass.resolve.IgnoredBindings.State import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} @@ -26,7 +32,7 @@ class IgnoredBindingsTest extends CompilerTest { * * @param ir the IR to desugar */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Runs ignores desugaring on [[ir]]. * @@ -34,7 +40,7 @@ class IgnoredBindingsTest extends CompilerTest { * place * @return [[ir]], with all ignores desugared */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { IgnoredBindings.runExpression(ir, inlineContext) } } @@ -56,17 +62,17 @@ class IgnoredBindingsTest extends CompilerTest { """ |_ -> (x = _ -> 1) -> x |""".stripMargin.preprocessExpression.get.resolve - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val blankArg = - ir.arguments.head.asInstanceOf[IR.DefinitionArgument.Specified] + ir.arguments.head.asInstanceOf[DefinitionArgument.Specified] val xArg = ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] "replace ignored arguments with fresh names" in { - blankArg.name shouldBe an[IR.Name.Literal] + blankArg.name shouldBe an[Name.Literal] } "mark ignored arguments as ignored" in { @@ -79,12 +85,12 @@ class IgnoredBindingsTest extends CompilerTest { "work when deeply nested" in { val nestedIgnore = xArg.defaultValue.get - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .arguments .head - .asInstanceOf[IR.DefinitionArgument.Specified] + .asInstanceOf[DefinitionArgument.Specified] - nestedIgnore.name shouldBe an[IR.Name.Literal] + nestedIgnore.name shouldBe an[Name.Literal] nestedIgnore.getMetadata(IgnoredBindings) shouldEqual Some(State.Ignored) } } @@ -99,13 +105,13 @@ class IgnoredBindingsTest extends CompilerTest { | x = y | 10 |""".stripMargin.preprocessExpression.get.resolve - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] val bindingName = ir.name - val bindingBody = ir.expression.asInstanceOf[IR.Expression.Block] + val bindingBody = ir.expression.asInstanceOf[Expression.Block] "replace the ignored binding with a fresh name" in { - bindingName shouldBe an[IR.Name.Literal] + bindingName shouldBe an[Name.Literal] } "f is a regular definition of a function" in { @@ -114,7 +120,7 @@ class IgnoredBindingsTest extends CompilerTest { "mark the binding as not ignored if it wasn't" in { val nonIgnored = - bindingBody.expressions(1).asInstanceOf[IR.Expression.Binding] + bindingBody.expressions(1).asInstanceOf[Expression.Binding] nonIgnored.getMetadata(IgnoredBindings) shouldEqual Some( State.NotIgnored @@ -123,9 +129,9 @@ class IgnoredBindingsTest extends CompilerTest { "work when deeply nested" in { val ignoredInBlock = - bindingBody.expressions.head.asInstanceOf[IR.Expression.Binding] + bindingBody.expressions.head.asInstanceOf[Expression.Binding] - ignoredInBlock.name shouldBe an[IR.Name.Literal] + ignoredInBlock.name shouldBe an[Name.Literal] } } @@ -138,25 +144,25 @@ class IgnoredBindingsTest extends CompilerTest { | Cons a _ -> case y of | MyCons a _ -> 10 |""".stripMargin.preprocessExpression.get.resolve - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val pattern = ir.branches.head.pattern.asInstanceOf[Pattern.Constructor] val aPat = pattern.fields.head.asInstanceOf[Pattern.Name] val ignoredPat = pattern.fields(1).asInstanceOf[Pattern.Name] val nestedCase = ir.branches.head.expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] val nestedPattern = nestedCase.branches.head.pattern.asInstanceOf[Pattern.Constructor] val nestedAPat = nestedPattern.fields.head.asInstanceOf[Pattern.Name] val nestedIgnoredPat = nestedPattern.fields(1).asInstanceOf[Pattern.Name] "replace the ignored binding with a fresh name" in { - ignoredPat.name should not be an[IR.Name.Blank] + ignoredPat.name should not be an[Name.Blank] } "mark the binding as ignored if it was" in { diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/MethodDefinitionsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/MethodDefinitionsTest.scala index a91872269275..697210a43c09 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/MethodDefinitionsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/MethodDefinitionsTest.scala @@ -2,7 +2,9 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.data.BindingsMap import org.enso.compiler.data.BindingsMap.Type import org.enso.compiler.pass.resolve.MethodDefinitions @@ -32,14 +34,14 @@ class MethodDefinitionsTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * * @param context the module context in which analysis takes place * @return [[ir]], with tail call analysis metadata attached */ - def analyse(implicit context: ModuleContext): IR.Module = { + def analyse(implicit context: ModuleContext): Module = { MethodDefinitions.runModule(ir, context) } } @@ -71,7 +73,7 @@ class MethodDefinitionsTest extends CompilerTest { "attach resolved atoms to the method definitions" in { ir.bindings(2) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .methodReference .typePointer .get @@ -84,12 +86,12 @@ class MethodDefinitionsTest extends CompilerTest { ) ) ir.bindings(3) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .methodReference .typePointer shouldBe None ir.bindings(4) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .methodReference .typePointer .get @@ -100,14 +102,14 @@ class MethodDefinitionsTest extends CompilerTest { ) ir.bindings(5) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .methodReference .typePointer - .get shouldBe a[IR.Error.Resolution] + .get shouldBe a[errors.Resolution] val conv1 = ir .bindings(6) - .asInstanceOf[IR.Module.Scope.Definition.Method.Conversion] + .asInstanceOf[definition.Method.Conversion] conv1.methodReference.typePointer.get.getMetadata( MethodDefinitions ) shouldEqual Some( @@ -129,7 +131,7 @@ class MethodDefinitionsTest extends CompilerTest { val conv2 = ir .bindings(7) - .asInstanceOf[IR.Module.Scope.Definition.Method.Conversion] + .asInstanceOf[definition.Method.Conversion] conv2.methodReference.typePointer.get.getMetadata( MethodDefinitions ) shouldEqual Some( @@ -140,12 +142,12 @@ class MethodDefinitionsTest extends CompilerTest { ) ) ) - conv2.sourceTypeName shouldBe an[IR.Error.Resolution] + conv2.sourceTypeName shouldBe an[errors.Resolution] val conv3 = ir .bindings(8) - .asInstanceOf[IR.Module.Scope.Definition.Method.Conversion] - conv3.methodReference.typePointer.get shouldBe an[IR.Error.Resolution] + .asInstanceOf[definition.Method.Conversion] + conv3.methodReference.typePointer.get shouldBe an[errors.Resolution] conv3.sourceTypeName.getMetadata(MethodDefinitions) shouldEqual Some( BindingsMap.Resolution( BindingsMap.ResolvedType( diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ModuleAnnotationsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ModuleAnnotationsTest.scala index e9feef7c26f5..c2461f23e08c 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ModuleAnnotationsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/ModuleAnnotationsTest.scala @@ -2,8 +2,12 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.ModuleContext -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Name +import org.enso.compiler.core.ir.expression.Comment +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.pass.resolve.ModuleAnnotations import org.enso.compiler.test.CompilerTest @@ -26,15 +30,15 @@ class ModuleAnnotationsTest extends CompilerTest { * * @param ir the IR to resolve */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { - /** Runs annotation resolution on an [[IR.Module]]. + /** Runs annotation resolution on an [[Module]]. * * @param moduleContext the module context in which the resolution takes * place * @return [[ir]], with all module-level annotations resolved */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { ModuleAnnotations.runModule(ir, moduleContext) } } @@ -64,8 +68,8 @@ class ModuleAnnotationsTest extends CompilerTest { val anns = ir.bindings.head.unsafeGetMetadata(ModuleAnnotations, "").annotations anns.length shouldEqual 2 - anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_1" - anns(1).asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_2" + anns.head.asInstanceOf[Name].name shouldEqual "@My_Annotation_1" + anns(1).asInstanceOf[Name].name shouldEqual "@My_Annotation_2" } "associate annotations with complex type definitions" in { @@ -81,8 +85,8 @@ class ModuleAnnotationsTest extends CompilerTest { val anns = ir.bindings.head.unsafeGetMetadata(ModuleAnnotations, "").annotations anns.length shouldEqual 2 - anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_1" - anns(1).asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_2" + anns.head.asInstanceOf[Name].name shouldEqual "@My_Annotation_1" + anns(1).asInstanceOf[Name].name shouldEqual "@My_Annotation_2" } "associate annotations with method definitions" in { @@ -93,12 +97,12 @@ class ModuleAnnotationsTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 1 - ir.bindings.head shouldBe a[Definition.Method.Binding] + ir.bindings.head shouldBe a[definition.Method.Binding] val anns = ir.bindings.head.unsafeGetMetadata(ModuleAnnotations, "").annotations anns.length shouldEqual 2 - anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_1" - anns(1).asInstanceOf[IR.Name].name shouldEqual "@My_Annotation_2" + anns.head.asInstanceOf[Name].name shouldEqual "@My_Annotation_1" + anns(1).asInstanceOf[Name].name shouldEqual "@My_Annotation_2" } "not associate annotations with comments" in { @@ -113,7 +117,7 @@ class ModuleAnnotationsTest extends CompilerTest { val anns = ir.bindings(1).unsafeGetMetadata(ModuleAnnotations, "").annotations anns.length shouldEqual 1 - anns.head.asInstanceOf[IR.Name].name shouldEqual "@My_Annotation" + anns.head.asInstanceOf[Name].name shouldEqual "@My_Annotation" } "not associate generic annotations with method definitions" in { @@ -124,8 +128,8 @@ class ModuleAnnotationsTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 3 - ir.bindings(0) shouldBe a[IR.Name.GenericAnnotation] - ir.bindings(1) shouldBe a[IR.Name.GenericAnnotation] + ir.bindings(0) shouldBe a[Name.GenericAnnotation] + ir.bindings(1) shouldBe a[Name.GenericAnnotation] } } @@ -145,7 +149,7 @@ class ModuleAnnotationsTest extends CompilerTest { ir.bindings.head shouldBe a[Definition.SugaredType] val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType] typ.body.length shouldEqual 2 - typ.body(0) shouldBe an[IR.Name.GenericAnnotation] + typ.body(0) shouldBe an[Name.GenericAnnotation] typ.body(1) shouldBe a[Definition.Data] } @@ -162,8 +166,8 @@ class ModuleAnnotationsTest extends CompilerTest { ir.bindings.head shouldBe a[Definition.SugaredType] val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType] typ.body.length shouldEqual 3 - typ.body(1) shouldBe an[IR.Name.GenericAnnotation] - typ.body(2) shouldBe an[IR.Function.Binding] + typ.body(1) shouldBe an[Name.GenericAnnotation] + typ.body(2) shouldBe an[Function.Binding] } "not associate annotations with comments" in { @@ -179,8 +183,8 @@ class ModuleAnnotationsTest extends CompilerTest { ir.bindings.head shouldBe a[Definition.SugaredType] val typ = ir.bindings.head.asInstanceOf[Definition.SugaredType] typ.body.length shouldEqual 3 - typ.body(0) shouldBe an[IR.Name.GenericAnnotation] - typ.body(1) shouldBe an[IR.Comment] + typ.body(0) shouldBe an[Name.GenericAnnotation] + typ.body(1) shouldBe an[Comment] typ.body(2) shouldBe a[Definition.Data] } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/OverloadsResolutionTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/OverloadsResolutionTest.scala index c2d40f286ad1..eec9c107b0c3 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/OverloadsResolutionTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/OverloadsResolutionTest.scala @@ -2,8 +2,9 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.resolve.OverloadsResolution import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -26,7 +27,7 @@ class OverloadsResolutionTest extends CompilerTest { * * @param ir the IR to desugar */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { /** Runs section desugaring on [[ir]]. * @@ -34,7 +35,7 @@ class OverloadsResolutionTest extends CompilerTest { * place * @return [[ir]], with all sections desugared */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { OverloadsResolution.runModule(ir, moduleContext) } } @@ -63,14 +64,14 @@ class OverloadsResolutionTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve "detect overloads within a given module" in { - exactly(2, ir.bindings) shouldBe an[IR.Error.Redefined.Method] + exactly(2, ir.bindings) shouldBe an[errors.Redefined.Method] } "replace all overloads by an error node" in { - ir.bindings(1) shouldBe an[IR.Error.Redefined.Method] - ir.bindings(2) shouldBe an[IR.Error.Redefined.Method] - val redef1 = ir.bindings(1).asInstanceOf[IR.Error.Redefined.Method] - val redef2 = ir.bindings(2).asInstanceOf[IR.Error.Redefined.Method] + ir.bindings(1) shouldBe an[errors.Redefined.Method] + ir.bindings(2) shouldBe an[errors.Redefined.Method] + val redef1 = ir.bindings(1).asInstanceOf[errors.Redefined.Method] + val redef2 = ir.bindings(2).asInstanceOf[errors.Redefined.Method] redef1.atomName.get.name shouldEqual atomName redef2.atomName.get.name shouldEqual atomName @@ -90,8 +91,8 @@ class OverloadsResolutionTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 2 - ir.bindings.head shouldBe a[Method.Conversion] - ir.bindings(1) shouldBe a[Method.Conversion] + ir.bindings.head shouldBe a[definition.Method.Conversion] + ir.bindings(1) shouldBe a[definition.Method.Conversion] } "raise an error if there are multiple definitions with the same source type" in { @@ -102,9 +103,9 @@ class OverloadsResolutionTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 3 - ir.bindings.head shouldBe a[Method.Conversion] - ir.bindings(1) shouldBe a[Method.Conversion] - ir.bindings(2) shouldBe an[IR.Error.Redefined.Conversion] + ir.bindings.head shouldBe a[definition.Method.Conversion] + ir.bindings(1) shouldBe a[definition.Method.Conversion] + ir.bindings(2) shouldBe an[errors.Redefined.Conversion] } } @@ -121,18 +122,18 @@ class OverloadsResolutionTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve "detect overloads within a given module" in { - exactly(2, ir.bindings) shouldBe an[IR.Error.Redefined.Type] + exactly(2, ir.bindings) shouldBe an[errors.Redefined.Type] } "replace all overloads by an error node" in { - ir.bindings(1) shouldBe an[IR.Error.Redefined.Type] + ir.bindings(1) shouldBe an[errors.Redefined.Type] ir.bindings(1) - .asInstanceOf[IR.Error.Redefined.Type] + .asInstanceOf[errors.Redefined.Type] .typeName .name shouldEqual atomName - ir.bindings(2) shouldBe an[IR.Error.Redefined.Type] + ir.bindings(2) shouldBe an[errors.Redefined.Type] ir.bindings(2) - .asInstanceOf[IR.Error.Redefined.Type] + .asInstanceOf[errors.Redefined.Type] .typeName .name shouldEqual atomName } 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 ab7bd782c6b4..563f73c3b837 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 @@ -2,7 +2,9 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Function, Module, Pattern} +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 @@ -36,7 +38,7 @@ class PatternsTest extends CompilerTest { * * @param ir the ir to analyse */ - implicit class AnalyseModule(ir: IR.Module) { + implicit class AnalyseModule(ir: Module) { /** Performs tail call analysis on [[ir]]. * @@ -69,25 +71,25 @@ class PatternsTest extends CompilerTest { "attach resolved atoms to the method definitions" in { val patterns = ir .bindings(1) - .asInstanceOf[IR.Module.Scope.Definition.Method.Explicit] + .asInstanceOf[definition.Method.Explicit] .body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .returnValue - .asInstanceOf[IR.Case.Expr] + .asInstanceOf[Case.Expr] .branches .map(_.pattern) patterns(0) - .asInstanceOf[IR.Pattern.Constructor] + .asInstanceOf[Pattern.Constructor] .constructor .getMetadata(Patterns) shouldBe defined - patterns(1) shouldBe a[IR.Error.Pattern] + patterns(1) shouldBe a[errors.Pattern] patterns(2) - .asInstanceOf[IR.Pattern.Constructor] - .constructor shouldBe a[IR.Error.Resolution] + .asInstanceOf[Pattern.Constructor] + .constructor shouldBe a[errors.Resolution] patterns(3) - .asInstanceOf[IR.Pattern.Type] + .asInstanceOf[Pattern.Type] .tpe .getMetadata(Patterns) shouldBe defined } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SugaredTypeFunctionsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SugaredTypeFunctionsTest.scala index 68be7f48559a..bbb233b035ee 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SugaredTypeFunctionsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SugaredTypeFunctionsTest.scala @@ -2,7 +2,9 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Function, Type} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.`type` import org.enso.compiler.pass.resolve.TypeFunctions import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.test.CompilerTest @@ -24,14 +26,14 @@ class SugaredTypeFunctionsTest extends CompilerTest { * * @param ir the expression to resolve typing functions in */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Resolves typing functions on [[ir]]. * * @param inlineContext the context win which resolution takes place * @return [[ir]], with typing functions resolved */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { TypeFunctions.runExpression(ir, inlineContext) } } @@ -55,7 +57,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |a : B |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Ascription] + ir shouldBe an[Type.Ascription] } "work for left sections" in { @@ -64,9 +66,9 @@ class SugaredTypeFunctionsTest extends CompilerTest { |(a :) |""".stripMargin.preprocessExpression.get.resolve - if (!ir.isInstanceOf[IR.Error.Syntax]) { - ir shouldBe an[IR.Function.Lambda] - ir.asInstanceOf[IR.Function.Lambda].body shouldBe an[IR.Type.Ascription] + if (!ir.isInstanceOf[errors.Syntax]) { + ir shouldBe an[Function.Lambda] + ir.asInstanceOf[Function.Lambda].body shouldBe an[Type.Ascription] } } @@ -76,12 +78,12 @@ class SugaredTypeFunctionsTest extends CompilerTest { |(:) |""".stripMargin.preprocessExpression.get.resolve - if (!ir.isInstanceOf[IR.Error.Syntax]) { - ir shouldBe an[IR.Function.Lambda] - ir.asInstanceOf[IR.Function.Lambda] + if (!ir.isInstanceOf[errors.Syntax]) { + ir shouldBe an[Function.Lambda] + ir.asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Function.Lambda] - .body shouldBe an[IR.Type.Ascription] + .asInstanceOf[Function.Lambda] + .body shouldBe an[Type.Ascription] } } @@ -91,9 +93,9 @@ class SugaredTypeFunctionsTest extends CompilerTest { |(: a) |""".stripMargin.preprocessExpression.get.resolve - if (!ir.isInstanceOf[IR.Error.Syntax]) { - ir shouldBe an[IR.Function.Lambda] - ir.asInstanceOf[IR.Function.Lambda].body shouldBe an[IR.Type.Ascription] + if (!ir.isInstanceOf[errors.Syntax]) { + ir shouldBe an[Function.Lambda] + ir.asInstanceOf[Function.Lambda].body shouldBe an[Type.Ascription] } } @@ -103,8 +105,8 @@ class SugaredTypeFunctionsTest extends CompilerTest { |_ : A |""".stripMargin.preprocessExpression.get.resolve - if (!ir.isInstanceOf[IR.Error.Syntax]) { - ir shouldBe an[IR.Type.Ascription] + if (!ir.isInstanceOf[errors.Syntax]) { + ir shouldBe an[Type.Ascription] } } @@ -114,7 +116,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |a : _ |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Ascription] + ir shouldBe an[Type.Ascription] } } @@ -127,7 +129,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |a : A |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Ascription] + ir shouldBe an[Type.Ascription] } "resolve context ascription" ignore { @@ -137,7 +139,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |a in IO |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Context] + ir shouldBe an[Type.Context] } "resolve error ascription" in { @@ -146,7 +148,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |IO ! Error |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Error] + ir shouldBe an[Type.Error] } "resolve subsumption" in { @@ -155,7 +157,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T <: P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Subsumption] + ir shouldBe an[`type`.Set.Subsumption] } "resolve equality" ignore { @@ -165,7 +167,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T ~ P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Equality] + ir shouldBe an[`type`.Set.Equality] } "resolve concatenation" in { @@ -174,7 +176,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T ; P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Concat] + ir shouldBe an[`type`.Set.Concat] } "resolve union" in { @@ -183,7 +185,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T | P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Union] + ir shouldBe an[`type`.Set.Union] } "resolve intersection" in { @@ -192,7 +194,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T & P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Intersection] + ir shouldBe an[`type`.Set.Intersection] } "resolve subtraction" ignore { @@ -202,7 +204,7 @@ class SugaredTypeFunctionsTest extends CompilerTest { |T \ P |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Type.Set.Subtraction] + ir shouldBe an[`type`.Set.Subtraction] } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SuspendedArgumentsTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SuspendedArgumentsTest.scala index c2c63ad0d716..6a39943a6785 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SuspendedArgumentsTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/SuspendedArgumentsTest.scala @@ -2,8 +2,12 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR -import org.enso.compiler.core.IR.Module.Scope.Definition.Method +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.analyse.AliasAnalysis import org.enso.compiler.pass.resolve.SuspendedArguments import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} @@ -32,14 +36,14 @@ class SuspendedArgumentsTest extends CompilerTest { * * @param ir the IR to add the extension method to */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { /** Resolves suspended arguments in [[ir]]. * * @param moduleContext the context in which resolution is taking place * @return [[ir]], with all suspended arguments resolved */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { SuspendedArguments.runModule(ir, moduleContext) } } @@ -49,14 +53,14 @@ class SuspendedArgumentsTest extends CompilerTest { * * @param ir the expression to add the extension method to */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Resolves suspended arguments in [[ir]]. * * @param inlineContext the context in which resolution is taking place * @return [[ir]], with all suspended arguments resolved */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { SuspendedArguments.runExpression(ir, inlineContext) } } @@ -91,9 +95,9 @@ class SuspendedArgumentsTest extends CompilerTest { |Any.id : Suspended -> a |Any.id self a = a |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] - val bodyLam = ir.body.asInstanceOf[IR.Function.Lambda] + val bodyLam = ir.body.asInstanceOf[Function.Lambda] bodyLam.arguments.length shouldEqual 2 assert( @@ -118,17 +122,17 @@ class SuspendedArgumentsTest extends CompilerTest { | | lazy_id a |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val bodyBlock = ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val lazyId = bodyBlock.expressions.head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] assert(lazyId.arguments.head.suspended, "x was not suspended") } @@ -141,9 +145,9 @@ class SuspendedArgumentsTest extends CompilerTest { |File.with_output_stream : Vector.Vector -> (Output_Stream -> Any ! File_Error) -> Any ! File_Error |File.with_output_stream open_options action = undefined |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[Method.Explicit] + .asInstanceOf[definition.Method.Explicit] - val bodyLam = ir.body.asInstanceOf[IR.Function.Lambda] + val bodyLam = ir.body.asInstanceOf[Function.Lambda] bodyLam.arguments.length shouldEqual 3 @@ -158,9 +162,9 @@ class SuspendedArgumentsTest extends CompilerTest { """File.from : Text -> Suspended -> Any |File.from (that : Text) config=Nothing = undefined |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[Method.Conversion] + .asInstanceOf[definition.Method.Conversion] - val bodyLam = ir.body.asInstanceOf[IR.Function.Lambda] + val bodyLam = ir.body.asInstanceOf[Function.Lambda] val args = bodyLam.arguments args.length shouldEqual 3 @@ -175,9 +179,9 @@ class SuspendedArgumentsTest extends CompilerTest { """File.from (~that : Text) = undefined |""".stripMargin.preprocessModule.resolve.bindings.head - ir shouldBe an[IR.Error.Conversion] - ir.asInstanceOf[IR.Error.Conversion] - .reason shouldBe an[IR.Error.Conversion.SuspendedSourceArgument] + ir shouldBe an[errors.Conversion] + ir.asInstanceOf[errors.Conversion] + .reason shouldBe an[errors.Conversion.SuspendedSourceArgument] } "work for local functions applications" in { @@ -190,12 +194,12 @@ class SuspendedArgumentsTest extends CompilerTest { | |foo 1 1 |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[Method] + .asInstanceOf[definition.Method] val lam = ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] val bodyBlock = lam.body - .asInstanceOf[IR.Application.Prefix] + .asInstanceOf[Application.Prefix] lam.arguments.length shouldEqual 2 lam.arguments(1).suspended shouldBe true @@ -213,12 +217,12 @@ class SuspendedArgumentsTest extends CompilerTest { |f : A -> Suspended -> B |f a b = b |""".stripMargin.preprocessExpression.get.resolve - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val func = ir.returnValue - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] assert(!func.arguments.head.suspended, "a is suspended") assert(func.arguments(1).suspended, "b is not suspended") } @@ -231,8 +235,8 @@ class SuspendedArgumentsTest extends CompilerTest { |(x -> y -> y + x) : Suspended -> a -> a |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Function.Lambda] - val lam = ir.asInstanceOf[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] + val lam = ir.asInstanceOf[Function.Lambda] assert(lam.arguments.head.suspended, "x is not suspended") assert(!lam.arguments(1).suspended, "y is suspended") } @@ -249,15 +253,15 @@ class SuspendedArgumentsTest extends CompilerTest { | f 100 50 |""".stripMargin.preprocessExpression.get.resolve - ir shouldBe an[IR.Function.Lambda] - val lam = ir.asInstanceOf[IR.Function.Lambda] + ir shouldBe an[Function.Lambda] + val lam = ir.asInstanceOf[Function.Lambda] val f = lam.body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] .expressions .head - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] assert(!f.arguments.head.suspended, "a was suspended") assert(f.arguments(1).suspended, "b was not suspended") diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeNamesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeNamesTest.scala index a7147210cbbb..0b55e531aeb5 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeNamesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeNamesTest.scala @@ -2,7 +2,8 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Diagnostic, Expression, Module} +import org.enso.compiler.core.ir.expression.errors import org.enso.compiler.data.BindingsMap.ResolutionNotFound import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.pass.resolve.{TypeNames, TypeSignatures} @@ -26,14 +27,14 @@ class TypeNamesTest extends CompilerTest { * * @param ir the IR to add the extension method to */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { /** Resolves type signatures in [[ir]]. * * @param moduleContext the context in which resolution is taking place * @return [[ir]], with all type signatures resolved */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { TypeNames.runModule(ir, moduleContext) } } @@ -43,14 +44,14 @@ class TypeNamesTest extends CompilerTest { * * @param ir the expression to add the extension method to */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Resolves type signatures in [[ir]]. * * @param inlineContext the context in which resolution is taking place * @return [[ir]], with all type signatures resolved */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { TypeNames.runExpression(ir, inlineContext) } } @@ -91,7 +92,7 @@ class TypeNamesTest extends CompilerTest { val meta = ir.bindings.last.getMetadata(TypeSignatures) meta shouldBe defined val diagnostics = meta.get.signature.preorder - .collect({ case err: IR.Diagnostic => + .collect({ case err: Diagnostic => err }) @@ -112,14 +113,14 @@ class TypeNamesTest extends CompilerTest { val meta = ir.bindings.last.getMetadata(TypeSignatures) meta shouldBe defined val diagnostics = meta.get.signature.preorder - .collect({ case err: IR.Diagnostic => + .collect({ case err: Diagnostic => err }) diagnostics.length shouldEqual 1 - val resolutionFailure = diagnostics.head.asInstanceOf[IR.Error.Resolution] + val resolutionFailure = diagnostics.head.asInstanceOf[errors.Resolution] resolutionFailure.name shouldBe "C" - resolutionFailure.reason shouldBe IR.Error.Resolution.ResolverError( + resolutionFailure.reason shouldBe errors.Resolution.ResolverError( ResolutionNotFound ) } @@ -135,15 +136,15 @@ class TypeNamesTest extends CompilerTest { val meta = ir.bindings.last.getMetadata(TypeSignatures) meta shouldBe defined val diagnostics = meta.get.signature.preorder - .collect({ case err: IR.Diagnostic => + .collect({ case err: Diagnostic => err }) diagnostics.length shouldEqual 3 diagnostics.foreach { - case d: IR.Error.Resolution => + case d: errors.Resolution => d.name shouldBe "Integer" - d.reason shouldBe IR.Error.Resolution.ResolverError( + d.reason shouldBe errors.Resolution.ResolverError( ResolutionNotFound ) case _ => @@ -164,7 +165,7 @@ class TypeNamesTest extends CompilerTest { val meta = ir.bindings.last.getMetadata(TypeSignatures) meta shouldBe defined val diagnostics = meta.get.signature.preorder - .collect({ case err: IR.Diagnostic => + .collect({ case err: Diagnostic => err }) diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeSignaturesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeSignaturesTest.scala index 53f800dabd7c..15c967a8ea5d 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeSignaturesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/pass/resolve/TypeSignaturesTest.scala @@ -2,7 +2,14 @@ package org.enso.compiler.test.pass.resolve import org.enso.compiler.Passes import org.enso.compiler.context.{FreshNameSupply, InlineContext, ModuleContext} -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.Expression +import org.enso.compiler.core.ir.Function +import org.enso.compiler.core.ir.Module +import org.enso.compiler.core.ir.Literal +import org.enso.compiler.core.ir.expression.Application +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Definition +import org.enso.compiler.core.ir.module.scope.definition import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager} import org.enso.compiler.pass.resolve.{ DocumentationComments, @@ -29,14 +36,14 @@ class TypeSignaturesTest extends CompilerTest { * * @param ir the IR to add the extension method to */ - implicit class ResolveModule(ir: IR.Module) { + implicit class ResolveModule(ir: Module) { /** Resolves type signatures in [[ir]]. * * @param moduleContext the context in which resolution is taking place * @return [[ir]], with all type signatures resolved */ - def resolve(implicit moduleContext: ModuleContext): IR.Module = { + def resolve(implicit moduleContext: ModuleContext): Module = { TypeSignatures.runModule(ir, moduleContext) } } @@ -46,14 +53,14 @@ class TypeSignaturesTest extends CompilerTest { * * @param ir the expression to add the extension method to */ - implicit class ResolveExpression(ir: IR.Expression) { + implicit class ResolveExpression(ir: Expression) { /** Resolves type signatures in [[ir]]. * * @param inlineContext the context in which resolution is taking place * @return [[ir]], with all type signatures resolved */ - def resolve(implicit inlineContext: InlineContext): IR.Expression = { + def resolve(implicit inlineContext: InlineContext): Expression = { TypeSignatures.runExpression(ir, inlineContext) } } @@ -115,11 +122,11 @@ class TypeSignaturesTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 5 - ir.bindings.head shouldBe an[IR.Error.Unexpected.TypeSignature] - ir.bindings(1) shouldBe an[IR.Error.Unexpected.TypeSignature] - ir.bindings(2) shouldBe an[IR.Module.Scope.Definition.Method] - ir.bindings(3) shouldBe an[IR.Module.Scope.Definition.Method] - ir.bindings(4) shouldBe an[IR.Error.Unexpected.TypeSignature] + ir.bindings.head shouldBe an[errors.Unexpected.TypeSignature] + ir.bindings(1) shouldBe an[errors.Unexpected.TypeSignature] + ir.bindings(2) shouldBe an[definition.Method] + ir.bindings(3) shouldBe an[definition.Method] + ir.bindings(4) shouldBe an[errors.Unexpected.TypeSignature] } "reattach documentation to method definitions" in { @@ -162,11 +169,11 @@ class TypeSignaturesTest extends CompilerTest { |""".stripMargin.preprocessModule.resolve ir.bindings.length shouldEqual 3 - ir.bindings(0) shouldBe an[IR.Module.Scope.Definition.Type] - ir.bindings(1) shouldBe an[IR.Module.Scope.Definition.Method] + ir.bindings(0) shouldBe an[Definition.Type] + ir.bindings(1) shouldBe an[definition.Method] ir.bindings(1).getMetadata(TypeSignatures) shouldBe defined ir.bindings(1).getMetadata(DocumentationComments) shouldBe defined - ir.bindings(2) shouldBe an[IR.Error.Unexpected.TypeSignature] + ir.bindings(2) shouldBe an[errors.Unexpected.TypeSignature] } "recurse into bodies" in { @@ -183,12 +190,12 @@ class TypeSignaturesTest extends CompilerTest { | | f 1 |""".stripMargin.preprocessModule.resolve.bindings.head - .asInstanceOf[IR.Module.Scope.Definition.Method] + .asInstanceOf[definition.Method] val block = ir.body - .asInstanceOf[IR.Function.Lambda] + .asInstanceOf[Function.Lambda] .body - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] block.expressions.length shouldEqual 2 block.expressions.head.getMetadata(TypeSignatures) shouldBe defined @@ -218,30 +225,30 @@ class TypeSignaturesTest extends CompilerTest { | | bad_sig : Int |""".stripMargin.preprocessExpression.get.resolve - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] - val block = ir.expression.asInstanceOf[IR.Expression.Block] + val block = ir.expression.asInstanceOf[Expression.Block] "associate signatures with bindings" in { val head = block.expressions.head - head shouldBe an[IR.Expression.Binding] + head shouldBe an[Expression.Binding] head.getMetadata(TypeSignatures) shouldBe defined head.getMetadata(DocumentationComments) shouldBe defined } "raise an error if a signature is divorced from its definition" in { - block.returnValue shouldBe an[IR.Error.Unexpected.TypeSignature] + block.returnValue shouldBe an[errors.Unexpected.TypeSignature] } "work recursively" in { val nested = block .expressions(1) - .asInstanceOf[IR.Expression.Binding] + .asInstanceOf[Expression.Binding] .expression - .asInstanceOf[IR.Expression.Block] + .asInstanceOf[Expression.Block] val head = nested.expressions.head - head shouldBe an[IR.Expression.Binding] + head shouldBe an[Expression.Binding] head.getMetadata(TypeSignatures) shouldBe defined head.getMetadata(DocumentationComments) shouldBe defined } @@ -256,15 +263,15 @@ class TypeSignaturesTest extends CompilerTest { |""".stripMargin.preprocessExpression.get.resolve "associate the signature with the typed expression" in { - ir shouldBe an[IR.Application.Prefix] + ir shouldBe an[Application.Prefix] ir.getMetadata(TypeSignatures) shouldBe defined } "work recursively" in { - val arg2Value = ir.asInstanceOf[IR.Application.Prefix].arguments(1).value - arg2Value shouldBe an[IR.Application.Prefix] - val snd = arg2Value.asInstanceOf[IR.Application.Prefix] - snd.arguments(0).value shouldBe an[IR.Literal.Number] + val arg2Value = ir.asInstanceOf[Application.Prefix].arguments(1).value + arg2Value shouldBe an[Application.Prefix] + val snd = arg2Value.asInstanceOf[Application.Prefix] + snd.arguments(0).value shouldBe an[Literal.Number] } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala index fb2618c411dd..80d7e0f9adf8 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/ImportExportTest.scala @@ -1,6 +1,8 @@ package org.enso.compiler.test.semantic -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Module, Warning} +import org.enso.compiler.core.ir.expression.errors +import org.enso.compiler.core.ir.module.scope.Import import org.enso.compiler.data.BindingsMap import org.enso.compiler.pass.analyse.BindingAnalysis import org.enso.interpreter.runtime @@ -72,7 +74,7 @@ class ImportExportTest } } - implicit private class UnwrapBindingMap(moduleIr: IR.Module) { + implicit private class UnwrapBindingMap(moduleIr: Module) { def unwrapBindingMap: BindingsMap = { moduleIr.unsafeGetMetadata(BindingAnalysis, "Should be present") } @@ -117,9 +119,9 @@ class ImportExportTest mainCode.createModule(packageQualifiedName.createChild("Main")).getIr mainIr.imports.size shouldEqual 1 mainIr.imports.head match { - case importErr: IR.Error.ImportExport => + case importErr: errors.ImportExport => fail( - s"Import should be resolved, but instead produced IR.Error.ImportExport with ${importErr.reason.message}" + s"Import should be resolved, but instead produced errors.ImportExport with ${importErr.reason.message}" ) case _ => () } @@ -173,7 +175,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe true + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe true } "result in error when importing a method from type" in { @@ -190,11 +192,11 @@ class ImportExportTest .getIr mainIr.imports.size shouldEqual 1 mainIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason .asInstanceOf[ - IR.Error.ImportExport.NoSuchConstructor - ] shouldEqual IR.Error.ImportExport + errors.ImportExport.NoSuchConstructor + ] shouldEqual errors.ImportExport .NoSuchConstructor("Other_Type", "method") } @@ -212,9 +214,9 @@ class ImportExportTest .getIr mainIr.imports .take(2) - .map(_.asInstanceOf[IR.Error.ImportExport].reason) shouldEqual List( - IR.Error.ImportExport.NoSuchConstructor("Other_Type", "method"), - IR.Error.ImportExport.NoSuchConstructor("Other_Type", "other_method") + .map(_.asInstanceOf[errors.ImportExport].reason) shouldEqual List( + errors.ImportExport.NoSuchConstructor("Other_Type", "method"), + errors.ImportExport.NoSuchConstructor("Other_Type", "other_method") ) } @@ -238,8 +240,8 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false - bIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false + bIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false val mainBindingMap = mainIr.unwrapBindingMap val bBindingMap = bIr.unwrapBindingMap mainBindingMap.resolvedImports.size shouldEqual 2 @@ -283,9 +285,9 @@ class ImportExportTest .getIr mainIr.imports .take(2) - .map(_.asInstanceOf[IR.Error.ImportExport].reason) shouldEqual List( - IR.Error.ImportExport.NoSuchConstructor("Other_Module_Type", "method"), - IR.Error.ImportExport + .map(_.asInstanceOf[errors.ImportExport].reason) shouldEqual List( + errors.ImportExport.NoSuchConstructor("Other_Module_Type", "method"), + errors.ImportExport .NoSuchConstructor("Other_Module_Type", "non_existing_method") ) } @@ -303,9 +305,9 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.ModuleDoesNotExist] + .asInstanceOf[errors.ImportExport.ModuleDoesNotExist] .name should include("static_method") } @@ -321,9 +323,9 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.ModuleDoesNotExist] + .asInstanceOf[errors.ImportExport.ModuleDoesNotExist] .name should include("Non_Existing_Symbol") } @@ -347,7 +349,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false val mainBindingMap = mainIr.unwrapBindingMap val resolvedImportTargets = mainBindingMap.resolvedImports.map(_.target) @@ -375,7 +377,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false val mainBindingMap = mainIr.unwrapBindingMap val resolvedImportTargets = mainBindingMap.resolvedImports.map(_.target) @@ -407,11 +409,11 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) mainModule.getIr.imports.head - .isInstanceOf[IR.Error.ImportExport] shouldBe true + .isInstanceOf[errors.ImportExport] shouldBe true mainModule.getIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.SymbolDoesNotExist] + .asInstanceOf[errors.ImportExport.SymbolDoesNotExist] .symbolName shouldEqual "A_Type" } } @@ -430,12 +432,12 @@ class ImportExportTest mainIr.imports.size shouldEqual 1 val in = mainIr.imports.head - .asInstanceOf[IR.Module.Scope.Import.Module] + .asInstanceOf[Import.Module] in.name.name.toString() should include("Test.Logical_Export.Main") in.onlyNames.get.map(_.name.toString()) shouldEqual List("Api") - val errors = mainIr.preorder.filter(x => x.isInstanceOf[IR.Error]) + val errors = mainIr.preorder.filter(x => x.isInstanceOf[Error]) errors.size shouldEqual 0 } @@ -449,7 +451,7 @@ class ImportExportTest .getIr mainIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason .message should include( "The symbol Impl (module or type) does not exist in module Test.Logical_Export.Main." @@ -475,7 +477,7 @@ class ImportExportTest val warn = mainIr .imports(1) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warn.size shouldEqual 1 warn.head.originalImport shouldEqual origImport warn.head.symbolName shouldEqual "A_Type" @@ -499,7 +501,7 @@ class ImportExportTest val warn = mainIr .imports(1) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warn.size shouldEqual 1 warn.head.originalImport shouldEqual origImport warn.head.symbolName shouldEqual "A_Type" @@ -523,7 +525,7 @@ class ImportExportTest val warn = mainIr .imports(1) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warn.size shouldEqual 1 warn.head.originalImport shouldEqual origImport warn.head.symbolName shouldEqual "A_Type" @@ -548,7 +550,7 @@ class ImportExportTest val warn = mainIr .imports(1) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warn.size shouldEqual 2 warn.foreach(_.originalImport shouldEqual origImport) warn.exists(_.symbolName == "A_Type") shouldEqual true @@ -573,7 +575,7 @@ class ImportExportTest .getIr mainIr.imports.size shouldEqual 2 mainIr.imports.foreach( - _.isInstanceOf[IR.Error.ImportExport] shouldEqual false + _.isInstanceOf[errors.ImportExport] shouldEqual false ) } @@ -597,9 +599,9 @@ class ImportExportTest val origImport = mainIr.imports(0) val ambiguousImport = mainIr .imports(1) - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.AmbiguousImport] + .asInstanceOf[errors.ImportExport.AmbiguousImport] ambiguousImport.symbolName shouldEqual "A_Type" ambiguousImport.originalImport shouldEqual origImport } @@ -619,7 +621,7 @@ class ImportExportTest val warns = mainIr .imports(0) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warns.size shouldEqual 1 warns.head.symbolName shouldEqual "A_Type" } @@ -640,9 +642,9 @@ class ImportExportTest val origImport = mainIr.imports(0) val ambiguousImport = mainIr .imports(1) - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.AmbiguousImport] + .asInstanceOf[errors.ImportExport.AmbiguousImport] ambiguousImport.symbolName shouldEqual "A_Type" ambiguousImport.originalImport shouldEqual origImport } @@ -664,7 +666,7 @@ class ImportExportTest val warns = mainIr .imports(1) .diagnostics - .collect({ case w: IR.Warning.DuplicatedImport => w }) + .collect({ case w: Warning.DuplicatedImport => w }) warns.size shouldEqual 1 warns.head.symbolName shouldEqual "A_Type" warns.head.originalImport shouldEqual origImport @@ -682,9 +684,9 @@ class ImportExportTest val origImport = mainIr.imports(0) val ambiguousImport = mainIr .imports(1) - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason - .asInstanceOf[IR.Error.ImportExport.AmbiguousImport] + .asInstanceOf[errors.ImportExport.AmbiguousImport] ambiguousImport.symbolName shouldEqual "A_Type" ambiguousImport.originalImport shouldEqual origImport } @@ -706,7 +708,7 @@ class ImportExportTest val origImport = mainIr.imports(0) val allWarns = mainIr.imports.flatMap(_.diagnostics.collect({ - case w: IR.Warning.DuplicatedImport => w + case w: Warning.DuplicatedImport => w })) allWarns.size shouldEqual 2 allWarns.foreach(_.symbolName shouldEqual "A_Type") @@ -730,7 +732,7 @@ class ImportExportTest val origImport = mainIr.imports(0) val allWarns = mainIr.imports.flatMap(_.diagnostics.collect({ - case w: IR.Warning.DuplicatedImport => w + case w: Warning.DuplicatedImport => w })) allWarns.size shouldEqual 2 allWarns.foreach(_.symbolName shouldEqual "A_Type") @@ -776,9 +778,9 @@ class ImportExportTest |""".stripMargin .createModule(packageQualifiedName.createChild("Main")) .getIr - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe true + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe true mainIr.imports.head - .asInstanceOf[IR.Error.ImportExport] + .asInstanceOf[errors.ImportExport] .reason .message should include("A_Type") } @@ -820,7 +822,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false } "resolve re-exported symbol" in { @@ -860,7 +862,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false } "resolve re-exported symbol along with all other symbols" in { @@ -900,7 +902,7 @@ class ImportExportTest .createModule(packageQualifiedName.createChild("Main")) .getIr mainIr.imports.size shouldEqual 1 - mainIr.imports.head.isInstanceOf[IR.Error.ImportExport] shouldBe false + mainIr.imports.head.isInstanceOf[errors.ImportExport] shouldBe false } } } diff --git a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/TypeSignaturesTest.scala b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/TypeSignaturesTest.scala index 9b3f1ff8c6fd..e9eca52d0bc0 100644 --- a/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/TypeSignaturesTest.scala +++ b/engine/runtime/src/test/scala/org/enso/compiler/test/semantic/TypeSignaturesTest.scala @@ -1,6 +1,9 @@ package org.enso.compiler.test.semantic -import org.enso.compiler.core.IR +import org.enso.compiler.core.ir.{Expression, Module, Type} +import org.enso.compiler.core.ir +import org.enso.compiler.core.ir.module.scope.definition +import org.enso.compiler.core.ir.`type` import org.enso.compiler.pass.resolve.{TypeNames, TypeSignatures} import org.enso.interpreter.runtime import org.enso.interpreter.runtime.EnsoContext @@ -45,12 +48,12 @@ trait TypeMatchers { val Input = Name("Input") - case class TypeMatcher(sig: Sig) extends Matcher[IR.Expression] { + case class TypeMatcher(sig: Sig) extends Matcher[Expression] { private def findInequalityWitness( sig: Sig, - expr: IR.Expression - ): Option[(Sig, IR.Expression, String)] = (sig, expr) match { - case (Name(n), t: IR.Name.Literal) => + expr: Expression + ): Option[(Sig, Expression, String)] = (sig, expr) match { + case (Name(n), t: ir.Name.Literal) => Option.when(n != t.name)((sig, expr, "names do not match")) case (AnyQualName(n), _) => val meta = expr.getMetadata(TypeNames) @@ -70,7 +73,7 @@ trait TypeMatchers { ) } } - case (Fn(args, res), t: IR.Type.Function) => + case (Fn(args, res), t: Type.Function) => if (args.length != t.args.length) { Some((sig, expr, "arity does not match")) } else { @@ -80,13 +83,13 @@ trait TypeMatchers { .headOption .orElse(findInequalityWitness(res, t.result)) } - case (Union(items), t: IR.Type.Set.Union) => + case (Union(items), t: `type`.Set.Union) => if (items.length != t.operands.length) { Some((sig, expr, "number of items does not match")) } else { items.lazyZip(t.operands).flatMap(findInequalityWitness).headOption } - case (In(typed, context), IR.Type.Context(irTyped, irContext, _, _, _)) => + case (In(typed, context), Type.Context(irTyped, irContext, _, _, _)) => findInequalityWitness(typed, irTyped).orElse( findInequalityWitness(context, irContext) ) @@ -94,7 +97,7 @@ trait TypeMatchers { case _ => Some((sig, expr, "constructors are incompatible")) } - override def apply(left: IR.Expression): MatchResult = { + override def apply(left: Expression): MatchResult = { findInequalityWitness(sig, left) match { case Some((s, t, r)) => MatchResult( @@ -148,7 +151,7 @@ class TypeSignaturesTest ) implicit private class PreprocessModule(code: String) { - def preprocessModule: IR.Module = { + def preprocessModule: Module = { val module = new runtime.Module(Module, null, code) langCtx.getCompiler.run(module) module.getIr @@ -156,11 +159,11 @@ class TypeSignaturesTest } private def getSignature( - module: IR.Module, + module: Module, methodName: String - ): IR.Expression = { + ): Expression = { val m = module.bindings.find { - case m: IR.Module.Scope.Definition.Method => + case m: definition.Method => m.methodName.name == methodName case _ => false }.get