// Copyright 2017 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 net.starlark.java.eval;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import net.starlark.java.spelling.SpellChecker;
import net.starlark.java.syntax.Argument;
import net.starlark.java.syntax.AssignmentStatement;
import net.starlark.java.syntax.BinaryOperatorExpression;
import net.starlark.java.syntax.CallExpression;
import net.starlark.java.syntax.Comprehension;
import net.starlark.java.syntax.ConditionalExpression;
import net.starlark.java.syntax.DefStatement;
import net.starlark.java.syntax.DictExpression;
import net.starlark.java.syntax.DotExpression;
import net.starlark.java.syntax.Expression;
import net.starlark.java.syntax.ExpressionStatement;
import net.starlark.java.syntax.FloatLiteral;
import net.starlark.java.syntax.FlowStatement;
import net.starlark.java.syntax.ForStatement;
import net.starlark.java.syntax.Identifier;
import net.starlark.java.syntax.IfStatement;
import net.starlark.java.syntax.IndexExpression;
import net.starlark.java.syntax.IntLiteral;
import net.starlark.java.syntax.LambdaExpression;
import net.starlark.java.syntax.ListExpression;
import net.starlark.java.syntax.LoadStatement;
import net.starlark.java.syntax.Location;
import net.starlark.java.syntax.Resolver;
import net.starlark.java.syntax.ReturnStatement;
import net.starlark.java.syntax.SliceExpression;
import net.starlark.java.syntax.Statement;
import net.starlark.java.syntax.StringLiteral;
import net.starlark.java.syntax.TokenKind;
import net.starlark.java.syntax.UnaryOperatorExpression;

final class Eval {

  private Eval() {} // uninstantiable

  // ---- entry point ----

  // Called from StarlarkFunction.fastcall.
  static Object execFunctionBody(StarlarkThread.Frame fr, List<Statement> statements)
      throws EvalException, InterruptedException {
    fr.thread.checkInterrupt();
    execStatements(fr, statements, /*indented=*/ false);
    return fr.result;
  }

  private static StarlarkFunction fn(StarlarkThread.Frame fr) {
    return (StarlarkFunction) fr.fn;
  }

  private static TokenKind execStatements(
      StarlarkThread.Frame fr, List<Statement> statements, boolean indented)
      throws EvalException, InterruptedException {
    boolean isToplevelFunction = fn(fr).isToplevel();

    // Hot code path, good chance of short lists which don't justify the iterator overhead.
    for (int i = 0; i < statements.size(); i++) {
      Statement stmt = statements.get(i);
      TokenKind flow = exec(fr, stmt);
      if (flow != TokenKind.PASS) {
        return flow;
      }

      // Hack for BzlLoadFunction's "export" semantics.
      // We enable it only for statements outside any function (isToplevelFunction)
      // and outside any if- or for- statements (!indented).
      if (isToplevelFunction && !indented && fr.thread.postAssignHook != null) {
        if (stmt instanceof AssignmentStatement) {
          AssignmentStatement assign = (AssignmentStatement) stmt;
          for (Identifier id : Identifier.boundIdentifiers(assign.getLHS())) {
            Object value = fn(fr).getGlobal(id.getBinding().getIndex());
            fr.thread.postAssignHook.assign(id.getName(), value);
          }
        }
      }
    }
    return TokenKind.PASS;
  }

  private static void execAssignment(StarlarkThread.Frame fr, AssignmentStatement node)
      throws EvalException, InterruptedException {
    try {
      if (node.isAugmented()) {
        execAugmentedAssignment(fr, node);
      } else {
        Object rvalue = eval(fr, node.getRHS());
        assign(fr, node.getLHS(), rvalue);
      }
    } catch (EvalException ex) {
      fr.setErrorLocation(node.getOperatorLocation());
      throw ex;
    }
  }

