diff --git a/engine/runtime-compiler/src/main/java/org/enso/compiler/context/NameResolutionAlgorithm.java b/engine/runtime-compiler/src/main/java/org/enso/compiler/context/NameResolutionAlgorithm.java index 7321924e544b..dc62bdd49758 100644 --- a/engine/runtime-compiler/src/main/java/org/enso/compiler/context/NameResolutionAlgorithm.java +++ b/engine/runtime-compiler/src/main/java/org/enso/compiler/context/NameResolutionAlgorithm.java @@ -2,10 +2,8 @@ import org.enso.compiler.MetadataInteropHelpers; import org.enso.compiler.core.ConstantsNames; -import org.enso.compiler.core.ir.Name; +import org.enso.compiler.core.ir.Name.Literal; import org.enso.compiler.data.BindingsMap; -import org.enso.compiler.pass.analyse.AliasAnalysis$; -import org.enso.compiler.pass.analyse.alias.AliasMetadata; import org.enso.compiler.pass.resolve.GlobalNames$; import scala.Option; @@ -15,7 +13,8 @@ *

The same logic is needed in two places: * *

    - *
  1. in the runtime ({@link org.enso.interpreter.runtime.IrToTruffle.ExpressionProcessor#processName}), + *
  2. in the runtime ({@link + * org.enso.interpreter.runtime.IrToTruffle.ExpressionProcessor#processName}), *
  3. in the type checker ({@link * org.enso.compiler.pass.analyse.types.TypePropagation#processName}). *
@@ -27,15 +26,23 @@ * @param The type describing a link to a local name in a current scope. * Depending on the context this may be a Graph.Link (in the compiler) or a FramePointer (in the * runtime). + * @param Type of the metadata that is associated with the name IR that is resolved. */ -public abstract class NameResolutionAlgorithm { - public final ResultType resolveName(Name.Literal name) { - AliasMetadata.Occurrence occurrenceMetadata = - MetadataInteropHelpers.getMetadata( - name, AliasAnalysis$.MODULE$, AliasMetadata.Occurrence.class); - var maybeLocalLink = findLocalLink(occurrenceMetadata); - if (maybeLocalLink.isDefined()) { - return resolveLocalName(maybeLocalLink.get()); +public abstract class NameResolutionAlgorithm { + + /** + * Resolves a name to {@code ResultType}. + * + * @param name literal name to be resolved + * @param meta Nullable metadata gathered from the {@code name} IR. + * @return The result of the resolution process. + */ + public final ResultType resolveName(Literal name, MetadataType meta) { + if (meta != null) { + var maybeLocalLink = findLocalLink(meta); + if (maybeLocalLink.isDefined()) { + return resolveLocalName(maybeLocalLink.get()); + } } BindingsMap.Resolution global = @@ -53,8 +60,13 @@ public final ResultType resolveName(Name.Literal name) { return resolveUnresolvedSymbol(name.name()); } - protected abstract Option findLocalLink( - AliasMetadata.Occurrence occurrenceMetadata); + /** + * Finds a local link in the current scope from the given {@code metadata}. + * + * @param metadata Not null. + * @return The local link if found, {@code None} otherwise. + */ + protected abstract Option findLocalLink(MetadataType metadata); protected abstract ResultType resolveLocalName(LocalNameLinkType localLink); diff --git a/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/types/TypePropagation.java b/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/types/TypePropagation.java index d9c3493216ee..27f254c31679 100644 --- a/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/types/TypePropagation.java +++ b/engine/runtime-compiler/src/main/java/org/enso/compiler/pass/analyse/types/TypePropagation.java @@ -4,6 +4,7 @@ import static org.enso.compiler.MetadataInteropHelpers.getMetadataOrNull; import java.util.List; +import org.enso.compiler.MetadataInteropHelpers; import org.enso.compiler.context.NameResolutionAlgorithm; import org.enso.compiler.core.CompilerError; import org.enso.compiler.core.IR; @@ -159,7 +160,10 @@ private TypeRepresentation processCaseExpression( private TypeRepresentation processName( Name.Literal literalName, LocalBindingsTyping localBindingsTyping) { var resolver = new CompilerNameResolution(localBindingsTyping); - return resolver.resolveName(literalName); + var occMeta = + MetadataInteropHelpers.getMetadataOrNull( + literalName, AliasAnalysis$.MODULE$, AliasMetadata.Occurrence.class); + return resolver.resolveName(literalName, occMeta); } private TypeRepresentation processLiteral(Literal literal) { @@ -333,7 +337,8 @@ private TypeRepresentation processUnresolvedSymbolApplication( } private class CompilerNameResolution - extends NameResolutionAlgorithm { + extends NameResolutionAlgorithm< + TypeRepresentation, CompilerNameResolution.LinkInfo, AliasMetadata.Occurrence> { private final LocalBindingsTyping localBindingsTyping; private CompilerNameResolution(LocalBindingsTyping localBindingsTyping) { diff --git a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/FramePointerAnalysis.scala b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/FramePointerAnalysis.scala index 7f0861e69b45..1822ba2b1550 100644 --- a/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/FramePointerAnalysis.scala +++ b/engine/runtime-compiler/src/main/scala/org/enso/compiler/pass/analyse/FramePointerAnalysis.scala @@ -388,6 +388,10 @@ case object FramePointerAnalysis extends IRPass { ) extends IRMetadata { override val metadataName: String = "FramePointer" + def parentLevel(): Int = framePointer.parentLevel + + def frameSlotIdx(): Int = framePointer.frameSlotIdx + /** @inheritdoc */ override def duplicate(): Option[Metadata] = { diff --git a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala index 9bd5ea3aba5a..944c51849019 100644 --- a/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala +++ b/engine/runtime/src/main/scala/org/enso/interpreter/runtime/IrToTruffle.scala @@ -51,6 +51,7 @@ import org.enso.compiler.pass.analyse.{ AliasAnalysis, BindingAnalysis, DataflowAnalysis, + FramePointerAnalysis, TailCall } import org.enso.compiler.pass.analyse.alias.AliasMetadata @@ -302,13 +303,12 @@ class IrToTruffle( val unprocessedArg = atomDefn.arguments(idx) val checkNode = checkAsTypes(unprocessedArg) val arg = argFactory.run(unprocessedArg, idx, checkNode) - val occInfo = unprocessedArg + val fp = unprocessedArg .unsafeGetMetadata( - AliasAnalysis, - "No occurrence on an argument definition." + FramePointerAnalysis, + "No frame pointer on an argument definition." ) - .unsafeAs[alias.AliasMetadata.Occurrence] - val slotIdx = localScope.getVarSlotIdx(occInfo.id) + val slotIdx = fp.frameSlotIdx() argDefs(idx) = arg val readArg = ReadArgumentNode.build( @@ -1823,17 +1823,14 @@ class IrToTruffle( private def processBinding( binding: Expression.Binding ): RuntimeExpression = { - val occInfo = binding + val fp = binding .unsafeGetMetadata( - AliasAnalysis, - "Binding with missing occurrence information." + FramePointerAnalysis, + "Binding with missing frame pointer." ) - .unsafeAs[AliasMetadata.Occurrence] currentVarName = binding.name.name - - val slotIdx = scope.getVarSlotIdx(occInfo.id) - + val slotIdx = fp.frameSlotIdx() setLocation( AssignmentNode.build(this.run(binding.expression, true, true), slotIdx), binding.location @@ -1889,7 +1886,11 @@ class IrToTruffle( val nameExpr = name match { case literalName: Name.Literal => val resolver = new RuntimeNameResolution() - resolver.resolveName(literalName) + val fpMeta = literalName.passData.get(FramePointerAnalysis) match { + case Some(meta: FramePointerAnalysis.FramePointerMeta) => meta + case _ => null + } + resolver.resolveName(literalName, fpMeta) case Name.MethodReference( None, Name.Literal(nameStr, _, _, _, _, _), @@ -1945,11 +1946,22 @@ class IrToTruffle( } private class RuntimeNameResolution - extends NameResolutionAlgorithm[RuntimeExpression, FramePointer] { + extends NameResolutionAlgorithm[ + RuntimeExpression, + FramePointer, + FramePointerAnalysis.FramePointerMeta + ] { override protected def findLocalLink( - occurrenceMetadata: org.enso.compiler.pass.analyse.alias.AliasMetadata.Occurrence - ): Option[FramePointer] = - scope.getFramePointer(occurrenceMetadata.id) + fpMeta: FramePointerAnalysis.FramePointerMeta + ): Option[FramePointer] = { + if (scope.flattenToParent && fpMeta.parentLevel() > 0) { + Some( + new FramePointer(fpMeta.parentLevel() - 1, fpMeta.frameSlotIdx()) + ) + } else { + Some(fpMeta.framePointer) + } + } override protected def resolveLocalName( localLink: FramePointer @@ -2191,14 +2203,12 @@ class IrToTruffle( val checkNode = checkAsTypes(unprocessedArg) val arg = argFactory.run(unprocessedArg, idx, checkNode) argDefinitions(idx) = arg - val occInfo = unprocessedArg + val fp = unprocessedArg .unsafeGetMetadata( - AliasAnalysis, - "No occurrence on an argument definition." + FramePointerAnalysis, + "No frame pointer on an argument definition." ) - .unsafeAs[AliasMetadata.Occurrence] - - val slotIdx = scope.getVarSlotIdx(occInfo.id) + val slotIdx = fp.frameSlotIdx() val readArg = ReadArgumentNode.build( idx,