// Copyright 2019 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.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.skyframe.serialization.DeserializationContext;
import com.google.devtools.build.lib.skyframe.serialization.ObjectCodec;
import com.google.devtools.build.lib.skyframe.serialization.SerializationContext;
import com.google.devtools.build.lib.skyframe.serialization.SerializationException;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.CodedOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * A {@link Module} represents a Starlark module, a container of global variables populated by
 * executing a Starlark file. Each top-level assignment updates a global variable in the module.
 *
 * <p>Each module references its "predeclared" environment, which is often shared among many
 * modules. These are the names that are defined even at the start of execution. For example, in
 * Bazel, the predeclared environment of the module for a BUILD or .bzl file defines name values
 * such as cc_binary and glob.
 *
 * <p>The predeclared environment implicitly includes the "universal" names present in every
 * Starlark thread in every dialect, such as None, len, and str; see {@link Starlark#UNIVERSE}.
 *
 * <p>Global bindings in a Module may shadow bindings inherited from the predeclared block.
 *
 * <p>A module may carry an arbitrary piece of client data. In Bazel, for example, the client data
 * records the module's build label (such as "//dir:file.bzl").
 *
 * <p>Use {@link #create} to create a {@link Module} with no predeclared bindings other than the
 * universal ones. Use {@link #withPredeclared(StarlarkSemantics, Map)} to create a module with the
 * predeclared environment specified by the map, using the semantics to determine whether any
 * FlagGuardedValues in the map are enabled or disabled.
 */
public final class Module implements Resolver.Module {

  // The module's predeclared environment. Excludes UNIVERSE bindings.
  private ImmutableMap<String, Object> predeclared;

  // The module's global bindings, in order of creation.
  private final LinkedHashMap<String, Object> globals = new LinkedHashMap<>();

  // Names of globals that are exported and can be loaded from other modules.
  // TODO(adonovan): eliminate this field when the resolver does its job properly.
  final HashSet<String> exportedGlobals = new HashSet<>();

  // An optional piece of metadata associated with the module/file.
  // May be set after construction (too obscure to burden the constructors).
  // Its toString appears to Starlark in str(function): "<function f from ...>".
  @Nullable private Object clientData;

  private Module(ImmutableMap<String, Object> predeclared) {
    this.predeclared = predeclared;
  }

  /**
   * Constructs a Module with the specified predeclared bindings, filtered by the semantics, in
   * addition to the standard environment, {@link Starlark#UNIVERSE}.
   */
  public static Module withPredeclared(
      StarlarkSemantics semantics, Map<String, Object> predeclared) {
    return new Module(filter(predeclared, semantics));
  }

  /**
   * Creates a module with no predeclared bindings other than the standard environment, {@link
   * Starlark#UNIVERSE}.
   */
  public static Module create() {
    return new Module(/*predeclared=*/ ImmutableMap.of());
  }

  /**
   * Returns the module (file) of the innermost enclosing Starlark function on the call stack, or
   * null if none of the active calls are functions defined in Starlark.
   *
   * <p>The name of this function is intentionally horrible to make you feel bad for using it.
   */
  @Nullable
  public static Module ofInnermostEnclosingStarlarkFunction(StarlarkThread thread) {
    for (Debug.Frame fr : thread.getDebugCallStack().reverse()) {
      if (fr.getFunction() instanceof StarlarkFunction) {
        return ((StarlarkFunction) fr.getFunction()).getModule();
      }
    }
    return null;
  }

  /**
   * Returns a map in which each semantics-enabled FlagGuardedValue has been replaced by the value
   * it guards. Disabled FlagGuardedValues are left in place, and should be treated as unavailable.
   * The iteration order is unchanged.
   */
  private static ImmutableMap<String, Object> filter(
      Map<String, Object> predeclared, StarlarkSemantics semantics) {
    ImmutableMap.Builder<String, Object> filtered = ImmutableMap.builder();
    for (Map.Entry<String, Object> bind : predeclared.entrySet()) {
      Object v = bind.getValue();
      if (v instanceof FlagGuardedValue) {
        FlagGuardedValue fv = (FlagGuardedValue) bind.getValue();
        if (fv.isObjectAccessibleUsingSemantics(semantics)) {
          v = fv.getObject();
        }
      }
      filtered.put(bind.getKey(), v);
    }
    return filtered.build();
  }

  /**
   * Sets the client data (an arbitrary application-specific value) associated with the module. It
   * may be retrieved using {@link #getClientData}. Its {@code toString} form appears in the result
   * of {@code str(fn)} where {@code fn} is a StarlarkFunction: "<function f from ...>".
   */
  public void setClientData(@Nullable Object clientData) {
    this.clientData = clientData;
  }

  /**
   * Returns the client data associated with this module by a prior call to {@link #setClientData}.
   */
  @Nullable
  public Object getClientData() {
    return clientData;
  }

  /** Returns the value of a predeclared (or universal) binding in this module. */
  Object getPredeclared(String name) {
    Object v = predeclared.get(name);
    if (v != null) {
      return v;
    }
    return Starlark.UNIVERSE.get(name);
  }

  /**
   * Returns this module's additional predeclared bindings. (Excludes {@link Starlark#UNIVERSE}.)
   *
   * <p>The map reflects any semantics-based filtering of FlagGuardedValues done by {@link
   * #withPredeclared}: enabled FlagGuardedValues are replaced by their underlying value.
   */
  public ImmutableMap<String, Object> getPredeclaredBindings() {
    return predeclared;
  }

  /**
   * Returns a read-only view of this module's global bindings.
   *
   * <p>The bindings are returned in a deterministic order (for a given sequence of initial values
   * and updates).
   */
  public Map<String, Object> getGlobals() {
    return Collections.unmodifiableMap(globals);
  }

  /**
   * Returns a map of bindings that are exported (i.e. symbols declared using `=` and `def`, but not
   * `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.
  public ImmutableMap<String, Object> getExportedGlobals() {
    ImmutableMap.Builder<String, Object> result = new ImmutableMap.Builder<>();
    for (Map.Entry<String, Object> entry : globals.entrySet()) {
      if (exportedGlobals.contains(entry.getKey())) {
        result.put(entry);
      }
    }
    return result.build();
  }

  /** Implements the resolver's module interface. */
  @Override
  public Set<String> getNames() {
    // TODO(adonovan): for now, the resolver treats all predeclared/universe
    //  and global names as one bucket (Scope.PREDECLARED). Fix that.
    // 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()) {
      if (bind.getValue() instanceof FlagGuardedValue) {
        continue; // disabled
      }
      names.add(bind.getKey());
    }
    return names;
  }

  @Override
  public String getUndeclaredNameError(String name) {
    Object v = getPredeclared(name);
    return v instanceof FlagGuardedValue
        ? ((FlagGuardedValue) v).getErrorFromAttemptingAccess(name)
        : null;
  }

  /**
   * 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.
   */
  public Object getGlobal(String name) {
    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);
    globals.put(name, value);
  }

  @Override
  public String toString() {
    return String.format("<module %s>", clientData == null ? "?" : clientData);
  }

  static final class ModuleCodec implements ObjectCodec<Module> {
    @Override
    public Class<Module> getEncodedClass() {
      return Module.class;
    }

    @Override
    public MemoizationStrategy getStrategy() {
      return MemoizationStrategy.MEMOIZE_BEFORE;
    }

    @Override
    public void serialize(SerializationContext context, Module module, CodedOutputStream codedOut)
        throws SerializationException, IOException {
      context.serialize(module.predeclared, codedOut);
      context.serialize(module.globals, codedOut);
      context.serialize(module.exportedGlobals, codedOut);
      context.serialize(module.clientData, codedOut);
    }

    @Override
    public Module deserialize(DeserializationContext context, CodedInputStream codedIn)
        throws SerializationException, IOException {
      // Modules and their globals form cycles in the object graph,
      // so we must register the empty Module object before reading
      // and populating its elements.
      //
      // The MEMOIZE_BEFORE machinery seems to require that registerInitialValue
      // be called even before we deserialize the predeclared map, even though it
      // is not cyclic. This seems like a bug.
      //
      // [brandjon notes: "I'll bet it's because Deserializer#tagForMemoizedBefore is getting
      // clobbered by any deserialization that occurs between the beginning of this function call
      // and the registerInitialValue call. This bit of extra statefulness is probably to avoid
      // threading it through the serialization signature, given that it's not used in all
      // codepaths."]
      Module module = create();
      context.registerInitialValue(module);

      ImmutableMap<String, Object> predeclared = context.deserialize(codedIn);
      Map<String, Object> globals = context.deserialize(codedIn);
      Set<String> exportedGlobals = context.deserialize(codedIn);
      Object clientData = context.deserialize(codedIn);

      module.predeclared = predeclared;
      module.globals.putAll(globals);
      module.exportedGlobals.addAll(exportedGlobals);
      module.setClientData(clientData);

      return module;
    }
  }
}
