Remove old Skylark Function hierarchy

Last step in refactoring of Skylark builtin functions.

--
MOS_MIGRATED_REVID=91796746
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/AbstractFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/AbstractFunction.java
deleted file mode 100644
index 7ed6d07..0000000
--- a/src/main/java/com/google/devtools/build/lib/syntax/AbstractFunction.java
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2014 Google Inc. 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 java.util.List;
-import java.util.Map;
-
-/**
- * Partial implementation of Function interface.
- */
-public abstract class AbstractFunction implements Function {
-
-  private final String name;
-
-  protected AbstractFunction(String name) {
-    this.name = name;
-  }
-
-  /**
-   * Returns the name of this function.
-   */
-  @Override
-  public String getName() {
-    return name;
-  }
-
-  @Override
-  public Class<?> getObjectType() {
-    return null;
-  }
-
-  @Override public String toString() {
-    return name;
-  }
-
-  /**
-   * Abstract implementation of Function that accepts no parameters.
-   */
-  public abstract static class NoArgFunction extends AbstractFunction {
-
-    public NoArgFunction(String name) {
-      super(name);
-    }
-
-    @Override
-    public Object call(List<Object> args, Map<String, Object> kwargs, FuncallExpression ast,
-        Environment env) throws EvalException, InterruptedException {
-      if (args.size() != 1 || !kwargs.isEmpty()) {
-        throw new EvalException(ast.getLocation(), "Invalid number of arguments (expected 0)");
-      }
-      return call(args.get(0), ast, env);
-    }
-
-    public abstract Object call(Object self, FuncallExpression ast, Environment env)
-        throws EvalException, InterruptedException;
-  }
-}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
index f1b148f..253e7a8 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/BaseFunction.java
@@ -58,7 +58,7 @@
 // Provide optimized argument frobbing depending of FunctionSignature and CallerSignature
 // (that FuncallExpression must supply), optimizing for the all-positional and all-keyword cases.
 // Also, use better pure maps to minimize map O(n) re-creation events when processing keyword maps.
