Move global objects to Runtime

Move away global constants and global namespaces out of Environment
and into a new file Runtime.

--
MOS_MIGRATED_REVID=101940218
diff --git a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
index b05082a..12d02c6 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/ImplicitOutputsFunction.java
@@ -27,9 +27,9 @@
 import com.google.devtools.build.lib.events.Location;
 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.Label;
+import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkCallbackFunction;
 import com.google.devtools.build.lib.util.StringUtil;
 import com.google.devtools.build.lib.vfs.FileSystemUtils;
@@ -91,7 +91,7 @@
         // since we don't yet have a build configuration.
         if (!map.isConfigurable(attrName, attrType)) {
           Object value = map.get(attrName, attrType);
-          attrValues.put(attrName, value == null ? Environment.NONE : value);
+          attrValues.put(attrName, value == null ? Runtime.NONE : value);
         }
       }
       ClassObject attrs = new SkylarkClassObject(attrValues, "Attribute '%s' either doesn't exist "
diff --git a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
index 64e1fe6..b94147d 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/PackageFactory.java
@@ -35,6 +35,7 @@
 import com.google.devtools.build.lib.syntax.BaseFunction;
 import com.google.devtools.build.lib.syntax.BuildFileAST;
 import com.google.devtools.build.lib.syntax.BuiltinFunction;
+import com.google.devtools.build.lib.syntax.ClassObject;
 import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.Environment.NoSuchVariableException;
 import com.google.devtools.build.lib.syntax.EvalException;
@@ -47,6 +48,7 @@
 import com.google.devtools.build.lib.syntax.Label;
 import com.google.devtools.build.lib.syntax.MethodLibrary;
 import com.google.devtools.build.lib.syntax.ParserInputSource;
+import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
 import com.google.devtools.build.lib.syntax.SkylarkSignature;
 import com.google.devtools.build.lib.syntax.SkylarkSignature.Param;
@@ -373,6 +375,7 @@
     threadPool.allowCoreThreadTimeOut(true);
     this.environmentExtensions = ImmutableList.copyOf(environmentExtensions);
     this.packageArguments = createPackageArguments();
+    this.nativeModule = newNativeModule();
   }
 
   /**
@@ -556,7 +559,7 @@
    * seen by the parser, because the presence of "subinclude" triggers
    * preprocessing.)
    */