  private static TokenKind execFor(StarlarkThread.Frame fr, ForStatement node)
      throws EvalException, InterruptedException {
    Iterable<?> seq = evalAsIterable(fr, node.getCollection());
    EvalUtils.addIterator(seq);
    try {
      for (Object it : seq) {
        assign(fr, node.getVars(), it);

        switch (execStatements(fr, node.getBody(), /*indented=*/ true)) {
          case PASS:
          case CONTINUE:
            // Stay in loop.
            fr.thread.checkInterrupt();
            continue;
          case BREAK:
            // Finish loop, execute next statement after loop.
            return TokenKind.PASS;
          case RETURN:
            // Finish loop, return from function.
            return TokenKind.RETURN;
          default:
            throw new IllegalStateException("unreachable");
        }
      }
    } catch (EvalException ex) {
      fr.setErrorLocation(node.getStartLocation());
      throw ex;
    } finally {
      EvalUtils.removeIterator(seq);
    }
    return TokenKind.PASS;
  }

  private static StarlarkFunction newFunction(StarlarkThread.Frame fr, Resolver.Function rfn)
      throws EvalException, InterruptedException {
    // Evaluate default value expressions of optional parameters.
    // We use MANDATORY to indicate a required parameter
    // (not null, because defaults must be a legal tuple value, as
    // it will be constructed by the code emitted by the compiler).
    // As an optimization, we omit the prefix of MANDATORY parameters.
    Object[] defaults = null;
    int nparams =
        rfn.getParameters().size() - (rfn.hasKwargs() ? 1 : 0) - (rfn.hasVarargs() ? 1 : 0);
    for (int i = 0; i < nparams; i++) {
      Expression expr = rfn.getParameters().get(i).getDefaultValue();
      if (expr == null && defaults == null) {
        continue; // skip prefix of required parameters
      }
      if (defaults == null) {
        defaults = new Object[nparams - i];
      }
      defaults[i - (nparams - defaults.length)] =
          expr == null ? StarlarkFunction.MANDATORY : eval(fr, expr);
    }
    if (defaults == null) {
      defaults = EMPTY;
    }

    // Capture the cells of the function's
    // free variables from the lexical environment.
    Object[] freevars = new Object[rfn.getFreeVars().size()];
    int i = 0;
    for (Resolver.Binding bind : rfn.getFreeVars()) {
      // Unlike expr(Identifier), we want the cell itself, not its content.
      switch (bind.getScope()) {
        case FREE:
          freevars[i++] = fn(fr).getFreeVar(bind.getIndex());
          break;
        case CELL:
          freevars[i++] = fr.locals[bind.getIndex()];
          break;
        default:
          throw new IllegalStateException("unexpected: " + bind);
      }
    }

    // Nested functions use the same globalIndex as their enclosing function,
    // since both were compiled from the same Program.
    StarlarkFunction fn = fn(fr);
    return new StarlarkFunction(
        rfn, fn.getModule(), fn.globalIndex, Tuple.wrap(defaults), Tuple.wrap(freevars));
  }

  private static TokenKind execIf(StarlarkThread.Frame fr, IfStatement node)
      throws EvalException, InterruptedException {
    boolean cond = Starlark.truth(eval(fr, node.getCondition()));
    if (cond) {
      return execStatements(fr, node.getThenBlock(), /*indented=*/ true);
    } else if (node.getElseBlock() != null) {
      return execStatements(fr, node.getElseBlock(), /*indented=*/ true);
    }
    return TokenKind.PASS;
  }

