Skip to content

Commit

Permalink
Work Ancestry out of force
Browse files Browse the repository at this point in the history
  • Loading branch information
holzensp committed Sep 24, 2024
1 parent 157031d commit 2ea92db
Showing 1 changed file with 19 additions and 72 deletions.
91 changes: 19 additions & 72 deletions pkl-core/src/main/java/org/pkl/core/runtime/VmObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -239,28 +239,39 @@ public final void force(boolean allowUndefinedValues, boolean recurse) {

if (recurse) forced = true;

var ancestry = Ancestry.startingFromLeaf(this);
var deletedKeys = new HashMap<Object, Integer>();
var deletedIndices = new ArrayDeque<SortedSet<Long>>();

try {
while (ancestry.toParent()) {
var owner = ancestry.current();
for (var owner = this; owner != null; owner = owner.getParent()) {

var indicesDeletedHere = owner.getDeletedIndices();
if (indicesDeletedHere != null) {
deletedIndices.push(indicesDeletedHere);
}
var keysDeletedHere = owner.getDeletedKeys();
for (var key : keysDeletedHere == null ? Collections.EMPTY_LIST : keysDeletedHere) {
deletedKeys.compute(key, (k, v) -> v == null ? 1 : v + 1);
}

var cursor = owner.members.getEntries();
var clazz = owner.getVmClass();
while (cursor.advance()) {
var memberKey = ancestry.toReferenceKey(cursor.getKey());
var referenceKey = toReferenceKey(cursor.getKey(), deletedKeys, deletedIndices);
var member = cursor.getValue();

// isAbstract() can occur when VmAbstractObject.toString() is called
// on a prototype of an abstract class (e.g., in the Java debugger)
if (memberKey == null
if (referenceKey == null
|| member.isLocalOrExternalOrAbstractOrDelete()
|| clazz.isHiddenProperty(memberKey)) {
|| clazz.isHiddenProperty(referenceKey)) {
continue;
}

var memberValue = getCachedValue(memberKey);
var memberValue = getCachedValue(referenceKey);
if (memberValue == null) {
try {
memberValue = VmUtils.doReadMember(this, owner, memberKey, member);
memberValue = VmUtils.doReadMember(this, owner, referenceKey, member);
} catch (VmUndefinedValueException e) {
if (!allowUndefinedValues) throw e;
continue;
Expand Down Expand Up @@ -338,68 +349,4 @@ private static EconomicMap<Object, Object> extractDeletions(
}
return cachedValues;
}

private static class Ancestry {
private final ArrayList<VmObject> ancests;
private int ptr;
private final HashMap<Object, Integer> deletedKeys;

private Ancestry(ArrayList<VmObject> ancestry, int ptr, HashMap<Object, Integer> deletedKeys) {
this.ancests = ancestry;
this.ptr = ptr;
this.deletedKeys = deletedKeys;
}

public static Ancestry startingFromLeaf(VmObject child) {
var anc = new ArrayList<VmObject>();
for (var owner = child; owner != null; owner = owner.getParent()) {
anc.add(owner);
}
return new Ancestry(anc, -1, new HashMap<>());
}

public boolean toParent() {
if (ptr == ancests.size() - 1) {
return false;
}
ptr++;
var current = ancests.get(ptr);
var keysDeletedHere = current.getDeletedKeys();
if (keysDeletedHere != null) {
for (var key : keysDeletedHere) {
deletedKeys.compute(key, (k, v) -> v == null ? 1 : v + 1);
}
}

return true;
}

public @Nullable Object toReferenceKey(Object definitionKey) {
if (deletedKeys.containsKey(definitionKey)) {
return null;
}

// TODO: Check whether element or entry; Long isn't enough to tell
if (!(definitionKey instanceof Long index)) {
return definitionKey;
}

// TODO: Consider building a _compact_ deletion queue
for (var i = ptr; i >= 0; i--) {
var indicesDeletedHere = ancests.get(i).getDeletedIndices();
if (indicesDeletedHere != null) {
if (indicesDeletedHere.contains(index)) {
return null;
}
index -= indicesDeletedHere.subSet(0L, index).size();
}
}

return index;
}

public VmObject current() {
return ancests.get(ptr);
}
}
}

0 comments on commit 2ea92db

Please sign in to comment.