code: public Object evaluate(Object pContext,
                             VariableResolver pResolver,
                             Map functions,
                             String defaultPrefix,
                             Logger pLogger)
              throws ELException {
  
          // if the Map is null, then the function is invalid
          if (functions == null) {
              pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName);
          }
  
          // normalize function name against default prefix
          String functionName = this.functionName;
          if (functionName.indexOf(":") == -1) {
              if (defaultPrefix == null) {
                  pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName);
              }
              functionName = defaultPrefix + ":" + functionName;
          }
  
          // ensure that the function's name is mapped
          Method target = (Method) functions.get(functionName);
          if (target == null) {
              pLogger.logError(Constants.UNKNOWN_FUNCTION, functionName);
          }
  
          // ensure that the number of arguments matches the number of parameters
          Class[] params = target.getParameterTypes();
          if (params.length != argumentList.size()) {
              pLogger.logError(Constants.INAPPROPRIATE_FUNCTION_ARG_COUNT,
                      new Integer(params.length),
                      new Integer(argumentList.size()));
          }
  
          // now, walk through each parameter, evaluating and casting its argument
          Object[] arguments = new Object[argumentList.size()];
          for (int i = 0; i < params.length; i++) {
              // evaluate
              arguments[i] = ((Expression) argumentList.get(i)).evaluate(pContext,
                      pResolver,
                      functions,
                      defaultPrefix,
                      pLogger);
              // coerce
              arguments[i] = Coercions.coerce(arguments[i], params[i], pLogger);
          }
  
          // finally, invoke the target method, which we know to be static
          try {
              return (target.invoke(null, arguments));
          } catch (InvocationTargetException ex) {
              pLogger.logError(Constants.FUNCTION_INVOCATION_ERROR,
                      ex.getTargetException(),
                      functionName);
              return null;
          } catch (Exception ex) {
              pLogger.logError(Constants.FUNCTION_INVOCATION_ERROR, ex, functionName);
              return null;
          }
      }
docs: Evaluates by looking up the name in the VariableResolver