aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
diff options
context:
space:
mode:
authorGravatar Francois-Rene Rideau <tunes@google.com>2015-02-27 15:20:29 +0000
committerGravatar Han-Wen Nienhuys <hanwen@google.com>2015-03-04 15:39:03 +0000
commit22513330de1212d05c2342d4290a057b214a9b96 (patch)
treeaec87019f248547e996826f542aca5df14ab31c6 /src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
parent72ca13d9c90f2c40ffe0c82e24d2f99289f851ce (diff)
Add Union, contains() to SkylarkType
Refactor SkylarkType, notably adding Union types and runtime typechecks. These are pre-requisites to unifying all Skylark function calls to use the same code path, that will check types (like SkylarkFunction currently does) as well handle a more complete Python calling convention (like MixedModeFunction is almost but not quite able to do). A SkylarkType can be either * a Simple type corresponding to a Java class, with special types TOP and BOTTOM corresponding respectively to Object and EmptyType (similar to Void). * a Combination of a generic class (LIST, MAP or SET) and an argument type * a Union of a finite number of types * a FunctionType associated with a name and a returnType (with ugly validation-time side-effects that we should probably move out of the type) Unions are necessary because: 1- the type of some builtin function arguments are actually the Union of some type and a function type for a callback that computes the actual value. 2- the type of some builtin function arguments declared as "List" is actually the Union of java List and SkylarkList. 3- instead of adding lots of special cases at the point of argument validation, it's cleaner and more generally useful to have explicit Union types, that can then be displayed to users for documentation or debugging purposes. Validation-time "type inference" is re-expressed simply as type intersection. None is treated specially as inferred into TOP instead of NoneType. Combination types are printed as genericType of argTypes, e.g. "dict of ints". "type" and "generic1" become "genericType" and "argType". In SkylarkList and SkylarkNestedSet, genericType becomes contentType. -- MOS_MIGRATED_REVID=87340881
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java27
1 files changed, 17 insertions, 10 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
index 489621122f..f848f91c2e 100644
--- a/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
+++ b/src/main/java/com/google/devtools/build/lib/rules/SkylarkRuleConfiguredTargetBuilder.java
@@ -33,10 +33,11 @@ import com.google.devtools.build.lib.syntax.ClassObject;
import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject;
import com.google.devtools.build.lib.syntax.Environment;
import com.google.devtools.build.lib.syntax.EvalException;
+import com.google.devtools.build.lib.syntax.EvalUtils;
import com.google.devtools.build.lib.syntax.Function;
import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
-import com.google.devtools.build.lib.syntax.SkylarkFunction;
import com.google.devtools.build.lib.syntax.SkylarkNestedSet;
+import com.google.devtools.build.lib.syntax.SkylarkType;
/**
* A helper class to build Rule Configured Targets via runtime loaded rule implementations
@@ -138,7 +139,7 @@ public final class SkylarkRuleConfiguredTargetBuilder {
private static ConfiguredTarget addStructFields(RuleContext ruleContext,
RuleConfiguredTargetBuilder builder, Object target, Artifact executable)
- throws EvalException {
+ throws EvalException {
Location loc = null;
Runfiles statelessRunfiles = null;
Runfiles dataRunfiles = null;
@@ -152,7 +153,7 @@ public final class SkylarkRuleConfiguredTargetBuilder {
builder.setFilesToBuild(cast("files", struct, SkylarkNestedSet.class, Artifact.class, loc)
.getSet(Artifact.class));
} else if (key.equals("runfiles")) {
- statelessRunfiles = cast("runfiles", struct, Runfiles.class, loc);
+ statelessRunfiles = cast("runfiles", struct, Runfiles.class, loc);
} else if (key.equals("data_runfiles")) {
dataRunfiles = cast("data_runfiles", struct, Runfiles.class, loc);
} else if (key.equals("default_runfiles")) {
@@ -201,16 +202,22 @@ public final class SkylarkRuleConfiguredTargetBuilder {
}
}
- private static <T> T cast(String paramName, ClassObject struct, Class<T> expectedType,
- Location loc) throws EvalException {
- return cast(paramName, struct, expectedType, Object.class, loc);
+ private static <T> T cast(String paramName, ClassObject struct, Class<T> expectedGenericType,
+ Class<?> expectedArgumentType, Location loc) throws EvalException {
+ Object value = struct.getValue(paramName);
+ return SkylarkType.cast(value, expectedGenericType, expectedArgumentType, loc,
+ "expected %s for '%s' but got %s instead: %s",
+ SkylarkType.of(expectedGenericType, expectedArgumentType),
+ paramName, EvalUtils.getDataTypeName(value, true), value);
}
private static <T> T cast(String paramName, ClassObject struct, Class<T> expectedType,
- Class<?> expectedGenericType, Location loc) throws EvalException {
- return SkylarkFunction.cast("rule_implementation.return", paramName,
- expectedType, expectedGenericType, struct.getValue(paramName), loc,
- "'" + paramName + "' field of the struct returned by the rule implementation function");
+ Location loc) throws EvalException {
+ Object value = struct.getValue(paramName);
+ return SkylarkType.cast(value, expectedType, loc,
+ "expected %s for '%s' but got %s instead: %s",
+ SkylarkType.of(expectedType),
+ paramName, EvalUtils.getDataTypeName(value, false), value);
}
private static Runfiles merge(Runfiles runfiles, Artifact executable) {