aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/syntax
diff options
context:
space:
mode:
authorGravatar Dmitry Lomov <dslomov@google.com>2016-08-05 08:38:26 +0000
committerGravatar Yun Peng <pcloudy@google.com>2016-08-05 13:32:33 +0000
commitcdb6ef554397c1d3da7ee9921305f646bec5ae16 (patch)
tree23cde8c143ecf6496570bf56ace1c6f405acbd35 /src/main/java/com/google/devtools/build/lib/syntax
parent6df3e71eb05493fa421121fa73e607a6fbf458c3 (diff)
Make SkylarkClassObject "Bazel-specific".
This in preparation to DeclaredProviders implementation. -- MOS_MIGRATED_REVID=129420617
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/syntax')
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java24
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java150
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/Concatable.java36
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/EvalUtils.java6
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/MethodLibrary.java19
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkNestedSet.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java5
7 files changed, 52 insertions, 190 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
index a31b037601..131ee54772 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BinaryOperatorExpression.java
@@ -18,7 +18,7 @@ import static com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils.append
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject;
+import com.google.devtools.build.lib.syntax.Concatable.Concatter;
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.compiler.ByteCodeMethodCalls;
@@ -29,17 +29,15 @@ import com.google.devtools.build.lib.syntax.compiler.Jump;
import com.google.devtools.build.lib.syntax.compiler.Jump.PrimitiveComparison;
import com.google.devtools.build.lib.syntax.compiler.LabelAdder;
import com.google.devtools.build.lib.syntax.compiler.VariableScope;
-
-import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
-import net.bytebuddy.implementation.bytecode.Duplication;
-import net.bytebuddy.implementation.bytecode.Removal;
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.IllegalFormatException;
import java.util.List;
+import net.bytebuddy.implementation.bytecode.ByteCodeAppender;
+import net.bytebuddy.implementation.bytecode.Duplication;
+import net.bytebuddy.implementation.bytecode.Removal;
+import net.bytebuddy.implementation.bytecode.StackManipulation;
/**
* Syntax node for a binary operator expression.
@@ -338,9 +336,15 @@ public final class BinaryOperatorExpression extends Expression {
return SkylarkDict.plus((SkylarkDict<?, ?>) lval, (SkylarkDict<?, ?>) rval, env);
}
- if (lval instanceof SkylarkClassObject && rval instanceof SkylarkClassObject) {
- return SkylarkClassObject.concat(
- (SkylarkClassObject) lval, (SkylarkClassObject) rval, location);
+ if (lval instanceof Concatable && rval instanceof Concatable) {
+ Concatable lobj = (Concatable) lval;
+ Concatable robj = (Concatable) rval;
+ Concatter concatter = lobj.getConcatter();
+ if (concatter != null && concatter.equals(robj.getConcatter())) {
+ return concatter.concat(lobj, robj, location);
+ } else {
+ throw typeException(lval, rval, Operator.PLUS, location);
+ }
}
// TODO(bazel-team): Remove this case. Union of sets should use '|' instead of '+'.
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java b/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
index 79c19610e0..8ea9aa1372 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/ClassObject.java
@@ -13,21 +13,7 @@
// limitations under the License.
package com.google.devtools.build.lib.syntax;
-import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Sets.SetView;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
-import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
-import com.google.devtools.build.lib.util.Preconditions;
-
-import java.io.Serializable;
-import java.util.Map;
-
import javax.annotation.Nullable;
/**
@@ -53,140 +39,4 @@ public interface ClassObject {
* of this struct, or returns null to use the default error message.
*/
@Nullable String errorMessage(String name);
-
- /** An implementation class of ClassObject for structs created in Skylark code. */
- // TODO(bazel-team): maybe move the SkylarkModule annotation to the ClassObject interface?
- @SkylarkModule(
- name = "struct",
- category = SkylarkModuleCategory.BUILTIN,
- doc =
- "A special language element to support structs (i.e. simple value objects). "
- + "See the global <a href=\"globals.html#struct\">struct</a> function "
- + "for more details."
- )
- public class SkylarkClassObject implements ClassObject, SkylarkValue, Serializable {
- /** Error message to use when errorMessage argument is null. */
- private static final String DEFAULT_ERROR_MESSAGE = "'struct' object has no attribute '%s'";
-
- private final ImmutableMap<String, Object> values;
- private final Location creationLoc;
- private final String errorMessage;
-
- /**
- * Primarily for testing purposes where no location is available and the default
- * errorMessage suffices.
- */
- public SkylarkClassObject(Map<String, Object> values) {
- this.values = copyValues(values);
- this.creationLoc = null;
- this.errorMessage = DEFAULT_ERROR_MESSAGE;
- }
-
- /**
- * Creates a built-in struct (i.e. without creation loc). The errorMessage has to have
- * exactly one '%s' parameter to substitute the struct field name.
- */
- public SkylarkClassObject(Map<String, Object> values, String errorMessage) {
- this.values = copyValues(values);
- this.creationLoc = null;
- this.errorMessage = Preconditions.checkNotNull(errorMessage);
- }
-
- public SkylarkClassObject(Map<String, Object> values, Location creationLoc) {
- this.values = copyValues(values);
- this.creationLoc = Preconditions.checkNotNull(creationLoc);
- this.errorMessage = DEFAULT_ERROR_MESSAGE;
- }
-
- // Ensure that values are all acceptable to Skylark before to stuff them in a ClassObject
- private ImmutableMap<String, Object> copyValues(Map<String, Object> values) {
- ImmutableMap.Builder<String, Object> builder = ImmutableMap.builder();
- for (Map.Entry<String, Object> e : values.entrySet()) {
- builder.put(e.getKey(), SkylarkType.convertToSkylark(e.getValue(), null));
- }
- return builder.build();
- }
-
- @Override
- public Object getValue(String name) {
- return values.get(name);
- }
-
- /**
- * Returns a value and try to cast it into specified type
- */
- public <TYPE> TYPE getValue(String key, Class<TYPE> type) throws EvalException {
- Object obj = values.get(key);
- if (obj == null) {
- return null;
- }
- SkylarkType.checkType(obj, type, key);
- return type.cast(obj);
- }
-
- @Override
- public ImmutableCollection<String> getKeys() {
- return values.keySet();
- }
-
- public Location getCreationLoc() {
- return Preconditions.checkNotNull(creationLoc,
- "This struct was not created in a Skylark code");
- }
-
- static SkylarkClassObject concat(
- SkylarkClassObject lval, SkylarkClassObject rval, Location loc) throws EvalException {
- SetView<String> commonFields = Sets.intersection(lval.values.keySet(), rval.values.keySet());
- if (!commonFields.isEmpty()) {
- throw new EvalException(loc, "Cannot concat structs with common field(s): "
- + Joiner.on(",").join(commonFields));
- }
- return new SkylarkClassObject(ImmutableMap.<String, Object>builder()
- .putAll(lval.values).putAll(rval.values).build(), loc);
- }
-
- @Override
- public String errorMessage(String name) {
- String suffix =
- "Available attributes: "
- + Joiner.on(", ").join(Ordering.natural().sortedCopy(values.keySet()));
- return String.format(errorMessage, name) + "\n" + suffix;
- }
-
- @Override
- public boolean isImmutable() {
- for (Object item : values.values()) {
- if (!EvalUtils.isImmutable(item)) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * Convert the object to string using Skylark syntax. The output tries to be
- * reversible (but there is no guarantee, it depends on the actual values).
- */
- @Override
- public void write(Appendable buffer, char quotationMark) {
- boolean first = true;
- Printer.append(buffer, "struct(");
- // Sort by key to ensure deterministic output.
- for (String key : Ordering.natural().sortedCopy(values.keySet())) {
- if (!first) {
- Printer.append(buffer, ", ");
- }
- first = false;
- Printer.append(buffer, key);
- Printer.append(buffer, " = ");
- Printer.write(buffer, values.get(key), quotationMark);
- }
- Printer.append(buffer, ")");
- }
-
- @Override
- public String toString() {
- return Printer.repr(this);
- }
- }
}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Concatable.java b/src/main/java/com/google/devtools/build/lib/syntax/Concatable.java
new file mode 100644
index 0000000000..81f489f7bf
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Concatable.java
@@ -0,0 +1,36 @@
+// Copyright 2016 The Bazel 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.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.devtools.build.lib.syntax;
+
+import com.google.devtools.build.lib.events.Location;
+import javax.annotation.Nullable;
+
+/**
+ * Skylark values that support '+' operator should implement this interface.
+ */
+public interface Concatable {
+
+ /**
+ * Implements 'plus' operator on ClassObjects.
+ */
+ interface Concatter {
+ Concatable concat(Concatable lval, Concatable rval, Location loc) throws EvalException;
+ }
+
+ /* Returns a concatter for this {@link Concatable}.
+ * Two {@link Concatable}s can be added together if their concatters are equal.
+ */
+ @Nullable
+ Concatter getConcatter();
+}
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 4a661896b6..386a9aefeb 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
@@ -26,12 +26,10 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.compiler.ByteCodeUtils;
import com.google.devtools.build.lib.util.Preconditions;
import com.google.devtools.build.lib.vfs.PathFragment;
-
-import net.bytebuddy.implementation.bytecode.StackManipulation;
-
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import net.bytebuddy.implementation.bytecode.StackManipulation;
/**
* Utilities used by the evaluator.
@@ -280,8 +278,6 @@ public final class EvalUtils {
} else if (NestedSet.class.isAssignableFrom(c) || SkylarkNestedSet.class.isAssignableFrom(c)) {
// TODO(bazel-team): no one should be seeing naked NestedSet at all.
return "set";
- } else if (ClassObject.SkylarkClassObject.class.isAssignableFrom(c)) {
- return "struct";
} else {
if (c.getSimpleName().isEmpty()) {
return c.getName();
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 f103211379..4b39a7d1c6 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
@@ -29,11 +29,9 @@ import com.google.devtools.build.lib.skylarkinterface.Param;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
-import com.google.devtools.build.lib.syntax.ClassObject.SkylarkClassObject;
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.Type.ConversionException;
-
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
@@ -1850,21 +1848,6 @@ public class MethodLibrary {
}
};
- @SkylarkSignature(name = "struct", returnType = SkylarkClassObject.class, doc =
- "Creates an immutable struct using the keyword arguments as attributes. It is used to group "
- + "multiple values together.Example:<br>"
- + "<pre class=\"language-python\">s = struct(x = 2, y = 3)\n"
- + "return s.x + getattr(s, \"y\") # returns 5</pre>",
- extraKeywords = @Param(name = "kwargs", doc = "the struct attributes"),
- useLocation = true)
- private static final BuiltinFunction struct = new BuiltinFunction("struct") {
- @SuppressWarnings("unchecked")
- public SkylarkClassObject invoke(SkylarkDict<String, Object> kwargs, Location loc)
- throws EvalException {
- return new SkylarkClassObject(kwargs, loc);
- }
- };
-
@SkylarkSignature(
name = "set",
returnType = SkylarkNestedSet.class,
@@ -2345,7 +2328,7 @@ public class MethodLibrary {
static final List<BaseFunction> skylarkGlobalFunctions =
ImmutableList.<BaseFunction>builder()
.addAll(buildGlobalFunctions)
- .add(dir, fail, getattr, hasattr, hash, print, struct, type)
+ .add(dir, fail, getattr, hasattr, hash, print, type)
.build();
/**
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 0f8a3d31bc..2a64d7931d 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
@@ -24,13 +24,11 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
import com.google.devtools.build.lib.skylarkinterface.SkylarkModuleCategory;
import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.util.Preconditions;
-
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
-
import javax.annotation.Nullable;
/** A generic type safe NestedSet wrapper for Skylark. */
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
index f662ea13b4..e73672a93b 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkType.java
@@ -27,7 +27,6 @@ import com.google.devtools.build.lib.skylarkinterface.SkylarkValue;
import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
import com.google.devtools.build.lib.util.Preconditions;
-
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
@@ -37,7 +36,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
-
import javax.annotation.Nullable;
/**
@@ -168,9 +166,6 @@ public abstract class SkylarkType implements Serializable {
/** The BOOLEAN type, that contains TRUE and FALSE */
public static final Simple BOOL = Simple.of(Boolean.class);
- /** The STRUCT type, for all Struct's */
- public static final Simple STRUCT = Simple.of(ClassObject.SkylarkClassObject.class);
-
/** The FUNCTION type, that contains all functions, otherwise dynamically typed at call-time */
public static final SkylarkFunctionType FUNCTION = new SkylarkFunctionType("unknown", TOP);