Ejemplo n.º 1
0
  @Override
  public Object call(Object[] arguments, FuncallExpression ast, Environment env)
      throws EvalException, InterruptedException {
    if (!env.mutability().isMutable()) {
      throw new EvalException(getLocation(), "Trying to call in frozen environment");
    }
    if (env.getStackTrace().contains(this)) {
      throw new EvalException(
          getLocation(),
          String.format(
              "Recursion was detected when calling '%s' from '%s'",
              getName(), Iterables.getLast(env.getStackTrace()).getName()));
    }

    if (enableCompiler && method.isPresent()) {
      Object returnValue = callCompiledFunction(arguments, ast, env);
      if (returnValue != null) {
        return returnValue;
      }
    }

    Profiler.instance().startTask(ProfilerTask.SKYLARK_USER_FN, getName());
    try {
      env.enterScope(this, ast, definitionGlobals);
      ImmutableList<String> names = signature.getSignature().getNames();

      // Registering the functions's arguments as variables in the local Environment
      int i = 0;
      for (String name : names) {
        env.update(name, arguments[i++]);
      }

      try {
        for (Statement stmt : statements) {
          if (stmt instanceof ReturnStatement) {
            // Performance optimization.
            // Executing the statement would throw an exception, which is slow.
            return ((ReturnStatement) stmt).getReturnExpression().eval(env);
          } else {
            stmt.exec(env);
          }
        }
      } catch (ReturnStatement.ReturnException e) {
        return e.getValue();
      }
      return Runtime.NONE;
    } finally {
      Profiler.instance().completeTask(ProfilerTask.SKYLARK_USER_FN);
      env.exitScope();
    }
  }
Ejemplo n.º 2
0
 /**
  * Checks that this Freezable object can be mutated from the given {@link Environment}.
  *
  * @param object a Freezable object that we check is still mutable.
  * @param env the {@link Environment} attempting the mutation.
  * @throws MutabilityException when the object was frozen already, or is from another context.
  */
 public static void checkMutable(Freezable object, Environment env) throws MutabilityException {
   if (!object.mutability().isMutable()) {
     throw new MutabilityException("trying to mutate a frozen object");
   }
   // Consider an {@link Environment} e1, in which is created {@link UserDefinedFunction} f1,
   // that closes over some variable v1 bound to list l1. If somehow, via the magic of callbacks,
   // f1 or l1 is passed as argument to some function f2 evaluated in {@link environment} e2
   // while e1 is be mutable, e2, being a different {@link Environment}, should not be
   // allowed to mutate objects from e1. It's a bug, that shouldn't happen in our current code
   // base, so we throw an AssertionError. If in the future such situations are allowed to happen,
   // then we should throw a MutabilityException instead.
   if (!object.mutability().equals(env.mutability())) {
     throw new AssertionError("trying to mutate an object from a different context");
   }
 }