added string support for lambda expressions

This commit is contained in:
wea_ondara
2022-09-18 14:28:50 +02:00
parent 6870435eea
commit 27198a1e78
12 changed files with 110 additions and 20 deletions

View File

@@ -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

View File

@@ -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 {

View File

@@ -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();
} }
} }

View File

@@ -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
; ;

View 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(", ")) + ")";
}
}

View File

@@ -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();
} }

View File

@@ -25,6 +25,6 @@ public class TableExpression extends ConstantExpression {
@Override @Override
public String toString() { public String toString() {
return "`" + super.toString() + "`"; return "`" + name + "`";
} }
} }

View File

@@ -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;
} }

View File

@@ -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());

View File

@@ -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) {
} }

View File

@@ -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;
} }
} }