MCPcopy Index your code
hub / github.com/clojure/clojure / FISupport

Class FISupport

src/jvm/clojure/lang/Compiler.java:1653–1806  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1651}
1652
1653static class FISupport {
1654 private static final IPersistentSet AFN_FIS = RT.set(Callable.class, Runnable.class, Comparator.class);
1655 private static final IPersistentSet OBJECT_METHODS = RT.set("equals", "toString", "hashCode");
1656
1657 // Return FI method if:
1658 // 1) Target is a functional interface and not already implemented by AFn
1659 // 2) Target method matches one of our fn invoker methods (0 <= arity <= 10)
1660 static java.lang.reflect.Method maybeFIMethod(Class target) {
1661 if (target != null && target.isAnnotationPresent(FunctionalInterface.class)
1662 && !AFN_FIS.contains(target)) {
1663
1664 java.lang.reflect.Method[] methods = target.getMethods();
1665 for (java.lang.reflect.Method method : methods) {
1666 if (method.getParameterCount() >= 0 && method.getParameterCount() <= 10
1667 && Modifier.isAbstract(method.getModifiers())
1668 && !OBJECT_METHODS.contains(method.getName()))
1669 return method;
1670 }
1671 }
1672 return null;
1673 }
1674
1675 // Invokers support only long, double, Object params; widen numerics
1676 private static Class toInvokerParamType(Class c) {
1677 if (c.equals(Byte.TYPE) || c.equals(Short.TYPE) || c.equals(Integer.TYPE) || c.equals(Long.TYPE)) {
1678 return Long.TYPE;
1679 } else if (c.equals(Float.TYPE) || c.equals(Double.TYPE)) {
1680 return Double.TYPE;
1681 }
1682 return Object.class;
1683 }
1684
1685 /**
1686 * If targetClass is FI and has an adaptable functional method
1687 * Find fn invoker method matching adaptable method of FI
1688 * Emit bytecode for (expr is emitted):
1689 * if(expr instanceof IFn && !(expr instanceof FI))
1690 * invokeDynamic(targetMethod, fnInvokerImplMethod)
1691 * Else emit nothing
1692 */
1693 static boolean maybeEmitFIAdapter(ObjExpr objx, GeneratorAdapter gen, Expr expr, Class targetClass) {
1694 // Optimization:
1695 // if(expr instanceof QualifiedMethodExpr)
1696 // emitInvokeDynamic(targetMethod, QME method) // DON'T emit expr
1697
1698 java.lang.reflect.Method targetMethod = maybeFIMethod(targetClass);
1699 if (targetMethod == null)
1700 return false;
1701
1702 // compute fn invoker method
1703 int paramCount = targetMethod.getParameterCount();
1704 Class[] invokerParams = new Class[paramCount + 1];
1705 invokerParams[0] = IFn.class; // close over Ifn as first arg
1706 StringBuilder invokeMethodBuilder = new StringBuilder("invoke");
1707 for (int i = 0; i < paramCount; i++) {
1708 // FnInvokers only has prims for first 2 args
1709 invokerParams[i + 1] = paramCount <= 2 ? toInvokerParamType(targetMethod.getParameterTypes()[i]) : Object.class;
1710 invokeMethodBuilder.append(FnInvokers.encodeInvokerType(invokerParams[i + 1]));

Callers

nothing calls this directly

Calls 1

setMethod · 0.95

Tested by

no test coverage detected