public static Type guessExpressionType(String expression, Map<String, Type> inputTypes)
      throws StringCompiler.CompileException, ClassNotFoundException {

    String expectedError = "cannot be converted to __TypeGuesserHelper__.BadReturnType";

    try {
      StringCompiler.getClass(
          "__TypeGuesserHelper__", typeGuesserSource(expression, inputTypes, "BadReturnType"));
      // Must have returned null.
      return Void.class;
    } catch (StringCompiler.CompileException exn) {
      // Use the error message to derive the actual type.
      for (Diagnostic<?> d : exn.getDiagnostics().getDiagnostics()) {
        String msg = d.getMessage(Locale.ROOT);
        int expectedErrorIndex = msg.indexOf(expectedError);
        if (expectedErrorIndex != -1) {
          String typeSource =
              msg.substring(
                  1 + "incompatible types: ".length() + msg.lastIndexOf('\n', expectedErrorIndex),
                  expectedErrorIndex);
          Class<?> clazz =
              StringCompiler.getClass(
                  "__TypeGuesserHelper__", typeGuesserSource(expression, inputTypes, typeSource));
          for (Method method : clazz.getMethods()) {
            if (method.getName().equals("method")) {
              return method.getGenericReturnType();
            }
          }
          // We should never get here.
          throw new RuntimeException("Unable to locate declared method.");
        }
      }
      // Must have been some other error.
      throw exn;
    }
  }
@Test
  public void testGuessExpressionType() throws Exception {
    assertEquals(
        double.class,
        StringCompiler.guessExpressionType(
            "a+b", ImmutableMap.of("a", int.class, "b", double.class)));
    assertEquals(
        double.class,
        StringCompiler.guessExpressionType(
            "a > 0 ? a : b", ImmutableMap.of("a", int.class, "b", double.class)));
    assertEquals(
        double.class,
        StringCompiler.guessExpressionType("a * Math.random()", ImmutableMap.of("a", int.class)));
    assertEquals(
        int.class,
        StringCompiler.guessExpressionType("(int) a", ImmutableMap.of("a", double.class)));
    assertEquals(
        long.class,
        StringCompiler.guessExpressionType(
            "a.getInt64(\"foo\")+b", ImmutableMap.of("a", Row.class, "b", int.class)));
  }