package org.enumerable.lambda.support.expression;
import static java.lang.System.*;
import static java.util.Arrays.*;
import static org.enumerable.lambda.support.expression.LambdaExpressionTrees.*;
import static org.junit.Assert.*;
import japa.parser.ast.expr.Expression;
import java.awt.Dimension;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.List;
import org.enumerable.lambda.weaving.InMemoryCompiler;
import org.junit.Test;
public class ExpressionTreeTest {
static boolean debug = false;
InMemoryCompiler compiler = new InMemoryCompiler();
@Test
public void parseLiteralExpressions() throws Exception {
assertEquals(parseExpression("0"), parseViaASM("0", int.class));
assertEquals(parseExpression("-1"), parseViaASM("-1", int.class));
assertEquals(parseExpression("1"), parseViaASM("1", int.class));
assertEquals(parseExpression("42"), parseViaASM("42", int.class));
assertEquals(parseExpression("" + (1024 * 1024)), parseViaASM("" + (1024 * 1024), int.class));
assertEquals(parseExpression("1.0"), parseViaASM("1.0", double.class));
assertEquals(parseExpression("1L"), parseViaASM("1L", long.class));
assertEquals(parseExpression("42L"), parseViaASM("42L", long.class));
assertEquals(parseExpression("1.0f"), parseViaASM("1.0f", float.class));
assertEquals(parseExpression("42.0f"), parseViaASM("42.0f", float.class));
assertEquals(parseExpression("-2"), parseViaASM("-2", int.class));
assertEquals(parseExpression("-1.0"), parseViaASM("-1.0", double.class));
assertEquals(parseExpression("-1L"), parseViaASM("-1L", long.class));
assertEquals(parseExpression("-1.0f"), parseViaASM("-1.0f", float.class));
assertEquals(parseExpression("" + (-1024 * 1024)), parseViaASM("" + (-1024 * 1024), int.class));
assertEquals(parseExpression("\"Hello World\""), parseViaASM("\"Hello World\"", String.class));
assertEquals(parseExpression("java.lang.String.class"), parseViaASM("java.lang.String.class", Class.class));
assertEquals(parseExpression("null"), parseViaASM("null", Object.class));
}
@Test
public void parseCharLiteralExpressionWhichCannotBeToldFromIntsInBytecode() throws Exception {
assertEquals(parseExpression("97"), parseViaASM("'a'", char.class));
}
@Test
public void parseBooleanLiteralExpressions() throws Exception {
assertEquals(parseExpression("true"), parseViaASM("true", boolean.class));
assertEquals(parseExpression("false"), parseViaASM("false", boolean.class));
}
@Test
public void parseInlinedUnaryExpressions() throws Exception {
assertEquals(parseExpression("1"), parseViaASM("+1", int.class));
assertEquals(parseExpression("-1"), parseViaASM("~0", int.class));
assertEquals(parseExpression("false"), parseViaASM("!true", boolean.class));
assertEquals(parseExpression("true"), parseViaASM("!false", boolean.class));
}
@Test
public void parseResolvedParameterExpressions() throws Exception {
assertEquals(parseExpression("i"), parseViaASM("i", int.class, param(int.class, "i")));
assertEquals(parseExpression("j"),
parseViaASM("j", int.class, param(int.class, "i"), param(int.class, "j")));
assertEquals(parseExpression("d"), parseViaASM("d", double.class, param(double.class, "d")));
assertEquals(parseExpression("j"), parseViaASM("j", int.class, param(double.class, "d"), param(int.class,
"j")));
}
@Test
public void parseThisExpressions() throws Exception {
assertEquals(parseExpression("this"), parseViaASM("this", Object.class));
assertEquals(parseExpression("this"), parseViaASM("this", Object.class, param(int.class, "i")));
}
@Test
public void parseIincUnaryExpressions() throws Exception {
assertEquals(parseExpression("i++"), parseViaASM("i++", int.class, param(int.class, "i")));
assertEquals(parseExpression("i--"), parseViaASM("i--", int.class, param(int.class, "i")));
assertEquals(parseExpression("++i"), parseViaASM("++i", int.class, param(int.class, "i")));
assertEquals(parseExpression("--i"), parseViaASM("--i", int.class, param(int.class, "i")));
assertEquals(parseExpression("++i"), parseViaASM("i += 1", int.class, param(int.class, "i")));
assertEquals(parseExpression("--i"), parseViaASM("i -= 1", int.class, param(int.class, "i")));
assertEquals(parseExpression("i += 2"), parseViaASM("i += 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i -= 2"), parseViaASM("i -= 2", int.class, param(int.class, "i")));
}
@Test
public void parseNegateUnaryExpressions() throws Exception {
assertEquals(parseExpression("-i"), parseViaASM("-i", int.class, param(int.class, "i")));
assertEquals(parseExpression("-d"), parseViaASM("-d", double.class, param(double.class, "d")));
assertEquals(parseExpression("-f"), parseViaASM("-f", float.class, param(float.class, "f")));
assertEquals(parseExpression("-l"), parseViaASM("-l", long.class, param(long.class, "l")));
}
@Test
public void parseInncUnaryExpressionsWhichAreBinaryInSouuce() throws Exception {
assertEquals(parseExpression("i += 2"), parseViaASM("i += 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i -= 2"), parseViaASM("i -= 2", int.class, param(int.class, "i")));
}
@Test
public void parseIncrementAssignUnaryExpressionsWhichAreBinaryInSouuce() throws Exception {
assertEquals(parseExpression("d += 2.0"), parseViaASM("d += 2.0", double.class, param(double.class, "d")));
assertEquals(parseExpression("d -= 2.0"), parseViaASM("d -= 2.0", double.class, param(double.class, "d")));
assertEquals(parseExpression("f += 2.0f"), parseViaASM("f += 2.0f", float.class, param(float.class, "f")));
assertEquals(parseExpression("f -= 2.0f"), parseViaASM("f -= 2.0f", float.class, param(float.class, "f")));
assertEquals(parseExpression("l += 2L"), parseViaASM("l += 2L", long.class, param(long.class, "l")));
assertEquals(parseExpression("l -= 2L"), parseViaASM("l -= 2L", long.class, param(long.class, "l")));
}
@Test
public void parseInverseUnaryExpressionsWhichAreBinaryXorInBytecode() throws Exception {
assertEquals(parseExpression("~i"), parseViaASM("~i", int.class, param(int.class, "i")));
assertEquals(parseExpression("~l"), parseViaASM("~l", long.class, param(long.class, "l")));
}
@Test
public void parsePrimitiveCastUnaryExpressions() throws Exception {
assertEquals(parseExpression("(int) l"), parseViaASM("(int) l", int.class, param(long.class, "l")));
assertEquals(parseExpression("(int) f"), parseViaASM("(int) f", int.class, param(float.class, "f")));
assertEquals(parseExpression("(int) d"), parseViaASM("(int) d", int.class, param(double.class, "d")));
assertEquals(parseExpression("(byte) i"), parseViaASM("(byte) i", byte.class, param(int.class, "i")));
assertEquals(parseExpression("(char) i"), parseViaASM("(char) i", char.class, param(int.class, "i")));
assertEquals(parseExpression("(short) i"), parseViaASM("(short) i", short.class, param(int.class, "i")));
assertEquals(parseExpression("(float) i"), parseViaASM("(float) i", float.class, param(int.class, "i")));
assertEquals(parseExpression("(float) l"), parseViaASM("(float) l", float.class, param(long.class, "l")));
assertEquals(parseExpression("(float) d"), parseViaASM("(float) d", float.class, param(double.class, "d")));
assertEquals(parseExpression("(long) i"), parseViaASM("(long) i", long.class, param(int.class, "i")));
assertEquals(parseExpression("(long) f"), parseViaASM("(long) f", long.class, param(float.class, "f")));
assertEquals(parseExpression("(long) d"), parseViaASM("(long) d", long.class, param(double.class, "d")));
assertEquals(parseExpression("(double) i"), parseViaASM("(double) i", double.class, param(int.class, "i")));
assertEquals(parseExpression("(double) l"), parseViaASM("(double) l", double.class, param(long.class, "l")));
assertEquals(parseExpression("(double) f"),
parseViaASM("(double) f", double.class, param(float.class, "f")));
}
@Test
public void parseInstanceOfExpressions() throws Exception {
assertEquals(parseExpression("o instanceof java.util.List"), parseViaASM("o instanceof java.util.List", boolean.class, param(
Object.class, "o")));
}
@Test
public void parseCastUnaryExpressions() throws Exception {
assertEquals(parseExpression("(String) o"), parseViaASM("(String) o", String.class,
param(Object.class, "o")));
assertEquals(parseExpression("(java.util.List) o"), parseViaASM("(java.util.List) o", List.class, param(
Object.class, "o")));
}
@Test
public void parseCastUnaryExpressionsWhichGetsRemovedInBytecode() throws Exception {
assertEquals(parseExpression("o"), parseViaASM("(Object) o", Object.class, param(Object.class, "o")));
}
@Test
public void parseMethodCalls() throws Exception {
assertEquals(parseExpression("System.currentTimeMillis()"), parseViaASM("System.currentTimeMillis()",
long.class));
assertEquals(parseExpression("toString()"), parseViaASM("toString()", String.class));
assertEquals(parseExpression("s.toUpperCase()"), parseViaASM("s.toUpperCase()", String.class, param(
String.class, "s")));
assertEquals(parseExpression("equals(\"Hello World\")"), parseViaASM("equals(\"Hello World\")",
boolean.class));
assertEquals(parseExpression("equals(s)"),
parseViaASM("equals(s)", boolean.class, param(String.class, "s")));
}
@Test
public void parseArithmeticBinaryExpressions() throws Exception {
assertEquals(parseExpression("i + i"), parseViaASM("i + i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i - i"), parseViaASM("i - i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i * i"), parseViaASM("i * i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i / i"), parseViaASM("i / i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i % i"), parseViaASM("i % i", int.class, param(int.class, "i")));
assertEquals(parseExpression("d + d"), parseViaASM("d + d", double.class, param(double.class, "d")));
assertEquals(parseExpression("d - d"), parseViaASM("d - d", double.class, param(double.class, "d")));
assertEquals(parseExpression("d * d"), parseViaASM("d * d", double.class, param(double.class, "d")));
assertEquals(parseExpression("d / d"), parseViaASM("d / d", double.class, param(double.class, "d")));
assertEquals(parseExpression("d % d"), parseViaASM("d % d", double.class, param(double.class, "d")));
assertEquals(parseExpression("f + f"), parseViaASM("f + f", float.class, param(float.class, "f")));
assertEquals(parseExpression("f - f"), parseViaASM("f - f", float.class, param(float.class, "f")));
assertEquals(parseExpression("f * f"), parseViaASM("f * f", float.class, param(float.class, "f")));
assertEquals(parseExpression("f / f"), parseViaASM("f / f", float.class, param(float.class, "f")));
assertEquals(parseExpression("f % f"), parseViaASM("f % f", float.class, param(float.class, "f")));
assertEquals(parseExpression("l + l"), parseViaASM("l + l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l - l"), parseViaASM("l - l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l * l"), parseViaASM("l * l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l / l"), parseViaASM("l / l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l % l"), parseViaASM("l % l", long.class, param(long.class, "l")));
}
@Test
public void parseShiftBinaryExpressions() throws Exception {
assertEquals(parseExpression("i << 2"), parseViaASM("i << 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i >> 2"), parseViaASM("i >> 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i >>> 2"), parseViaASM("i >>> 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("l << 2"), parseViaASM("l << 2", long.class, param(long.class, "l")));
assertEquals(parseExpression("l >> 2"), parseViaASM("l >> 2", long.class, param(long.class, "l")));
assertEquals(parseExpression("l >>> 2"), parseViaASM("l >>> 2", long.class, param(long.class, "l")));
}
@Test
public void parseBitwiseBinaryExpressions() throws Exception {
assertEquals(parseExpression("i | i"), parseViaASM("i | i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i & i"), parseViaASM("i & i", int.class, param(int.class, "i")));
assertEquals(parseExpression("i ^ i"), parseViaASM("i ^ i", int.class, param(int.class, "i")));
assertEquals(parseExpression("l | l"), parseViaASM("l | l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l & l"), parseViaASM("l & l", long.class, param(long.class, "l")));
assertEquals(parseExpression("l ^ l"), parseViaASM("l ^ l", long.class, param(long.class, "l")));
}
@Test
public void parseAssignExpressions() throws Exception {
assertEquals(parseExpression("i = 2"), parseViaASM("i = 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("Math.max(i = 2, i)"), parseViaASM("Math.max(i = 2, i)", int.class, param(
int.class, "i")));
}
@Test
public void parseAssignExpressionsWhichAreExpandedInBytecode() throws Exception {
assertEquals(parseExpression("i -= 2"), parseViaASM("i -= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i *= 2"), parseViaASM("i *= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i /= 2"), parseViaASM("i /= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i &= 2"), parseViaASM("i &= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i |= 2"), parseViaASM("i |= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i ^= 2"), parseViaASM("i ^= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i %= 2"), parseViaASM("i %= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i <<= 2"), parseViaASM("i <<= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i >>= 2"), parseViaASM("i >>= 2", int.class, param(int.class, "i")));
assertEquals(parseExpression("i >>>= 2"), parseViaASM("i >>>= 2", int.class, param(int.class, "i")));
}
@Test
public void parseArrayAccessExpressions() throws Exception {
assertEquals(parseExpression("i[0]"), parseViaASM("i[0]", int.class, param(int[].class, "i")));
assertEquals(parseExpression("d[0]"), parseViaASM("d[0]", double.class, param(double[].class, "d")));
assertEquals(parseExpression("f[0]"), parseViaASM("f[0]", float.class, param(float[].class, "f")));
assertEquals(parseExpression("l[0]"), parseViaASM("l[0]", long.class, param(long[].class, "l")));
assertEquals(parseExpression("i[0] = 2"), parseViaASM("i[0] = 2", int.class, param(int[].class, "i")));
assertEquals(parseExpression("d[0] = 2.0"), parseViaASM("d[0] = 2.0", double.class, param(double[].class,
"d")));
assertEquals(parseExpression("f[0] = 2.0f"), parseViaASM("f[0] = 2.0f", float.class, param(float[].class,
"f")));
assertEquals(parseExpression("l[0] = 2L"), parseViaASM("l[0] = 2L", long.class, param(long[].class, "l")));
}
@Test
public void parseArrayLengthExpression() throws Exception {
assertEquals(parseExpression("i.length"), parseViaASM("i.length", int.class, param(int[].class, "i")));
}
@Test
public void parseFieldExpressions() throws Exception {
assertEquals(parseExpression("d.width"), parseViaASM("d.width", int.class, param(Dimension.class, "d")));
assertEquals(parseExpression("System.out"), parseViaASM("System.out", PrintStream.class));
assertEquals(parseExpression("d.width = 1"), parseViaASM("d.width = 1", int.class, param(Dimension.class,
"d")));
}
@Test
public void parseNewExpression() throws Exception {
assertEquals(parseExpression("new String()"), parseViaASM("new String()", String.class));
assertEquals(parseExpression("new String(\"Hello World\")"), parseViaASM("new String(\"Hello World\")",
String.class));
}
@Test
public void parseNewArrayExpression() throws Exception {
assertEquals(parseExpression("new String[0]"), parseViaASM("new String[0]", String[].class));
assertEquals(parseExpression("new String[] {\"Hello World\"}"), parseViaASM(
"new String[] {\"Hello World\"}", String[].class));
assertEquals(parseExpression("new String[] {\"Hello\", \"World\"}"), parseViaASM(
"new String[] {\"Hello\", \"World\"}", String[].class));
}
@Test
public void parseNewPrimtiveArrayExpression() throws Exception {
assertEquals(parseExpression("new int[0]"), parseViaASM("new int[0]", int[].class));
assertEquals(parseExpression("new int[] {1}"), parseViaASM("new int[] {1}", int[].class));
assertEquals(parseExpression("new int[] {1, 2}"), parseViaASM("new int[] {1, 2}", int[].class));
assertEquals(parseExpression("new double[0]"), parseViaASM("new double[0]", double[].class));
assertEquals(parseExpression("new double[] {1.0}"), parseViaASM("new double[] {1.0}", double[].class));
assertEquals(parseExpression("new double[] {1.0, 2.0}"), parseViaASM("new double[] {1.0, 2.0}",
double[].class));
assertEquals(parseExpression("new float[0]"), parseViaASM("new float[0]", float[].class));
assertEquals(parseExpression("new float[] {1.0f}"), parseViaASM("new float[] {1.0f}", float[].class));
assertEquals(parseExpression("new float[] {1.0f, 2.0f}"), parseViaASM("new float[] {1.0f, 2.0f}",
float[].class));
assertEquals(parseExpression("new long[0]"), parseViaASM("new long[0]", long[].class));
assertEquals(parseExpression("new long[] {1L}"), parseViaASM("new long[] {1L}", long[].class));
assertEquals(parseExpression("new long[] {1L, 2L}"), parseViaASM("new long[] {1L, 2L}", long[].class));
}
@Test
public void parseNewArrayExpressionWithEmptyInitilizerWhichGetsRemovedInBytecode() throws Exception {
assertEquals(parseExpression("new String[0]"), parseViaASM("new String[] {}", String[].class));
}
@Test
public void parseNotUnaryExpression() throws Exception {
assertEquals(parseExpression("!b"), parseViaASM("!b", boolean.class, param(boolean.class, "b")));
}
@Test
public void parseIntComparsionBinaryExpression() throws Exception {
assertEquals(parseExpression("i == 1"), parseViaASM("i == 1", boolean.class, param(int.class, "i")));
assertEquals(parseExpression("i != 1"), parseViaASM("i != 1", boolean.class, param(int.class, "i")));
assertEquals(parseExpression("i < 1"), parseViaASM("i < 1", boolean.class, param(int.class, "i")));
assertEquals(parseExpression("i > 1"), parseViaASM("i > 1", boolean.class, param(int.class, "i")));
assertEquals(parseExpression("i <= 1"), parseViaASM("i <= 1", boolean.class, param(int.class, "i")));
assertEquals(parseExpression("i >= 1"), parseViaASM("i >= 1", boolean.class, param(int.class, "i")));
}
@Test
public void parseReferenceComparsionBinaryExpression() throws Exception {
assertEquals(parseExpression("o1 == o2"), parseViaASM("o1 == o2", boolean.class, param(Object.class, "o1"),
param(Object.class, "o2")));
assertEquals(parseExpression("o1 != o2"), parseViaASM("o1 != o2", boolean.class, param(Object.class, "o1"),
param(Object.class, "o2")));
}
@Test
public void parseReferenceComparsionWithNullBinaryExpression() throws Exception {
assertEquals(parseExpression("o == null"),
parseViaASM("o == null", boolean.class, param(Object.class, "o")));
assertEquals(parseExpression("o != null"),
parseViaASM("o != null", boolean.class, param(Object.class, "o")));
if (InMemoryCompiler.useECJ) {
assertEquals(parseExpression("o == null"), parseViaASM("null == o", boolean.class, param(Object.class,
"o")));
assertEquals(parseExpression("o != null"), parseViaASM("null != o", boolean.class, param(Object.class,
"o")));
} else {
assertEquals(parseExpression("null == o"), parseViaASM("null == o", boolean.class, param(Object.class,
"o")));
assertEquals(parseExpression("null != o"), parseViaASM("null != o", boolean.class, param(Object.class,
"o")));
}
}
@Test
public void parseLongComparsionBinaryExpression() throws Exception {
assertEquals(parseExpression("l == 1L"), parseViaASM("l == 1L", boolean.class, param(long.class, "l")));
assertEquals(parseExpression("l != 1L"), parseViaASM("l != 1L", boolean.class, param(long.class, "l")));
assertEquals(parseExpression("l < 1L"), parseViaASM("l < 1L", boolean.class, param(long.class, "l")));
assertEquals(parseExpression("l > 1L"), parseViaASM("l > 1L", boolean.class, param(long.class, "l")));
assertEquals(parseExpression("l <= 1L"), parseViaASM("l <= 1L", boolean.class, param(long.class, "l")));
assertEquals(parseExpression("l >= 1L"), parseViaASM("l >= 1L", boolean.class, param(long.class, "l")));
}
@Test
public void parseFloatComparsionBinaryExpression() throws Exception {
assertEquals(parseExpression("f == 1.0f"), parseViaASM("f == 1.0f", boolean.class, param(float.class, "f")));
assertEquals(parseExpression("f != 1.0f"), parseViaASM("f != 1.0f", boolean.class, param(float.class, "f")));
assertEquals(parseExpression("f < 1.0f"), parseViaASM("f < 1.0f", boolean.class, param(float.class, "f")));
assertEquals(parseExpression("f > 1.0f"), parseViaASM("f > 1.0f", boolean.class, param(float.class, "f")));
assertEquals(parseExpression("f <= 1.0f"), parseViaASM("f <= 1.0f", boolean.class, param(float.class, "f")));
assertEquals(parseExpression("f >= 1.0f"), parseViaASM("f >= 1.0f", boolean.class, param(float.class, "f")));
}
@Test
public void parseDoubleComparsionBinaryExpression() throws Exception {
assertEquals(parseExpression("d == 1.0"), parseViaASM("d == 1.0", boolean.class, param(double.class, "d")));
assertEquals(parseExpression("d != 1.0"), parseViaASM("d != 1.0", boolean.class, param(double.class, "d")));
assertEquals(parseExpression("d < 1.0"), parseViaASM("d < 1.0", boolean.class, param(double.class, "d")));
assertEquals(parseExpression("d > 1.0"), parseViaASM("d > 1.0", boolean.class, param(double.class, "d")));
assertEquals(parseExpression("d <= 1.0"), parseViaASM("d <= 1.0", boolean.class, param(double.class, "d")));
assertEquals(parseExpression("d >= 1.0"), parseViaASM("d >= 1.0", boolean.class, param(double.class, "d")));
}
@Test
public void parseBooleanUnaryExpressionWhichAreBinaryInBytecode() throws Exception {
assertEquals(parseExpression("b"), parseViaASM("b == true", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("!b"), parseViaASM("b == false", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("b"), parseViaASM("true == b", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("!b"), parseViaASM("false == b", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("!b"), parseViaASM("b != true", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("b"), parseViaASM("b != false", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("!b"), parseViaASM("true != b", boolean.class, param(boolean.class, "b")));
assertEquals(parseExpression("b"), parseViaASM("false != b", boolean.class, param(boolean.class, "b")));
}
@Test
public void parseBooleanLogicalBinaryExpressionWhichArUnaryInByteCode() throws Exception {
assertEquals(parseExpression("false"), parseViaASM("true && false", boolean.class));
assertEquals(parseExpression("false"), parseViaASM("false && true", boolean.class));
assertEquals(parseExpression("false"), parseViaASM("false && false", boolean.class));
assertEquals(parseExpression("true"), parseViaASM("true && true", boolean.class));
assertEquals(parseExpression("true"), parseViaASM("true || false", boolean.class));
assertEquals(parseExpression("true"), parseViaASM("false || true", boolean.class));
assertEquals(parseExpression("true"), parseViaASM("true || true", boolean.class));
assertEquals(parseExpression("false"), parseViaASM("false || false", boolean.class));
}
@Test
public void parseBooleanLogicalBinaryExpression() throws Exception {
assertEquals(parseExpression("b1 && b2"), parseViaASM("b1 && b2", boolean.class,
param(boolean.class, "b1"), param(boolean.class, "b2")));
assertEquals(parseExpression("b1 || b2"), parseViaASM("b1 || b2", boolean.class,
param(boolean.class, "b1"), param(boolean.class, "b2")));
}
@Test
public void parseBooleanNestedLogicalBinaryExpressions() throws Exception {
assertEquals(parseExpression("i == 1 && b"), parseViaASM("i == 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i == 1 || b"), parseViaASM("i == 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i == 1"), parseViaASM("b && i == 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i == 1"), parseViaASM("b || i == 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i != 1 && b"), parseViaASM("i != 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i != 1 || b"), parseViaASM("i != 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i != 1"), parseViaASM("b && i != 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i != 1"), parseViaASM("b || i != 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i > 1 && b"), parseViaASM("i > 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i > 1"), parseViaASM("b && i > 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i > 1 || b"), parseViaASM("i > 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i > 1"), parseViaASM("b || i > 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i < 1 && b"), parseViaASM("i < 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i < 1"), parseViaASM("b && i < 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i < 1 || b"), parseViaASM("i < 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i < 1"), parseViaASM("b || i < 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i <= 1 && b"), parseViaASM("i <= 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i <= 1"), parseViaASM("b && i <= 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i <= 1 || b"), parseViaASM("i <= 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i <= 1"), parseViaASM("b || i <= 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i >= 1 && b"), parseViaASM("i >= 1 && b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b && i >= 1"), parseViaASM("b && i >= 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("i >= 1 || b"), parseViaASM("i >= 1 || b", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("b || i >= 1"), parseViaASM("b || i >= 1", boolean.class, param(boolean.class,
"b"), param(int.class, "i")));
assertEquals(parseExpression("o == null && b"), parseViaASM("o == null && b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("o == null || b"), parseViaASM("o == null || b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("b && o == null"), parseViaASM("b && o == null", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("b || o == null"), parseViaASM("b || o == null", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("o != null && b"), parseViaASM("o != null && b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("o != null || b"), parseViaASM("o != null || b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("b && o != null"), parseViaASM("b && o != null", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("b || o != null"), parseViaASM("b || o != null", boolean.class, param(
boolean.class, "b"), param(Object.class, "o")));
assertEquals(parseExpression("o1 == o2 && b"), parseViaASM("o1 == o2 && b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("o1 == o2 || b"), parseViaASM("o1 == o2 || b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("b && o1 == o2"), parseViaASM("b && o1 == o2", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("b || o1 == o2"), parseViaASM("b || o1 == o2", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("o1 != o2 && b"), parseViaASM("o1 != o2 && b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("o1 != o2 || b"), parseViaASM("o1 != o2 || b", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("b && o1 != o2"), parseViaASM("b && o1 != o2", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("b || o1 != o2"), parseViaASM("b || o1 != o2", boolean.class, param(
boolean.class, "b"), param(Object.class, "o1"), param(Object.class, "o2")));
assertEquals(parseExpression("i1 > 1 && i2 < 1"), parseViaASM("i1 > 1 && i2 < 1", boolean.class, param(
int.class, "i1"), param(int.class, "i2")));
assertEquals(parseExpression("i1 > 1 || i2 < 1"), parseViaASM("i1 > 1 || i2 < 1", boolean.class, param(
int.class, "i1"), param(int.class, "i2")));
}
@Test
public void parseConditionalTernaryExpression() throws Exception {
assertEquals(parseExpression("b ? \"Hello\" : \"World\""), parseViaASM("b ? \"Hello\" : \"World\"",
String.class, param(boolean.class, "b")));
}
@Test
public void parseConditionalTernaryExpressionsWhichAreInlinedInBytecode() throws Exception {
assertEquals(parseExpression("\"Hello\""), parseViaASM("true ? \"Hello\" : \"World\"", String.class));
assertEquals(parseExpression("\"World\""), parseViaASM("false ? \"Hello\" : \"World\"", String.class));
}
static int expressionId = 1;
Param param(Class<?> type, String name) {
return new Param(type, name);
}
class Param {
Class<?> type;
String name;
Param(Class<?> type, String name) {
this.type = type;
this.name = name;
}
public String toString() {
if (type.isArray())
return type.getComponentType() + "[] " + name;
return type.getName() + " " + name;
}
}
Expression parseViaASM(String expression, Class<?> returnValue, Param... parameters) throws Exception {
Class<?> c = compileExpression(expression, returnValue, parameters);
Class<?>[] parameterTypes = new Class<?>[parameters.length];
String[] parameterNames = new String[parameters.length];
for (int i = 0; i < parameters.length; i++) {
parameterNames[i] = parameters[i].name;
parameterTypes[i] = parameters[i].type;
}
Method method = c.getDeclaredMethod("eval", parameterTypes);
debug("compiling: " + expression);
debug("asm:");
if (debug)
printASMifiedMethod(method);
Expression result = parseExpressionFromSingleMethodClass(c, parameterNames);
debug("decompiled: " + result + (result == null ? "" : " // " + result.getClass()));
debug("");
return result;
}
Class<?> compileExpression(String expression, Class<?> returnValue, Param... parameters) throws IOException {
String className = "Expression" + expressionId++;
String parametersString = asList(parameters).toString();
parametersString = "(" + parametersString.substring(1, parametersString.length() - 1) + ")";
parametersString = parametersString.substring(0, parametersString.length() - 1) + ")";
String returnType = returnValue.isArray() ? returnValue.getComponentType().getName() + "[]" : returnValue
.getName();
String source = "class " + className + " { " + returnType + " eval" + parametersString + " { return "
+ expression + "; }}";
return (Class<?>) compiler.compile(className, source);
}
void debug(String msg) {
if (debug)
out.println(msg);
}
}