mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 14:52:01 +03:00
Un-nest AliasAnalysis Info and Graph to allow easier usage from Java (#9451)
This commit is contained in:
parent
de9f2764f9
commit
90b3003312
@ -1,7 +1,8 @@
|
|||||||
package org.enso.compiler.pass.analyse;
|
package org.enso.compiler.pass.analyse;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph;
|
import org.enso.compiler.pass.analyse.alias.Graph;
|
||||||
|
import org.enso.compiler.pass.analyse.alias.Info;
|
||||||
import org.enso.compiler.pass.resolve.DocumentationComments;
|
import org.enso.compiler.pass.resolve.DocumentationComments;
|
||||||
import org.enso.compiler.pass.resolve.DocumentationComments$;
|
import org.enso.compiler.pass.resolve.DocumentationComments$;
|
||||||
import org.enso.compiler.pass.resolve.ExpressionAnnotations$;
|
import org.enso.compiler.pass.resolve.ExpressionAnnotations$;
|
||||||
@ -54,12 +55,24 @@ import scala.Option;
|
|||||||
@Persistable(clazz = GenericAnnotations$.class, id = 1216)
|
@Persistable(clazz = GenericAnnotations$.class, id = 1216)
|
||||||
@Persistable(clazz = ExpressionAnnotations$.class, id = 1217)
|
@Persistable(clazz = ExpressionAnnotations$.class, id = 1217)
|
||||||
@Persistable(clazz = FullyQualifiedNames$.class, id = 1218)
|
@Persistable(clazz = FullyQualifiedNames$.class, id = 1218)
|
||||||
@Persistable(clazz = AliasAnalysis$Info$Occurrence.class, id = 1261, allowInlining = false)
|
@Persistable(clazz = Info.Occurrence.class, id = 1261, allowInlining = false)
|
||||||
@Persistable(clazz = AliasAnalysis$Info$Scope$Root.class, id = 1262, allowInlining = false)
|
@Persistable(
|
||||||
@Persistable(clazz = AliasAnalysis$Info$Scope$Child.class, id = 1263, allowInlining = false)
|
clazz = org.enso.compiler.pass.analyse.alias.Info$Scope$Root.class,
|
||||||
@Persistable(clazz = AliasAnalysis$Graph$Occurrence$Use.class, id = 1264, allowInlining = false)
|
id = 1262,
|
||||||
@Persistable(clazz = AliasAnalysis$Graph$Occurrence$Def.class, id = 1265, allowInlining = false)
|
allowInlining = false)
|
||||||
@Persistable(clazz = AliasAnalysis$Graph$Link.class, id = 1266, allowInlining = false)
|
@Persistable(
|
||||||
|
clazz = org.enso.compiler.pass.analyse.alias.Info$Scope$Child.class,
|
||||||
|
id = 1263,
|
||||||
|
allowInlining = false)
|
||||||
|
@Persistable(
|
||||||
|
clazz = org.enso.compiler.pass.analyse.alias.Graph$Occurrence$Use.class,
|
||||||
|
id = 1264,
|
||||||
|
allowInlining = false)
|
||||||
|
@Persistable(
|
||||||
|
clazz = org.enso.compiler.pass.analyse.alias.Graph$Occurrence$Def.class,
|
||||||
|
id = 1265,
|
||||||
|
allowInlining = false)
|
||||||
|
@Persistable(clazz = Graph.Link.class, id = 1266, allowInlining = false)
|
||||||
public final class PassPersistance {
|
public final class PassPersistance {
|
||||||
private PassPersistance() {}
|
private PassPersistance() {}
|
||||||
|
|
||||||
@ -106,26 +119,22 @@ public final class PassPersistance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@org.openide.util.lookup.ServiceProvider(service = Persistance.class)
|
@org.openide.util.lookup.ServiceProvider(service = Persistance.class)
|
||||||
public static final class PersistAliasAnalysisGraphScope
|
public static final class PersistAliasAnalysisGraphScope extends Persistance<Graph.Scope> {
|
||||||
extends Persistance<org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope> {
|
|
||||||
public PersistAliasAnalysisGraphScope() {
|
public PersistAliasAnalysisGraphScope() {
|
||||||
super(org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope.class, false, 1267);
|
super(Graph.Scope.class, false, 1267);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope readObject(Input in)
|
protected Graph.Scope readObject(Input in) throws IOException {
|
||||||
throws IOException {
|
|
||||||
var childScopes = in.readInline(scala.collection.immutable.List.class);
|
var childScopes = in.readInline(scala.collection.immutable.List.class);
|
||||||
var occurrences = (scala.collection.immutable.Set) in.readObject();
|
var occurrences = (scala.collection.immutable.Set) in.readObject();
|
||||||
var allDefinitions = in.readInline(scala.collection.immutable.List.class);
|
var allDefinitions = in.readInline(scala.collection.immutable.List.class);
|
||||||
var parent =
|
var parent = new Graph.Scope(childScopes, occurrences, allDefinitions);
|
||||||
new org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope(
|
|
||||||
childScopes, occurrences, allDefinitions);
|
|
||||||
var optionParent = Option.apply(parent);
|
var optionParent = Option.apply(parent);
|
||||||
childScopes.forall(
|
childScopes.forall(
|
||||||
(object) -> {
|
(object) -> {
|
||||||
var ch = (org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope) object;
|
var ch = (Graph.Scope) object;
|
||||||
ch.parent_$eq(optionParent);
|
ch.parent_$eq(optionParent);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
@ -134,9 +143,7 @@ public final class PassPersistance {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void writeObject(
|
protected void writeObject(Graph.Scope obj, Output out) throws IOException {
|
||||||
org.enso.compiler.pass.analyse.AliasAnalysis$Graph$Scope obj, Output out)
|
|
||||||
throws IOException {
|
|
||||||
out.writeInline(scala.collection.immutable.List.class, obj.childScopes());
|
out.writeInline(scala.collection.immutable.List.class, obj.childScopes());
|
||||||
out.writeObject(obj.occurrences());
|
out.writeObject(obj.occurrences());
|
||||||
out.writeInline(scala.collection.immutable.List.class, obj.allDefinitions());
|
out.writeInline(scala.collection.immutable.List.class, obj.allDefinitions());
|
||||||
@ -153,7 +160,7 @@ public final class PassPersistance {
|
|||||||
protected Graph readObject(Input in) throws IOException {
|
protected Graph readObject(Input in) throws IOException {
|
||||||
var g = new Graph();
|
var g = new Graph();
|
||||||
|
|
||||||
var rootScope = (AliasAnalysis$Graph$Scope) in.readObject();
|
var rootScope = (Graph.Scope) in.readObject();
|
||||||
assignParents(rootScope);
|
assignParents(rootScope);
|
||||||
g.rootScope_$eq(rootScope);
|
g.rootScope_$eq(rootScope);
|
||||||
|
|
||||||
@ -175,7 +182,7 @@ public final class PassPersistance {
|
|||||||
out.writeInt(obj.nextIdCounter());
|
out.writeInt(obj.nextIdCounter());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void assignParents(AliasAnalysis$Graph$Scope scope) {
|
private static void assignParents(Graph.Scope scope) {
|
||||||
var option = Option.apply(scope);
|
var option = Option.apply(scope);
|
||||||
scope
|
scope
|
||||||
.childScopes()
|
.childScopes()
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
package org.enso.compiler.context
|
package org.enso.compiler.context
|
||||||
|
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph
|
import org.enso.compiler.pass.analyse.DataflowAnalysis
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{
|
import org.enso.compiler.pass.analyse.alias.{Graph => AliasGraph}
|
||||||
Id,
|
|
||||||
Occurrence,
|
|
||||||
Scope => AliasScope
|
|
||||||
}
|
|
||||||
import org.enso.compiler.pass.analyse.{AliasAnalysis, DataflowAnalysis}
|
|
||||||
|
|
||||||
import scala.jdk.CollectionConverters._
|
import scala.jdk.CollectionConverters._
|
||||||
|
|
||||||
@ -33,19 +28,19 @@ import scala.jdk.CollectionConverters._
|
|||||||
*/
|
*/
|
||||||
class LocalScope(
|
class LocalScope(
|
||||||
final val parentScope: Option[LocalScope],
|
final val parentScope: Option[LocalScope],
|
||||||
final val aliasingGraph: AliasAnalysis.Graph,
|
final val aliasingGraph: AliasGraph,
|
||||||
final val scope: AliasAnalysis.Graph.Scope,
|
final val scope: AliasGraph.Scope,
|
||||||
final val dataflowInfo: DataflowAnalysis.Metadata,
|
final val dataflowInfo: DataflowAnalysis.Metadata,
|
||||||
final val flattenToParent: Boolean = false,
|
final val flattenToParent: Boolean = false,
|
||||||
private val parentFrameSlotIdxs: Map[Graph.Id, Int] = Map()
|
private val parentFrameSlotIdxs: Map[AliasGraph.Id, Int] = Map()
|
||||||
) {
|
) {
|
||||||
private lazy val localFrameSlotIdxs: Map[Graph.Id, Int] =
|
private lazy val localFrameSlotIdxs: Map[AliasGraph.Id, Int] =
|
||||||
gatherLocalFrameSlotIdxs()
|
gatherLocalFrameSlotIdxs()
|
||||||
|
|
||||||
/** All frame slot indexes, including local and all the parents.
|
/** All frame slot indexes, including local and all the parents.
|
||||||
* Useful for quick searching for [[FramePointer]] of parent scopes.
|
* Useful for quick searching for [[FramePointer]] of parent scopes.
|
||||||
*/
|
*/
|
||||||
private lazy val allFrameSlotIdxs: Map[Graph.Id, Int] =
|
private lazy val allFrameSlotIdxs: Map[AliasGraph.Id, Int] =
|
||||||
parentFrameSlotIdxs ++ localFrameSlotIdxs
|
parentFrameSlotIdxs ++ localFrameSlotIdxs
|
||||||
|
|
||||||
/** Creates a new child with a new aliasing scope.
|
/** Creates a new child with a new aliasing scope.
|
||||||
@ -62,7 +57,7 @@ class LocalScope(
|
|||||||
* @return a child of this scope
|
* @return a child of this scope
|
||||||
*/
|
*/
|
||||||
def createChild(
|
def createChild(
|
||||||
childScope: AliasScope,
|
childScope: AliasGraph.Scope,
|
||||||
flattenToParent: Boolean = false
|
flattenToParent: Boolean = false
|
||||||
): LocalScope = {
|
): LocalScope = {
|
||||||
new LocalScope(
|
new LocalScope(
|
||||||
@ -83,7 +78,7 @@ class LocalScope(
|
|||||||
* analysis.
|
* analysis.
|
||||||
* @return the frame slot index for `id`.
|
* @return the frame slot index for `id`.
|
||||||
*/
|
*/
|
||||||
def getVarSlotIdx(id: Graph.Id): Int = {
|
def getVarSlotIdx(id: AliasGraph.Id): Int = {
|
||||||
assert(
|
assert(
|
||||||
localFrameSlotIdxs.contains(id),
|
localFrameSlotIdxs.contains(id),
|
||||||
"Cannot find " + id + " in " + localFrameSlotIdxs
|
"Cannot find " + id + " in " + localFrameSlotIdxs
|
||||||
@ -98,7 +93,7 @@ class LocalScope(
|
|||||||
* analysis
|
* analysis
|
||||||
* @return the frame pointer for `id`, if it exists
|
* @return the frame pointer for `id`, if it exists
|
||||||
*/
|
*/
|
||||||
def getFramePointer(id: Graph.Id): Option[FramePointer] = {
|
def getFramePointer(id: AliasGraph.Id): Option[FramePointer] = {
|
||||||
aliasingGraph
|
aliasingGraph
|
||||||
.defLinkFor(id)
|
.defLinkFor(id)
|
||||||
.flatMap { link =>
|
.flatMap { link =>
|
||||||
@ -126,7 +121,7 @@ class LocalScope(
|
|||||||
* indexes in the frame. Takes into account all the
|
* indexes in the frame. Takes into account all the
|
||||||
* internal slots, that are prepended to every frame.
|
* internal slots, that are prepended to every frame.
|
||||||
*/
|
*/
|
||||||
private def gatherLocalFrameSlotIdxs(): Map[Id, Int] = {
|
private def gatherLocalFrameSlotIdxs(): Map[AliasGraph.Id, Int] = {
|
||||||
scope.allDefinitions.zipWithIndex.map { case (definition, i) =>
|
scope.allDefinitions.zipWithIndex.map { case (definition, i) =>
|
||||||
definition.id -> (i + LocalScope.internalSlotsSize)
|
definition.id -> (i + LocalScope.internalSlotsSize)
|
||||||
}.toMap
|
}.toMap
|
||||||
@ -139,13 +134,13 @@ class LocalScope(
|
|||||||
*/
|
*/
|
||||||
private def flattenBindingsWithLevel(
|
private def flattenBindingsWithLevel(
|
||||||
level: Int
|
level: Int
|
||||||
): Map[Graph.Symbol, FramePointer] = {
|
): Map[AliasGraph.Symbol, FramePointer] = {
|
||||||
var parentResult: Map[Graph.Symbol, FramePointer] = parentScope
|
var parentResult: Map[AliasGraph.Symbol, FramePointer] = parentScope
|
||||||
.flatMap(scope => Some(scope.flattenBindingsWithLevel(level + 1)))
|
.flatMap(scope => Some(scope.flattenBindingsWithLevel(level + 1)))
|
||||||
.getOrElse(Map())
|
.getOrElse(Map())
|
||||||
|
|
||||||
scope.occurrences.foreach {
|
scope.occurrences.foreach {
|
||||||
case x: Occurrence.Def =>
|
case x: AliasGraph.Occurrence.Def =>
|
||||||
parentResult += x.symbol -> new FramePointer(
|
parentResult += x.symbol -> new FramePointer(
|
||||||
level,
|
level,
|
||||||
allFrameSlotIdxs(x.id)
|
allFrameSlotIdxs(x.id)
|
||||||
@ -166,7 +161,7 @@ object LocalScope {
|
|||||||
* @return a defaulted local scope
|
* @return a defaulted local scope
|
||||||
*/
|
*/
|
||||||
def root: LocalScope = {
|
def root: LocalScope = {
|
||||||
val graph = new AliasAnalysis.Graph
|
val graph = new AliasGraph
|
||||||
new LocalScope(
|
new LocalScope(
|
||||||
None,
|
None,
|
||||||
graph,
|
graph,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -78,7 +78,7 @@ object AutomaticParallelism extends IRPass {
|
|||||||
ir: Expression,
|
ir: Expression,
|
||||||
parallelismStatus: ParallelismStatus,
|
parallelismStatus: ParallelismStatus,
|
||||||
id: Int,
|
id: Int,
|
||||||
assignment: Option[AliasAnalysis.Graph.Id],
|
assignment: Option[alias.Graph.Id],
|
||||||
dependencies: Set[Int],
|
dependencies: Set[Int],
|
||||||
blockAssignment: Option[BlockAssignment]
|
blockAssignment: Option[BlockAssignment]
|
||||||
)
|
)
|
||||||
@ -215,7 +215,7 @@ object AutomaticParallelism extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Alias analysis left a binding behind"
|
"Alias analysis left a binding behind"
|
||||||
)
|
)
|
||||||
.asInstanceOf[AliasAnalysis.Info.Occurrence]
|
.asInstanceOf[alias.Info.Occurrence]
|
||||||
line.copy(assignment = Some(aaInfo.id))
|
line.copy(assignment = Some(aaInfo.id))
|
||||||
case _ => line
|
case _ => line
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ object AutomaticParallelism extends IRPass {
|
|||||||
n
|
n
|
||||||
}
|
}
|
||||||
.flatMap(_.getMetadata(AliasAnalysis))
|
.flatMap(_.getMetadata(AliasAnalysis))
|
||||||
.collect { case occ: AliasAnalysis.Info.Occurrence =>
|
.collect { case occ: alias.Info.Occurrence =>
|
||||||
occ
|
occ
|
||||||
}
|
}
|
||||||
.flatMap(occ => occ.graph.defLinkFor(occ.id))
|
.flatMap(occ => occ.graph.defLinkFor(occ.id))
|
||||||
|
@ -548,7 +548,7 @@ case object DataflowAnalysis extends IRPass {
|
|||||||
"Name occurrence with missing aliasing information."
|
"Name occurrence with missing aliasing information."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.asInstanceOf[AliasAnalysis.Info.Occurrence]
|
.asInstanceOf[alias.Info.Occurrence]
|
||||||
|
|
||||||
name match {
|
name match {
|
||||||
case _: Name.Blank =>
|
case _: Name.Blank =>
|
||||||
@ -560,7 +560,7 @@ case object DataflowAnalysis extends IRPass {
|
|||||||
val key: DependencyInfo.Type = defIdForName match {
|
val key: DependencyInfo.Type = defIdForName match {
|
||||||
case Some(defLink) =>
|
case Some(defLink) =>
|
||||||
aliasInfo.graph.getOccurrence(defLink.target) match {
|
aliasInfo.graph.getOccurrence(defLink.target) match {
|
||||||
case Some(AliasAnalysis.Graph.Occurrence.Def(_, _, id, ext, _)) =>
|
case Some(alias.Graph.Occurrence.Def(_, _, id, ext, _)) =>
|
||||||
DependencyInfo.Type.Static(id, ext)
|
DependencyInfo.Type.Static(id, ext)
|
||||||
case _ =>
|
case _ =>
|
||||||
DependencyInfo.Type.Dynamic(name.name, None)
|
DependencyInfo.Type.Dynamic(name.name, None)
|
||||||
|
@ -202,7 +202,7 @@ case object DemandAnalysis extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Missing alias occurrence information for a name usage"
|
"Missing alias occurrence information for a name usage"
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[alias.Info.Occurrence]
|
||||||
|
|
||||||
aliasInfo.graph.defLinkFor(aliasInfo.id).isDefined
|
aliasInfo.graph.defLinkFor(aliasInfo.id).isDefined
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,717 @@
|
|||||||
|
package org.enso.compiler.pass.analyse.alias
|
||||||
|
|
||||||
|
import org.enso.compiler.core.{CompilerError, ExternalID, Identifier}
|
||||||
|
import org.enso.syntax.text.Debug
|
||||||
|
import org.enso.compiler.pass.analyse.alias.Graph.{Occurrence, Scope}
|
||||||
|
|
||||||
|
import java.util.UUID
|
||||||
|
import scala.collection.mutable
|
||||||
|
import scala.reflect.ClassTag
|
||||||
|
|
||||||
|
/** A graph containing aliasing information for a given root scope in Enso. */
|
||||||
|
sealed class Graph extends Serializable {
|
||||||
|
var rootScope: Graph.Scope = new Graph.Scope()
|
||||||
|
var links: Set[Graph.Link] = Set()
|
||||||
|
var nextIdCounter = 0
|
||||||
|
|
||||||
|
private var globalSymbols: Map[Graph.Symbol, Occurrence.Global] =
|
||||||
|
Map()
|
||||||
|
|
||||||
|
/** @return a deep structural copy of `this` */
|
||||||
|
def deepCopy(
|
||||||
|
scope_mapping: mutable.Map[Scope, Scope] = mutable.Map()
|
||||||
|
): Graph = {
|
||||||
|
val copy = new Graph
|
||||||
|
copy.rootScope = this.rootScope.deepCopy(scope_mapping)
|
||||||
|
copy.links = this.links
|
||||||
|
copy.globalSymbols = this.globalSymbols
|
||||||
|
copy.nextIdCounter = this.nextIdCounter
|
||||||
|
copy
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Registers a requested global symbol in the aliasing scope.
|
||||||
|
*
|
||||||
|
* @param sym the symbol occurrence
|
||||||
|
*/
|
||||||
|
def addGlobalSymbol(sym: Occurrence.Global): Unit = {
|
||||||
|
if (!globalSymbols.contains(sym.symbol)) {
|
||||||
|
globalSymbols = globalSymbols + (sym.symbol -> sym)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a deep copy of the aliasing graph structure.
|
||||||
|
*
|
||||||
|
* @return a copy of the graph structure
|
||||||
|
*/
|
||||||
|
def copy: Graph = {
|
||||||
|
val graph = new Graph
|
||||||
|
graph.links = links
|
||||||
|
graph.rootScope = rootScope.deepCopy(mutable.Map())
|
||||||
|
graph.nextIdCounter = nextIdCounter
|
||||||
|
|
||||||
|
graph
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines whether `this` is equal to `obj`.
|
||||||
|
*
|
||||||
|
* @param obj the object to compare against.
|
||||||
|
* @return `true` if `this == obj`, otherwise `false`
|
||||||
|
*/
|
||||||
|
override def equals(obj: Any): Boolean =
|
||||||
|
obj match {
|
||||||
|
case that: Graph =>
|
||||||
|
(this.links == that.links) && (this.rootScope == that.rootScope)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Generates a new identifier for a node in the graph.
|
||||||
|
*
|
||||||
|
* @return a unique identifier for this graph
|
||||||
|
*/
|
||||||
|
def nextId(): Graph.Id = {
|
||||||
|
val nextId = nextIdCounter
|
||||||
|
nextIdCounter += 1
|
||||||
|
nextId
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resolves any links for the given usage of a symbol, assuming the symbol
|
||||||
|
* is a local variable.
|
||||||
|
*
|
||||||
|
* @param occurrence the symbol usage
|
||||||
|
* @return the link, if it exists
|
||||||
|
*/
|
||||||
|
def resolveLocalUsage(
|
||||||
|
occurrence: Graph.Occurrence.Use
|
||||||
|
): Option[Graph.Link] = {
|
||||||
|
scopeFor(occurrence.id).flatMap(_.resolveUsage(occurrence).map { link =>
|
||||||
|
links += link
|
||||||
|
link
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resolves any links for the given usage of a symbol, assuming the symbol
|
||||||
|
* is global (i.e. method, constructor etc.)
|
||||||
|
*
|
||||||
|
* @param occurrence the symbol usage
|
||||||
|
* @return the link, if it exists
|
||||||
|
*/
|
||||||
|
def resolveGlobalUsage(
|
||||||
|
occurrence: Graph.Occurrence.Use
|
||||||
|
): Option[Graph.Link] = {
|
||||||
|
scopeFor(occurrence.id) match {
|
||||||
|
case Some(scope) =>
|
||||||
|
globalSymbols
|
||||||
|
.get(occurrence.symbol)
|
||||||
|
.map(g => Graph.Link(occurrence.id, scope.scopesToRoot + 1, g.id))
|
||||||
|
case None => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns a string representation of the graph.
|
||||||
|
*
|
||||||
|
* @return a string representation of `this`
|
||||||
|
*/
|
||||||
|
override def toString: String =
|
||||||
|
s"Graph(links = $links, rootScope = $rootScope)"
|
||||||
|
|
||||||
|
/** Pretty prints the graph.
|
||||||
|
*
|
||||||
|
* @return a pretty-printed string representation of the graph
|
||||||
|
*/
|
||||||
|
def pprint: String = {
|
||||||
|
val original = toString
|
||||||
|
Debug.pretty(original)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets all links in which the provided `id` is a participant.
|
||||||
|
*
|
||||||
|
* @param id the identifier for the symbol
|
||||||
|
* @return a list of links in which `id` occurs
|
||||||
|
*/
|
||||||
|
def linksFor(id: Graph.Id): Set[Graph.Link] = {
|
||||||
|
links.filter(l => l.source == id || l.target == id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds all links in the graph where `symbol` appears in the role
|
||||||
|
* specified by `T`.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol to find links for
|
||||||
|
* @tparam T the role in which `symbol` should occur
|
||||||
|
* @return a set of all links in which `symbol` occurs with role `T`
|
||||||
|
*/
|
||||||
|
def linksFor[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): Set[Graph.Link] = {
|
||||||
|
val idsForSym = rootScope.symbolToIds[T](symbol)
|
||||||
|
|
||||||
|
links.filter(l =>
|
||||||
|
idsForSym.contains(l.source) || idsForSym.contains(l.target)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Obtains the occurrence for a given ID, from whichever scope in which it
|
||||||
|
* occurs.
|
||||||
|
*
|
||||||
|
* @param id the occurrence identifier
|
||||||
|
* @return the occurrence for `id`, if it exists
|
||||||
|
*/
|
||||||
|
def getOccurrence(id: Graph.Id): Option[Occurrence] =
|
||||||
|
scopeFor(id).flatMap(_.getOccurrence(id))
|
||||||
|
|
||||||
|
/** Gets the link from an id to the definition of the symbol it represents.
|
||||||
|
*
|
||||||
|
* @param id the identifier to find the definition link for
|
||||||
|
* @return the definition link for `id` if it exists
|
||||||
|
*/
|
||||||
|
def defLinkFor(id: Graph.Id): Option[Graph.Link] = {
|
||||||
|
linksFor(id).find { edge =>
|
||||||
|
val occ = getOccurrence(edge.target)
|
||||||
|
occ match {
|
||||||
|
case Some(Occurrence.Def(_, _, _, _, _)) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the scope where a given ID is defined in the graph.
|
||||||
|
*
|
||||||
|
* @param id the id to find the scope for
|
||||||
|
* @return the scope where `id` occurs
|
||||||
|
*/
|
||||||
|
def scopeFor(id: Graph.Id): Option[Graph.Scope] = {
|
||||||
|
rootScope.scopeFor(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds the scopes in which a name occurs with a given role.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol
|
||||||
|
* @tparam T the role in which `symbol` occurs
|
||||||
|
* @return all the scopes where `symbol` occurs with role `T`
|
||||||
|
*/
|
||||||
|
def scopesFor[T <: Graph.Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): List[Graph.Scope] = {
|
||||||
|
rootScope.scopesForSymbol[T](symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Counts the number of scopes in this scope.
|
||||||
|
*
|
||||||
|
* @return the number of scopes that are either this scope or children of
|
||||||
|
* it
|
||||||
|
*/
|
||||||
|
def numScopes: Int = {
|
||||||
|
rootScope.scopeCount
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines the maximum nesting depth of scopes through this scope.
|
||||||
|
*
|
||||||
|
* @return the maximum nesting depth of scopes through this scope.
|
||||||
|
*/
|
||||||
|
def nesting: Int = {
|
||||||
|
rootScope.maxNesting
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines if the provided ID is capable of shadowing other bindings
|
||||||
|
*
|
||||||
|
* @param id the occurrence identifier
|
||||||
|
* @return `true` if `id` shadows other bindings, otherwise `false`
|
||||||
|
*/
|
||||||
|
def canShadow(id: Graph.Id): Boolean = {
|
||||||
|
scopeFor(id)
|
||||||
|
.flatMap(
|
||||||
|
_.getOccurrence(id).flatMap {
|
||||||
|
case d: Occurrence.Def => Some(d)
|
||||||
|
case _ => None
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.isDefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Computes the bindings that are shadowed by the binding with the provided
|
||||||
|
* `definition`.
|
||||||
|
*
|
||||||
|
* Please note that just because [[canShadow]] states that an identifier is
|
||||||
|
* _capable_ of shadowing, that does not mean that it is necessarily known
|
||||||
|
* to do so.
|
||||||
|
*
|
||||||
|
* @param definition the definition to find the 'shadowees' of
|
||||||
|
* @return the bindings shadowed by `definition`
|
||||||
|
*/
|
||||||
|
def knownShadowedDefinitions(
|
||||||
|
definition: Occurrence
|
||||||
|
): Set[Graph.Occurrence] = {
|
||||||
|
def getShadowedIds(
|
||||||
|
scope: Graph.Scope
|
||||||
|
): Set[Graph.Occurrence] = {
|
||||||
|
scope.occurrences.collect {
|
||||||
|
case d: Occurrence.Def if d.symbol == definition.symbol => d
|
||||||
|
case g: Occurrence.Global if g.symbol == definition.symbol => g
|
||||||
|
} ++ scope.parent.map(getShadowedIds).getOrElse(Set())
|
||||||
|
}
|
||||||
|
|
||||||
|
definition match {
|
||||||
|
case d: Occurrence.Def =>
|
||||||
|
scopeFor(d.id).flatMap(_.parent) match {
|
||||||
|
case Some(scope) => getShadowedIds(scope) // + globals
|
||||||
|
case None => Set()
|
||||||
|
}
|
||||||
|
case _: Occurrence.Global => Set()
|
||||||
|
case _: Occurrence.Use => Set()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines if the provided id is linked to a binding that shadows
|
||||||
|
* another binding.
|
||||||
|
*
|
||||||
|
* @param id the identifier to check
|
||||||
|
* @return `true` if the definition of the symbol for `id` shadows another
|
||||||
|
* binding for the same symbol, `false`, otherwise
|
||||||
|
*/
|
||||||
|
def linkedToShadowingBinding(id: Graph.Id): Boolean = {
|
||||||
|
defLinkFor(id).isDefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets all symbols defined in the graph.
|
||||||
|
*
|
||||||
|
* @return the set of symbols defined in this graph
|
||||||
|
*/
|
||||||
|
def symbols: Set[Graph.Symbol] = {
|
||||||
|
rootScope.symbols
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Goes from a symbol to all identifiers that relate to that symbol in
|
||||||
|
* the role specified by `T`.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol to find identifiers for
|
||||||
|
* @tparam T the role in which `symbol` should occur
|
||||||
|
* @return a list of identifiers for that symbol
|
||||||
|
*/
|
||||||
|
def symbolToIds[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): List[Graph.Id] = {
|
||||||
|
rootScope.symbolToIds[T](symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Goes from an identifier to the associated symbol.
|
||||||
|
*
|
||||||
|
* @param id the identifier of an occurrence
|
||||||
|
* @return the symbol associated with `id`, if it exists
|
||||||
|
*/
|
||||||
|
def idToSymbol(
|
||||||
|
id: Graph.Id
|
||||||
|
): Option[Graph.Symbol] = {
|
||||||
|
rootScope.idToSymbol(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object Graph {
|
||||||
|
|
||||||
|
/** The type of symbols on the graph. */
|
||||||
|
type Symbol = String
|
||||||
|
|
||||||
|
/** The type of identifiers on the graph. */
|
||||||
|
type Id = Int
|
||||||
|
|
||||||
|
/** A representation of a local scope in Enso.
|
||||||
|
*
|
||||||
|
* @param childScopes all scopes that are _direct_ children of `this`
|
||||||
|
* @param occurrences all symbol occurrences in `this` scope
|
||||||
|
* @param allDefinitions all definitions in this scope, including synthetic ones.
|
||||||
|
* Note that there may not be a link for all these definitions.
|
||||||
|
*/
|
||||||
|
sealed class Scope(
|
||||||
|
var childScopes: List[Scope] = List(),
|
||||||
|
var occurrences: Set[Occurrence] = Set(),
|
||||||
|
var allDefinitions: List[Occurrence.Def] = List()
|
||||||
|
) extends Serializable {
|
||||||
|
|
||||||
|
var parent: Option[Scope] = None
|
||||||
|
|
||||||
|
/** Counts the number of scopes from this scope to the root.
|
||||||
|
*
|
||||||
|
* This count includes the root scope, but not the current scope.
|
||||||
|
*
|
||||||
|
* @return the number of scopes from this scope to the root
|
||||||
|
*/
|
||||||
|
def scopesToRoot: Int = {
|
||||||
|
parent.flatMap(scope => Some(scope.scopesToRoot + 1)).getOrElse(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Sets the parent of the scope.
|
||||||
|
*
|
||||||
|
* The parent scope must not be redefined.
|
||||||
|
*
|
||||||
|
* @return this scope with parent scope set
|
||||||
|
*/
|
||||||
|
def withParent(parentScope: Scope): this.type = {
|
||||||
|
assert(parent.isEmpty)
|
||||||
|
this.parent = Some(parentScope)
|
||||||
|
this
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a structural copy of this scope, ensuring that replicated
|
||||||
|
* scopes are memoised.
|
||||||
|
*
|
||||||
|
* @return a copy of `this`
|
||||||
|
*/
|
||||||
|
def deepCopy(
|
||||||
|
mapping: mutable.Map[Scope, Scope] = mutable.Map()
|
||||||
|
): Scope = {
|
||||||
|
mapping.get(this) match {
|
||||||
|
case Some(newCorrespondingScope) => newCorrespondingScope
|
||||||
|
case None =>
|
||||||
|
val childScopeCopies: mutable.ListBuffer[Scope] =
|
||||||
|
mutable.ListBuffer()
|
||||||
|
this.childScopes.foreach(scope =>
|
||||||
|
childScopeCopies += scope.deepCopy(mapping)
|
||||||
|
)
|
||||||
|
val newScope =
|
||||||
|
new Scope(childScopeCopies.toList, occurrences, allDefinitions)
|
||||||
|
mapping.put(this, newScope)
|
||||||
|
newScope
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks whether `this` is equal to `obj`.
|
||||||
|
*
|
||||||
|
* @param obj the object to compare `this` against
|
||||||
|
* @return `true` if `this == obj`, otherwise `false`
|
||||||
|
*/
|
||||||
|
override def equals(obj: Any): Boolean =
|
||||||
|
obj match {
|
||||||
|
case that: Scope =>
|
||||||
|
if (this.childScopes.length == that.childScopes.length) {
|
||||||
|
val childScopesEqual =
|
||||||
|
this.childScopes.zip(that.childScopes).forall(t => t._1 == t._2)
|
||||||
|
val occurrencesEqual = this.occurrences == that.occurrences
|
||||||
|
|
||||||
|
childScopesEqual && occurrencesEqual
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates and returns a scope that is a child of this one.
|
||||||
|
*
|
||||||
|
* @return a scope that is a child of `this`
|
||||||
|
*/
|
||||||
|
def addChild(): Scope = {
|
||||||
|
val scope = new Scope()
|
||||||
|
scope.parent = Some(this)
|
||||||
|
childScopes ::= scope
|
||||||
|
|
||||||
|
scope
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds the specified symbol occurrence to this scope.
|
||||||
|
*
|
||||||
|
* @param occurrence the occurrence to add
|
||||||
|
*/
|
||||||
|
def add(occurrence: Occurrence): Unit = {
|
||||||
|
occurrences += occurrence
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Adds a definition, including a definition with synthetic name, without
|
||||||
|
* any links.
|
||||||
|
*
|
||||||
|
* @param definition The definition to add.
|
||||||
|
*/
|
||||||
|
def addDefinition(definition: Occurrence.Def): Unit = {
|
||||||
|
allDefinitions = allDefinitions ++ List(definition)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds an occurrence for the provided ID in the current scope, if it
|
||||||
|
* exists.
|
||||||
|
*
|
||||||
|
* @param id the occurrence identifier
|
||||||
|
* @return the occurrence for `id`, if it exists
|
||||||
|
*/
|
||||||
|
def getOccurrence(id: Graph.Id): Option[Occurrence] = {
|
||||||
|
occurrences.find(o => o.id == id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds any occurrences for the provided symbol in the current scope, if
|
||||||
|
* it exists.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol of the occurrence
|
||||||
|
* @tparam T the role for the symbol
|
||||||
|
* @return the occurrences for `name`, if they exist
|
||||||
|
*/
|
||||||
|
def getOccurrences[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): Set[Occurrence] = {
|
||||||
|
occurrences.collect {
|
||||||
|
case o: T if o.symbol == symbol => o
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Unsafely gets the occurrence for the provided ID in the current scope.
|
||||||
|
*
|
||||||
|
* Please note that this will crash if the ID is not defined in this
|
||||||
|
* scope.
|
||||||
|
*
|
||||||
|
* @param id the occurrence identifier
|
||||||
|
* @return the occurrence for `id`
|
||||||
|
*/
|
||||||
|
def unsafeGetOccurrence(id: Graph.Id): Occurrence = {
|
||||||
|
getOccurrence(id).get
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks whether a symbol occurs in a given role in the current scope.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol to check for
|
||||||
|
* @tparam T the role for it to occur in
|
||||||
|
* @return `true` if `symbol` occurs in role `T` in this scope, `false`
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
def hasSymbolOccurrenceAs[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): Boolean = {
|
||||||
|
occurrences.collect { case x: T if x.symbol == symbol => x }.nonEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resolves usages of symbols into links where possible, creating an edge
|
||||||
|
* from the usage site to the definition site.
|
||||||
|
*
|
||||||
|
* @param occurrence the symbol usage
|
||||||
|
* @param parentCounter the number of scopes that the link has traversed
|
||||||
|
* @return the link from `occurrence` to the definition of that symbol, if it
|
||||||
|
* exists
|
||||||
|
*/
|
||||||
|
def resolveUsage(
|
||||||
|
occurrence: Graph.Occurrence.Use,
|
||||||
|
parentCounter: Int = 0
|
||||||
|
): Option[Graph.Link] = {
|
||||||
|
val definition = occurrences.find {
|
||||||
|
case Graph.Occurrence.Def(_, name, _, _, _) =>
|
||||||
|
name == occurrence.symbol
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
|
|
||||||
|
definition match {
|
||||||
|
case None =>
|
||||||
|
parent.flatMap(_.resolveUsage(occurrence, parentCounter + 1))
|
||||||
|
case Some(target) =>
|
||||||
|
Some(Graph.Link(occurrence.id, parentCounter, target.id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Creates a string representation of the scope.
|
||||||
|
*
|
||||||
|
* @return a string representation of `this`
|
||||||
|
*/
|
||||||
|
override def toString: String =
|
||||||
|
s"Scope(occurrences = $occurrences, childScopes = $childScopes)"
|
||||||
|
|
||||||
|
/** Counts the number of scopes in this scope.
|
||||||
|
*
|
||||||
|
* @return the number of scopes that are either this scope or children of
|
||||||
|
* it
|
||||||
|
*/
|
||||||
|
def scopeCount: Int = {
|
||||||
|
childScopes.map(_.scopeCount).sum + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Determines the maximum nesting depth of scopes through this scope.
|
||||||
|
*
|
||||||
|
* @return the maximum nesting depth of scopes through this scope.
|
||||||
|
*/
|
||||||
|
def maxNesting: Int = {
|
||||||
|
childScopes.map(_.maxNesting).foldLeft(0)(Math.max) + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the scope where a given ID is defined in the graph.
|
||||||
|
*
|
||||||
|
* @param id the id to find the scope for
|
||||||
|
* @return the scope where `id` occurs
|
||||||
|
*/
|
||||||
|
def scopeFor(id: Graph.Id): Option[Scope] = {
|
||||||
|
val possibleCandidates = occurrences.filter(o => o.id == id)
|
||||||
|
|
||||||
|
if (possibleCandidates.isEmpty) {
|
||||||
|
if (childScopes.isEmpty) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
var childCandidate: Scope = null
|
||||||
|
val iter = childScopes.iterator
|
||||||
|
var moreThanOne = false
|
||||||
|
while (iter.hasNext && !moreThanOne) {
|
||||||
|
iter.next().scopeFor(id) match {
|
||||||
|
case Some(s) =>
|
||||||
|
if (childCandidate == null) {
|
||||||
|
childCandidate = s
|
||||||
|
} else {
|
||||||
|
moreThanOne = true
|
||||||
|
}
|
||||||
|
case None =>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (childCandidate == null) {
|
||||||
|
None
|
||||||
|
} else if (moreThanOne) {
|
||||||
|
throw new CompilerError(s"ID $id defined in multiple scopes.")
|
||||||
|
} else {
|
||||||
|
Some(childCandidate)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (possibleCandidates.size == 1) {
|
||||||
|
Some(this)
|
||||||
|
} else {
|
||||||
|
throw new CompilerError(s"Multiple occurrences found for ID $id.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the n-th parent of `this` scope.
|
||||||
|
*
|
||||||
|
* @param n the number of scopes to walk up
|
||||||
|
* @return the n-th parent of `this` scope, if present
|
||||||
|
*/
|
||||||
|
def nThParent(n: Int): Option[Scope] = {
|
||||||
|
if (n == 0) Some(this) else this.parent.flatMap(_.nThParent(n - 1))
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Finds the scopes in which a symbol occurs with a given role.
|
||||||
|
*
|
||||||
|
* Users of this function _must_ explicitly specify `T`, otherwise the
|
||||||
|
* results will be an empty list.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol
|
||||||
|
* @tparam T the role in which `name` occurs
|
||||||
|
* @return all the scopes where `name` occurs with role `T`
|
||||||
|
*/
|
||||||
|
def scopesForSymbol[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): List[Scope] = {
|
||||||
|
val occursInThisScope = hasSymbolOccurrenceAs[T](symbol)
|
||||||
|
|
||||||
|
val occurrencesInChildScopes =
|
||||||
|
childScopes.flatMap(_.scopesForSymbol[T](symbol))
|
||||||
|
|
||||||
|
if (occursInThisScope) {
|
||||||
|
this +: occurrencesInChildScopes
|
||||||
|
} else {
|
||||||
|
occurrencesInChildScopes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the set of all symbols in this scope and its children.
|
||||||
|
*
|
||||||
|
* @return the set of symbols
|
||||||
|
*/
|
||||||
|
def symbols: Set[Graph.Symbol] = {
|
||||||
|
val symbolsInThis = occurrences.map(_.symbol)
|
||||||
|
val symbolsInChildScopes = childScopes.flatMap(_.symbols)
|
||||||
|
|
||||||
|
symbolsInThis ++ symbolsInChildScopes
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Goes from a symbol to all identifiers that relate to that symbol in
|
||||||
|
* the role specified by `T`.
|
||||||
|
*
|
||||||
|
* @param symbol the symbol to find identifiers for
|
||||||
|
* @tparam T the role in which `symbol` should occur
|
||||||
|
* @return a list of identifiers for that symbol
|
||||||
|
*/
|
||||||
|
def symbolToIds[T <: Occurrence: ClassTag](
|
||||||
|
symbol: Graph.Symbol
|
||||||
|
): List[Graph.Id] = {
|
||||||
|
val scopes =
|
||||||
|
scopesForSymbol[T](symbol).flatMap(_.getOccurrences[T](symbol))
|
||||||
|
scopes.map(_.id)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Goes from an identifier to the associated symbol.
|
||||||
|
*
|
||||||
|
* @param id the identifier of an occurrence
|
||||||
|
* @return the symbol associated with `id`, if it exists
|
||||||
|
*/
|
||||||
|
def idToSymbol(
|
||||||
|
id: Graph.Id
|
||||||
|
): Option[Graph.Symbol] = {
|
||||||
|
scopeFor(id).flatMap(_.getOccurrence(id)).map(_.symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Checks if `this` scope is a child of the provided `scope`.
|
||||||
|
*
|
||||||
|
* @param scope the potential parent scope
|
||||||
|
* @return `true` if `this` is a child of `scope`, otherwise `false`
|
||||||
|
*/
|
||||||
|
def isChildOf(scope: Scope): Boolean = {
|
||||||
|
val isDirectChildOf = scope.childScopes.contains(this)
|
||||||
|
|
||||||
|
val isChildOfChildren = scope.childScopes
|
||||||
|
.map(scope => this.isChildOf(scope))
|
||||||
|
.foldLeft(false)(_ || _)
|
||||||
|
|
||||||
|
isDirectChildOf || isChildOfChildren
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A link in the [[Graph]].
|
||||||
|
*
|
||||||
|
* The source of the link should always be an [[Occurrence.Use]] while the
|
||||||
|
* target of the link should always be an [[Occurrence.Def]].
|
||||||
|
*
|
||||||
|
* @param source the source ID of the link in the graph
|
||||||
|
* @param scopeCount the number of scopes that the link traverses
|
||||||
|
* @param target the target ID of the link in the graph
|
||||||
|
*/
|
||||||
|
sealed case class Link(source: Id, scopeCount: Int, target: Id)
|
||||||
|
extends Serializable
|
||||||
|
|
||||||
|
/** An occurrence of a given symbol in the aliasing graph. */
|
||||||
|
sealed trait Occurrence extends Serializable {
|
||||||
|
val id: Id
|
||||||
|
val symbol: Graph.Symbol
|
||||||
|
}
|
||||||
|
object Occurrence {
|
||||||
|
|
||||||
|
/** The definition of a symbol in the aliasing graph.
|
||||||
|
*
|
||||||
|
* @param id the identifier of the name in the graph
|
||||||
|
* @param symbol the text of the name
|
||||||
|
* @param identifier the identifier of the symbol
|
||||||
|
* @param externalId the external identifier for the IR node defining
|
||||||
|
* the symbol
|
||||||
|
* @param isLazy whether or not the symbol is defined as lazy
|
||||||
|
*/
|
||||||
|
sealed case class Def(
|
||||||
|
override val id: Id,
|
||||||
|
override val symbol: Graph.Symbol,
|
||||||
|
identifier: UUID @Identifier,
|
||||||
|
externalId: Option[UUID @ExternalID],
|
||||||
|
isLazy: Boolean = false
|
||||||
|
) extends Occurrence
|
||||||
|
|
||||||
|
/** A usage of a symbol in the aliasing graph
|
||||||
|
*
|
||||||
|
* Name usages _need not_ correspond to name definitions, as dynamic
|
||||||
|
* symbol resolution means that a name used at runtime _may not_ be
|
||||||
|
* statically visible in the scope.
|
||||||
|
*
|
||||||
|
* @param id the identifier of the name in the graph
|
||||||
|
* @param symbol the text of the name
|
||||||
|
* @param identifier the identifier of the symbol
|
||||||
|
* @param externalId the external identifier for the IR node defining
|
||||||
|
* the symbol
|
||||||
|
*/
|
||||||
|
sealed case class Use(
|
||||||
|
override val id: Id,
|
||||||
|
override val symbol: Graph.Symbol,
|
||||||
|
identifier: UUID @Identifier,
|
||||||
|
externalId: Option[UUID @ExternalID]
|
||||||
|
) extends Occurrence
|
||||||
|
|
||||||
|
// TODO [AA] At some point the analysis should make use of these.
|
||||||
|
/** Represents a global symbol that has been _asked for_ in the program.
|
||||||
|
*
|
||||||
|
* @param id the identifier of the name in the graph
|
||||||
|
* @param symbol the text of the name
|
||||||
|
*/
|
||||||
|
sealed case class Global(
|
||||||
|
override val id: Id,
|
||||||
|
override val symbol: Graph.Symbol
|
||||||
|
) extends Occurrence
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
package org.enso.compiler.pass.analyse.alias
|
||||||
|
|
||||||
|
import org.enso.compiler.pass.IRPass
|
||||||
|
|
||||||
|
/** Information about the aliasing state for a given IR node. */
|
||||||
|
sealed trait Info extends IRPass.IRMetadata {
|
||||||
|
|
||||||
|
/** The aliasing graph. */
|
||||||
|
val graph: Graph
|
||||||
|
}
|
||||||
|
object Info {
|
||||||
|
sealed trait Scope extends Info
|
||||||
|
object Scope {
|
||||||
|
|
||||||
|
/** Aliasing information for a root scope.
|
||||||
|
*
|
||||||
|
* A root scope has a 1:1 correspondence with a top-level binding.
|
||||||
|
*
|
||||||
|
* @param graph the graph containing the alias information for that node
|
||||||
|
*/
|
||||||
|
sealed case class Root(override val graph: Graph) extends Scope {
|
||||||
|
override val metadataName: String = "Info.Scope.Root"
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def prepareForSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Root = this
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def restoreFromSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Option[Root] = Some(this)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def duplicate(): Option[IRPass.IRMetadata] = None
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Aliasing information about a child scope.
|
||||||
|
*
|
||||||
|
* @param graph the graph
|
||||||
|
* @param scope the child scope in `graph`
|
||||||
|
*/
|
||||||
|
sealed case class Child(
|
||||||
|
override val graph: Graph,
|
||||||
|
scope: Graph.Scope
|
||||||
|
) extends Scope {
|
||||||
|
override val metadataName: String = "Info.Scope.Child"
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def prepareForSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Child = this
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def restoreFromSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Option[Child] = Some(this)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def duplicate(): Option[IRPass.IRMetadata] = None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Aliasing information for a piece of [[IR]] that is contained within a
|
||||||
|
* [[Scope]].
|
||||||
|
*
|
||||||
|
* @param graph the graph in which this IR node can be found
|
||||||
|
* @param id the identifier of this IR node in `graph`
|
||||||
|
*/
|
||||||
|
sealed case class Occurrence(
|
||||||
|
override val graph: Graph,
|
||||||
|
id: Graph.Id
|
||||||
|
) extends Info {
|
||||||
|
override val metadataName: String = "Info.Occurrence"
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def prepareForSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Occurrence = this
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def restoreFromSerialization(
|
||||||
|
compiler: Compiler
|
||||||
|
): Option[Occurrence] = Some(this)
|
||||||
|
|
||||||
|
/** @inheritdoc */
|
||||||
|
override def duplicate(): Option[IRPass.IRMetadata] = None
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import org.enso.compiler.core.ir.expression.{errors, warnings, Case, Foreign}
|
|||||||
import org.enso.compiler.core.CompilerError
|
import org.enso.compiler.core.CompilerError
|
||||||
import org.enso.compiler.pass.IRPass
|
import org.enso.compiler.pass.IRPass
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis
|
import org.enso.compiler.pass.analyse.AliasAnalysis
|
||||||
|
import org.enso.compiler.pass.analyse.alias.{Info => AliasInfo}
|
||||||
import org.enso.compiler.pass.desugar._
|
import org.enso.compiler.pass.desugar._
|
||||||
import org.enso.compiler.pass.optimise.LambdaConsolidate
|
import org.enso.compiler.pass.optimise.LambdaConsolidate
|
||||||
import org.enso.compiler.pass.resolve.{ExpressionAnnotations, IgnoredBindings}
|
import org.enso.compiler.pass.resolve.{ExpressionAnnotations, IgnoredBindings}
|
||||||
@ -109,7 +110,7 @@ case object UnusedBindings extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Aliasing information is required for linting."
|
"Aliasing information is required for linting."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
||||||
|
|
||||||
if (!isIgnored && !isUsed) {
|
if (!isIgnored && !isUsed) {
|
||||||
@ -188,7 +189,7 @@ case object UnusedBindings extends IRPass {
|
|||||||
"Aliasing information missing from function argument but is " +
|
"Aliasing information missing from function argument but is " +
|
||||||
"required for linting."
|
"required for linting."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
||||||
|
|
||||||
argument match {
|
argument match {
|
||||||
@ -270,7 +271,7 @@ case object UnusedBindings extends IRPass {
|
|||||||
"Aliasing information missing from pattern but is " +
|
"Aliasing information missing from pattern but is " +
|
||||||
"required for linting."
|
"required for linting."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
||||||
|
|
||||||
if (!isIgnored && !isUsed) {
|
if (!isIgnored && !isUsed) {
|
||||||
@ -300,7 +301,7 @@ case object UnusedBindings extends IRPass {
|
|||||||
"Aliasing information missing from pattern but is " +
|
"Aliasing information missing from pattern but is " +
|
||||||
"required for linting."
|
"required for linting."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
val isUsed = aliasInfo.graph.linksFor(aliasInfo.id).nonEmpty
|
||||||
|
|
||||||
if (!isIgnored && !isUsed) {
|
if (!isIgnored && !isUsed) {
|
||||||
|
@ -22,6 +22,10 @@ import org.enso.compiler.pass.analyse.{
|
|||||||
DemandAnalysis,
|
DemandAnalysis,
|
||||||
TailCall
|
TailCall
|
||||||
}
|
}
|
||||||
|
import org.enso.compiler.pass.analyse.alias.{
|
||||||
|
Graph => AliasGraph,
|
||||||
|
Info => AliasInfo
|
||||||
|
}
|
||||||
import org.enso.compiler.pass.desugar._
|
import org.enso.compiler.pass.desugar._
|
||||||
import org.enso.compiler.pass.resolve.IgnoredBindings
|
import org.enso.compiler.pass.resolve.IgnoredBindings
|
||||||
|
|
||||||
@ -150,7 +154,7 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Missing aliasing information for an argument definition"
|
"Missing aliasing information for an argument definition"
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
shadowedBindingIds.contains(aliasInfo.id)
|
shadowedBindingIds.contains(aliasInfo.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,7 +349,7 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
*/
|
*/
|
||||||
def getShadowedBindingIds(
|
def getShadowedBindingIds(
|
||||||
args: List[DefinitionArgument]
|
args: List[DefinitionArgument]
|
||||||
): Set[AliasAnalysis.Graph.Id] = {
|
): Set[AliasGraph.Id] = {
|
||||||
args
|
args
|
||||||
.map { case spec: DefinitionArgument.Specified =>
|
.map { case spec: DefinitionArgument.Specified =>
|
||||||
val aliasInfo =
|
val aliasInfo =
|
||||||
@ -354,13 +358,13 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Missing aliasing information for an argument definition."
|
"Missing aliasing information for an argument definition."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
aliasInfo.graph
|
aliasInfo.graph
|
||||||
.getOccurrence(aliasInfo.id)
|
.getOccurrence(aliasInfo.id)
|
||||||
.flatMap(occ => Some(aliasInfo.graph.knownShadowedDefinitions(occ)))
|
.flatMap(occ => Some(aliasInfo.graph.knownShadowedDefinitions(occ)))
|
||||||
.getOrElse(Set())
|
.getOrElse(Set())
|
||||||
}
|
}
|
||||||
.foldLeft(Set[AliasAnalysis.Graph.Occurrence]())(_ ++ _)
|
.foldLeft(Set[AliasGraph.Occurrence]())(_ ++ _)
|
||||||
.map(_.id)
|
.map(_.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -382,7 +386,7 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Missing aliasing information for an argument definition."
|
"Missing aliasing information for an argument definition."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
|
|
||||||
// Empty set is used to indicate that it isn't shadowed
|
// Empty set is used to indicate that it isn't shadowed
|
||||||
val usageIds =
|
val usageIds =
|
||||||
@ -393,7 +397,7 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
.map(link => aliasInfo.graph.getOccurrence(link.source))
|
.map(link => aliasInfo.graph.getOccurrence(link.source))
|
||||||
.collect {
|
.collect {
|
||||||
case Some(
|
case Some(
|
||||||
AliasAnalysis.Graph.Occurrence.Use(_, _, identifier, _)
|
AliasGraph.Occurrence.Use(_, _, identifier, _)
|
||||||
) =>
|
) =>
|
||||||
identifier
|
identifier
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import org.enso.compiler.core.Implicits.{AsDiagnostics, AsMetadata}
|
|||||||
import org.enso.compiler.core.ir.expression.Application
|
import org.enso.compiler.core.ir.expression.Application
|
||||||
import org.enso.compiler.pass.IRPass
|
import org.enso.compiler.pass.IRPass
|
||||||
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
||||||
|
import org.enso.compiler.pass.analyse.alias.{Info => AliasInfo}
|
||||||
import org.enso.compiler.pass.desugar.Imports
|
import org.enso.compiler.pass.desugar.Imports
|
||||||
import org.enso.editions.LibraryName
|
import org.enso.editions.LibraryName
|
||||||
|
|
||||||
@ -407,7 +408,7 @@ case object FullyQualifiedNames extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"no alias analysis info on a name"
|
"no alias analysis info on a name"
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val defLink = aliasInfo.graph.defLinkFor(aliasInfo.id)
|
val defLink = aliasInfo.graph.defLinkFor(aliasInfo.id)
|
||||||
defLink.isDefined
|
defLink.isDefined
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,7 @@ import org.enso.compiler.core.ConstantsNames
|
|||||||
import org.enso.compiler.core.ir.expression.Application
|
import org.enso.compiler.core.ir.expression.Application
|
||||||
import org.enso.compiler.pass.IRPass
|
import org.enso.compiler.pass.IRPass
|
||||||
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
import org.enso.compiler.pass.analyse.{AliasAnalysis, BindingAnalysis}
|
||||||
|
import org.enso.compiler.pass.analyse.alias.{Info => AliasInfo}
|
||||||
|
|
||||||
/** Resolves name occurences in non-pattern contexts.
|
/** Resolves name occurences in non-pattern contexts.
|
||||||
*
|
*
|
||||||
@ -435,7 +436,7 @@ case object GlobalNames extends IRPass {
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"no alias analysis info on a name"
|
"no alias analysis info on a name"
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val defLink = aliasInfo.graph.defLinkFor(aliasInfo.id)
|
val defLink = aliasInfo.graph.defLinkFor(aliasInfo.id)
|
||||||
defLink.isDefined
|
defLink.isDefined
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ 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.definition
|
||||||
import org.enso.compiler.pass.PassConfiguration._
|
import org.enso.compiler.pass.PassConfiguration._
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis
|
import org.enso.compiler.pass.analyse.AliasAnalysis
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{Link, Occurrence}
|
import org.enso.compiler.pass.analyse.alias.Graph.{Link, Occurrence}
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.{Graph, Info}
|
import org.enso.compiler.pass.analyse.alias.{Graph, Info}
|
||||||
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
|
import org.enso.compiler.pass.{PassConfiguration, PassGroup, PassManager}
|
||||||
import org.enso.compiler.test.CompilerTest
|
import org.enso.compiler.test.CompilerTest
|
||||||
|
|
||||||
@ -413,7 +413,7 @@ class AliasAnalysisTest extends CompilerTest {
|
|||||||
.members
|
.members
|
||||||
.head
|
.head
|
||||||
val goodMeta = goodAtom.getMetadata(AliasAnalysis)
|
val goodMeta = goodAtom.getMetadata(AliasAnalysis)
|
||||||
val goodGraph = goodMeta.get.unsafeAs[AliasAnalysis.Info.Scope.Root].graph
|
val goodGraph = goodMeta.get.unsafeAs[Info.Scope.Root].graph
|
||||||
|
|
||||||
val badAtom =
|
val badAtom =
|
||||||
"""
|
"""
|
||||||
@ -424,7 +424,7 @@ class AliasAnalysisTest extends CompilerTest {
|
|||||||
.members
|
.members
|
||||||
.head
|
.head
|
||||||
val badMeta = badAtom.getMetadata(AliasAnalysis)
|
val badMeta = badAtom.getMetadata(AliasAnalysis)
|
||||||
val badGraph = badMeta.get.unsafeAs[AliasAnalysis.Info.Scope.Root].graph
|
val badGraph = badMeta.get.unsafeAs[Info.Scope.Root].graph
|
||||||
|
|
||||||
"assign Info.Scope.Root metadata to the atom" in {
|
"assign Info.Scope.Root metadata to the atom" in {
|
||||||
goodMeta shouldBe defined
|
goodMeta shouldBe defined
|
||||||
|
@ -45,14 +45,17 @@ import org.enso.compiler.data.BindingsMap.{
|
|||||||
}
|
}
|
||||||
import org.enso.compiler.data.{BindingsMap, CompilerConfig}
|
import org.enso.compiler.data.{BindingsMap, CompilerConfig}
|
||||||
import org.enso.compiler.exception.BadPatternMatch
|
import org.enso.compiler.exception.BadPatternMatch
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.Graph.{Scope => AliasScope}
|
import org.enso.compiler.pass.analyse.alias.Graph.{Scope => AliasScope}
|
||||||
import org.enso.compiler.pass.analyse.AliasAnalysis.{Graph => AliasGraph}
|
|
||||||
import org.enso.compiler.pass.analyse.{
|
import org.enso.compiler.pass.analyse.{
|
||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
BindingAnalysis,
|
BindingAnalysis,
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
TailCall
|
TailCall
|
||||||
}
|
}
|
||||||
|
import org.enso.compiler.pass.analyse.alias.{
|
||||||
|
Graph => AliasGraph,
|
||||||
|
Info => AliasInfo
|
||||||
|
}
|
||||||
import org.enso.compiler.pass.resolve.{
|
import org.enso.compiler.pass.resolve.{
|
||||||
ExpressionAnnotations,
|
ExpressionAnnotations,
|
||||||
GenericAnnotations,
|
GenericAnnotations,
|
||||||
@ -90,7 +93,7 @@ import org.enso.interpreter.node.{
|
|||||||
}
|
}
|
||||||
import org.enso.interpreter.runtime.EnsoContext
|
import org.enso.interpreter.runtime.EnsoContext
|
||||||
import org.enso.interpreter.runtime.callable
|
import org.enso.interpreter.runtime.callable
|
||||||
import org.enso.interpreter.runtime.callable.argument.{ArgumentDefinition}
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition
|
||||||
import org.enso.interpreter.runtime.data.atom.{Atom, AtomConstructor}
|
import org.enso.interpreter.runtime.data.atom.{Atom, AtomConstructor}
|
||||||
import org.enso.interpreter.runtime.callable.function.{
|
import org.enso.interpreter.runtime.callable.function.{
|
||||||
FunctionSchema,
|
FunctionSchema,
|
||||||
@ -104,7 +107,7 @@ import org.enso.interpreter.runtime.callable.{
|
|||||||
}
|
}
|
||||||
import org.enso.interpreter.runtime.data.Type
|
import org.enso.interpreter.runtime.data.Type
|
||||||
import org.enso.interpreter.runtime.data.text.Text
|
import org.enso.interpreter.runtime.data.text.Text
|
||||||
import org.enso.interpreter.runtime.scope.{ModuleScope}
|
import org.enso.interpreter.runtime.scope.ModuleScope
|
||||||
import org.enso.interpreter.{Constants, EnsoLanguage}
|
import org.enso.interpreter.{Constants, EnsoLanguage}
|
||||||
|
|
||||||
import java.math.BigInteger
|
import java.math.BigInteger
|
||||||
@ -259,7 +262,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No root scope on an atom definition."
|
"No root scope on an atom definition."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
.unsafeAs[AliasInfo.Scope.Root]
|
||||||
|
|
||||||
val dataflowInfo = atomDefn.unsafeGetMetadata(
|
val dataflowInfo = atomDefn.unsafeGetMetadata(
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
@ -290,7 +293,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No occurrence on an argument definition."
|
"No occurrence on an argument definition."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
val slotIdx = localScope.getVarSlotIdx(occInfo.id)
|
val slotIdx = localScope.getVarSlotIdx(occInfo.id)
|
||||||
argDefs(idx) = arg
|
argDefs(idx) = arg
|
||||||
val readArg =
|
val readArg =
|
||||||
@ -359,7 +362,7 @@ class IrToTruffle(
|
|||||||
s"Missing scope information for method " +
|
s"Missing scope information for method " +
|
||||||
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
|
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
.unsafeAs[AliasInfo.Scope.Root]
|
||||||
val dataflowInfo = methodDef.unsafeGetMetadata(
|
val dataflowInfo = methodDef.unsafeGetMetadata(
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
"Method definition missing dataflow information."
|
"Method definition missing dataflow information."
|
||||||
@ -595,7 +598,7 @@ class IrToTruffle(
|
|||||||
scopeElements.init
|
scopeElements.init
|
||||||
.mkString(Constants.SCOPE_SEPARATOR)
|
.mkString(Constants.SCOPE_SEPARATOR)
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
.unsafeAs[AliasInfo.Scope.Root]
|
||||||
val dataflowInfo = annotation.unsafeGetMetadata(
|
val dataflowInfo = annotation.unsafeGetMetadata(
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
"Missing dataflow information for annotation " +
|
"Missing dataflow information for annotation " +
|
||||||
@ -672,7 +675,7 @@ class IrToTruffle(
|
|||||||
s"Missing scope information for conversion " +
|
s"Missing scope information for conversion " +
|
||||||
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
|
s"`${methodDef.typeName.map(_.name + ".").getOrElse("")}${methodDef.methodName.name}`."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Root]
|
.unsafeAs[AliasInfo.Scope.Root]
|
||||||
val dataflowInfo = methodDef.unsafeGetMetadata(
|
val dataflowInfo = methodDef.unsafeGetMetadata(
|
||||||
DataflowAnalysis,
|
DataflowAnalysis,
|
||||||
"Method definition missing dataflow information."
|
"Method definition missing dataflow information."
|
||||||
@ -1122,7 +1125,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Missing scope information on block."
|
"Missing scope information on block."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Child]
|
.unsafeAs[AliasInfo.Scope.Child]
|
||||||
|
|
||||||
val childFactory = this.createChild("suspended-block", scopeInfo.scope)
|
val childFactory = this.createChild("suspended-block", scopeInfo.scope)
|
||||||
val childScope = childFactory.scope
|
val childScope = childFactory.scope
|
||||||
@ -1232,7 +1235,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No scope information on a case branch."
|
"No scope information on a case branch."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Child]
|
.unsafeAs[AliasInfo.Scope.Child]
|
||||||
|
|
||||||
val childProcessor = this.createChild("case_branch", scopeInfo.scope)
|
val childProcessor = this.createChild("case_branch", scopeInfo.scope)
|
||||||
|
|
||||||
@ -1601,7 +1604,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"Binding with missing occurrence information."
|
"Binding with missing occurrence information."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
|
|
||||||
currentVarName = binding.name.name
|
currentVarName = binding.name.name
|
||||||
|
|
||||||
@ -1625,7 +1628,7 @@ class IrToTruffle(
|
|||||||
): RuntimeExpression = {
|
): RuntimeExpression = {
|
||||||
val scopeInfo = function
|
val scopeInfo = function
|
||||||
.unsafeGetMetadata(AliasAnalysis, "No scope info on a function.")
|
.unsafeGetMetadata(AliasAnalysis, "No scope info on a function.")
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Child]
|
.unsafeAs[AliasInfo.Scope.Child]
|
||||||
|
|
||||||
if (function.body.isInstanceOf[Function]) {
|
if (function.body.isInstanceOf[Function]) {
|
||||||
throw new CompilerError(
|
throw new CompilerError(
|
||||||
@ -1665,7 +1668,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No occurrence on variable usage."
|
"No occurrence on variable usage."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
|
|
||||||
val framePointer = scope.getFramePointer(useInfo.id)
|
val framePointer = scope.getFramePointer(useInfo.id)
|
||||||
val global = name.getMetadata(GlobalNames)
|
val global = name.getMetadata(GlobalNames)
|
||||||
@ -1946,7 +1949,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No occurrence on an argument definition."
|
"No occurrence on an argument definition."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Occurrence]
|
.unsafeAs[AliasInfo.Occurrence]
|
||||||
|
|
||||||
val slotIdx = scope.getVarSlotIdx(occInfo.id)
|
val slotIdx = scope.getVarSlotIdx(occInfo.id)
|
||||||
val readArg =
|
val readArg =
|
||||||
@ -2176,7 +2179,7 @@ class IrToTruffle(
|
|||||||
AliasAnalysis,
|
AliasAnalysis,
|
||||||
"No scope attached to a call argument."
|
"No scope attached to a call argument."
|
||||||
)
|
)
|
||||||
.unsafeAs[AliasAnalysis.Info.Scope.Child]
|
.unsafeAs[AliasInfo.Scope.Child]
|
||||||
|
|
||||||
val shouldCreateClosureRootNode = value match {
|
val shouldCreateClosureRootNode = value match {
|
||||||
case _: Name => false
|
case _: Name => false
|
||||||
|
Loading…
Reference in New Issue
Block a user