  private static void execLoad(StarlarkThread.Frame fr, LoadStatement node) throws EvalException {
    // Has the application defined a behavior for load statements in this thread?
    StarlarkThread.Loader loader = fr.thread.getLoader();
    if (loader == null) {
      fr.setErrorLocation(node.getStartLocation());
      throw Starlark.errorf("load statements may not be executed in this thread");
    }

    // Load module.
    String moduleName = node.getImport().getValue();
    Module module = loader.load(moduleName);
    if (module == null) {
      fr.setErrorLocation(node.getStartLocation());
      throw Starlark.errorf("module '%s' not found", moduleName);
    }

    for (LoadStatement.Binding binding : node.getBindings()) {
      // Extract symbol.
      Identifier orig = binding.getOriginalName();
      Object value = module.getGlobal(orig.getName());
      if (value == null) {
        fr.setErrorLocation(orig.getStartLocation());
        throw Starlark.errorf(
            "file '%s' does not contain symbol '%s'%s",
            moduleName,
            orig.getName(),
            SpellChecker.didYouMean(orig.getName(), module.getGlobals().keySet()));
      }

      assignIdentifier(fr, binding.getLocalName(), value);
    }
  }

  private static TokenKind execReturn(StarlarkThread.Frame fr, ReturnStatement node)
      throws EvalException, InterruptedException {
    Expression result = node.getResult();
    if (result != null) {
      fr.result = eval(fr, result);
    }
    return TokenKind.RETURN;
  }

  private static TokenKind exec(StarlarkThread.Frame fr, Statement st)
      throws EvalException, InterruptedException {
    if (fr.dbg != null) {
      Location loc = st.getStartLocation(); // not very precise
      fr.setLocation(loc);
      fr.dbg.before(fr.thread, loc); // location is now redundant since it's in the thread
    }

    if (++fr.thread.steps >= fr.thread.stepLimit) {
      throw new EvalException("Starlark computation cancelled: too many steps");
    }

    switch (st.kind()) {
      case ASSIGNMENT:
        execAssignment(fr, (AssignmentStatement) st);
        return TokenKind.PASS;
      case EXPRESSION:
        eval(fr, ((ExpressionStatement) st).getExpression());
        return TokenKind.PASS;
      case FLOW:
        return ((FlowStatement) st).getFlowKind();
      case FOR:
        return execFor(fr, (ForStatement) st);
      case DEF:
        DefStatement def = (DefStatement) st;
        StarlarkFunction fn = newFunction(fr, def.getResolvedFunction());
        assignIdentifier(fr, def.getIdentifier(), fn);
        return TokenKind.PASS;
      case IF:
        return execIf(fr, (IfStatement) st);
      case LOAD:
        execLoad(fr, (LoadStatement) st);
        return TokenKind.PASS;
      case RETURN:
        return execReturn(fr, (ReturnStatement) st);
    }
    throw new IllegalArgumentException("unexpected statement: " + st.kind());
  }

  /**
   * Updates the environment bindings, and possibly mutates objects, so as to assign the given value
   * to the given expression. Might not set the frame location on error.
   */
  private static void assign(StarlarkThread.Frame fr, Expression lhs, Object value)
      throws EvalException, InterruptedException {
    if (lhs instanceof Identifier) {
      // x = ...
      assignIdentifier(fr, (Identifier) lhs, value);

    } else if (lhs instanceof IndexExpression) {
      // x[i] = ...
      Object object = eval(fr, ((IndexExpression) lhs).getObject());
      Object key = eval(fr, ((IndexExpression) lhs).getKey());
      EvalUtils.setIndex(object, key, value);

    } else if (lhs instanceof ListExpression) {
      // a, b, c = ...
      ListExpression list = (ListExpression) lhs;
      assignSequence(fr, list.getElements(), value);

    } else if (lhs instanceof DotExpression) {
      // x.f = ...
      DotExpression dot = (DotExpression) lhs;
      Object object = eval(fr, dot.getObject());
      String field = dot.getField().getName();
      try {
        EvalUtils.setField(object, field, value);
      } catch (EvalException ex) {
        fr.setErrorLocation(dot.getDotLocation());
        throw ex;
      }
    } else {
      // Not possible for resolved ASTs.
      throw Starlark.errorf("cannot assign to '%s'", lhs);
    }
  }

