BEGIN_PUBLIC
starlark: delete Module.getTransitiveBindings and get
Make clients spell out what they mean instead of just
looking for key/value pairs in random places.
Starlark is a statically scoped language, after all.
END_PUBLIC
PiperOrigin-RevId: 343547890
diff --git a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
index 26cfa20..dec32c0 100644
--- a/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/skyframe/StarlarkBuiltinsFunction.java
@@ -186,7 +186,7 @@
@Nullable
private static ImmutableMap<String, Object> getDict(Module module, String dictName)
throws EvalException {
- Object value = module.get(dictName);
+ Object value = module.getGlobal(dictName);
if (value == null) {
throw Starlark.errorf("expected a '%s' dictionary to be defined", dictName);
}
diff --git a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
index a854a93..c11cce8 100644
--- a/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
+++ b/src/main/java/com/google/devtools/build/skydoc/fakebuildapi/FakeStarlarkAttrModuleApi.java
@@ -21,7 +21,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import net.starlark.java.eval.Dict;
import net.starlark.java.eval.EvalException;
import net.starlark.java.eval.Module;
@@ -270,11 +269,17 @@
* name will be set to "Unknown Provider".
*/
private static String providerName(ProviderApi provider, StarlarkThread thread) {
- Map<String, Object> bindings =
- Module.ofInnermostEnclosingStarlarkFunction(thread).getTransitiveBindings();
- for (Entry<String, Object> envEntry : bindings.entrySet()) {
- if (provider.equals(envEntry.getValue())) {
- return envEntry.getKey();
+ Module bzl = Module.ofInnermostEnclosingStarlarkFunction(thread);
+ // user-defined provider?
+ for (Map.Entry<String, Object> e : bzl.getGlobals().entrySet()) {
+ if (provider.equals(e.getValue())) {
+ return e.getKey();
+ }
+ }
+ // predeclared provider? (e.g. DefaultInfo)
+ for (Map.Entry<String, Object> e : bzl.getPredeclaredBindings().entrySet()) {
+ if (provider.equals(e.getValue())) {
+ return e.getKey();
}
}
return "Unknown Provider";
diff --git a/src/main/java/net/starlark/java/eval/Eval.java b/src/main/java/net/starlark/java/eval/Eval.java
index d650715..c4e6b70 100644
--- a/src/main/java/net/starlark/java/eval/Eval.java
+++ b/src/main/java/net/starlark/java/eval/Eval.java
@@ -642,8 +642,17 @@
result = fn(fr).getModule().getGlobal(id.getName());
break;
case PREDECLARED:
- // TODO(adonovan): call getPredeclared
- result = fn(fr).getModule().get(id.getName());
+ // TODO(adonovan): don't call getGlobal. This requires the Resolver to distinguish
+ // "predeclared" vars from "already defined module globals" instead of lumping them
+ // together via getNames. The latter odd category exists in the REPL, and
+ // in EvaluationTestCase, which calls Starlark.execFile repeatedly on the same Module.
+ // The REPL could just create a new module for each chunk, whose predeclared vars
+ // are the previous module's globals, but things may be trickier in EvaluationTestCase.
+ Module module = fn(fr).getModule();
+ result = module.getGlobal(id.getName());
+ if (result == null) {
+ result = module.getPredeclared(id.getName());
+ }
break;
default:
throw new IllegalStateException(bind.toString());
diff --git a/src/main/java/net/starlark/java/eval/Module.java b/src/main/java/net/starlark/java/eval/Module.java
index 83b0551..fd9cc560 100644
--- a/src/main/java/net/starlark/java/eval/Module.java
+++ b/src/main/java/net/starlark/java/eval/Module.java
@@ -172,7 +172,8 @@
* `load`).
*/
// TODO(adonovan): whether bindings are exported should be decided by the resolver;
- // non-exported bindings should never be added to the module. Delete this.
+ // non-exported bindings should never be added to the module. Delete this,
+ // once loads bind locally (then all globals will be exported).
public ImmutableMap<String, Object> getExportedGlobals() {
ImmutableMap.Builder<String, Object> result = new ImmutableMap.Builder<>();
for (Map.Entry<String, Object> entry : globals.entrySet()) {
@@ -191,12 +192,14 @@
// TODO(adonovan): opt: change the resolver to request names on
// demand to avoid all this set copying.
HashSet<String> names = new HashSet<>();
- for (Map.Entry<String, Object> bind : getTransitiveBindings().entrySet()) {
+ names.addAll(Starlark.UNIVERSE.keySet());
+ for (Map.Entry<String, Object> bind : getPredeclaredBindings().entrySet()) {
if (bind.getValue() instanceof FlagGuardedValue) {
continue; // disabled
}
names.add(bind.getKey());
}
+ names.addAll(globals.keySet());
return names;
}
@@ -210,20 +213,6 @@
}
/**
- * Returns a new map containing the predeclared (including universal) and global bindings of this
- * module.
- */
- // TODO(adonovan): eliminate; clients should explicitly choose getPredeclared or getGlobals.
- public Map<String, Object> getTransitiveBindings() {
- // Can't use ImmutableMap.Builder because it doesn't allow duplicates.
- LinkedHashMap<String, Object> env = new LinkedHashMap<>();
- env.putAll(Starlark.UNIVERSE);
- env.putAll(predeclared);
- env.putAll(globals);
- return env;
- }
-
- /**
* Returns the value of the specified global variable, or null if not bound. Does not look in the
* predeclared environment.
*/
@@ -231,22 +220,6 @@
return globals.get(name);
}
- /**
- * Returns the value of the named variable in the module global environment (as if by {@link
- * #getGlobal}), or if not bound there, in the predeclared environment (as if by {@link
- * #getPredeclared}, or if not bound there, null.
- */
- public Object get(String name) {
- // TODO(adonovan): delete this whole function, and getTransitiveBindings.
- // With proper resolution, the interpreter will know whether
- // to look in the module or the predeclared/universal environment.
- Object v = getGlobal(name);
- if (v != null) {
- return v;
- }
- return getPredeclared(name);
- }
-
/** Updates a global binding in the module environment. */
public void setGlobal(String name, Object value) {
Preconditions.checkNotNull(value, "Module.setGlobal(%s, null)", name);