docs: public DataPoints[] evaluate(final List<DataPoints[]> query_results) {
      // TODO - size the array
      final List<DataPoints[]> materialized = Lists.newArrayList();
      List<Integer> metric_query_keys = null;
      if (sub_metric_queries != null && sub_metric_queries.size() > 0) {
        metric_query_keys = Lists.newArrayList(sub_metric_queries.keySet());
        Collections.sort(metric_query_keys);
      }
  
      int metric_pointer = 0;
      int sub_expression_pointer = 0;
      for (int i = 0; i < parameter_index.size(); i++) {
        final Parameter param = parameter_index.get(i);
  
        if (param == Parameter.METRIC_QUERY) {
          if (metric_query_keys == null) {
            throw new RuntimeException("Attempt to read metric " +
                    "results when none exist");
          }
  
          final int ix = metric_query_keys.get(metric_pointer++);
          materialized.add(query_results.get(ix));
        } else if (param == Parameter.SUB_EXPRESSION) {
          final ExpressionTree st = sub_expressions.get(sub_expression_pointer++);
          materialized.add(st.evaluate(query_results));
        } else {
          throw new IllegalDataException("Unknown parameter type: " + param 
              + " in tree: " + this);
        }
      }
      
      return expression.evaluate(data_query, materialized, func_params);
    }