  private static void assignIdentifier(StarlarkThread.Frame fr, Identifier id, Object value)
      throws EvalException {
    Resolver.Binding bind = id.getBinding();
    switch (bind.getScope()) {
      case LOCAL:
        fr.locals[bind.getIndex()] = value;
        break;
      case CELL:
        ((StarlarkFunction.Cell) fr.locals[bind.getIndex()]).x = value;
        break;
      case GLOBAL:
        fn(fr).setGlobal(bind.getIndex(), value);
        break;
      default:
        throw new IllegalStateException(bind.getScope().toString());
    }
  }

  /**
   * Recursively assigns an iterable value to a non-empty sequence of assignable expressions. Might
   * not set frame location on error.
   */
  private static void assignSequence(StarlarkThread.Frame fr, List<Expression> lhs, Object x)
      throws EvalException, InterruptedException {
    // TODO(adonovan): lock/unlock rhs during iteration so that
    // assignments fail when the left side aliases the right,
    // which is a tricky case in Python assignment semantics.
    int nrhs = Starlark.len(x);
    int nlhs = lhs.size();
    if (nrhs < 0 || x instanceof String) { // strings are not iterable
      throw Starlark.errorf(
          "got '%s' in sequence assignment (want %d-element sequence)", Starlark.type(x), nlhs);
    }
    Iterable<?> rhs = Starlark.toIterable(x);
    if (nlhs != nrhs) {
      throw Starlark.errorf(
          "too %s values to unpack (got %d, want %d)", nrhs < nlhs ? "few" : "many", nrhs, nlhs);
    }
    int i = 0;
    for (Object item : rhs) {
      assign(fr, lhs.get(i), item);
      i++;
    }
  }

  // Might not set frame location on error.
  private static void execAugmentedAssignment(StarlarkThread.Frame fr, AssignmentStatement stmt)
      throws EvalException, InterruptedException {
    Expression lhs = stmt.getLHS();
    TokenKind op = stmt.getOperator();
    Expression rhs = stmt.getRHS();

    if (lhs instanceof Identifier) {
      // x op= y    (lhs must be evaluated only once)
      Object x = eval(fr, lhs);
      Object y = eval(fr, rhs);
      Object z;
      try {
        z = inplaceBinaryOp(fr, op, x, y);
      } catch (EvalException ex) {
        fr.setErrorLocation(stmt.getOperatorLocation());
        throw ex;
      }
      assignIdentifier(fr, (Identifier) lhs, z);

    } else if (lhs instanceof IndexExpression) {
      // object[index] op= y
      // The object and key should be evaluated only once, so we don't use lhs.eval().
      IndexExpression index = (IndexExpression) lhs;
      Object object = eval(fr, index.getObject());
      Object key = eval(fr, index.getKey());
      Object x = EvalUtils.index(fr.thread, object, key);
      // Evaluate rhs after lhs.
      Object y = eval(fr, rhs);
      Object z;
      try {
        z = inplaceBinaryOp(fr, op, x, y);
      } catch (EvalException ex) {
        fr.setErrorLocation(stmt.getOperatorLocation());
        throw ex;
      }
      try {
        EvalUtils.setIndex(object, key, z);
      } catch (EvalException ex) {
        fr.setErrorLocation(stmt.getOperatorLocation());
        throw ex;
      }

    } else if (lhs instanceof DotExpression) {
      // object.field op= y  (lhs must be evaluated only once)
      DotExpression dot = (DotExpression) lhs;
      Object object = eval(fr, dot.getObject());
      String field = dot.getField().getName();
      try {
        Object x =
            Starlark.getattr(
                fr.thread.mutability(),
                fr.thread.getSemantics(),
                object,
                field,
                /*defaultValue=*/ null);
        Object y = eval(fr, rhs);
        Object z;
        try {
          z = inplaceBinaryOp(fr, op, x, y);
        } catch (EvalException ex) {
          fr.setErrorLocation(stmt.getOperatorLocation());
          throw ex;
        }
        EvalUtils.setField(object, field, z);
      } catch (EvalException ex) {
        fr.setErrorLocation(dot.getDotLocation());
        throw ex;
      }

    } else {
      // Not possible for resolved ASTs.
      fr.setErrorLocation(stmt.getOperatorLocation());
      throw Starlark.errorf("cannot perform augmented assignment on '%s'", lhs);
    }
  }

