bazel syntax: add 'truth' method to base SkylarkValue interface
Also:
- rename EvalUtils.toBoolean to Starlark.truth
- make it strict about argument validity
- replace cases with method call
PiperOrigin-RevId: 278917917
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
index 3ce1002..1f1fab3 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkActionFactory.java
@@ -57,6 +57,7 @@
import com.google.devtools.build.lib.syntax.SkylarkDict;
import com.google.devtools.build.lib.syntax.SkylarkList;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -613,7 +614,7 @@
if (progressMessage != Runtime.NONE) {
builder.setProgressMessageNonLazy((String) progressMessage);
}
- if (EvalUtils.toBoolean(useDefaultShellEnv)) {
+ if (Starlark.truth(useDefaultShellEnv)) {
builder.useDefaultShellEnvironment();
}
diff --git a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
index 5196387..e758d8a 100644
--- a/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
+++ b/src/main/java/com/google/devtools/build/lib/analysis/skylark/SkylarkRuleContext.java
@@ -87,6 +87,7 @@
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkSemantics;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -1000,10 +1001,10 @@
new Runfiles.Builder(
getRuleContext().getWorkspaceName(), getConfiguration().legacyExternalRunfiles());
boolean checkConflicts = false;
- if (EvalUtils.toBoolean(collectData)) {
+ if (Starlark.truth(collectData)) {
builder.addRunfiles(getRuleContext(), RunfilesProvider.DATA_RUNFILES);
}
- if (EvalUtils.toBoolean(collectDefault)) {
+ if (Starlark.truth(collectDefault)) {
builder.addRunfiles(getRuleContext(), RunfilesProvider.DEFAULT_RUNFILES);
}
if (!files.isEmpty()) {
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
index b25522b..9174a28 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkdebug/server/ThreadHandler.java
@@ -28,6 +28,7 @@
import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.ParserInput;
import com.google.devtools.build.lib.syntax.Runtime;
+import com.google.devtools.build.lib.syntax.Starlark;
import com.google.devtools.build.lib.syntax.StarlarkThread;
import com.google.devtools.build.lib.syntax.SyntaxError;
import com.google.devtools.build.lib.vfs.PathFragment;
@@ -383,7 +384,7 @@
return true;
}
try {
- return EvalUtils.toBoolean(doEvaluate(thread, condition));
+ return Starlark.truth(doEvaluate(thread, condition));
} catch (SyntaxError | EvalException | InterruptedException e) {
throw new ConditionalBreakpointException(e.getMessage());
}
diff --git a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkValue.java b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkValue.java
index f44420c..5a48206 100644
--- a/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkValue.java
+++ b/src/main/java/com/google/devtools/build/lib/skylarkinterface/SkylarkValue.java
@@ -59,6 +59,11 @@
str(printer);
}
+ /** Returns the truth-value of this Starlark value. */
+ default boolean truth() {
+ return true;
+ }
+
/**
* Returns if the value is immutable.
*
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Eval.java b/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
index 9404440..2d6a784 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Eval.java
@@ -152,7 +152,7 @@
}
private TokenKind execIf(IfStatement node) throws EvalException, InterruptedException {
- boolean cond = EvalUtils.toBoolean(eval(thread, node.getCondition()));
+ boolean cond = Starlark.truth(eval(thread, node.getCondition()));
if (cond) {
return execStatementsInternal(node.getThenBlock());
} else if (node.getElseBlock() != null) {
@@ -422,9 +422,9 @@
// AND and OR require short-circuit evaluation.
switch (binop.getOperator()) {
case AND:
- return EvalUtils.toBoolean(x) ? eval(thread, binop.getY()) : x;
+ return Starlark.truth(x) ? eval(thread, binop.getY()) : x;
case OR:
- return EvalUtils.toBoolean(x) ? x : eval(thread, binop.getY());
+ return Starlark.truth(x) ? x : eval(thread, binop.getY());
default:
Object y = eval(thread, binop.getY());
return EvalUtils.binaryOp(binop.getOperator(), x, y, thread, binop.getLocation());
@@ -438,7 +438,7 @@
{
ConditionalExpression cond = (ConditionalExpression) expr;
Object v = eval(thread, cond.getCondition());
- return eval(thread, EvalUtils.toBoolean(v) ? cond.getThenCase() : cond.getElseCase());
+ return eval(thread, Starlark.truth(v) ? cond.getThenCase() : cond.getElseCase());
}
case DICT_EXPR:
@@ -659,7 +659,7 @@
} else {
Comprehension.If ifClause = (Comprehension.If) clause;
- if (EvalUtils.toBoolean(eval(thread, ifClause.getCondition()))) {
+ if (Starlark.truth(eval(thread, ifClause.getCondition()))) {
execClauses(index + 1);
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
index 676d0be..a533cec 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java
@@ -17,7 +17,6 @@
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.devtools.build.lib.collect.nestedset.NestedSet;
@@ -305,34 +304,6 @@
return obj;
}
- /**
- * Returns the truth value of an object, according to Python rules.
- * http://docs.python.org/2/library/stdtypes.html#truth-value-testing
- */
- // TODO(adonovan): rename 'Skylark.truth', make it a default-true method of SkylarkValue,
- // and delete most of the cases.
- public static boolean toBoolean(Object o) {
- if (o == null || o == Runtime.NONE) {
- return false;
- } else if (o instanceof Boolean) {
- return (Boolean) o;
- } else if (o instanceof String) {
- return !((String) o).isEmpty();
- } else if (o instanceof Integer) {
- return (Integer) o != 0;
- } else if (o instanceof Collection<?>) {
- return !((Collection<?>) o).isEmpty();
- } else if (o instanceof Map<?, ?>) {
- return !((Map<?, ?>) o).isEmpty();
- } else if (o instanceof SkylarkNestedSet) {
- return !((SkylarkNestedSet) o).isEmpty();
- } else if (o instanceof Iterable<?>) {
- return !Iterables.isEmpty((Iterable<?>) o);
- } else {
- return true;
- }
- }
-
public static Collection<?> toCollection(Object o, Location loc, @Nullable StarlarkThread thread)
throws EvalException {
if (o instanceof Collection) {
@@ -1056,7 +1027,7 @@
throws EvalException, InterruptedException {
switch (op) {
case NOT:
- return !toBoolean(x);
+ return !Starlark.truth(x);
case MINUS:
if (x instanceof Integer) {
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
index 6d6758c..89eb9c2 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java
@@ -155,7 +155,7 @@
Object collection, boolean value, Location loc, StarlarkThread thread) throws EvalException {
Iterable<?> iterable = EvalUtils.toIterable(collection, loc, thread);
for (Object obj : iterable) {
- if (EvalUtils.toBoolean(obj) == value) {
+ if (Starlark.truth(obj) == value) {
return true;
}
}
@@ -427,7 +427,7 @@
noneable = true)
})
public Boolean bool(Object x) throws EvalException {
- return EvalUtils.toBoolean(x);
+ return Starlark.truth(x);
}
private final ImmutableMap<String, Integer> intPrefixes =
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
index 740fcd8..6338786 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Runtime.java
@@ -65,6 +65,11 @@
}
@Override
+ public boolean truth() {
+ return false;
+ }
+
+ @Override
public void repr(SkylarkPrinter printer) {
printer.append("None");
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
index 0032149..578d926 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkList.java
@@ -50,6 +50,11 @@
/** Returns true if this list is a Skylark tuple. */
public abstract boolean isTuple();
+ @Override
+ public final boolean truth() {
+ return !isEmpty();
+ }
+
/**
* Returns an ImmutableList object with the current underlying contents of this SkylarkList.
*/
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
index b5be8f9..0c64848 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java
@@ -363,6 +363,11 @@
return set.isEmpty();
}
+ @Override
+ public boolean truth() {
+ return !set.isEmpty();
+ }
+
public SkylarkType getContentType() {
return contentType;
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Starlark.java b/src/main/java/com/google/devtools/build/lib/syntax/Starlark.java
index 5e37f8d..aa3b1fe 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Starlark.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Starlark.java
@@ -13,6 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.syntax;
+import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.util.Pair;
import java.util.Map;
import java.util.Set;
@@ -23,12 +24,30 @@
* all clients of the Starlark interpreter.
*/
// TODO(adonovan): move these here:
-// UNIVERSE, None, len, truth, str, iterate, equal, compare, getattr, index,
+// UNIVERSE, None, len, str, iterate, equal, compare, getattr, index,
// slice, parse, exec, eval, and so on.
public final class Starlark {
private Starlark() {} // uninstantiable
+ /**
+ * Returns the truth value of a valid Starlark value, as if by the Starlark expression {@code
+ * bool(x)}.
+ */
+ public static boolean truth(Object x) {
+ if (x instanceof Boolean) {
+ return (Boolean) x;
+ } else if (x instanceof SkylarkValue) {
+ return ((SkylarkValue) x).truth();
+ } else if (x instanceof String) {
+ return !((String) x).isEmpty();
+ } else if (x instanceof Integer) {
+ return (Integer) x != 0;
+ } else {
+ throw new IllegalArgumentException("invalid Starlark value: " + x.getClass());
+ }
+ }
+
// TODO(adonovan):
//
// The code below shows the API that is the destination toward which all of the recent
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
index 73e8397..789eba3 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/StarlarkMutable.java
@@ -315,6 +315,11 @@
}
@Override
+ public final boolean truth() {
+ return !isEmpty();
+ }
+
+ @Override
public Set<K> keySet() {
return Collections.unmodifiableMap(getContentsUnsafe()).keySet();
}