mirror of
https://github.com/apple/pkl.git
synced 2026-04-14 12:39:44 +02:00
Add methods from List/Map to Listing/Mapping (#683)
* Add `values` to `Mapping` * Add `entries` to `Mapping` * Add `containsValue` to `Mapping` * Add `every` to `Mapping` * Add `any` to `Mapping` * Add `toDynamic` to `Mapping` * Add `lastIndex` to `Listing` * Add `getOrNull` to `Listing` * Add `first` to `Listing` * Add `firstOrNull` to `Listing` * Add `last` to `Listing` * Add `lastOrNull` to `Listing` * Add `single` to `Listing` * Add `singleOrNull` to `Listing` * Add `contains` to `Listing` * Add `any` to `Listing` * Add `every` to `Listing` * Fixup `any` to `Listing` * Revert "Add `toDynamic` to `Mapping`" This reverts commit 5551974ecd8110aa2eb8f546e992c32d3181df9b. * Revert "Add `values` to `Mapping`" This reverts commit 6fc78796 * Revert "Add `entries` to `Mapping`" This reverts commit a7e8dfc4 * Annotate new members with `Since` 0.27 * Fix documentation in `base.pkl` * Add location information to empty/single checks in `Listing` operations * Remove additional variable for laziness preservation * Apply spotless * Apply suggestions from code review Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com> --------- Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
This commit is contained in:
committed by
GitHub
parent
71db4d0fae
commit
a03827951c
@@ -15,9 +15,11 @@
|
||||
*/
|
||||
package org.pkl.core.stdlib.base;
|
||||
|
||||
import com.oracle.truffle.api.CompilerDirectives;
|
||||
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import org.pkl.core.ast.PklNode;
|
||||
import org.pkl.core.ast.lambda.*;
|
||||
import org.pkl.core.ast.member.ObjectMember;
|
||||
import org.pkl.core.runtime.*;
|
||||
@@ -44,6 +46,23 @@ public final class ListingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class lastIndex extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected long eval(VmListing self) {
|
||||
return self.getLength() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class getOrNull extends ExternalMethod1Node {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self, long index) {
|
||||
if (index < 0 || index >= self.getLength()) {
|
||||
return VmNull.withoutDefault();
|
||||
}
|
||||
return VmUtils.readMember(self, index);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class isDistinct extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
@@ -89,6 +108,58 @@ public final class ListingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class first extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
checkNonEmpty(self, this);
|
||||
return VmUtils.readMember(self, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class firstOrNull extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
if (self.isEmpty()) {
|
||||
return VmNull.withoutDefault();
|
||||
}
|
||||
return VmUtils.readMember(self, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class last extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
checkNonEmpty(self, this);
|
||||
return VmUtils.readMember(self, self.getLength() - 1L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class lastOrNull extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
var length = self.getLength();
|
||||
return length == 0 ? VmNull.withoutDefault() : VmUtils.readMember(self, length - 1L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class single extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
checkSingleton(self, this);
|
||||
return VmUtils.readMember(self, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class singleOrNull extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
protected Object eval(VmListing self) {
|
||||
if (self.getLength() != 1) {
|
||||
return VmNull.withoutDefault();
|
||||
}
|
||||
return VmUtils.readMember(self, 0L);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class distinctBy extends ExternalMethod1Node {
|
||||
@Child private ApplyVmFunction1Node applyNode = ApplyVmFunction1Node.create();
|
||||
|
||||
@@ -116,6 +187,59 @@ public final class ListingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class every extends ExternalMethod1Node {
|
||||
@Child private ApplyVmFunction1Node applyNode = ApplyVmFunction1Node.create();
|
||||
|
||||
@Specialization
|
||||
protected boolean eval(VmListing self, VmFunction predicate) {
|
||||
var result = new MutableBoolean(true);
|
||||
self.iterateMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (value == null) {
|
||||
value = VmUtils.readMember(self, key);
|
||||
}
|
||||
result.set(applyNode.executeBoolean(predicate, value));
|
||||
return result.get();
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class any extends ExternalMethod1Node {
|
||||
@Child private ApplyVmFunction1Node applyNode = ApplyVmFunction1Node.create();
|
||||
|
||||
@Specialization
|
||||
protected boolean eval(VmListing self, VmFunction predicate) {
|
||||
var result = new MutableBoolean(false);
|
||||
self.iterateMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (value == null) {
|
||||
value = VmUtils.readMember(self, key);
|
||||
}
|
||||
result.set(applyNode.executeBoolean(predicate, value));
|
||||
return !result.get();
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class contains extends ExternalMethod1Node {
|
||||
@Specialization
|
||||
protected boolean eval(VmListing self, Object element) {
|
||||
var result = new MutableBoolean(false);
|
||||
self.iterateMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (value == null) {
|
||||
value = VmUtils.readMember(self, key);
|
||||
}
|
||||
result.set(element.equals(value));
|
||||
return !result.get();
|
||||
});
|
||||
LoopNode.reportLoopCount(this, self.getLength());
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class fold extends ExternalMethod2Node {
|
||||
@Child private ApplyVmFunction2Node applyLambdaNode = ApplyVmFunction2NodeGen.create();
|
||||
|
||||
@@ -194,4 +318,24 @@ public final class ListingNodes {
|
||||
return builder.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkNonEmpty(VmListing self, PklNode node) {
|
||||
if (self.isEmpty()) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw new VmExceptionBuilder()
|
||||
.evalError("expectedNonEmptyListing")
|
||||
.withLocation(node)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSingleton(VmListing self, PklNode node) {
|
||||
if (self.getLength() != 1) {
|
||||
CompilerDirectives.transferToInterpreter();
|
||||
throw new VmExceptionBuilder()
|
||||
.evalError("expectedSingleElementListing")
|
||||
.withLocation(node)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
|
||||
import com.oracle.truffle.api.dsl.Specialization;
|
||||
import com.oracle.truffle.api.nodes.IndirectCallNode;
|
||||
import java.util.HashSet;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction2Node;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction2NodeGen;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction3Node;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction3NodeGen;
|
||||
import org.pkl.core.runtime.*;
|
||||
@@ -27,6 +29,7 @@ import org.pkl.core.stdlib.ExternalMethod1Node;
|
||||
import org.pkl.core.stdlib.ExternalMethod2Node;
|
||||
import org.pkl.core.stdlib.ExternalPropertyNode;
|
||||
import org.pkl.core.util.EconomicMaps;
|
||||
import org.pkl.core.util.MutableBoolean;
|
||||
import org.pkl.core.util.MutableLong;
|
||||
import org.pkl.core.util.MutableReference;
|
||||
|
||||
@@ -86,6 +89,22 @@ public final class MappingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class containsValue extends ExternalMethod1Node {
|
||||
@Specialization
|
||||
protected boolean eval(VmMapping self, Object value) {
|
||||
var foundValue = new MutableBoolean(false);
|
||||
self.iterateMemberValues(
|
||||
(key, member, memberValue) -> {
|
||||
if (memberValue == null) {
|
||||
memberValue = VmUtils.readMember(self, key);
|
||||
}
|
||||
foundValue.set(value.equals(memberValue));
|
||||
return !foundValue.get();
|
||||
});
|
||||
return foundValue.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class getOrNull extends ExternalMethod1Node {
|
||||
@Child private IndirectCallNode callNode = IndirectCallNode.create();
|
||||
|
||||
@@ -110,6 +129,42 @@ public final class MappingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class every extends ExternalMethod1Node {
|
||||
@Child private ApplyVmFunction2Node applyLambdaNode = ApplyVmFunction2NodeGen.create();
|
||||
|
||||
@Specialization
|
||||
protected boolean eval(VmMapping self, VmFunction function) {
|
||||
var result = new MutableBoolean(true);
|
||||
self.iterateMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (value == null) {
|
||||
value = VmUtils.readMember(self, key);
|
||||
}
|
||||
result.set(applyLambdaNode.executeBoolean(function, key, value));
|
||||
return result.get();
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class any extends ExternalMethod1Node {
|
||||
@Child private ApplyVmFunction2Node applyLambdaNode = ApplyVmFunction2NodeGen.create();
|
||||
|
||||
@Specialization
|
||||
protected boolean eval(VmMapping self, VmFunction function) {
|
||||
var result = new MutableBoolean(false);
|
||||
self.iterateMemberValues(
|
||||
(key, member, value) -> {
|
||||
if (value == null) {
|
||||
value = VmUtils.readMember(self, key);
|
||||
}
|
||||
result.set(applyLambdaNode.executeBoolean(function, key, value));
|
||||
return !result.get();
|
||||
});
|
||||
return result.get();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class toMap extends ExternalMethod0Node {
|
||||
@Specialization
|
||||
protected VmMap eval(VmMapping self) {
|
||||
|
||||
@@ -518,6 +518,12 @@ Expected a single-element collection.
|
||||
cannotFlattenCollectionWithNonCollectionElement=\
|
||||
Cannot flatten a collection containing a non-collection element.
|
||||
|
||||
expectedNonEmptyListing=\
|
||||
Expected a non-empty Listing.
|
||||
|
||||
expectedSingleElementListing=\
|
||||
Expected a single-element Listing.
|
||||
|
||||
integerOverflow=\
|
||||
Integer overflow.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user