  private static Object inplaceBinaryOp(StarlarkThread.Frame fr, TokenKind op, Object x, Object y)
      throws EvalException {
    // list += iterable  behaves like  list.extend(iterable)
    // TODO(b/141263526): following Python, allow list+=iterable (but not list+iterable).
    if (op == TokenKind.PLUS && x instanceof StarlarkList && y instanceof StarlarkList) {
      StarlarkList<?> list = (StarlarkList) x;
      list.extend(y);
      return list;
    } else if (op == TokenKind.PIPE && x instanceof Dict && y instanceof Map) {
      // dict |= map merges the contents of the second operand (usually a dict) into the first.
      @SuppressWarnings("unchecked")
      Dict<Object, Object> xDict = (Dict<Object, Object>) x;
      @SuppressWarnings("unchecked")
      Map<Object, Object> yMap = (Map<Object, Object>) y;
      xDict.putEntries(yMap);
      return xDict;
    }
    return EvalUtils.binaryOp(op, x, y, fr.thread);
  }

  // ---- expressions ----

  private static Object eval(StarlarkThread.Frame fr, Expression expr)
      throws EvalException, InterruptedException {
    if (++fr.thread.steps >= fr.thread.stepLimit) {
      throw new EvalException("Starlark computation cancelled: too many steps");
    }

    // The switch cases have been split into separate functions
    // to reduce the stack usage during recursion, which is
    // especially important in practice for deeply nested a+...+z
    // expressions; see b/153764542.
    switch (expr.kind()) {
      case BINARY_OPERATOR:
        return evalBinaryOperator(fr, (BinaryOperatorExpression) expr);
      case COMPREHENSION:
        return evalComprehension(fr, (Comprehension) expr);
      case CONDITIONAL:
        return evalConditional(fr, (ConditionalExpression) expr);
      case DICT_EXPR:
        return evalDict(fr, (DictExpression) expr);
      case DOT:
        return evalDot(fr, (DotExpression) expr);
      case CALL:
        return evalCall(fr, (CallExpression) expr);
      case IDENTIFIER:
        return evalIdentifier(fr, (Identifier) expr);
      case INDEX:
        return evalIndex(fr, (IndexExpression) expr);
      case INT_LITERAL:
        // TODO(adonovan): opt: avoid allocation by saving
        // the StarlarkInt in the IntLiteral (a temporary hack
        // until we use a compiled representation).
        Number n = ((IntLiteral) expr).getValue();
        if (n instanceof Integer) {
          return StarlarkInt.of((Integer) n);
        } else if (n instanceof Long) {
          return StarlarkInt.of((Long) n);
        } else {
          return StarlarkInt.of((BigInteger) n);
        }
      case FLOAT_LITERAL:
        return StarlarkFloat.of(((FloatLiteral) expr).getValue());
      case LAMBDA:
        return newFunction(fr, ((LambdaExpression) expr).getResolvedFunction());
      case LIST_EXPR:
        return evalList(fr, (ListExpression) expr);
      case SLICE:
        return evalSlice(fr, (SliceExpression) expr);
      case STRING_LITERAL:
        return ((StringLiteral) expr).getValue();
      case UNARY_OPERATOR:
        return evalUnaryOperator(fr, (UnaryOperatorExpression) expr);
    }
    throw new IllegalArgumentException("unexpected expression: " + expr.kind());
  }