-public abstract class BaseFunction implements Function {
+public abstract class BaseFunction {
 
   // The name of the function
   private final String name;
@@ -405,7 +405,6 @@
    * @return the value resulting from evaluating the function with the given arguments
    * @throws construction of EvalException-s containing source information.
    */
-  @Override
   public Object call(@Nullable List<Object> args,
       @Nullable Map<String, Object> kwargs,
       @Nullable FuncallExpression ast,
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
index a4a4bce..ea00506 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Environment.java
@@ -71,8 +71,8 @@
 
   protected final Map<String, Object> env = new HashMap<>();
 
-  // Functions with namespaces. Works only in the global environment.
-  protected final Map<Class<?>, Map<String, Function>> functions = new HashMap<>();
+  // BaseFunctions with namespaces. Works only in the global environment.
+  protected final Map<Class<?>, Map<String, BaseFunction>> functions = new HashMap<>();
 
   /**
    * The parent environment. For Skylark it's the global environment,
@@ -303,15 +303,15 @@
   /**
    * Registers a function with namespace to this global environment.
    */
-  public void registerFunction(Class<?> nameSpace, String name, Function function) {
+  public void registerFunction(Class<?> nameSpace, String name, BaseFunction function) {
     Preconditions.checkArgument(parent == null);
     if (!functions.containsKey(nameSpace)) {
-      functions.put(nameSpace, new HashMap<String, Function>());
+      functions.put(nameSpace, new HashMap<String, BaseFunction>());
     }
     functions.get(nameSpace).put(name, function);
   }
 
-  private Map<String, Function> getNamespaceFunctions(Class<?> nameSpace) {
+  private Map<String, BaseFunction> getNamespaceFunctions(Class<?> nameSpace) {
     if (disabledNameSpaces.contains(nameSpace)
         || (parent != null && parent.disabledNameSpaces.contains(nameSpace))) {
       return null;
@@ -326,8 +326,8 @@
   /**
    * Returns the function of the namespace of the given name or null of it does not exists.
    */
-  public Function getFunction(Class<?> nameSpace, String name) {
-    Map<String, Function> nameSpaceFunctions = getNamespaceFunctions(nameSpace);
+  public BaseFunction getFunction(Class<?> nameSpace, String name) {
+    Map<String, BaseFunction> nameSpaceFunctions = getNamespaceFunctions(nameSpace);
     return nameSpaceFunctions != null ? nameSpaceFunctions.get(name) : null;
   }
 
@@ -335,7 +335,7 @@
    * Returns the function names registered with the namespace.
    */
   public Set<String> getFunctionNames(Class<?> nameSpace) {
-    Map<String, Function> nameSpaceFunctions = getNamespaceFunctions(nameSpace);
+    Map<String, BaseFunction> nameSpaceFunctions = getNamespaceFunctions(nameSpace);
     return nameSpaceFunctions != null ? nameSpaceFunctions.keySet() : ImmutableSet.<String>of();
   }
 
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 bef2b09..ca73ea4 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
@@ -14,6 +14,7 @@
 package com.google.devtools.build.lib.syntax;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
 import com.google.common.base.Joiner;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
@@ -134,7 +135,7 @@
    *         dictionary key) according to the rules of the Build language.
    */
   public static boolean isImmutable(Object o) {
-    if (o instanceof Map<?, ?> || o instanceof Function
+    if (o instanceof Map<?, ?> || o instanceof BaseFunction
         || o instanceof FilesetEntry || o instanceof GlobList<?>) {
       return false;
     } else if (o instanceof List<?>) {
@@ -282,7 +283,7 @@
       return "glob list";
     } else if (Map.class.isAssignableFrom(c)) {
       return "dict";
-    } else if (Function.class.isAssignableFrom(c)) {
+    } else if (BaseFunction.class.isAssignableFrom(c)) {
       return "function";
     } else if (c.equals(FilesetEntry.class)) {
       return "FilesetEntry";
@@ -371,8 +372,8 @@
       }
       buffer.append(")");
 
-    } else if (o instanceof Function) {
-      Function func = (Function) o;
+    } else if (o instanceof BaseFunction) {
+      BaseFunction func = (BaseFunction) o;
       buffer.append("<function " + func.getName() + ">");
 
     } else if (o instanceof FilesetEntry) {
@@ -504,8 +505,7 @@
    * Pretty-print values of 'o' separated by the separator.
    */
   public static String prettyPrintValues(String separator, Iterable<Object> o) {
-    return Joiner.on(separator).join(Iterables.transform(o,
-        new com.google.common.base.Function<Object, String>() {
+    return Joiner.on(separator).join(Iterables.transform(o, new Function<Object, String>() {
       @Override
       public String apply(Object input) {
         return prettyPrintValue(input);
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
index f32dcdf..b996588 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/FuncallExpression.java
@@ -420,7 +420,7 @@
 
   @SuppressWarnings("unchecked")
   private void evalArguments(ImmutableList.Builder<Object> posargs, Map<String, Object> kwargs,
-      Environment env, Function function)
+      Environment env, BaseFunction function)
       throws EvalException, InterruptedException {
     ArgConversion conversion = getArgConversion(function);
     ImmutableList.Builder<String> duplicates = new ImmutableList.Builder<>();
@@ -473,7 +473,7 @@
     Map<String, Object> kwargs = new HashMap<>();
 
     Object returnValue;
-    Function function;
+    BaseFunction function;
     if (obj != null) { // obj.func(...)
       Object objValue = obj.eval(env);
       // Strings, lists and dictionaries (maps) have functions that we want to use in MethodLibrary.
@@ -513,8 +513,8 @@
       }
     } else { // func(...)
       Object funcValue = func.eval(env);
-      if ((funcValue instanceof Function)) {
-        function = (Function) funcValue;
+      if ((funcValue instanceof BaseFunction)) {
+        function = (BaseFunction) funcValue;
         evalArguments(posargs, kwargs, env, function);
         returnValue = function.call(
             posargs.build(), ImmutableMap.<String, Object>copyOf(kwargs), this, env);
@@ -534,7 +534,7 @@
     return returnValue;
   }
 
-  private ArgConversion getArgConversion(Function function) {
+  private ArgConversion getArgConversion(BaseFunction function) {
     if (function == null) {
       // It means we try to call a Java function.
       return ArgConversion.FROM_SKYLARK;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Function.java b/src/main/java/com/google/devtools/build/lib/syntax/Function.java
deleted file mode 100644
index 5636a95..0000000
--- a/src/main/java/com/google/devtools/build/lib/syntax/Function.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 Google Inc. 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 java.util.List;
-import java.util.Map;
-
-/**
- * Function values in the BUILD language.
- *
- * <p>Each implementation of this interface defines a function in the BUILD language.
- *
- */
-public interface Function {
-
-  /**
-   * Implements the behavior of a call to a function with positional arguments
-   * "args" and keyword arguments "kwargs". The "ast" argument is provided to
-   * allow construction of EvalExceptions containing source information.
-   */
-  Object call(List<Object> args,
-              Map<String, Object> kwargs,
-              FuncallExpression ast,
-              Environment env)
-      throws EvalException, InterruptedException;
-
-  /**
-   * Returns the name of the function.
-   */
-  String getName();
-
-  // TODO(bazel-team): implement this for MethodLibrary functions as well.
-  /**
-   * Returns the type of the object on which this function is defined or null
-   * if this is a global function.
-   */
-  Class<?> getObjectType();
-}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/MixedModeFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/MixedModeFunction.java
deleted file mode 100644
index 0248331..0000000
--- a/src/main/java/com/google/devtools/build/lib/syntax/MixedModeFunction.java
+++ /dev/null
@@ -1,248 +0,0 @@
-// Copyright 2014 Google Inc. 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.common.base.Joiner;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.packages.Type.ConversionException;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-/**
- * Abstract implementation of Function for functions that accept a mixture of
- * positional and keyword parameters, as in Python.
- */
-public abstract class MixedModeFunction extends AbstractFunction {
-
-  // Nomenclature:
-  // "Parameters" are formal parameters of a function definition.
-  // "Arguments" are actual parameters supplied at the call site.
-
-  // A function signature, including defaults and types
-  // never null after it is configured
-  protected FunctionSignature.WithValues<Object, SkylarkType> signature;
-
-  // Number of regular named parameters (excluding *p and **p) in the
-  // equivalent Python function definition).
-  private final List<String> parameters;
-
-  // Number of leading "parameters" which are mandatory
-  private final int numMandatoryParameters;
-
-  // True if this function requires all arguments to be named
-  // TODO(bazel-team): replace this by a count of arguments before the * with optional arg,
-  // in the style Python 3 or PEP 3102.
-  private final boolean onlyNamedArguments;
-
-  // Location of the function definition, or null for builtin functions.
-  protected final Location location;
-
-  /**
-   * Constructs an instance of Function that supports Python-style mixed-mode
-   * parameter passing.
-   *
-   * @param parameters a list of named parameters
-   * @param numMandatoryParameters the number of leading parameters which are
-   *        considered mandatory; the remaining ones may be omitted, in which
-   *        case they will have the default value of null.
-   */
-  public MixedModeFunction(String name,
-                           Iterable<String> parameters,
-                           int numMandatoryParameters,
-                           boolean onlyNamedArguments) {
-    this(name, parameters, numMandatoryParameters, onlyNamedArguments, null);
-  }
-
-  protected MixedModeFunction(String name,
-                              Iterable<String> parameters,
-                              int numMandatoryParameters,
-                              boolean onlyNamedArguments,
-                              Location location) {
-    super(name);
-    this.parameters = ImmutableList.copyOf(parameters);
-    this.numMandatoryParameters = numMandatoryParameters;
-    this.onlyNamedArguments = onlyNamedArguments;
-    this.location = location;
-
-    // Fake a signature from the above
-    this.signature = FunctionSignature.WithValues.<Object, SkylarkType>create(
-        FunctionSignature.of(numMandatoryParameters, this.parameters.toArray(new String[0])));
-  }
-
-
-  /** Create a function using a signature with defaults */
-  public MixedModeFunction(String name,
-      FunctionSignature.WithValues<Object, SkylarkType> signature,
-      Location location) {
-    super(name);
-
-    // TODO(bazel-team): lift the following limitations, by actually implementing
-    // the full function call protocol.
-    FunctionSignature sig = signature.getSignature();
-    FunctionSignature.Shape shape = sig.getShape();
-    Preconditions.checkArgument(!shape.hasKwArg() && !shape.hasStarArg()
-        && shape.getNamedOnly() == 0, "no star, star-star or named-only parameters (for now)");
-
-    this.signature = signature;
-    this.parameters = ImmutableList.copyOf(sig.getNames());
-    this.numMandatoryParameters = shape.getMandatoryPositionals();
-    this.onlyNamedArguments = false;
-    this.location = location;
-  }
-
-  /** Create a function using a signature without defaults */
-  public MixedModeFunction(String name, FunctionSignature signature) {
-    this(name, FunctionSignature.WithValues.<Object, SkylarkType>create(signature), null);
-  }
-
-  // TODO(bazel-team): find a home for this function, maybe a better implementation.
-  private static <E> ArrayList<E> listDifference (List<E> plus, List<E> minus) {
-    final ArrayList<E> list = new ArrayList<>();
-    list.addAll(plus);
-    list.removeAll(minus);
-    return list;
-  }
-
-  @Override
-  public Object call(List<Object> args,
-                     Map<String, Object> kwargs,
-                     FuncallExpression ast,
-                     Environment env)
-      throws EvalException, InterruptedException {
-
-    // ast is null when called from Java (as there's no Skylark call site).
-    Location loc = ast == null ? location : ast.getLocation();
-    if (onlyNamedArguments && !args.isEmpty()) {
-      throw new EvalException(loc,
-          getSignature() + " does not accept positional arguments");
-    }
-
-    if (kwargs == null) {
-      kwargs = ImmutableMap.<String, Object>of();
-    }
-
-    int numParams = parameters.size();
-    int numArgs = args.size();
-    Object[] namedArguments = new Object[numParams];
-
-    // first, positional arguments:
-    if (numArgs > numParams) {
-      throw new EvalException(loc,
-          "too many positional arguments in call to " + getSignature());
-    }
-    for (int ii = 0; ii < numArgs; ++ii) {
-      namedArguments[ii] = args.get(ii);
-    }
-
-    // TODO(bazel-team): here, support *varargs splicing
-
-    // second, keyword arguments:
-    for (Map.Entry<String, Object> entry : kwargs.entrySet()) {
-      String keyword = entry.getKey();
-      int pos = parameters.indexOf(keyword);
-      if (pos == -1) {
-        List<String> unexpected =
-            listDifference(new ArrayList<>(kwargs.keySet()), parameters);
-        Collections.sort(unexpected); // issue stable error messages.
-        throw new EvalException(loc,
-            "unexpected keyword" + (unexpected.size() > 1 ? "s" : "") + " '"
-            + Joiner.on("', '").join(unexpected)
-            + "' in call to " + getSignature());
-      } else {
-        if (namedArguments[pos] != null) {
-          throw new EvalException(loc, getSignature()
-              + " got multiple values for keyword argument '" + keyword + "'");
-        }
-        namedArguments[pos] = kwargs.get(keyword);
-      }
-    }
-
-    // third, check mandatory parameters:
-    for (int ii = 0; ii < numMandatoryParameters; ++ii) {
-      if (namedArguments[ii] == null) {
-        throw new EvalException(loc,
-            getSignature() + " received insufficient arguments");
-      }
-    }
-
-    // fourth, fill in defaults from the signature, if any
-    List<Object> defaults = signature.getDefaultValues();
-    if (defaults != null) {
-      int jj = 0;
-      for (int ii = numMandatoryParameters; ii < numParams; ++ii) {
-        if (namedArguments[ii] == null) {
-          namedArguments[ii] = defaults.get(jj);
-        }
-        jj++;
-      }
-    }
-
-    try {
-      return call(namedArguments, ast, env);
-    } catch (ConversionException | IllegalArgumentException | IllegalStateException
-        | ClassCastException e) {
-      throw new EvalException(loc, e.getMessage());
-    }
-  }
-
-  /**
-   * Like Function.call, but generalised to support Python-style mixed-mode
-   * keyword and positional parameter passing.
-   *
-   * @param args an array of argument values corresponding to the list
-   *        of named parameters passed to the constructor.
-   */
-  protected Object call(Object[] args, FuncallExpression ast)
-      throws EvalException, ConversionException, InterruptedException {
-    throw new UnsupportedOperationException("Method not overridden");
-  }
-
-  /**
-   * Override this method instead of the one above, if you need to access
-   * the environment.
-   */
-  protected Object call(Object[] args, FuncallExpression ast, Environment env)
-      throws EvalException, ConversionException, InterruptedException {
-    return call(args, ast);
-  }
-
-  /**
-   * Render this object in the form of an equivalent Python function signature.
-   */
-  public String getSignature() {
-    StringBuilder sb = new StringBuilder();
-    sb.append(getName()).append('(');
-    int ii = 0;
-    int len = parameters.size();
-    for (; ii < len; ++ii) {
-      String parameter = parameters.get(ii);
-      if (ii > 0) {
-        sb.append(", ");
-      }
-      sb.append(parameter);
-      if (ii >= numMandatoryParameters) {
-        sb.append(" = null");
-      }
-    }
-    sb.append(')');
-    return sb.toString();
-  }
-
-}
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkCallbackFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkCallbackFunction.java
index bff06d5..94b1917 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkCallbackFunction.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkCallbackFunction.java
@@ -20,11 +20,11 @@
  */
 public class SkylarkCallbackFunction {
 
-  private final Function callback;
+  private final BaseFunction callback;
   private final FuncallExpression ast;
   private final SkylarkEnvironment funcallEnv;
 
-  public SkylarkCallbackFunction(Function callback, FuncallExpression ast,
+  public SkylarkCallbackFunction(BaseFunction callback, FuncallExpression ast,
       SkylarkEnvironment funcallEnv) {
     this.callback = callback;
     this.ast = ast;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
index 11e3522..087bdc4 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkEnvironment.java
@@ -123,7 +123,7 @@
     for (Entry<String, Object> entry : env.entrySet()) {
       newEnv.env.put(entry.getKey(), entry.getValue());
     }
-    for (Map.Entry<Class<?>, Map<String, Function>> functionMap : functions.entrySet()) {
+    for (Map.Entry<Class<?>, Map<String, BaseFunction>> functionMap : functions.entrySet()) {
       newEnv.functions.put(functionMap.getKey(), functionMap.getValue());
     }
     return newEnv;
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkFunction.java b/src/main/java/com/google/devtools/build/lib/syntax/SkylarkFunction.java
deleted file mode 100644
index c90a4ef..0000000
--- a/src/main/java/com/google/devtools/build/lib/syntax/SkylarkFunction.java
+++ /dev/null
@@ -1,254 +0,0 @@
-// Copyright 2014 Google Inc. 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.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.devtools.build.lib.events.Location;
-import com.google.devtools.build.lib.packages.Type.ConversionException;
-import com.google.devtools.build.lib.syntax.EvalException.EvalExceptionWithJavaCause;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.concurrent.ExecutionException;
-
-/**
- * A function class for Skylark built in functions. Supports mandatory and optional arguments.
- * All usable arguments have to be specified. In case of ambiguous arguments (a parameter is
- * specified as positional and keyword arguments in the function call) an exception is thrown.
- */
-public abstract class SkylarkFunction extends BaseFunction {
-
-  private ImmutableList<String> parameters;
-  private ImmutableMap<String, SkylarkSignature.Param> parameterTypes;
-  private int mandatoryParamNum;
-  private boolean configured = false;
-  private Class<?> objectType;
-  private boolean onlyLoadingPhase;
-
-  /**
-   * Creates a SkylarkFunction with the given name.
-   */
-  public SkylarkFunction(String name) {
-    super(name);
-  }
-
-  /**
-   * Configures the parameter of this Skylark function using the annotation.
-   */
-  public void configure(SkylarkSignature annotation) {
-    Preconditions.checkState(!configured);
-    Preconditions.checkArgument(
-        getName().equals(annotation.name()), "%s != %s", getName(), annotation.name());
-    Preconditions.checkArgument(
-        annotation.optionalPositionals().length == 0 || annotation.mandatoryNamedOnly().length == 0,
-        "SkylarkFunction %s: forbidden simultaneous optionalPositionals and mandatoryNamedOnly",
-        getName());
-    Preconditions.checkArgument(
-        annotation.extraPositionals().length == 0 && annotation.extraKeywords().length == 0,
-        "SkylarkFunction %s: forbidden extra arguments", getName());
-    mandatoryParamNum = 0;
-    ImmutableList.Builder<String> paramListBuilder = ImmutableList.builder();
-    ImmutableMap.Builder<String, SkylarkSignature.Param> paramTypeBuilder = ImmutableMap.builder();
-    for (SkylarkSignature.Param param : annotation.mandatoryPositionals()) {
-      if (!param.name().equals("self")) {
-        paramListBuilder.add(param.name());
-        paramTypeBuilder.put(param.name(), param);
-        mandatoryParamNum++;
-      }
-    }
-    for (SkylarkSignature.Param param : annotation.optionalPositionals()) {
-      paramListBuilder.add(param.name());
-      paramTypeBuilder.put(param.name(), param);
-    }
-    for (SkylarkSignature.Param param : annotation.mandatoryNamedOnly()) {
-      paramListBuilder.add(param.name());
-      paramTypeBuilder.put(param.name(), param);
-      mandatoryParamNum++;
-    }
-    for (SkylarkSignature.Param param : annotation.optionalNamedOnly()) {
-      paramListBuilder.add(param.name());
-      paramTypeBuilder.put(param.name(), param);
-    }
-    parameters = paramListBuilder.build();
-    parameterTypes = paramTypeBuilder.build();
-    this.objectType = annotation.objectType().equals(Object.class) ? null : annotation.objectType();
-    this.onlyLoadingPhase = annotation.onlyLoadingPhase();
-    configured = true;
-  }
-
-  /**
-   * Returns true if the SkylarkFunction is configured.
-   */
-  public boolean isConfigured() {
-    return configured;
-  }
-
-  @Override
-  public Class<?> getObjectType() {
-    return objectType;
-  }
-
-  public boolean isOnlyLoadingPhase() {
-    return onlyLoadingPhase;
-  }
-
-  @Override
-  public Object call(List<Object> args,
-                     Map<String, Object> kwargs,
-                     FuncallExpression ast,
-                     Environment env)
-      throws EvalException, InterruptedException {
-    Preconditions.checkState(configured, "Function %s was not configured", getName());
-    try {
-      ImmutableMap.Builder<String, Object> arguments = new ImmutableMap.Builder<>();
-      if (objectType != null && !FuncallExpression.isNamespace(objectType)) {
-        args = new ArrayList<>(args); // args immutable, get a mutable copy.
-        arguments.put("self", args.remove(0));
-      }
-
-      int maxParamNum = parameters.size();
-      int paramNum = args.size() + kwargs.size();
-
-      if (paramNum < mandatoryParamNum) {
-        throw new EvalException(ast.getLocation(),
-            String.format("incorrect number of arguments (got %s, expected at least %s)",
-                paramNum, mandatoryParamNum));
-      } else if (paramNum > maxParamNum) {
-        throw new EvalException(ast.getLocation(),
-            String.format("incorrect number of arguments (got %s, expected at most %s)",
-                paramNum, maxParamNum));
-      }
-
-      for (int i = 0; i < mandatoryParamNum; i++) {
-        Preconditions.checkState(i < args.size() || kwargs.containsKey(parameters.get(i)),
-            String.format("missing mandatory parameter: %s", parameters.get(i)));
-      }
-
-      for (int i = 0; i < args.size(); i++) {
-        checkTypeAndAddArg(parameters.get(i), args.get(i), arguments, ast.getLocation());
-      }
-
-      for (Entry<String, Object> kwarg : kwargs.entrySet()) {
-        int idx = parameters.indexOf(kwarg.getKey());
-        if (idx < 0) {
-          throw new EvalException(ast.getLocation(),
-              String.format("unknown keyword argument: %s", kwarg.getKey()));
-        }
-        if (idx < args.size()) {
-          throw new EvalException(ast.getLocation(),
-              String.format("ambiguous argument: %s", kwarg.getKey()));
-        }
-        checkTypeAndAddArg(kwarg.getKey(), kwarg.getValue(), arguments, ast.getLocation());
-      }
-
-      return call(arguments.build(), ast, env);
-    } catch (ConversionException | IllegalArgumentException | IllegalStateException
-        | ClassCastException | ClassNotFoundException | ExecutionException e) {
-      if (e.getMessage() != null) {
-        throw new EvalException(ast.getLocation(), e.getMessage());
-      } else {
-        // TODO(bazel-team): ideally this shouldn't happen, however we need this for debugging
-        throw new EvalExceptionWithJavaCause(ast.getLocation(), e);
-      }
-    }
-  }
-
-  private void checkTypeAndAddArg(String paramName, Object value,
-      ImmutableMap.Builder<String, Object> arguments, Location loc) throws EvalException {
-    SkylarkSignature.Param param = parameterTypes.get(paramName);
-    if (param.callbackEnabled() && value instanceof Function) {
-      // If we pass a function as an argument we trust the Function implementation with the type
-      // check. It's OK since the function needs to be called manually anyway.
-      arguments.put(paramName, value);
-      return;
-    }
-    checkType(getName(), paramName, SkylarkType.of(param.type(), param.generic1()),
-        value, loc, param.doc());
-    arguments.put(paramName, value);
-  }
-
-  public static void checkType(String functionName, String paramName,
-      SkylarkType type, Object value, Location loc, String paramDoc) throws EvalException {
-    if (type != null && value != null) { // TODO(bazel-team): should we give a pass to NONE here?
-      if (!type.contains(value)) {
-        throw new EvalException(loc, String.format(
-            "expected %s for '%s' while calling %s but got %s instead: %s",
-            type, paramName, functionName, EvalUtils.getDataTypeName(value, true), value));
-      }
-    }
-  }
-
-  /**
-   * The actual function call. All positional and keyword arguments are put in the
-   * arguments map.
-   */
-  protected abstract Object call(
-      Map<String, Object> arguments, FuncallExpression ast, Environment env) throws EvalException,
-      ConversionException,
-      IllegalArgumentException,
-      IllegalStateException,
-      InterruptedException,
-      ClassCastException,
-      ClassNotFoundException,
-      ExecutionException;
-
-  /**
-   * An intermediate class to provide a simpler interface for Skylark functions.
-   */
-  public abstract static class SimpleSkylarkFunction extends SkylarkFunction {
-
-    public SimpleSkylarkFunction(String name) {
-      super(name);
-    }
-
-    @Override
-    protected final Object call(
-        Map<String, Object> arguments, FuncallExpression ast, Environment env) throws EvalException,
-        ConversionException,
-        IllegalArgumentException,
-        IllegalStateException,
-        ClassCastException,
-        ExecutionException {
-      return call(arguments, ast.getLocation());
-    }
-
-    /**
-     * The actual function call. All positional and keyword arguments are put in the
-     * arguments map.
-     */
-    protected abstract Object call(Map<String, Object> arguments, Location loc)
-        throws EvalException,
-        ConversionException,
-        IllegalArgumentException,
-        IllegalStateException,
-        ClassCastException,
-        ExecutionException;
-  }
-
-  // TODO(bazel-team): this is only used in MixedModeFunctions in MethodLibrary, migrate those
-  // to SkylarkFunction then remove this.
-  public static <TYPE> TYPE cast(Object elem, Class<TYPE> type, String what, Location loc)
-      throws EvalException {
-    try {
-      return type.cast(elem);
-    } catch (ClassCastException e) {
-      throw new EvalException(loc, String.format("expected %s for '%s' but got %s instead",
-          EvalUtils.getDataTypeNameFromClass(type), what, EvalUtils.getDataTypeName(elem)));
-    }
-  }
-}
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 f07fd61..b6c3767 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
@@ -492,7 +492,7 @@
       return LIST;
     } else if (SkylarkNestedSet.class.isAssignableFrom(type)) {
       return SET;
-    } else if (Function.class.isAssignableFrom(type)) {
+    } else if (BaseFunction.class.isAssignableFrom(type)) {
       return new SkylarkFunctionType("unknown", TOP);
     } else {
       return Simple.of(type);
@@ -533,7 +533,7 @@
       }
     }
     @Override public Class<?> getType() {
-      return Function.class;
+      return BaseFunction.class;
     }
     @Override public String toString() {
       return (returnType == TOP || returnType == null ? "" : returnType + "-returning ")
@@ -542,7 +542,7 @@
 
     public boolean contains(Object value) {
       // This returns true a bit too much, not looking at the result type.
-      return value instanceof Function;
+      return value instanceof BaseFunction;
     }
 
     public static SkylarkFunctionType of(String name) {
@@ -839,7 +839,7 @@
    * Creates a SkylarkType from the SkylarkSignature annotation.
    */
   public static SkylarkType getReturnType(SkylarkSignature annotation) {
-    if (Function.class.isAssignableFrom(annotation.returnType())) {
+    if (BaseFunction.class.isAssignableFrom(annotation.returnType())) {
       return SkylarkFunctionType.of(annotation.name());
     } else {
       return Simple.of(annotation.returnType());