-  @SkylarkSignature(name = "mocksubinclude", returnType = Environment.NoneType.class,
+  @SkylarkSignature(name = "mocksubinclude", returnType = Runtime.NoneType.class,
       doc = "implement the mocksubinclude function emitted by the PythonPreprocessor",
       mandatoryPositionals = {
         @Param(name = "label", type = Object.class,
@@ -568,7 +571,7 @@
       new BuiltinFunction.Factory("mocksubinclude") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("mocksubinclude", this) {
-            public Environment.NoneType invoke(Object labelO, String pathString,
+            public Runtime.NoneType invoke(Object labelO, String pathString,
                 Location loc) throws ConversionException {
               Label label = Type.LABEL.convert(labelO, "'mocksubinclude' argument",
                   context.pkgBuilder.getBuildFileLabel());
@@ -583,7 +586,7 @@
               }
 
               context.pkgBuilder.addSubinclude(label, path);
-              return Environment.NONE;
+              return Runtime.NONE;
             }
           };
         }
@@ -604,7 +607,7 @@
    * <p>Where ":env1", "env2", ... are all environment rules declared in the same package. All
    * parameters are mandatory.
    */
-  @SkylarkSignature(name = "environment_group", returnType = Environment.NoneType.class,
+  @SkylarkSignature(name = "environment_group", returnType = Runtime.NoneType.class,
       doc = "Defines a cc_library, by wrapping around the usual library "
       + "and also defining a headers target.",
       mandatoryNamedOnly = {
@@ -620,7 +623,7 @@
       new BuiltinFunction.Factory("environment_group") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("environment_group", this) {
-            public Environment.NoneType invoke(String name, Object environmentsO, Object defaultsO,
+            public Runtime.NoneType invoke(String name, Object environmentsO, Object defaultsO,
                 Location loc) throws EvalException, ConversionException {
               List<Label> environments = Type.LABEL_LIST.convert(environmentsO,
                   "'environment_group argument'", context.pkgBuilder.getBuildFileLabel());
@@ -630,7 +633,7 @@
               try {
                 context.pkgBuilder.addEnvironmentGroup(name, environments, defaults,
                     context.eventHandler, loc);
-                return Environment.NONE;
+                return Runtime.NONE;
               } catch (Label.SyntaxException e) {
                 throw new EvalException(loc,
                     "environment group has invalid name: " + name + ": " + e.getMessage());
@@ -646,7 +649,7 @@
    * Returns a function-value implementing "exports_files" in the specified
    * package context.
    */
-  @SkylarkSignature(name = "exports_files", returnType = Environment.NoneType.class,
+  @SkylarkSignature(name = "exports_files", returnType = Runtime.NoneType.class,
       doc = "Declare a set of files as exported",
       mandatoryPositionals = {
         @Param(name = "srcs", type = HackHackEitherList.class, generic1 = String.class,
@@ -666,7 +669,7 @@
       new BuiltinFunction.Factory("exports_files") {
         public BuiltinFunction create () {
           return new BuiltinFunction("exports_files", this) {
-            public Environment.NoneType invoke(Object srcs, Object visibility, Object licenses,
+            public Runtime.NoneType invoke(Object srcs, Object visibility, Object licenses,
                 FuncallExpression ast, Environment env)
                 throws EvalException, ConversionException {
               return callExportsFiles(srcs, visibility, licenses, ast, env);
@@ -675,7 +678,7 @@
         }
       };
 
-  static Environment.NoneType callExportsFiles(Object srcs, Object visibilityO, Object licensesO,
+  static Runtime.NoneType callExportsFiles(Object srcs, Object visibilityO, Object licensesO,
       FuncallExpression ast, Environment env) throws EvalException, ConversionException {
     Package.LegacyBuilder pkgBuilder = getContext(env, ast).pkgBuilder;
     List<String> files = Type.STRING_LIST.convert(srcs, "'exports_files' operand");
@@ -720,7 +723,7 @@
         throw new EvalException(ast.getLocation(), e.getMessage());
       }
     }
-    return Environment.NONE;
+    return Runtime.NONE;
   }
 
   /**
@@ -728,7 +731,7 @@
    * context.
    * TODO(bazel-team): Remove in favor of package.licenses.
    */
-  @SkylarkSignature(name = "licenses", returnType = Environment.NoneType.class,
+  @SkylarkSignature(name = "licenses", returnType = Runtime.NoneType.class,
       doc = "Declare the license(s) for the code in the current package.",
       mandatoryPositionals = {
         @Param(name = "license_strings", type = HackHackEitherList.class, generic1 = String.class,
@@ -738,7 +741,7 @@
       new BuiltinFunction.Factory("licenses") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("licenses", this) {
-            public Environment.NoneType invoke(Object licensesO, Location loc) {
+            public Runtime.NoneType invoke(Object licensesO, Location loc) {
               try {
                 License license = Type.LICENSE.convert(licensesO, "'licenses' operand");
                 context.pkgBuilder.setDefaultLicense(license);
@@ -746,7 +749,7 @@
                 context.eventHandler.handle(Event.error(loc, e.getMessage()));
                 context.pkgBuilder.setContainsErrors();
               }
-              return Environment.NONE;
+              return Runtime.NONE;
             }
           };
         }
@@ -755,9 +758,12 @@
   /**
    * Returns a function-value implementing "distribs" in the specified package
    * context.
-   * TODO(bazel-team): Remove in favor of package.distribs.
    */
-  @SkylarkSignature(name = "distribs", returnType = Environment.NoneType.class,
+  // TODO(bazel-team): Remove in favor of package.distribs.
+  // TODO(bazel-team): Remove all these new*Function-s and/or have static functions
+  // that consult the context dynamically via getContext(env, ast) since we have that,
+  // and share the functions with the native package... which requires unifying the List types.
+  @SkylarkSignature(name = "distribs", returnType = Runtime.NoneType.class,
       doc = "Declare the distribution(s) for the code in the current package.",
       mandatoryPositionals = {
         @Param(name = "distribution_strings", type = Object.class,
@@ -767,7 +773,7 @@
       new BuiltinFunction.Factory("distribs") {
         public BuiltinFunction create(final PackageContext context) {
           return new BuiltinFunction("distribs", this) {
-            public Environment.NoneType invoke(Object object, Location loc) {
+            public Runtime.NoneType invoke(Object object, Location loc) {
               try {
                 Set<DistributionType> distribs = Type.DISTRIBUTIONS.convert(object,
                     "'distribs' operand");
@@ -776,13 +782,13 @@
                 context.eventHandler.handle(Event.error(loc, e.getMessage()));
                 context.pkgBuilder.setContainsErrors();
               }
-              return Environment.NONE;
+              return Runtime.NONE;
             }
           };
         }
       };
 
-  @SkylarkSignature(name = "package_group", returnType = Environment.NoneType.class,
+  @SkylarkSignature(name = "package_group", returnType = Runtime.NoneType.class,
       doc = "Declare a set of files as exported",
       mandatoryNamedOnly = {
         @Param(name = "name", type = String.class,
@@ -800,7 +806,7 @@
       new BuiltinFunction.Factory("package_group") {
         public BuiltinFunction create() {
           return new BuiltinFunction("package_group", this) {
-            public Environment.NoneType invoke(String name, Object packages, Object includes,
+            public Runtime.NoneType invoke(String name, Object packages, Object includes,
                 FuncallExpression ast, Environment env) throws EvalException, ConversionException {
               return callPackageFunction(name, packages, includes, ast, env);
             }
@@ -808,7 +814,7 @@
         }
       };
 
-  static Environment.NoneType callPackageFunction(String name, Object packagesO, Object includesO,
+  static Runtime.NoneType callPackageFunction(String name, Object packagesO, Object includesO,
       FuncallExpression ast, Environment env) throws EvalException, ConversionException {
     PackageContext context = getContext(env, ast);
 
@@ -820,7 +826,7 @@
     try {
       context.pkgBuilder.addPackageGroup(name, packages, includes, context.eventHandler,
           ast.getLocation());
-      return Environment.NONE;
+      return Runtime.NONE;
     } catch (Label.SyntaxException e) {
       throw new EvalException(ast.getLocation(),
           "package group has invalid name: " + name + ": " + e.getMessage());
@@ -890,7 +896,7 @@
               "at least one argument must be given to the 'package' function");
         }
 
-        return Environment.NONE;
+        return Runtime.NONE;
       }
     };
   }
@@ -937,7 +943,7 @@
       final RuleFactory ruleFactory, final String ruleClass) {
     return new BuiltinFunction(ruleClass, FunctionSignature.KWARGS, BuiltinFunction.USE_AST_ENV) {
       @SuppressWarnings("unchecked")
-      public Environment.NoneType invoke(Map<String, Object> kwargs,
+      public Runtime.NoneType invoke(Map<String, Object> kwargs,
           FuncallExpression ast, Environment env)
           throws EvalException {
         env.checkLoadingPhase(ruleClass, ast.getLocation());
@@ -946,7 +952,7 @@
         } catch (RuleFactory.InvalidRuleException | Package.NameConflictException e) {
           throw new EvalException(ast.getLocation(), e.getMessage());
         }
-        return Environment.NONE;
+        return Runtime.NONE;
       }
     };
   }
@@ -1171,23 +1177,40 @@
     }
   }
 
+  private final ClassObject nativeModule;
+
+  /** @return the Skylark struct to bind to "native" */
+  public ClassObject getNativeModule() {
+    return nativeModule;
+  }
+
   /**
-   * Returns the list of native rule functions created using the {@link RuleClassProvider}
+   * Returns a native module with the functions created using the {@link RuleClassProvider}
    * of this {@link PackageFactory}.
    */
-  public ImmutableList<BaseFunction> collectNativeRuleFunctions() {
-    ImmutableList.Builder<BaseFunction> builder = ImmutableList.builder();
+  private ClassObject newNativeModule() {
+    ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
+    for (String nativeFunction : Runtime.getFunctionNames(SkylarkNativeModule.class)) {
+      builder.put(nativeFunction, Runtime.getFunction(SkylarkNativeModule.class, nativeFunction));
+    }
     for (String ruleClass : ruleFactory.getRuleClassNames()) {
-      builder.add(newRuleFunction(ruleFactory, ruleClass));
+      builder.put(ruleClass, newRuleFunction(ruleFactory, ruleClass));
     }
-    builder.add(newPackageFunction(packageArguments));
+    builder.put("package", newPackageFunction(packageArguments));
     for (EnvironmentExtension extension : environmentExtensions) {
-      builder.addAll(extension.nativeModuleFunctions());
+      for (BaseFunction function : extension.nativeModuleFunctions()) {
+        builder.put(function.getName(), function);
+      }
     }
-    return builder.build();
+    return new ClassObject.SkylarkClassObject(builder.build(), "no native function or rule '%s'");
   }
 
   private void buildPkgEnv(Environment pkgEnv, PackageContext context, RuleFactory ruleFactory) {
+    // TODO(bazel-team): remove the naked functions that are redundant with the nativeModule,
+    // or if not possible, at least make them straight copies from the native module variant.
+    // or better, use a common Environment.Frame for these common bindings
+    // (that shares a backing ImmutableMap for the bindings?)
+    pkgEnv.update("native", nativeModule);
     pkgEnv.update("distribs", newDistribsFunction.apply(context));
     pkgEnv.update("glob", newGlobFunction.apply(context, /*async=*/false));
     pkgEnv.update("mocksubinclude", newMockSubincludeFunction.apply(context));
@@ -1269,7 +1292,7 @@
 
     pkgEnv.setImportedExtensions(imports);
     pkgEnv.updateAndPropagate(PKG_CONTEXT, context);
-    pkgEnv.updateAndPropagate(Environment.PKG_NAME, packageId.toString());
+    pkgEnv.updateAndPropagate(Runtime.PKG_NAME, packageId.toString());
 
     if (!validateAssignmentStatements(pkgEnv, buildFileAST, eventHandler)) {
       pkgBuilder.setContainsErrors();
diff --git a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
index ee1fce3..ddbda14 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/RuleClass.java
@@ -34,12 +34,12 @@
 import com.google.devtools.build.lib.packages.RuleClass.Builder.RuleClassType;
 import com.google.devtools.build.lib.syntax.Argument;
 import com.google.devtools.build.lib.syntax.BaseFunction;
-import com.google.devtools.build.lib.syntax.Environment;
 import com.google.devtools.build.lib.syntax.FragmentClassNameResolver;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.GlobList;
 import com.google.devtools.build.lib.syntax.Label;
 import com.google.devtools.build.lib.syntax.Label.SyntaxException;
+import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkEnvironment;
 import com.google.devtools.build.lib.util.StringUtil;
 import com.google.devtools.build.lib.vfs.PathFragment;
@@ -1394,7 +1394,7 @@
     for (Map.Entry<String, Object> entry : attributeValues.entrySet()) {
       String attributeName = entry.getKey();
       Object attributeValue = entry.getValue();
-      if (attributeValue == Environment.NONE) {  // Ignore all None values.
+      if (attributeValue == Runtime.NONE) {  // Ignore all None values.
         continue;
       }
       Integer attrIndex = setRuleAttributeValue(rule, eventHandler, attributeName, attributeValue);
diff --git a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
index 1f32cbd..02752f5 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/SkylarkNativeModule.java
@@ -20,6 +20,7 @@
 import com.google.devtools.build.lib.syntax.EvalException;
 import com.google.devtools.build.lib.syntax.FuncallExpression;
 import com.google.devtools.build.lib.syntax.GlobList;
+import com.google.devtools.build.lib.syntax.Runtime;
 import com.google.devtools.build.lib.syntax.SkylarkList;
 import com.google.devtools.build.lib.syntax.SkylarkModule;
 import com.google.devtools.build.lib.syntax.SkylarkSignature;
@@ -73,7 +74,7 @@
   };
 
   @SkylarkSignature(name = "package_group", objectType = SkylarkNativeModule.class,
-      returnType = Environment.NoneType.class,
+      returnType = Runtime.NoneType.class,
       doc = "This function defines a set of packages and assigns a label to the group. "
           + "The label can be referenced in <code>visibility</code> attributes.",
       mandatoryNamedOnly = {
@@ -88,7 +89,7 @@
           doc = "Other package groups that are included in this one.")},
       useAst = true, useEnvironment = true)
   private static final BuiltinFunction packageGroup = new BuiltinFunction("package_group") {
-      public Environment.NoneType invoke(String name, SkylarkList packages, SkylarkList includes,
+      public Runtime.NoneType invoke(String name, SkylarkList packages, SkylarkList includes,
                 FuncallExpression ast, Environment env) throws EvalException, ConversionException {
         env.checkLoadingPhase("native.package_group", ast.getLocation());
         return PackageFactory.callPackageFunction(name, packages, includes, ast, env);
@@ -96,7 +97,7 @@
     };
 
   @SkylarkSignature(name = "exports_files", objectType = SkylarkNativeModule.class,
-      returnType = Environment.NoneType.class,
+      returnType = Runtime.NoneType.class,
       doc = "Specifies a list of files belonging to this package that are exported to other "
           + "packages but not otherwise mentioned.",
       mandatoryPositionals = {
@@ -113,10 +114,10 @@
           doc = "Licenses to be specified.")},
       useAst = true, useEnvironment = true)
   private static final BuiltinFunction exportsFiles = new BuiltinFunction("exports_files") {
-      public Environment.NoneType invoke(SkylarkList srcs, Object visibility, Object licenses,
+      public Runtime.NoneType invoke(SkylarkList srcs, Object visibility, Object licenses,
           FuncallExpression ast, Environment env)
           throws EvalException, ConversionException {
-        env.checkLoadingPhase("native.exports_file", ast.getLocation());
+        env.checkLoadingPhase("native.exports_files", ast.getLocation());
         return PackageFactory.callExportsFiles(srcs, visibility, licenses, ast, env);
       }
     };
diff --git a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
index 4a312f7..054865f 100644
--- a/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
+++ b/src/main/java/com/google/devtools/build/lib/packages/WorkspaceFactory.java
@@ -14,7 +14,7 @@
 
 package com.google.devtools.build.lib.packages;
 
-import static com.google.devtools.build.lib.syntax.Environment.NONE;
+import static com.google.devtools.build.lib.syntax.Runtime.NONE;
 
 import com.google.devtools.build.lib.cmdline.LabelValidator;
 import com.google.devtools.build.lib.events.Event;