  private static Object evalBinaryOperator(StarlarkThread.Frame fr, BinaryOperatorExpression binop)
      throws EvalException, InterruptedException {
    Object x = eval(fr, binop.getX());
    // AND and OR require short-circuit evaluation.
    switch (binop.getOperator()) {
      case AND:
        return Starlark.truth(x) ? eval(fr, binop.getY()) : x;
      case OR:
        return Starlark.truth(x) ? x : eval(fr, binop.getY());
      default:
        Object y = eval(fr, binop.getY());
        try {
          return EvalUtils.binaryOp(binop.getOperator(), x, y, fr.thread);
        } catch (EvalException ex) {
          fr.setErrorLocation(binop.getOperatorLocation());
          throw ex;
        }
    }
  }

  private static Object evalConditional(StarlarkThread.Frame fr, ConditionalExpression cond)
      throws EvalException, InterruptedException {
    Object v = eval(fr, cond.getCondition());
    return eval(fr, Starlark.truth(v) ? cond.getThenCase() : cond.getElseCase());
  }

  private static Object evalDict(StarlarkThread.Frame fr, DictExpression dictexpr)
      throws EvalException, InterruptedException {
    Dict<Object, Object> dict = Dict.of(fr.thread.mutability());
    for (DictExpression.Entry entry : dictexpr.getEntries()) {
      Object k = eval(fr, entry.getKey());
      Object v = eval(fr, entry.getValue());
      int before = dict.size();
      try {
        dict.putEntry(k, v);
      } catch (EvalException ex) {
        fr.setErrorLocation(entry.getColonLocation());
        throw ex;
      }
      if (dict.size() == before) {
        fr.setErrorLocation(entry.getColonLocation());
        throw Starlark.errorf("dictionary expression has duplicate key: %s", Starlark.repr(k));
      }
    }
    return dict;
  }

  private static Object evalDot(StarlarkThread.Frame fr, DotExpression dot)
      throws EvalException, InterruptedException {
    Object object = eval(fr, dot.getObject());
    String name = dot.getField().getName();
    try {
      return Starlark.getattr(
          fr.thread.mutability(), fr.thread.getSemantics(), object, name, /*defaultValue=*/ null);
    } catch (EvalException ex) {
      fr.setErrorLocation(dot.getDotLocation());
      throw ex;
    }
  }

