co.streamx.fluent.extree.expression.LambdaExpression Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ex-tree Show documentation
Show all versions of ex-tree Show documentation
Build AST from the bytecode
The newest version!
package co.streamx.fluent.extree.expression;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;
import lombok.Getter;
import lombok.NonNull;
/**
* Describes a lambda expression. This captures a block of code that is similar to a method body.
*
* Use {@link #parse(Object)} method to get a lambda expression tree.
*
*
* @param type of the lambda represented by this LambdaExpression.
*
*
*/
@Getter
public final class LambdaExpression extends InvocableExpression {
private final Expression body;
private final List locals;
private final Object key;
private final Supplier> parser;
// private static final Map, WeakReference>> _cache = Collections
// .synchronizedMap(new WeakHashMap, WeakReference>>());
LambdaExpression(Class> resultType, @NonNull Expression body, List params,
@NonNull List locals, Object key, Supplier> parser) {
super(ExpressionType.Lambda, resultType, params);
if (!TypeConverter.isAssignable(resultType, body.getResultType()))
throw new IllegalArgumentException(body.getResultType() + " is not assignable to " + resultType);
this.body = body;
this.locals = locals;
this.key = key;
this.parser = parser;
}
/**
* Gets a value indicating whether the lambda expression tree node represents a lambda expression calling a
* method.
*
* @return boolean indicator.
*/
public boolean isMethodRef() {
return parser != null;
}
/**
* If the LambdaExpression wraps a method call, then returns the method representation as an AST.
* Otherwise, returns the current lambda expression.
* The result is always semantically equivalent to the current lambda expression.
*
* @return lambda expression.
*/
public LambdaExpression parseMethodRef() {
return isMethodRef() ? parser.get() : this;
}
/**
* Creates {@link LambdaExpression} representing the lambda expression tree.
*
* @param the type of lambda to parse
*
* @param lambda - the lambda
*
* @return {@link LambdaExpression} representing the lambda expression tree.
*/
@SuppressWarnings("unchecked")
public static LambdaExpression parse(T lambda) {
LambdaExpression lambdaE;
// WeakReference> wlambda = _cache.get(lambda.getClass());
// if (wlambda != null) {
// lambdaE = (LambdaExpression) wlambda.get();
// if (lambdaE != null)
// return (LambdaExpression) lambdaE.accept(new InstanceReplacer(lambda));
// }
lambdaE = (LambdaExpression) ExpressionClassCracker.get().lambda(lambda, true);
// _cache.put(lambda.getClass(), new WeakReference>(lambdaE));
return lambdaE;
}
/**
* Creates {@link LambdaExpression} representing the passed method expression tree.
*
* @param the type of lambda to parse
*
* @param methodReference - reference to a method, e.g. MyClass::doWork
*
* @return {@link LambdaExpression} representing the lambda expression tree.
*/
@SuppressWarnings("unchecked")
public static LambdaExpression parseMethod(T methodReference) {
return (LambdaExpression) ExpressionClassCracker.get().lambda(methodReference, false);
}
/**
* Creates {@link LambdaExpression} representing the passed method expression tree.
*
* @param method to parse
* @param instance Required if the method is not static, otherwise null.
* @return {@link LambdaExpression} representing the lambda expression tree.
*/
public static LambdaExpression> parseMethod(Method method,
Object instance) {
if (Modifier.isStatic(method.getModifiers()) ^ instance == null)
throw new IllegalArgumentException("Instance does not suit the method: " + method);
return ExpressionClassCracker.get()
.lambdaFromFileSystem(instance, method, method.getDeclaringClass().getClassLoader());
}
/**
* Produces a {@link Function} that represents the expression.
*
* @param e {@link Expression} to compile
* @return {@link Function} that represents the expression.
*/
public static Function