added string support for lambda expressions
This commit is contained in:
@@ -8,7 +8,6 @@
|
|||||||
- references to platform specific impls
|
- references to platform specific impls
|
||||||
|
|
||||||
## Asm
|
## Asm
|
||||||
- equals function for primitive and string + String::equalsIgnoreCase
|
|
||||||
- equals function for registered primitive conversion types
|
- equals function for registered primitive conversion types
|
||||||
- IConst0Fixer: IConst0/1 on its own => false/true
|
- IConst0Fixer: IConst0/1 on its own => false/true
|
||||||
- actually parse getter
|
- actually parse getter
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package jef.asm;
|
|||||||
import jef.expressions.BinaryExpression;
|
import jef.expressions.BinaryExpression;
|
||||||
import jef.expressions.ConstantExpression;
|
import jef.expressions.ConstantExpression;
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
|
import jef.expressions.FunctionExpression;
|
||||||
import jef.expressions.IntermediateFieldExpression;
|
import jef.expressions.IntermediateFieldExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
import jef.expressions.ParameterExpression;
|
import jef.expressions.ParameterExpression;
|
||||||
@@ -114,6 +115,18 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
var element = varStack.pop();
|
var element = varStack.pop();
|
||||||
var collection = varStack.pop();
|
var collection = varStack.pop();
|
||||||
varStack.push(new BinaryExpression(element, collection, BinaryExpression.Operator.IN));
|
varStack.push(new BinaryExpression(element, collection, BinaryExpression.Operator.IN));
|
||||||
|
} else if (name.equals("equals")
|
||||||
|
&& owner.equals("java/lang/String")) {
|
||||||
|
var value = varStack.pop();
|
||||||
|
var variable = varStack.pop();
|
||||||
|
varStack.push(new BinaryExpression(variable, value, BinaryExpression.Operator.EQ));
|
||||||
|
} else if (name.equals("equalsIgnoreCase")
|
||||||
|
&& owner.equals("java/lang/String")) {
|
||||||
|
var value = varStack.pop();
|
||||||
|
var variable = varStack.pop();
|
||||||
|
varStack.push(new BinaryExpression(new FunctionExpression(FunctionExpression.TOLOWER, List.of(variable)),
|
||||||
|
new FunctionExpression(FunctionExpression.TOLOWER, List.of(value)),
|
||||||
|
BinaryExpression.Operator.EQ));
|
||||||
} else if (descriptor.startsWith("()")) {
|
} else if (descriptor.startsWith("()")) {
|
||||||
var method = Class.forName(owner.replace("/", ".")).getDeclaredMethod(name);
|
var method = Class.forName(owner.replace("/", ".")).getDeclaredMethod(name);
|
||||||
var res = new OptimizedAsmParser(method).parse();
|
var res = new OptimizedAsmParser(method).parse();
|
||||||
@@ -136,6 +149,9 @@ class FilterMethodVisitor extends MethodVisitor {
|
|||||||
throw new RuntimeException("method insn: unsupported function " + name + " in " + owner);
|
throw new RuntimeException("method insn: unsupported function " + name + " in " + owner);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
if (e instanceof RuntimeException re) {
|
||||||
|
throw re;
|
||||||
|
}
|
||||||
throw new RuntimeException("method insn: ", e);
|
throw new RuntimeException("method insn: ", e);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ public class ConstantExpression implements Expression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
if (value instanceof String) {
|
||||||
|
return "\"" + value + "\"";
|
||||||
|
}
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ public interface Expression {
|
|||||||
BINARY,
|
BINARY,
|
||||||
CONSTANT,
|
CONSTANT,
|
||||||
FIELD,
|
FIELD,
|
||||||
|
FUNCTION,
|
||||||
INTERMEDIATE_FIELD,
|
INTERMEDIATE_FIELD,
|
||||||
LIMIT,
|
LIMIT,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -42,7 +43,7 @@ public interface Expression {
|
|||||||
BIT_SHIFT(10), // <<, >>
|
BIT_SHIFT(10), // <<, >>
|
||||||
ADD_SUB(13), // +, -
|
ADD_SUB(13), // +, -
|
||||||
MUL_DIV_MOD(14), // *, /, %
|
MUL_DIV_MOD(14), // *, /, %
|
||||||
UNARY_PRE(15), // +, -, !, ~, --i, ++i
|
UNARY_PRE(15), // +, -, !, ~, --i, ++i, function calls
|
||||||
UNARY_POST(16), // i++, i--
|
UNARY_POST(16), // i++, i--
|
||||||
CONSTANT(17), // constant values
|
CONSTANT(17), // constant values
|
||||||
;
|
;
|
||||||
|
|||||||
32
src/main/java/jef/expressions/FunctionExpression.java
Normal file
32
src/main/java/jef/expressions/FunctionExpression.java
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
package jef.expressions;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
@EqualsAndHashCode
|
||||||
|
public class FunctionExpression implements Expression {
|
||||||
|
public static final String TOLOWER = "TOLOWER";
|
||||||
|
private final String function;
|
||||||
|
private final List<Expression> parameters;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Type getType() {
|
||||||
|
return Type.FUNCTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Priority getPriority() {
|
||||||
|
return Priority.UNARY_PRE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return function + "(" + parameters.stream().map(Expression::toString).collect(Collectors.joining(", ")) + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import lombok.EqualsAndHashCode;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@@ -33,7 +32,7 @@ public class ParameterExpression extends ConstantExpression implements Expressio
|
|||||||
} else if (this.value == null) {
|
} else if (this.value == null) {
|
||||||
return "null";
|
return "null";
|
||||||
} else if (this.value instanceof Collection) {
|
} else if (this.value instanceof Collection) {
|
||||||
return "(" + ((Collection<?>) this.value).stream().map(e -> e == null ? "NULL" : Objects.toString(e)).collect(Collectors.joining(", ")) + ")";
|
return "(" + ((Collection<?>) this.value).stream().map(e -> e == null ? "NULL" : (e instanceof String ? "\"" + e + "\"" : e.toString())).collect(Collectors.joining(", ")) + ")";
|
||||||
}
|
}
|
||||||
return value.toString();
|
return value.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ public class TableExpression extends ConstantExpression {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "`" + super.toString() + "`";
|
return "`" + name + "`";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import jef.expressions.BinaryExpression;
|
|||||||
import jef.expressions.ConstantExpression;
|
import jef.expressions.ConstantExpression;
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
import jef.expressions.FieldExpression;
|
import jef.expressions.FieldExpression;
|
||||||
|
import jef.expressions.FunctionExpression;
|
||||||
import jef.expressions.IntermediateFieldExpression;
|
import jef.expressions.IntermediateFieldExpression;
|
||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
@@ -28,6 +29,7 @@ public abstract class ExpressionModifier {
|
|||||||
case BINARY -> modifyBinary((BinaryExpression) expr);
|
case BINARY -> modifyBinary((BinaryExpression) expr);
|
||||||
case CONSTANT -> modifyConstant((ConstantExpression) expr);
|
case CONSTANT -> modifyConstant((ConstantExpression) expr);
|
||||||
case FIELD -> modifyField((FieldExpression) expr);
|
case FIELD -> modifyField((FieldExpression) expr);
|
||||||
|
case FUNCTION -> modifyFunction((FunctionExpression) expr);
|
||||||
case INTERMEDIATE_FIELD -> modifyIntermediateField((IntermediateFieldExpression) expr);
|
case INTERMEDIATE_FIELD -> modifyIntermediateField((IntermediateFieldExpression) expr);
|
||||||
case LIMIT -> modifyLimit((LimitExpression) expr);
|
case LIMIT -> modifyLimit((LimitExpression) expr);
|
||||||
case NULL -> modifyNull((NullExpression) expr);
|
case NULL -> modifyNull((NullExpression) expr);
|
||||||
@@ -63,6 +65,10 @@ public abstract class ExpressionModifier {
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Expression modifyFunction(FunctionExpression expr) {
|
||||||
|
return new FunctionExpression(expr.getFunction(), expr.getParameters().stream().map(this::modify).toList());
|
||||||
|
}
|
||||||
|
|
||||||
public Expression modifyIntermediateField(IntermediateFieldExpression expr) {
|
public Expression modifyIntermediateField(IntermediateFieldExpression expr) {
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import jef.expressions.AndExpression;
|
|||||||
import jef.expressions.BinaryExpression;
|
import jef.expressions.BinaryExpression;
|
||||||
import jef.expressions.ConstantExpression;
|
import jef.expressions.ConstantExpression;
|
||||||
import jef.expressions.FieldExpression;
|
import jef.expressions.FieldExpression;
|
||||||
|
import jef.expressions.FunctionExpression;
|
||||||
import jef.expressions.IntermediateFieldExpression;
|
import jef.expressions.IntermediateFieldExpression;
|
||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
@@ -56,6 +57,11 @@ public class DebugExpressionVisitor extends ExpressionVisitor {
|
|||||||
System.out.println(i() + expr.toString());
|
System.out.println(i() + expr.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitFunction(FunctionExpression expr) {
|
||||||
|
System.out.println(i() + expr.toString());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitIntermediateField(IntermediateFieldExpression expr) {
|
public void visitIntermediateField(IntermediateFieldExpression expr) {
|
||||||
System.out.println(i() + expr.toString());
|
System.out.println(i() + expr.toString());
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import jef.expressions.BinaryExpression;
|
|||||||
import jef.expressions.ConstantExpression;
|
import jef.expressions.ConstantExpression;
|
||||||
import jef.expressions.Expression;
|
import jef.expressions.Expression;
|
||||||
import jef.expressions.FieldExpression;
|
import jef.expressions.FieldExpression;
|
||||||
|
import jef.expressions.FunctionExpression;
|
||||||
import jef.expressions.IntermediateFieldExpression;
|
import jef.expressions.IntermediateFieldExpression;
|
||||||
import jef.expressions.LimitExpression;
|
import jef.expressions.LimitExpression;
|
||||||
import jef.expressions.NullExpression;
|
import jef.expressions.NullExpression;
|
||||||
@@ -24,6 +25,7 @@ public abstract class ExpressionVisitor {
|
|||||||
case BINARY -> visitBinary((BinaryExpression) expr);
|
case BINARY -> visitBinary((BinaryExpression) expr);
|
||||||
case CONSTANT -> visitConstant((ConstantExpression) expr);
|
case CONSTANT -> visitConstant((ConstantExpression) expr);
|
||||||
case FIELD -> visitField((FieldExpression) expr);
|
case FIELD -> visitField((FieldExpression) expr);
|
||||||
|
case FUNCTION -> visitFunction((FunctionExpression) expr);
|
||||||
case INTERMEDIATE_FIELD -> visitIntermediateField((IntermediateFieldExpression) expr);
|
case INTERMEDIATE_FIELD -> visitIntermediateField((IntermediateFieldExpression) expr);
|
||||||
case LIMIT -> visitLimit((LimitExpression) expr);
|
case LIMIT -> visitLimit((LimitExpression) expr);
|
||||||
case NULL -> visitNull((NullExpression) expr);
|
case NULL -> visitNull((NullExpression) expr);
|
||||||
@@ -56,6 +58,9 @@ public abstract class ExpressionVisitor {
|
|||||||
public void visitField(FieldExpression expr) {
|
public void visitField(FieldExpression expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void visitFunction(FunctionExpression expr) {
|
||||||
|
}
|
||||||
|
|
||||||
public void visitIntermediateField(IntermediateFieldExpression expr) {
|
public void visitIntermediateField(IntermediateFieldExpression expr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -166,6 +166,28 @@ public class OptimizedAsmParserTest {
|
|||||||
Assertions.assertEquals("`b`", act);
|
Assertions.assertEquals("`b`", act);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectionContains() throws AsmParseException {
|
||||||
|
String act;
|
||||||
|
var s = Arrays.asList(null, 2, "str");
|
||||||
|
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> s.contains(e.i)).parse().getExpression().toString();
|
||||||
|
Assertions.assertEquals("`i` IN (NULL, 2, \"str\")", act);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectionEquals() throws AsmParseException {
|
||||||
|
String act;
|
||||||
|
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.s.equals("str")).parse().getExpression().toString();
|
||||||
|
Assertions.assertEquals("`s` = \"str\"", act);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCollectionEqualsIgnoreCase() throws AsmParseException {
|
||||||
|
String act;
|
||||||
|
act = new OptimizedAsmParser((SerializablePredicate<?>) (TestClass e) -> e.s.equalsIgnoreCase("str")).parse().getExpression().toString();
|
||||||
|
Assertions.assertEquals("TOLOWER(`s`) = TOLOWER(\"str\")", act);
|
||||||
|
}
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
public static class TestClass extends SerializableObject {
|
public static class TestClass extends SerializableObject {
|
||||||
public int i = 1;
|
public int i = 1;
|
||||||
@@ -174,5 +196,6 @@ public class OptimizedAsmParserTest {
|
|||||||
public float f;
|
public float f;
|
||||||
public long l;
|
public long l;
|
||||||
public boolean b;
|
public boolean b;
|
||||||
|
public String s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user