  private static Object evalCall(StarlarkThread.Frame fr, CallExpression call)
      throws EvalException, InterruptedException {
    fr.thread.checkInterrupt();

    Object fn = eval(fr, call.getFunction());

    // Starlark arguments are ordered: positionals < keywords < *args < **kwargs.
    //
    // This is stricter than Python2, which doesn't constrain keywords wrt *args,
    // but this ensures that the effects of evaluation of Starlark arguments occur
    // in source order.
    //
    // Starlark does not support Python3's multiple *args and **kwargs
    // nor freer ordering, such as f(a, *list, *list, **dict, **dict, b=1).
    // Supporting it would complicate a compiler, and produce effects out of order.
    // Also, Python's argument ordering rules are complex and the errors sometimes cryptic.

    // StarStar and Star args are guaranteed to be last, if they occur.
    ImmutableList<Argument> arguments = call.getArguments();
    int n = arguments.size();
    Argument.StarStar starstar = null;
    if (n > 0 && arguments.get(n - 1) instanceof Argument.StarStar) {
      starstar = (Argument.StarStar) arguments.get(n - 1);
      n--;
    }
    Argument.Star star = null;
    if (n > 0 && arguments.get(n - 1) instanceof Argument.Star) {
      star = (Argument.Star) arguments.get(n - 1);
      n--;
    }
    // Inv: n = |positional| + |named|

    // Allocate assuming no *args/**kwargs.
    int npos = call.getNumPositionalArguments();
    int i;

    // f(expr) -- positional args
    Object[] positional = npos == 0 ? EMPTY : new Object[npos];
    for (i = 0; i < npos; i++) {
      Argument arg = arguments.get(i);
      Object value = eval(fr, arg.getValue());
      positional[i] = value;
    }

    // f(id=expr) -- named args
    Object[] named = n == npos ? EMPTY : new Object[2 * (n - npos)];
    for (int j = 0; i < n; i++) {
      Argument.Keyword arg = (Argument.Keyword) arguments.get(i);
      Object value = eval(fr, arg.getValue());
      named[j++] = arg.getName();
      named[j++] = value;
    }

    // f(*args) -- varargs
    if (star != null) {
      Object value = eval(fr, star.getValue());
      if (!(value instanceof StarlarkIterable)) {
        fr.setErrorLocation(star.getStartLocation());
        throw Starlark.errorf("argument after * must be an iterable, not %s", Starlark.type(value));
      }
      // TODO(adonovan): opt: if value.size is known, preallocate (and skip if empty).
      ArrayList<Object> list = new ArrayList<>();
      Collections.addAll(list, positional);
      Iterables.addAll(list, ((Iterable<?>) value));
      positional = list.toArray();
    }

    // f(**kwargs)
    if (starstar != null) {
      Object value = eval(fr, starstar.getValue());
      // Unlike *args, we don't have a Starlark-specific mapping interface to check for in **kwargs,
      // so check for Java's Map instead.
      if (!(value instanceof Map)) {
        fr.setErrorLocation(starstar.getStartLocation());
        throw Starlark.errorf("argument after ** must be a dict, not %s", Starlark.type(value));
      }
      Map<?, ?> kwargs = (Map<?, ?>) value;
      int j = named.length;
      named = Arrays.copyOf(named, j + 2 * kwargs.size());
      for (Map.Entry<?, ?> e : kwargs.entrySet()) {
        if (!(e.getKey() instanceof String)) {
          fr.setErrorLocation(starstar.getStartLocation());
          throw Starlark.errorf("keywords must be strings, not %s", Starlark.type(e.getKey()));
        }
        named[j++] = e.getKey();
        named[j++] = e.getValue();
      }
    }

    Location loc = call.getLparenLocation(); // (Location is prematerialized)
    fr.setLocation(loc);
    try {
      return Starlark.fastcall(fr.thread, fn, positional, named);
    } catch (EvalException ex) {
      fr.setErrorLocation(loc);
      throw ex;
    }
  }

  private static Object evalIdentifier(StarlarkThread.Frame fr, Identifier id)
      throws EvalException, InterruptedException {
    Resolver.Binding bind = id.getBinding();
    Object result;
    switch (bind.getScope()) {
      case LOCAL:
        result = fr.locals[bind.getIndex()];
        break;
      case CELL:
        result = ((StarlarkFunction.Cell) fr.locals[bind.getIndex()]).x;
        break;
      case FREE:
        result = fn(fr).getFreeVar(bind.getIndex()).x;
        break;
      case GLOBAL:
        result = fn(fr).getGlobal(bind.getIndex());
        break;
      case PREDECLARED:
        result = fn(fr).getModule().getPredeclared(id.getName());
        break;
      case UNIVERSAL:
        result = Starlark.UNIVERSE.get(id.getName());
        break;
      default:
        throw new IllegalStateException(bind.toString());
    }
    if (result == null) {
      fr.setErrorLocation(id.getStartLocation());
      throw Starlark.errorf(
          "%s variable '%s' is referenced before assignment.", bind.getScope(), id.getName());
    }
    return result;
  }

  private static Object evalIndex(StarlarkThread.Frame fr, IndexExpression index)
      throws EvalException, InterruptedException {
    Object object = eval(fr, index.getObject());
    Object key = eval(fr, index.getKey());
    try {
      return EvalUtils.index(fr.thread, object, key);
    } catch (EvalException ex) {
      fr.setErrorLocation(index.getLbracketLocation());
      throw ex;
    }
  }

  private static Object evalList(StarlarkThread.Frame fr, ListExpression expr)
      throws EvalException, InterruptedException {
    int n = expr.getElements().size();
    Object[] array = new Object[n];
    for (int i = 0; i < n; i++) {
      array[i] = eval(fr, expr.getElements().get(i));
    }
    return expr.isTuple() ? Tuple.wrap(array) : StarlarkList.wrap(fr.thread.mutability(), array);
  }

