mirror of
https://github.com/apple/pkl.git
synced 2026-03-11 21:05:26 +01:00
Add getOrDefault method to Listing and Mapping (#1053)
This PR adds methods to Listing and Mapping that can be used to retrieve members. If the member for the index/key isn't present, it applies default to the index/key. In both cases, this is essentially sugar for getOrNull(<index/key>) ?? default.apply(<index/key>). Co-authored-by: Daniel Chao <daniel.h.chao@gmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ 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.IndirectCallNode;
|
||||
import com.oracle.truffle.api.nodes.LoopNode;
|
||||
import org.pkl.core.ast.PklNode;
|
||||
import org.pkl.core.ast.lambda.*;
|
||||
@@ -62,6 +63,20 @@ public final class ListingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class getOrDefault extends ExternalMethod1Node {
|
||||
@Child private IndirectCallNode callNode = IndirectCallNode.create();
|
||||
@Child private ApplyVmFunction1Node applyNode = ApplyVmFunction1Node.create();
|
||||
|
||||
@Specialization
|
||||
protected Object eval(VmListing self, long index) {
|
||||
if (index < 0 || index >= self.getLength()) {
|
||||
var defaultFunction = (VmFunction) VmUtils.readMember(self, Identifier.DEFAULT, callNode);
|
||||
return applyNode.execute(defaultFunction, index);
|
||||
}
|
||||
return VmUtils.readMember(self, index);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class isDistinct extends ExternalPropertyNode {
|
||||
@Specialization
|
||||
@TruffleBoundary
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright © 2024 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
* Copyright © 2024-2025 Apple Inc. and the Pkl project authors. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,6 +19,7 @@ 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.ApplyVmFunction1Node;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction2Node;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction2NodeGen;
|
||||
import org.pkl.core.ast.lambda.ApplyVmFunction3Node;
|
||||
@@ -114,6 +115,22 @@ public final class MappingNodes {
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class getOrDefault extends ExternalMethod1Node {
|
||||
@Child private IndirectCallNode callNode = IndirectCallNode.create();
|
||||
@Child private ApplyVmFunction1Node applyNode = ApplyVmFunction1Node.create();
|
||||
|
||||
@Specialization
|
||||
protected Object eval(VmMapping self, Object key) {
|
||||
var value = VmUtils.readMemberOrNull(self, key, callNode);
|
||||
if (value != null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
var defaultFunction = (VmFunction) VmUtils.readMember(self, Identifier.DEFAULT, callNode);
|
||||
return applyNode.execute(defaultFunction, key);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract static class fold extends ExternalMethod2Node {
|
||||
@Child private ApplyVmFunction3Node applyLambdaNode = ApplyVmFunction3NodeGen.create();
|
||||
|
||||
|
||||
@@ -29,3 +29,7 @@ res4 = (res3) {
|
||||
name = "Barn Owl"
|
||||
}
|
||||
}
|
||||
|
||||
res5 = (res4.getOrDefault(99)) {
|
||||
name = "Bald Eagle"
|
||||
}
|
||||
|
||||
@@ -38,3 +38,7 @@ res3: Mapping<String, Person> = new {
|
||||
age = 60
|
||||
}
|
||||
}
|
||||
|
||||
res4 = (res3.getOrDefault("Bald Eagle")) {
|
||||
age = 99
|
||||
}
|
||||
|
||||
@@ -38,3 +38,7 @@ res4 {
|
||||
age = 5
|
||||
}
|
||||
}
|
||||
res5 {
|
||||
name = "Bald Eagle"
|
||||
age = 99
|
||||
}
|
||||
|
||||
@@ -32,3 +32,7 @@ res3 {
|
||||
age = 60
|
||||
}
|
||||
}
|
||||
res4 {
|
||||
name = "Bald Eagle"
|
||||
age = 99
|
||||
}
|
||||
|
||||
@@ -1887,6 +1887,14 @@ class Listing<out Element> extends Object {
|
||||
@Since { version = "0.27.0" }
|
||||
external function getOrNull(index: Int): Element?
|
||||
|
||||
/// Returns the element at [index].
|
||||
///
|
||||
/// Returns [default] applied to [index] if [index] is outside the bounds of this listing.
|
||||
///
|
||||
/// This is equivalent to `getOrNull(index) ?? default.apply(index)`.
|
||||
@Since { version = "0.29.0" }
|
||||
external function getOrDefault(index: Int): Element
|
||||
|
||||
/// Tells if this listing has no duplicate elements.
|
||||
///
|
||||
/// Facts:
|
||||
@@ -2050,6 +2058,13 @@ class Mapping<out Key, out Value> extends Object {
|
||||
/// This is the nullable equivalent of the subscript operator (`object[key]`).
|
||||
external function getOrNull(key: Any): Value?
|
||||
|
||||
/// Returns the value associated with [key] or [default] applied to [key] if this mapping does
|
||||
/// not contain [key].
|
||||
///
|
||||
/// This is equivalent to `getOrNull(key) ?? default.apply(key)`.
|
||||
@Since { version = "0.29.0" }
|
||||
external function getOrDefault(key: Any): Value
|
||||
|
||||
/// Folds the entries of this mapping in iteration order using [operator], starting with [initial].
|
||||
external function fold<Result>(initial: Result, operator: (Result, Key, Value) -> Result): Result
|
||||
|
||||
|
||||
Reference in New Issue
Block a user