Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ class AccessPath(
AccessPath(apManager, base, access, exclusions)

override fun getAllAccessors(): Set<Accessor> =
access?.accessorList()?.toSet().orEmpty()
access?.allAccessors().orEmpty()

// [any] is matched syntactically everywhere: it is compared as an ordinary accessor symbol,
// and against a tree it matches only the tree's own [any] edge.
override fun startsWithAccessor(accessor: Accessor): Boolean = with(apManager) {
if (access == null) return false
return access.accessor.accessor == accessor
Expand Down Expand Up @@ -100,7 +102,7 @@ class AccessPath(
with(node.manager) { setOf(node.accessor.accessor) }

override fun getAllAccessors(): Set<Accessor> =
node.accessorList().toSet()
node.allAccessors()

override fun readAccessor(accessor: Accessor): InitialFactAp.Delta? = with(node.manager) {
if (node.accessor.accessor == accessor) return node.next?.let { Delta(it) }
Expand Down Expand Up @@ -140,6 +142,7 @@ class AccessPath(
return listOfNotNull(node.filter(other.exclusions)?.let { AccessPathDelta.Delta(it) })
}

// An [any] step of this path matches only the raw [any] edge of the tree (or splits at an abstract tree node)
override fun splitDelta(other: FinalFactAp): List<Pair<InitialFactAp, InitialFactAp.Delta>> {
other as AccessTree

Expand All @@ -163,6 +166,8 @@ class AccessPath(
}

null
} else if (node.accessor == ANY_ACCESSOR_IDX) {
otherNode.getAnyChild()
} else {
otherNode.getChild(node.accessor)
}
Expand Down Expand Up @@ -264,7 +269,14 @@ class AccessPath(
val next: AccessNode?
) {
private val hash: Int
val size: Int

// size in the low 31 bits, containsAny in the sign bit: keeps the node at its old footprint
private val sizeAndAnyFlag: Int

val size: Int get() = sizeAndAnyFlag and Int.MAX_VALUE

/** This node or one of its successors is an [any] accessor. */
val containsAny: Boolean get() = sizeAndAnyFlag < 0

init {
var hash = accessor
Expand All @@ -275,7 +287,8 @@ class AccessPath(
init {
var size = 1
if (next != null) size += next.size
this.size = size
val containsAny = accessor == ANY_ACCESSOR_IDX || next?.containsAny == true
this.sizeAndAnyFlag = if (containsAny) size or Int.MIN_VALUE else size
}

override fun hashCode(): Int = hash
Expand Down Expand Up @@ -309,8 +322,32 @@ class AccessPath(
return node
}

private fun firstAnyNode(): AccessNode? {
if (!containsAny) return null
var node = this
while (node.accessor != ANY_ACCESSOR_IDX) {
node = node.next ?: return null
}
return node
}

fun accessorList(): List<Accessor> = toList().map { with(manager) { it.accessor } }

/** All accessors of the path except [any], consistent with [AccessTree.AccessNode.collectAccessorsTo]. */
fun allAccessors(): Set<Accessor> {
if (!containsAny) return accessorList().toSet()

val result = hashSetOf<Accessor>()
var node = this
while (true) {
val accessor = node.accessor
if (accessor != ANY_ACCESSOR_IDX) {
result.add(with(manager) { accessor.accessor })
}
node = node.next ?: return result
}
}

override fun toString(): String = accessorList().joinToString("") { it.toSuffix() }

fun addParent(accessor: AccessorIdx): AccessNode {
Expand All @@ -332,7 +369,8 @@ class AccessPath(
AccessNode(manager, accessor, this)
}

accessor == ANY_ACCESSOR_IDX -> this // todo: All accessors are not supported in tree base ap
// A path holds at most one [any]: [any].p.[any].y == [any].y
accessor == ANY_ACCESSOR_IDX -> firstAnyNode() ?: AccessNode(manager, accessor, this)

accessor == TYPE_INFO_GROUP_ACCESSOR_IDX -> AccessNode(manager, accessor, this)
accessor.isTypeInfoAccessor() -> AccessNode(manager, accessor, this)
Expand Down
Loading
Loading