  private static Object evalSlice(StarlarkThread.Frame fr, SliceExpression slice)
      throws EvalException, InterruptedException {
    Object x = eval(fr, slice.getObject());
    Object start = slice.getStart() == null ? Starlark.NONE : eval(fr, slice.getStart());
    Object stop = slice.getStop() == null ? Starlark.NONE : eval(fr, slice.getStop());
    Object step = slice.getStep() == null ? Starlark.NONE : eval(fr, slice.getStep());
    try {
      return Starlark.slice(fr.thread.mutability(), x, start, stop, step);
    } catch (EvalException ex) {
      fr.setErrorLocation(slice.getLbracketLocation());
      throw ex;
    }
  }

  private static Object evalUnaryOperator(StarlarkThread.Frame fr, UnaryOperatorExpression unop)
      throws EvalException, InterruptedException {
    Object x = eval(fr, unop.getX());
    try {
      return EvalUtils.unaryOp(unop.getOperator(), x);
    } catch (EvalException ex) {
      fr.setErrorLocation(unop.getStartLocation());
      throw ex;
    }
  }

  private static Object evalComprehension(StarlarkThread.Frame fr, Comprehension comp)
      throws EvalException, InterruptedException {
    final Dict<Object, Object> dict = comp.isDict() ? Dict.of(fr.thread.mutability()) : null;
    final StarlarkList<Object> list =
        comp.isDict() ? null : StarlarkList.newList(fr.thread.mutability());

    // The Lambda class serves as a recursive lambda closure.
    class Lambda {
      // execClauses(index) recursively executes the clauses starting at index,
      // and finally evaluates the body and adds its value to the result.
      void execClauses(int index) throws EvalException, InterruptedException {
        fr.thread.checkInterrupt();

        // recursive case: one or more clauses
        if (index < comp.getClauses().size()) {
          Comprehension.Clause clause = comp.getClauses().get(index);
          if (clause instanceof Comprehension.For) {
            Comprehension.For forClause = (Comprehension.For) clause;

            Iterable<?> seq = evalAsIterable(fr, forClause.getIterable());
            EvalUtils.addIterator(seq);
            try {
              for (Object elem : seq) {
                assign(fr, forClause.getVars(), elem);
                execClauses(index + 1);
              }
            } catch (EvalException ex) {
              fr.setErrorLocation(forClause.getStartLocation());
              throw ex;
            } finally {
              EvalUtils.removeIterator(seq);
            }

          } else {
            Comprehension.If ifClause = (Comprehension.If) clause;
            if (Starlark.truth(eval(fr, ifClause.getCondition()))) {
              execClauses(index + 1);
            }
          }
          return;
        }

        // base case: evaluate body and add to result.
        if (dict != null) {
          DictExpression.Entry body = (DictExpression.Entry) comp.getBody();
          Object k = eval(fr, body.getKey());
          try {
            Starlark.checkHashable(k);
            Object v = eval(fr, body.getValue());
            dict.putEntry(k, v);
          } catch (EvalException ex) {
            fr.setErrorLocation(body.getColonLocation());
            throw ex;
          }
        } else {
          list.addElement(eval(fr, ((Expression) comp.getBody())));
        }
      }
    }
    new Lambda().execClauses(0);

    return comp.isDict() ? dict : list;
  }

  /**
   * Evaluates an expression to an iterable Starlark value and returns an {@code Iterable} view of
   * it. If evaluation fails or the value is not iterable, throws {@code EvalException} and sets the
   * error location to the expression's start.
   */
  private static Iterable<?> evalAsIterable(StarlarkThread.Frame fr, Expression expr)
      throws EvalException, InterruptedException {
    Object o = eval(fr, expr);
    try {
      return Starlark.toIterable(o);
    } catch (EvalException ex) {
      fr.setErrorLocation(expr.getStartLocation());
      throw ex;
    }
  }

  private static final Object[] EMPTY = {};
}
