Implement toString in painless's AST
This should make debugging painless' analysis and code generation a little easier. The `toString` implementations mirror the AST somewhat, and look like `(SSource (SReturn (ENumeric 1)))`.
This commit is contained in:
parent
cb5c25ab4f
commit
f5c8c746e6
|
@ -27,7 +27,7 @@ package org.elasticsearch.painless;
|
|||
*/
|
||||
public enum Operation {
|
||||
|
||||
MUL ( "+" ),
|
||||
MUL ( "*" ),
|
||||
DIV ( "/" ),
|
||||
REM ( "%" ),
|
||||
ADD ( "+" ),
|
||||
|
|
|
@ -24,9 +24,18 @@ import org.elasticsearch.painless.Locals;
|
|||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.lang.Math.max;
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* The superclass for all nodes.
|
||||
*/
|
||||
|
@ -62,7 +71,87 @@ public abstract class ANode {
|
|||
*/
|
||||
abstract void write(MethodWriter writer, Globals globals);
|
||||
|
||||
/**
|
||||
* Create an error with location information pointing to this node.
|
||||
*/
|
||||
RuntimeException createError(RuntimeException exception) {
|
||||
return location.createError(exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* Subclasses should implement this with a method like {@link #singleLineToString(Object...)} or
|
||||
* {@link #multilineToString(Collection, Collection)}.
|
||||
*/
|
||||
public abstract String toString();
|
||||
|
||||
// Below are utilities for building the toString
|
||||
|
||||
/**
|
||||
* Build {@link #toString()} for a node without inserting line breaks between the sub-nodes.
|
||||
*/
|
||||
protected String singleLineToString(Object... subs) {
|
||||
return singleLineToString(Arrays.asList(subs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link #toString()} for a node without inserting line breaks between the sub-nodes.
|
||||
*/
|
||||
protected String singleLineToString(Collection<? extends Object> subs) {
|
||||
return joinWithName(getClass().getSimpleName(), subs, emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link #toString()} for a node that optionally ends in {@code (Args some arguments here)}. Usually function calls.
|
||||
*/
|
||||
protected String singleLineToStringWithOptionalArgs(Collection<? extends ANode> arguments, Object... restOfSubs) {
|
||||
List<Object> subs = new ArrayList<>();
|
||||
Collections.addAll(subs, restOfSubs);
|
||||
if (false == arguments.isEmpty()) {
|
||||
subs.add(joinWithName("Args", arguments, emptyList()));
|
||||
}
|
||||
return singleLineToString(subs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build {@link #toString()} for a node that should have new lines after some of its sub-nodes.
|
||||
*/
|
||||
protected String multilineToString(Collection<? extends Object> sameLine, Collection<? extends Object> ownLine) {
|
||||
return joinWithName(getClass().getSimpleName(), sameLine, ownLine);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip two (potentially uneven) lists together into for {@link #toString()}.
|
||||
*/
|
||||
protected List<String> pairwiseToString(Collection<? extends Object> lefts, Collection<? extends Object> rights) {
|
||||
List<String> pairs = new ArrayList<>(max(lefts.size(), rights.size()));
|
||||
Iterator<? extends Object> left = lefts.iterator();
|
||||
Iterator<? extends Object> right = rights.iterator();
|
||||
while (left.hasNext() || right.hasNext()) {
|
||||
pairs.add(joinWithName("Pair",
|
||||
Arrays.asList(left.hasNext() ? left.next() : "<uneven>", right.hasNext() ? right.next() : "<uneven>"),
|
||||
emptyList()));
|
||||
}
|
||||
return pairs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a {@link #toString()} for some expressions. Usually best to use {@link #singleLineToString(Object...)} or
|
||||
* {@link #multilineToString(Collection, Collection)} instead because they include the name of the node by default.
|
||||
*/
|
||||
protected String joinWithName(String name, Collection<? extends Object> sameLine,
|
||||
Collection<? extends Object> ownLine) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
b.append('(').append(name);
|
||||
for (Object sub : sameLine) {
|
||||
b.append(' ').append(sub);
|
||||
}
|
||||
if (ownLine.size() == 1 && sameLine.isEmpty()) {
|
||||
b.append(' ').append(ownLine.iterator().next());
|
||||
} else {
|
||||
for (Object sub : ownLine) {
|
||||
b.append("\n ").append(Objects.toString(sub).replace("\n", "\n "));
|
||||
}
|
||||
}
|
||||
return b.append(')').toString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,8 @@ import org.elasticsearch.painless.Location;
|
|||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -322,4 +324,24 @@ public final class EAssignment extends AExpression {
|
|||
lhs.store(writer, globals); // store the lhs's value from the stack in its respective variable/field/array
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
List<Object> subs = new ArrayList<>();
|
||||
subs.add(lhs);
|
||||
if (rhs != null) {
|
||||
// Make sure "=" is in the symbol so this is easy to read at a glance
|
||||
subs.add(operation == null ? "=" : operation.symbol + "=");
|
||||
subs.add(rhs);
|
||||
return singleLineToString(subs);
|
||||
}
|
||||
subs.add(operation.symbol);
|
||||
if (pre) {
|
||||
subs.add("pre");
|
||||
}
|
||||
if (post) {
|
||||
subs.add("post");
|
||||
}
|
||||
return singleLineToString(subs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -681,4 +681,9 @@ public final class EBinary extends AExpression {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(left, operation.symbol, right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,4 +114,9 @@ public final class EBool extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(left, operation.symbol, right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,4 +56,9 @@ public final class EBoolean extends AExpression {
|
|||
void write(MethodWriter adapter, Globals globals) {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(constant);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -88,4 +88,9 @@ public final class ECallLocal extends AExpression {
|
|||
|
||||
writer.invokeStatic(CLASS_TYPE, method.method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,4 +136,9 @@ public final class ECapturingFunctionRef extends AExpression implements ILambda
|
|||
public Type[] getCaptures() {
|
||||
return new Type[] { captured.type.type };
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(variable, call);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,4 +60,9 @@ final class ECast extends AExpression {
|
|||
writer.writeDebugInfo(location);
|
||||
writer.writeCast(cast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(cast.to, child);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -568,4 +568,9 @@ public final class EComp extends AExpression {
|
|||
writer.mark(end);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(left, operation.symbol, right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,4 +106,9 @@ public final class EConditional extends AExpression {
|
|||
right.write(writer, globals);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(condition, left, right);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,4 +89,13 @@ final class EConstant extends AExpression {
|
|||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String c = constant.toString();
|
||||
if (constant instanceof String) {
|
||||
c = "'" + c + "'";
|
||||
}
|
||||
return singleLineToString(constant.getClass().getSimpleName(), c);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,4 +75,9 @@ public final class EDecimal extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,4 +105,9 @@ public class EElvis extends AExpression {
|
|||
rhs.write(writer, globals);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(lhs, rhs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -74,4 +74,9 @@ public final class EExplicit extends AExpression {
|
|||
|
||||
return child.cast(locals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(type, child);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,4 +130,9 @@ public final class EFunctionRef extends AExpression implements ILambda {
|
|||
public Type[] getCaptures() {
|
||||
return new Type[0]; // no captures
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(type, call);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Represents instanceof operator.
|
||||
* Represents {@code instanceof} operator.
|
||||
* <p>
|
||||
* Unlike java's, this works for primitive types too.
|
||||
*/
|
||||
|
@ -96,4 +96,9 @@ public final class EInstanceof extends AExpression {
|
|||
writer.instanceOf(org.objectweb.asm.Type.getType(resolvedType));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(expression, type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,16 +19,16 @@
|
|||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.FunctionRef;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.elasticsearch.painless.Locals;
|
||||
import org.elasticsearch.painless.Locals.Variable;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.node.SFunction.FunctionReserved;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.FunctionRef;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.lang.invoke.LambdaMetafactory;
|
||||
|
@ -245,4 +245,9 @@ public final class ELambda extends AExpression implements ILambda {
|
|||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(pairwiseToString(paramTypeStrs, paramNameStrs), statements);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,4 +101,9 @@ public final class EListInit extends AExpression {
|
|||
writer.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(values);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,4 +124,9 @@ public final class EMapInit extends AExpression {
|
|||
writer.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(pairwiseToString(keys, values));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.elasticsearch.painless.Locals;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -108,4 +108,9 @@ public final class ENewArray extends AExpression {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, type, initialize ? "init" : "dims");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
import org.elasticsearch.painless.Definition.Type;
|
||||
import org.elasticsearch.painless.Globals;
|
||||
import org.elasticsearch.painless.Locals;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -110,4 +110,9 @@ public final class ENewObj extends AExpression {
|
|||
|
||||
writer.invokeConstructor(constructor.owner.type, constructor.method);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,4 +66,9 @@ public final class ENull extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
writer.visitInsn(Opcodes.ACONST_NULL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ import org.elasticsearch.painless.Locals;
|
|||
import org.elasticsearch.painless.MethodWriter;
|
||||
|
||||
/**
|
||||
* Respresents a non-decimal numeric constant.
|
||||
* Represents a non-decimal numeric constant.
|
||||
*/
|
||||
public final class ENumeric extends AExpression {
|
||||
|
||||
|
@ -121,4 +121,12 @@ public final class ENumeric extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
throw createError(new IllegalStateException("Illegal tree structure."));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (radix != 10) {
|
||||
return singleLineToString(value, radix);
|
||||
}
|
||||
return singleLineToString(value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,4 +104,23 @@ public final class ERegex extends AExpression {
|
|||
throw new IllegalArgumentException("Unknown flag [" + c + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder f = new StringBuilder();
|
||||
if ((flags & Pattern.CANON_EQ) != 0) f.append('c');
|
||||
if ((flags & Pattern.CASE_INSENSITIVE) != 0) f.append('i');
|
||||
if ((flags & Pattern.LITERAL) != 0) f.append('l');
|
||||
if ((flags & Pattern.MULTILINE) != 0) f.append('m');
|
||||
if ((flags & Pattern.DOTALL) != 0) f.append('s');
|
||||
if ((flags & Pattern.UNICODE_CHARACTER_CLASS) != 0) f.append('U');
|
||||
if ((flags & Pattern.UNICODE_CASE) != 0) f.append('u');
|
||||
if ((flags & Pattern.COMMENTS) != 0) f.append('x');
|
||||
|
||||
String p = "/" + pattern + "/";
|
||||
if (f.length() == 0) {
|
||||
return singleLineToString(p);
|
||||
}
|
||||
return singleLineToString(p, f);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,4 +60,9 @@ public final class EStatic extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(type);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,9 @@ public final class EString extends AExpression {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
throw new IllegalStateException("Illegal tree structure.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString("'" + constant.toString() + "'");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -249,4 +249,9 @@ public final class EUnary extends AExpression {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(operation.symbol, child);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,4 +95,9 @@ public final class EVariable extends AStoreable {
|
|||
void store(MethodWriter writer, Globals globals) {
|
||||
writer.visitVarInsn(actual.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,4 +117,9 @@ public final class PBrace extends AStoreable {
|
|||
void store(MethodWriter writer, Globals globals) {
|
||||
sub.store(writer, globals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,4 +106,9 @@ public final class PCallInvoke extends AExpression {
|
|||
prefix.write(writer, globals);
|
||||
sub.write(writer, globals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, prefix, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ public final class PField extends AStoreable {
|
|||
Sort sort = prefix.actual.sort;
|
||||
|
||||
if (sort == Sort.ARRAY) {
|
||||
sub = new PSubArrayLength(location,prefix.actual.name, value);
|
||||
sub = new PSubArrayLength(location, prefix.actual.name, value);
|
||||
} else if (sort == Sort.DEF) {
|
||||
sub = new PSubDefField(location, value);
|
||||
} else {
|
||||
|
@ -157,4 +157,12 @@ public final class PField extends AStoreable {
|
|||
void store(MethodWriter writer, Globals globals) {
|
||||
sub.store(writer, globals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (nullSafe) {
|
||||
return singleLineToString("nullSafe", prefix, value);
|
||||
}
|
||||
return singleLineToString(prefix, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,4 +97,9 @@ final class PSubArrayLength extends AStoreable {
|
|||
void store(MethodWriter writer, Globals globals) {
|
||||
throw new IllegalStateException("Illegal tree structure.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,4 +96,9 @@ final class PSubBrace extends AStoreable {
|
|||
writer.writeDebugInfo(location);
|
||||
writer.arrayStore(actual.type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,4 +81,9 @@ final class PSubCallInvoke extends AExpression {
|
|||
|
||||
method.write(writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, prefix, method.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,4 +104,9 @@ final class PSubDefArray extends AStoreable {
|
|||
org.objectweb.asm.Type.getMethodType(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, index.actual.type, actual.type);
|
||||
writer.invokeDefCall("arrayStore", methodType, DefBootstrap.ARRAY_STORE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,4 +114,9 @@ final class PSubDefCall extends AExpression {
|
|||
args.addAll(pointers);
|
||||
writer.invokeDefCall(name, methodType, DefBootstrap.METHOD_CALL, args.toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToStringWithOptionalArgs(arguments, prefix, name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,4 +99,9 @@ final class PSubDefField extends AStoreable {
|
|||
org.objectweb.asm.Type.getMethodType(Definition.VOID_TYPE.type, Definition.DEF_TYPE.type, actual.type);
|
||||
writer.invokeDefCall(value, methodType, DefBootstrap.STORE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,4 +110,9 @@ final class PSubField extends AStoreable {
|
|||
writer.putField(field.owner.type, field.javaName, field.type.type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, field.name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,4 +134,9 @@ final class PSubListShortcut extends AStoreable {
|
|||
|
||||
writer.writePop(setter.rtn.sort.size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -137,4 +137,9 @@ final class PSubMapShortcut extends AStoreable {
|
|||
|
||||
writer.writePop(setter.rtn.sort.size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,4 +67,9 @@ public class PSubNullSafeCallInvoke extends AExpression {
|
|||
guarded.write(writer, globals);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(guarded);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -96,4 +96,9 @@ public class PSubNullSafeField extends AStoreable {
|
|||
void store(MethodWriter writer, Globals globals) {
|
||||
throw createError(new IllegalArgumentException("Can't write to null safe field"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(guarded);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,4 +126,9 @@ final class PSubShortcut extends AStoreable {
|
|||
|
||||
writer.writePop(setter.rtn.sort.size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(prefix, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* Represents a set of statements as a branch of control-flow.
|
||||
*/
|
||||
|
@ -86,4 +88,9 @@ public final class SBlock extends AStatement {
|
|||
statement.write(writer, globals);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(emptyList(), statements);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -56,4 +56,9 @@ public final class SBreak extends AStatement {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
writer.goTo(brake);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,4 +117,9 @@ public final class SCatch extends AStatement {
|
|||
writer.goTo(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(type, name, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,4 +59,9 @@ public final class SContinue extends AStatement {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
writer.goTo(continu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* Represents a series of declarations.
|
||||
*/
|
||||
|
@ -63,4 +65,9 @@ public final class SDeclBlock extends AStatement {
|
|||
declaration.write(writer, globals);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(emptyList(), declarations);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -101,4 +101,12 @@ public final class SDeclaration extends AStatement {
|
|||
|
||||
writer.visitVarInsn(variable.type.type.getOpcode(Opcodes.ISTORE), variable.getSlot());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (expression == null) {
|
||||
return singleLineToString(type, name);
|
||||
}
|
||||
return singleLineToString(type, name, expression);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,4 +125,9 @@ public final class SDo extends AStatement {
|
|||
writer.goTo(start);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(condition, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,4 +114,9 @@ public class SEach extends AStatement {
|
|||
void write(MethodWriter writer, Globals globals) {
|
||||
sub.write(writer, globals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(type, name, expression, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,4 +82,9 @@ public final class SExpression extends AStatement {
|
|||
writer.writePop(expression.expected.sort.size);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(expression);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,11 @@ import org.elasticsearch.painless.MethodWriter;
|
|||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
|
||||
/**
|
||||
* Represents a for loop.
|
||||
*/
|
||||
|
@ -203,4 +206,9 @@ public final class SFor extends AStatement {
|
|||
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(emptyList(), Arrays.asList(initializer, condition, afterthought, block));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import java.util.List;
|
|||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.elasticsearch.painless.WriterConstants.CLASS_TYPE;
|
||||
|
||||
/**
|
||||
|
@ -220,4 +221,15 @@ public final class SFunction extends AStatement {
|
|||
false);
|
||||
writer.push(handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
List<Object> description = new ArrayList<>();
|
||||
description.add(rtnTypeStr);
|
||||
description.add(name);
|
||||
if (false == (paramTypeStrs.isEmpty() && paramNameStrs.isEmpty())) {
|
||||
description.add(joinWithName("Args", pairwiseToString(paramTypeStrs, paramNameStrs), emptyList()));
|
||||
}
|
||||
return multilineToString(description, statements);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,4 +94,9 @@ public final class SIf extends AStatement {
|
|||
|
||||
writer.mark(fals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(condition, ifblock);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,12 @@ import org.elasticsearch.painless.MethodWriter;
|
|||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* Represents an if/else block.
|
||||
*/
|
||||
|
@ -128,4 +131,9 @@ public final class SIfElse extends AStatement {
|
|||
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(singleton(condition), Arrays.asList(ifblock, elseblock));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,4 +65,9 @@ public final class SReturn extends AStatement {
|
|||
expression.write(writer, globals);
|
||||
writer.returnValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(expression);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import java.util.Map;
|
|||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.elasticsearch.painless.WriterConstants.BASE_CLASS_TYPE;
|
||||
import static org.elasticsearch.painless.WriterConstants.CLASS_TYPE;
|
||||
import static org.elasticsearch.painless.WriterConstants.CONSTRUCTOR;
|
||||
|
@ -332,4 +333,12 @@ public final class SSource extends AStatement {
|
|||
public byte[] getBytes() {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
List<Object> subs = new ArrayList<>(functions.size() + statements.size());
|
||||
subs.addAll(functions);
|
||||
subs.addAll(statements);
|
||||
return multilineToString(emptyList(), subs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,4 +107,9 @@ final class SSubEachArray extends AStatement {
|
|||
writer.goTo(begin);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(variable.type.name, variable.name, expression, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,4 +129,9 @@ final class SSubEachIterable extends AStatement {
|
|||
writer.goTo(begin);
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(variable.type.name, variable.name, expression, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,4 +64,9 @@ public final class SThrow extends AStatement {
|
|||
expression.write(writer, globals);
|
||||
writer.throwException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(expression);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
|
||||
/**
|
||||
* Represents the try block as part of a try-catch block.
|
||||
*/
|
||||
|
@ -124,4 +126,9 @@ public final class STry extends AStatement {
|
|||
writer.mark(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return multilineToString(singleton(block), catches);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -134,4 +134,9 @@ public final class SWhile extends AStatement {
|
|||
|
||||
writer.mark(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return singleLineToString(condition, block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,905 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.painless.node;
|
||||
|
||||
import org.elasticsearch.painless.CompilerSettings;
|
||||
import org.elasticsearch.painless.Definition;
|
||||
import org.elasticsearch.painless.Definition.Cast;
|
||||
import org.elasticsearch.painless.Definition.Field;
|
||||
import org.elasticsearch.painless.Definition.Method;
|
||||
import org.elasticsearch.painless.Definition.MethodKey;
|
||||
import org.elasticsearch.painless.Definition.RuntimeClass;
|
||||
import org.elasticsearch.painless.Definition.Struct;
|
||||
import org.elasticsearch.painless.FeatureTest;
|
||||
import org.elasticsearch.painless.Locals.Variable;
|
||||
import org.elasticsearch.painless.Location;
|
||||
import org.elasticsearch.painless.Operation;
|
||||
import org.elasticsearch.painless.antlr.Walker;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static java.util.Collections.singletonList;
|
||||
|
||||
/**
|
||||
* Tests {@link Object#toString} implementations on all extensions of {@link ANode}.
|
||||
*/
|
||||
public class NodeToStringTests extends ESTestCase {
|
||||
public void testEAssignment() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SExpression (EAssignment (EVariable i) = (ENumeric 2)))\n"
|
||||
+ " (SReturn (EVariable i)))",
|
||||
"def i;\n"
|
||||
+ "i = 2;\n"
|
||||
+ "return i");
|
||||
for (String operator : new String[] {"+", "-", "*", "/", "%", "&", "^", "|", "<<", ">>", ">>>"}) {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i (ENumeric 1)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable i) " + operator + "= (ENumeric 2)))\n"
|
||||
+ " (SReturn (EVariable i)))",
|
||||
"def i = 1;\n"
|
||||
+ "i " + operator + "= 2;\n"
|
||||
+ "return i");
|
||||
}
|
||||
// Compound
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SReturn (EAssignment (EVariable i) = (ENumeric 2))))",
|
||||
"def i;\n"
|
||||
+ "return i = 2");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SReturn (EAssignment (EVariable i) ++ post)))",
|
||||
"def i;\n"
|
||||
+ "return i++");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SReturn (EAssignment (EVariable i) ++ pre)))",
|
||||
"def i;\n"
|
||||
+ "return ++i");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SReturn (EAssignment (EVariable i) -- post)))",
|
||||
"def i;\n"
|
||||
+ "return i--");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def i))\n"
|
||||
+ " (SReturn (EAssignment (EVariable i) -- pre)))",
|
||||
"def i;\n"
|
||||
+ "return --i");
|
||||
}
|
||||
|
||||
public void testEBinary() {
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) * (ENumeric 1))))", "return 1 * 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) / (ENumeric 1))))", "return 1 / 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) % (ENumeric 1))))", "return 1 % 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) + (ENumeric 1))))", "return 1 + 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) - (ENumeric 1))))", "return 1 - 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (EString 'asb') =~ (ERegex /cat/))))", "return 'asb' =~ /cat/");
|
||||
assertToString("(SSource (SReturn (EBinary (EString 'asb') ==~ (ERegex /cat/))))", "return 'asb' ==~ /cat/");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) << (ENumeric 1))))", "return 1 << 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) >> (ENumeric 1))))", "return 1 >> 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) >>> (ENumeric 1))))", "return 1 >>> 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) & (ENumeric 1))))", "return 1 & 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) ^ (ENumeric 1))))", "return 1 ^ 1");
|
||||
assertToString( "(SSource (SReturn (EBinary (ENumeric 1) | (ENumeric 1))))", "return 1 | 1");
|
||||
}
|
||||
|
||||
public void testEBool() {
|
||||
assertToString("(SSource (SReturn (EBool (EBoolean true) && (EBoolean false))))", "return true && false");
|
||||
assertToString("(SSource (SReturn (EBool (EBoolean true) || (EBoolean false))))", "return true || false");
|
||||
}
|
||||
|
||||
public void testEBoolean() {
|
||||
assertToString("(SSource (SReturn (EBoolean true)))", "return true");
|
||||
assertToString("(SSource (SReturn (EBoolean false)))", "return false");
|
||||
}
|
||||
|
||||
public void testECallLocal() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a\n"
|
||||
+ " (SReturn (EBoolean true)))\n"
|
||||
+ " (SReturn (ECallLocal a)))",
|
||||
"def a() {\n"
|
||||
+ " return true\n"
|
||||
+ "}\n"
|
||||
+ "return a()");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a (Args (Pair int i) (Pair int j))\n"
|
||||
+ " (SReturn (EBoolean true)))\n"
|
||||
+ " (SReturn (ECallLocal a (Args (ENumeric 1) (ENumeric 2)))))",
|
||||
"def a(int i, int j) {\n"
|
||||
+ " return true\n"
|
||||
+ "}\n"
|
||||
+ "return a(1, 2)");
|
||||
}
|
||||
|
||||
public void testECapturingFunctionRef() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration Integer x (PCallInvoke (EStatic Integer) valueOf (Args (ENumeric 5)))))\n"
|
||||
+ " (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args (ECapturingFunctionRef x toString)))))",
|
||||
"Integer x = Integer.valueOf(5);\n"
|
||||
+ "return Optional.empty().orElseGet(x::toString)");
|
||||
}
|
||||
|
||||
public void testECast() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
AExpression child = new EConstant(l, "test");
|
||||
Cast cast = new Cast(Definition.STRING_TYPE, Definition.INT_OBJ_TYPE, true);
|
||||
assertEquals("(ECast Integer (EConstant String 'test'))", new ECast(l, child, cast).toString());
|
||||
|
||||
l = new Location(getTestName(), 1);
|
||||
child = new EBinary(l, Operation.ADD, new EConstant(l, "test"), new EConstant(l, 12));
|
||||
cast = new Cast(Definition.INT_OBJ_TYPE, Definition.BOOLEAN_OBJ_TYPE, true);
|
||||
assertEquals("(ECast Boolean (EBinary (EConstant String 'test') + (EConstant Integer 12)))", new ECast(l, child, cast).toString());
|
||||
}
|
||||
|
||||
public void testEComp() {
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) < (ENumeric 10))))", "return params.a < 10");
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) <= (ENumeric 10))))", "return params.a <= 10");
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) > (ENumeric 10))))", "return params.a > 10");
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) >= (ENumeric 10))))", "return params.a >= 10");
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) == (ENumeric 10))))", "return params.a == 10");
|
||||
assertToString("(SSource (SReturn (EComp (PField (EVariable params) a) === (ENumeric 10))))", "return params.a === 10");
|
||||
assertToString( "(SSource (SReturn (EComp (PField (EVariable params) a) != (ENumeric 10))))", "return params.a != 10");
|
||||
assertToString("(SSource (SReturn (EComp (PField (EVariable params) a) !== (ENumeric 10))))", "return params.a !== 10");
|
||||
}
|
||||
|
||||
public void testEConditional() {
|
||||
assertToString("(SSource (SReturn (EConditional (PField (EVariable params) a) (ENumeric 1) (ENumeric 6))))",
|
||||
"return params.a ? 1 : 6");
|
||||
}
|
||||
|
||||
public void testEConstant() {
|
||||
assertEquals("(EConstant String '121')", new EConstant(new Location(getTestName(), 0), "121").toString());
|
||||
assertEquals("(EConstant String '92 ')", new EConstant(new Location(getTestName(), 0), "92 ").toString());
|
||||
assertEquals("(EConstant Integer 1237)", new EConstant(new Location(getTestName(), 1), 1237).toString());
|
||||
assertEquals("(EConstant Boolean true)", new EConstant(new Location(getTestName(), 2), true).toString());
|
||||
}
|
||||
|
||||
public void testEDecimal() {
|
||||
assertToString("(SSource (SReturn (EDecimal 1.0)))", "return 1.0");
|
||||
assertToString("(SSource (SReturn (EDecimal 14.121d)))", "return 14.121d");
|
||||
assertToString("(SSource (SReturn (EDecimal 2234.1f)))", "return 2234.1f");
|
||||
assertToString("(SSource (SReturn (EDecimal 14.121D)))", "return 14.121D");
|
||||
assertToString("(SSource (SReturn (EDecimal 1234.1F)))", "return 1234.1F");
|
||||
}
|
||||
|
||||
public void testEElvis() {
|
||||
assertToString("(SSource (SReturn (EElvis (PField (EVariable params) a) (ENumeric 1))))", "return params.a ?: 1");
|
||||
}
|
||||
|
||||
public void testEExplicit() {
|
||||
assertToString("(SSource (SReturn (EExplicit byte (PField (EVariable params) a))))", "return (byte)(params.a)");
|
||||
}
|
||||
|
||||
public void testEFunctionRef() {
|
||||
assertToString(
|
||||
"(SSource (SReturn "
|
||||
+ "(PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args (EFunctionRef Optional empty)))))",
|
||||
"return Optional.empty().orElseGet(Optional::empty)");
|
||||
}
|
||||
|
||||
public void testEInstanceOf() {
|
||||
assertToString("(SSource (SReturn (EInstanceof (ENewObj Object) Object)))", "return new Object() instanceof Object");
|
||||
assertToString("(SSource (SReturn (EInstanceof (ENumeric 12) double)))", "return 12 instanceof double");
|
||||
}
|
||||
|
||||
public void testELambda() {
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args "
|
||||
+ "(ELambda (SReturn (ENumeric 1)))))))",
|
||||
"return Optional.empty().orElseGet(() -> {\n"
|
||||
+ " return 1\n"
|
||||
+ "})");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (PCallInvoke (EStatic Optional) empty) orElseGet (Args "
|
||||
+ "(ELambda (SReturn (ENumeric 1)))))))",
|
||||
"return Optional.empty().orElseGet(() -> 1)");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (PCallInvoke (PCallInvoke (EListInit (ENumeric 1) (ENumeric 2) (ENumeric 3)) stream) "
|
||||
+ "mapToInt (Args (ELambda (Pair def x)\n"
|
||||
+ " (SReturn (EBinary (EVariable x) + (ENumeric 1)))))) sum)))",
|
||||
"return [1, 2, 3].stream().mapToInt((def x) -> {\n"
|
||||
+ " return x + 1\n"
|
||||
+ "}).sum()");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (PCallInvoke (PCallInvoke (EListInit (ENumeric 1) (ENumeric 2) (ENumeric 3)) stream) "
|
||||
+ "mapToInt (Args (ELambda (Pair def x)\n"
|
||||
+ " (SReturn (EBinary (EVariable x) + (ENumeric 1)))))) sum)))",
|
||||
"return [1, 2, 3].stream().mapToInt(x -> x + 1).sum()");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair def a) (Pair def b)\n"
|
||||
+ " (SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length))))))))",
|
||||
"return ['a', 'b'].sort((def a, def b) -> {\n"
|
||||
+ " return a.length() - b.length()\n"
|
||||
+ "})");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair def a) (Pair def b)\n"
|
||||
+ " (SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length))))))))",
|
||||
"return ['a', 'b'].sort((a, b) -> a.length() - b.length())");
|
||||
assertToString(
|
||||
"(SSource (SReturn (PCallInvoke (EListInit (EString 'a') (EString 'b')) sort (Args (ELambda (Pair def a) (Pair def b)\n"
|
||||
+ " (SIf (EComp (EVariable a) < (EVariable b)) (SBlock "
|
||||
+ "(SReturn (EBinary (PCallInvoke (EVariable a) length) - (PCallInvoke (EVariable b) length)))))\n"
|
||||
+ " (SReturn (ENumeric 1)))))))",
|
||||
"return ['a', 'b'].sort((def a, def b) -> {\n"
|
||||
+ " if (a < b) {\n"
|
||||
+ " return a.length() - b.length()\n"
|
||||
+ " }\n"
|
||||
+ " return 1\n"
|
||||
+ "})");
|
||||
}
|
||||
|
||||
public void testEListInit() {
|
||||
assertToString("(SSource (SReturn (EListInit (ENumeric 1) (ENumeric 2) (EString 'cat') (EString 'dog') (ENewObj Object))))",
|
||||
"return [1, 2, 'cat', 'dog', new Object()]");
|
||||
assertToString("(SSource (SReturn (EListInit)))", "return []");
|
||||
}
|
||||
|
||||
public void testEMapInit() {
|
||||
assertToString("(SSource (SReturn (EMapInit "
|
||||
+ "(Pair (EString 'a') (ENumeric 1)) "
|
||||
+ "(Pair (EString 'b') (ENumeric 3)) "
|
||||
+ "(Pair (ENumeric 12) (ENewObj Object)))))",
|
||||
"return ['a': 1, 'b': 3, 12: new Object()]");
|
||||
assertToString("(SSource (SReturn (EMapInit)))", "return [:]");
|
||||
}
|
||||
|
||||
public void testENewArray() {
|
||||
assertToString("(SSource (SReturn (ENewArray int dims (Args (ENumeric 10)))))", "return new int[10]");
|
||||
assertToString("(SSource (SReturn (ENewArray int dims (Args (ENumeric 10) (ENumeric 4) (ENumeric 5)))))",
|
||||
"return new int[10][4][5]");
|
||||
assertToString("(SSource (SReturn (ENewArray int init (Args (ENumeric 1) (ENumeric 2) (ENumeric 3)))))",
|
||||
"return new int[] {1, 2, 3}");
|
||||
assertToString("(SSource (SReturn (ENewArray def init (Args (ENumeric 1) (ENumeric 2) (EString 'bird')))))",
|
||||
"return new def[] {1, 2, 'bird'}");
|
||||
}
|
||||
|
||||
public void testENewObj() {
|
||||
assertToString("(SSource (SReturn (ENewObj Object)))", "return new Object()");
|
||||
assertToString("(SSource (SReturn (ENewObj DateTimeException (Args (EString 'test')))))", "return new DateTimeException('test')");
|
||||
}
|
||||
|
||||
public void testENull() {
|
||||
assertToString("(SSource (SReturn (ENull)))", "return null");
|
||||
}
|
||||
|
||||
public void testENumeric() {
|
||||
assertToString("(SSource (SReturn (ENumeric 1)))", "return 1");
|
||||
assertToString("(SSource (SReturn (ENumeric 114121d)))", "return 114121d");
|
||||
assertToString("(SSource (SReturn (ENumeric 114134f)))", "return 114134f");
|
||||
assertToString("(SSource (SReturn (ENumeric 114121D)))", "return 114121D");
|
||||
assertToString("(SSource (SReturn (ENumeric 111234F)))", "return 111234F");
|
||||
assertToString("(SSource (SReturn (ENumeric 774121l)))", "return 774121l");
|
||||
assertToString("(SSource (SReturn (ENumeric 881234L)))", "return 881234L");
|
||||
|
||||
assertToString("(SSource (SReturn (ENumeric 1 16)))", "return 0x1");
|
||||
assertToString("(SSource (SReturn (ENumeric 774121l 16)))", "return 0x774121l");
|
||||
assertToString("(SSource (SReturn (ENumeric 881234L 16)))", "return 0x881234L");
|
||||
|
||||
assertToString("(SSource (SReturn (ENumeric 1 8)))", "return 01");
|
||||
assertToString("(SSource (SReturn (ENumeric 774121l 8)))", "return 0774121l");
|
||||
assertToString("(SSource (SReturn (ENumeric 441234L 8)))", "return 0441234L");
|
||||
}
|
||||
|
||||
public void testERegex() {
|
||||
assertToString("(SSource (SReturn (ERegex /foo/)))", "return /foo/");
|
||||
assertToString("(SSource (SReturn (ERegex /foo/ cix)))", "return /foo/cix");
|
||||
assertToString("(SSource (SReturn (ERegex /foo/ cix)))", "return /foo/xci");
|
||||
}
|
||||
|
||||
public void testEStatic() {
|
||||
assertToString("(SSource (SReturn (PCallInvoke (EStatic Optional) empty)))", "return Optional.empty()");
|
||||
}
|
||||
|
||||
public void testEString() {
|
||||
assertToString("(SSource (SReturn (EString 'foo')))", "return 'foo'");
|
||||
assertToString("(SSource (SReturn (EString ' oo')))", "return ' oo'");
|
||||
assertToString("(SSource (SReturn (EString 'fo ')))", "return 'fo '");
|
||||
assertToString("(SSource (SReturn (EString ' o ')))", "return ' o '");
|
||||
}
|
||||
|
||||
public void testEUnary() {
|
||||
assertToString("(SSource (SReturn (EUnary ! (EBoolean true))))", "return !true");
|
||||
assertToString("(SSource (SReturn (EUnary ~ (ENumeric 1))))", "return ~1");
|
||||
assertToString("(SSource (SReturn (EUnary + (ENumeric 1))))", "return +1");
|
||||
assertToString("(SSource (SReturn (EUnary - (ENumeric 1))))", "return -(1)");
|
||||
}
|
||||
|
||||
public void testEVariable() {
|
||||
assertToString("(SSource (SReturn (EVariable params)))", "return params");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def a (ENumeric 1)))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a = 1;\n"
|
||||
+ "return a");
|
||||
}
|
||||
|
||||
public void testPBrace() {
|
||||
assertToString("(SSource (SReturn (PBrace (PField (EVariable params) a) (ENumeric 10))))", "return params.a[10]");
|
||||
assertToString("(SSource (SReturn (PBrace (EVariable params) (EString 'a'))))", "return params['a']");
|
||||
}
|
||||
|
||||
public void testPCallInvoke() {
|
||||
assertToString("(SSource (SReturn (PCallInvoke (EStatic Optional) empty)))", "return Optional.empty()");
|
||||
assertToString("(SSource (SReturn (PCallInvoke (EStatic Optional) of (Args (ENumeric 1)))))", "return Optional.of(1)");
|
||||
assertToString("(SSource (SReturn (PCallInvoke (EStatic Objects) equals (Args (ENumeric 1) (ENumeric 2)))))",
|
||||
"return Objects.equals(1, 2)");
|
||||
assertToString("(SSource (SReturn (PCallInvoke (EVariable params) equals (Args (ENumeric 1)))))", "return params.equals(1)");
|
||||
}
|
||||
|
||||
public void testPField() {
|
||||
assertToString("(SSource (SReturn (PField (EVariable params) a)))", "return params.a");
|
||||
assertToString("(SSource (SReturn (PField nullSafe (EVariable params) a)))", "return params?.a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int[] a (ENewArray int dims (Args (ENumeric 10)))))\n"
|
||||
+ " (SReturn (PField (EVariable a) length)))",
|
||||
"int[] a = new int[10];\n"
|
||||
+ "return a.length");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration org.elasticsearch.painless.FeatureTest a (ENewObj org.elasticsearch.painless.FeatureTest)))\n"
|
||||
+ " (SExpression (EAssignment (PField (EVariable a) x) = (ENumeric 10)))\n"
|
||||
+ " (SReturn (PField (EVariable a) x)))",
|
||||
"org.elasticsearch.painless.FeatureTest a = new org.elasticsearch.painless.FeatureTest();\n"
|
||||
+ "a.x = 10;\n"
|
||||
+ "return a.x");
|
||||
}
|
||||
|
||||
public void testPSubArrayLength() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
PSubArrayLength node = new PSubArrayLength(l, "int", "a");
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubArrayLength (EVariable a))", node.toString());
|
||||
assertEquals("(PSubNullSafeField (PSubArrayLength (EVariable a)))", new PSubNullSafeField(l, node).toString());
|
||||
}
|
||||
|
||||
public void testPSubBrace() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
PSubBrace node = new PSubBrace(l, Definition.INT_TYPE, new ENumeric(l, "1", 10));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubBrace (EVariable a) (ENumeric 1))", node.toString());
|
||||
}
|
||||
|
||||
public void testPSubCallInvoke() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
RuntimeClass c = Definition.getRuntimeClass(Integer.class);
|
||||
Method m = c.methods.get(new MethodKey("toString", 0));
|
||||
PSubCallInvoke node = new PSubCallInvoke(l, m, null, emptyList());
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubCallInvoke (EVariable a) toString)", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubCallInvoke (EVariable a) toString))", new PSubNullSafeCallInvoke(l, node).toString());
|
||||
|
||||
l = new Location(getTestName(), 1);
|
||||
m = c.methods.get(new MethodKey("equals", 1));
|
||||
node = new PSubCallInvoke(l, m, null, singletonList(new EVariable(l, "b")));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubCallInvoke (EVariable a) equals (Args (EVariable b)))", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubCallInvoke (EVariable a) equals (Args (EVariable b))))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
}
|
||||
|
||||
public void testPSubDefArray() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
PSubDefArray node = new PSubDefArray(l, new EConstant(l, 1));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubDefArray (EVariable a) (EConstant Integer 1))", node.toString());
|
||||
}
|
||||
|
||||
public void testPSubDefCall() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
PSubDefCall node = new PSubDefCall(l, "toString", emptyList());
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubDefCall (EVariable a) toString)", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) toString))", new PSubNullSafeCallInvoke(l, node).toString());
|
||||
|
||||
l = new Location(getTestName(), 0);
|
||||
node = new PSubDefCall(l, "equals", singletonList(new EVariable(l, "b")));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubDefCall (EVariable a) equals (Args (EVariable b)))", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) equals (Args (EVariable b))))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
|
||||
l = new Location(getTestName(), 0);
|
||||
node = new PSubDefCall(l, "superWeird", Arrays.asList(new EVariable(l, "b"), new EVariable(l, "c"), new EVariable(l, "d")));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubDefCall (EVariable a) superWeird (Args (EVariable b) (EVariable c) (EVariable d)))", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubDefCall (EVariable a) superWeird (Args (EVariable b) (EVariable c) (EVariable d))))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
}
|
||||
|
||||
public void testPSubDefField() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
PSubDefField node = new PSubDefField(l, "ok");
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubDefField (EVariable a) ok)", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubDefField (EVariable a) ok))", new PSubNullSafeCallInvoke(l, node).toString());
|
||||
}
|
||||
|
||||
public void testPSubField() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Struct s = Definition.getType(Boolean.class.getSimpleName()).struct;
|
||||
Field f = s.staticMembers.get("TRUE");
|
||||
PSubField node = new PSubField(l, f);
|
||||
node.prefix = new EStatic(l, "Boolean");
|
||||
assertEquals("(PSubField (EStatic Boolean) TRUE)", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubField (EStatic Boolean) TRUE))", new PSubNullSafeCallInvoke(l, node).toString());
|
||||
}
|
||||
|
||||
public void testPSubListShortcut() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Struct s = Definition.getType(List.class.getSimpleName()).struct;
|
||||
PSubListShortcut node = new PSubListShortcut(l, s, new EConstant(l, 1));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubListShortcut (EVariable a) (EConstant Integer 1))", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubListShortcut (EVariable a) (EConstant Integer 1)))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
|
||||
l = new Location(getTestName(), 0);
|
||||
s = Definition.getType(List.class.getSimpleName()).struct;
|
||||
node = new PSubListShortcut(l, s, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubListShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
||||
}
|
||||
|
||||
public void testPSubMapShortcut() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Struct s = Definition.getType(Map.class.getSimpleName()).struct;
|
||||
PSubMapShortcut node = new PSubMapShortcut(l, s, new EConstant(l, "cat"));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubMapShortcut (EVariable a) (EConstant String 'cat'))", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubMapShortcut (EVariable a) (EConstant String 'cat')))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
|
||||
l = new Location(getTestName(), 1);
|
||||
s = Definition.getType(Map.class.getSimpleName()).struct;
|
||||
node = new PSubMapShortcut(l, s, new EBinary(l, Operation.ADD, new EConstant(l, 1), new EConstant(l, 4)));
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubMapShortcut (EVariable a) (EBinary (EConstant Integer 1) + (EConstant Integer 4)))", node.toString());
|
||||
}
|
||||
|
||||
public void testPSubShortcut() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Struct s = Definition.getType(FeatureTest.class.getName()).struct;
|
||||
Method getter = s.methods.get(new MethodKey("getX", 0));
|
||||
Method setter = s.methods.get(new MethodKey("setX", 1));
|
||||
PSubShortcut node = new PSubShortcut(l, "x", FeatureTest.class.getName(), getter, setter);
|
||||
node.prefix = new EVariable(l, "a");
|
||||
assertEquals("(PSubShortcut (EVariable a) x)", node.toString());
|
||||
assertEquals("(PSubNullSafeCallInvoke (PSubShortcut (EVariable a) x))",
|
||||
new PSubNullSafeCallInvoke(l, node).toString());
|
||||
}
|
||||
|
||||
public void testSBreak() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n"
|
||||
+ " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n"
|
||||
+ " (SExpression (EAssignment (EVariable itr) ++ post))\n"
|
||||
+ " (SIf (EComp (EVariable itr) > (ENumeric 10000)) (SBlock (SBreak)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n"
|
||||
+ " (SReturn (EVariable b)))",
|
||||
"int itr = 2;\n"
|
||||
+ "int a = 1;\n"
|
||||
+ "int b = 1;\n"
|
||||
+ "do {\n"
|
||||
+ " itr++;\n"
|
||||
+ " if (itr > 10000) {\n"
|
||||
+ " break\n"
|
||||
+ " }\n"
|
||||
+ " int tmp = a;\n"
|
||||
+ " a = b;\n"
|
||||
+ " b = tmp + b\n"
|
||||
+ "} while (b < 1000);\n"
|
||||
+ "return b");
|
||||
}
|
||||
|
||||
public void testSContinue() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n"
|
||||
+ " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n"
|
||||
+ " (SExpression (EAssignment (EVariable itr) ++ post))\n"
|
||||
+ " (SIf (EComp (EVariable itr) < (ENumeric 10000)) (SBlock (SContinue)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n"
|
||||
+ " (SReturn (EVariable b)))",
|
||||
"int itr = 2;\n"
|
||||
+ "int a = 1;\n"
|
||||
+ "int b = 1;\n"
|
||||
+ "do {\n"
|
||||
+ " itr++;\n"
|
||||
+ " if (itr < 10000) {\n"
|
||||
+ " continue\n"
|
||||
+ " }\n"
|
||||
+ " int tmp = a;\n"
|
||||
+ " a = b;\n"
|
||||
+ " b = tmp + b\n"
|
||||
+ "} while (b < 1000);\n"
|
||||
+ "return b");
|
||||
}
|
||||
|
||||
public void testSDeclBlock() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def a))\n"
|
||||
+ " (SExpression (EAssignment (EVariable a) = (ENumeric 10)))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a;\n"
|
||||
+ "a = 10;\n"
|
||||
+ "return a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration def a (ENumeric 10)))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a = 10;\n"
|
||||
+ "return a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock\n"
|
||||
+ " (SDeclaration def a)\n"
|
||||
+ " (SDeclaration def b)\n"
|
||||
+ " (SDeclaration def c))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a, b, c;\n"
|
||||
+ "return a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock\n"
|
||||
+ " (SDeclaration def a (ENumeric 10))\n"
|
||||
+ " (SDeclaration def b (ENumeric 20))\n"
|
||||
+ " (SDeclaration def c (ENumeric 100)))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a = 10, b = 20, c = 100;\n"
|
||||
+ "return a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock\n"
|
||||
+ " (SDeclaration def a (ENumeric 10))\n"
|
||||
+ " (SDeclaration def b)\n"
|
||||
+ " (SDeclaration def c (ENumeric 100)))\n"
|
||||
+ " (SReturn (EVariable a)))",
|
||||
"def a = 10, b, c = 100;\n"
|
||||
+ "return a");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SIf (PField (EVariable params) a) (SBlock\n"
|
||||
+ " (SDeclBlock\n"
|
||||
+ " (SDeclaration def a (ENumeric 10))\n"
|
||||
+ " (SDeclaration def b)\n"
|
||||
+ " (SDeclaration def c (ENumeric 100)))\n"
|
||||
+ " (SReturn (EVariable a))))\n"
|
||||
+ " (SReturn (EBoolean false)))",
|
||||
"if (params.a) {"
|
||||
+ " def a = 10, b, c = 100;\n"
|
||||
+ " return a\n"
|
||||
+ "}\n"
|
||||
+ "return false");
|
||||
}
|
||||
|
||||
public void testSDo() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int itr (ENumeric 2)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int a (ENumeric 1)))\n"
|
||||
+ " (SDeclBlock (SDeclaration int b (ENumeric 1)))\n"
|
||||
+ " (SDo (EComp (EVariable b) < (ENumeric 1000)) (SBlock\n"
|
||||
+ " (SExpression (EAssignment (EVariable itr) ++ post))\n"
|
||||
+ " (SDeclBlock (SDeclaration int tmp (EVariable a)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable a) = (EVariable b)))\n"
|
||||
+ " (SExpression (EAssignment (EVariable b) = (EBinary (EVariable tmp) + (EVariable b))))))\n"
|
||||
+ " (SReturn (EVariable b)))",
|
||||
"int itr = 2;\n"
|
||||
+ "int a = 1;\n"
|
||||
+ "int b = 1;\n"
|
||||
+ "do {\n"
|
||||
+ " itr++;\n"
|
||||
+ " int tmp = a;\n"
|
||||
+ " a = b;\n"
|
||||
+ " b = tmp + b\n"
|
||||
+ "} while (b < 1000);\n"
|
||||
+ "return b");
|
||||
}
|
||||
|
||||
public void testSEach() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int l (ENumeric 0)))\n"
|
||||
+ " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock "
|
||||
+ "(SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s) length)))))\n"
|
||||
+ " (SReturn (EVariable l)))",
|
||||
"int l = 0;\n"
|
||||
+ "for (String s : ['cat', 'dog', 'chicken']) {\n"
|
||||
+ " l += s.length()\n"
|
||||
+ "}\n"
|
||||
+ "return l");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int l (ENumeric 0)))\n"
|
||||
+ " (SEach String s (EListInit (EString 'cat') (EString 'dog') (EString 'chicken')) (SBlock\n"
|
||||
+ " (SDeclBlock (SDeclaration String s2 (EBinary (EString 'dire ') + (EVariable s))))\n"
|
||||
+ " (SExpression (EAssignment (EVariable l) += (PCallInvoke (EVariable s2) length)))))\n"
|
||||
+ " (SReturn (EVariable l)))",
|
||||
"int l = 0;\n"
|
||||
+ "for (String s : ['cat', 'dog', 'chicken']) {\n"
|
||||
+ " String s2 = 'dire ' + s;\n"
|
||||
+ " l += s2.length()\n"
|
||||
+ "}\n"
|
||||
+ "return l");
|
||||
}
|
||||
|
||||
public void testSFor() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int sum (ENumeric 0)))\n"
|
||||
+ " (SFor\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n"
|
||||
+ " (EComp (EVariable i) < (ENumeric 1000))\n"
|
||||
+ " (EAssignment (EVariable i) ++ post)\n"
|
||||
+ " (SBlock (SExpression (EAssignment (EVariable sum) += (EVariable i)))))\n"
|
||||
+ " (SReturn (EVariable sum)))",
|
||||
"int sum = 0;\n"
|
||||
+ "for (int i = 0; i < 1000; i++) {\n"
|
||||
+ " sum += i\n"
|
||||
+ "}\n"
|
||||
+ "return sum");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int sum (ENumeric 0)))\n"
|
||||
+ " (SFor\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n"
|
||||
+ " (EComp (EVariable i) < (ENumeric 1000))\n"
|
||||
+ " (EAssignment (EVariable i) ++ post)\n"
|
||||
+ " (SBlock (SFor\n"
|
||||
+ " (SDeclBlock (SDeclaration int j (ENumeric 0)))\n"
|
||||
+ " (EComp (EVariable j) < (ENumeric 1000))\n"
|
||||
+ " (EAssignment (EVariable j) ++ post)\n"
|
||||
+ " (SBlock (SExpression (EAssignment (EVariable sum) += (EBinary (EVariable i) * (EVariable j))))))))\n"
|
||||
+ " (SReturn (EVariable sum)))",
|
||||
"int sum = 0;\n"
|
||||
+ "for (int i = 0; i < 1000; i++) {\n"
|
||||
+ " for (int j = 0; j < 1000; j++) {\n"
|
||||
+ " sum += i * j\n"
|
||||
+ " }\n"
|
||||
+ "}\n"
|
||||
+ "return sum");
|
||||
}
|
||||
|
||||
public void testSIf() {
|
||||
assertToString(
|
||||
"(SSource (SIf (PField (EVariable param) a) (SBlock (SReturn (EBoolean true)))))",
|
||||
"if (param.a) {\n"
|
||||
+ " return true\n"
|
||||
+"}");
|
||||
assertToString(
|
||||
"(SSource (SIf (PField (EVariable param) a) (SBlock\n"
|
||||
+ " (SIf (PField (EVariable param) b) (SBlock (SReturn (EBoolean true))))\n"
|
||||
+ " (SReturn (EBoolean false)))))",
|
||||
"if (param.a) {\n"
|
||||
+ " if (param.b) {\n"
|
||||
+ " return true\n"
|
||||
+ " }\n"
|
||||
+ " return false\n"
|
||||
+"}");
|
||||
}
|
||||
|
||||
public void testSIfElse() {
|
||||
assertToString(
|
||||
"(SSource (SIfElse (PField (EVariable param) a)\n"
|
||||
+ " (SBlock (SReturn (EBoolean true)))\n"
|
||||
+ " (SBlock (SReturn (EBoolean false)))))",
|
||||
"if (param.a) {\n"
|
||||
+ " return true\n"
|
||||
+ "} else {\n"
|
||||
+ " return false\n"
|
||||
+ "}");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n"
|
||||
+ " (SIfElse (PField (EVariable param) a)\n"
|
||||
+ " (SBlock (SIfElse (PField (EVariable param) b)\n"
|
||||
+ " (SBlock (SReturn (EBoolean true)))\n"
|
||||
+ " (SBlock (SReturn (EString 'cat')))))\n"
|
||||
+ " (SBlock (SReturn (EBoolean false)))))",
|
||||
"int i = 0;\n"
|
||||
+ "if (param.a) {\n"
|
||||
+ " if (param.b) {\n"
|
||||
+ " return true\n"
|
||||
+ " } else {\n"
|
||||
+ " return 'cat'\n"
|
||||
+ " }\n"
|
||||
+ "} else {"
|
||||
+ " return false\n"
|
||||
+ "}");
|
||||
}
|
||||
|
||||
public void testSSubEachArray() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Variable v = new Variable(l, "test", Definition.INT_TYPE, 5, false);
|
||||
AExpression e = new ENewArray(l, "int", Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)), true);
|
||||
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
||||
SSubEachArray node = new SSubEachArray(l, v, e, b);
|
||||
assertEquals(
|
||||
"(SSubEachArray int test (ENewArray int init (Args (EConstant Integer 1) (EConstant Integer 2) (EConstant Integer 3))) "
|
||||
+ "(SBlock (SReturn (EConstant Integer 5))))",
|
||||
node.toString());
|
||||
}
|
||||
|
||||
public void testSSubEachIterable() {
|
||||
Location l = new Location(getTestName(), 0);
|
||||
Variable v = new Variable(l, "test", Definition.INT_TYPE, 5, false);
|
||||
AExpression e = new EListInit(l, Arrays.asList(new EConstant(l, 1), new EConstant(l, 2), new EConstant(l, 3)));
|
||||
SBlock b = new SBlock(l, singletonList(new SReturn(l, new EConstant(l, 5))));
|
||||
SSubEachIterable node = new SSubEachIterable(l, v, e, b);
|
||||
assertEquals(
|
||||
"(SSubEachIterable int test (EListInit (EConstant Integer 1) (EConstant Integer 2) (EConstant Integer 3)) (SBlock "
|
||||
+ "(SReturn (EConstant Integer 5))))",
|
||||
node.toString());
|
||||
}
|
||||
|
||||
public void testSThrow() {
|
||||
assertToString("(SSource (SThrow (ENewObj RuntimeException)))", "throw new RuntimeException()");
|
||||
}
|
||||
|
||||
public void testSWhile() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 0)))\n"
|
||||
+ " (SWhile (EComp (EVariable i) < (ENumeric 10)) (SBlock (SExpression (EAssignment (EVariable i) ++ post))))\n"
|
||||
+ " (SReturn (EVariable i)))",
|
||||
"int i = 0;\n"
|
||||
+ "while (i < 10) {\n"
|
||||
+ " i++\n"
|
||||
+ "}\n"
|
||||
+ "return i");
|
||||
}
|
||||
|
||||
public void testSFunction() {
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a\n"
|
||||
+ " (SReturn (EBoolean true)))\n"
|
||||
+ " (SReturn (EBoolean true)))",
|
||||
"def a() {\n"
|
||||
+ " return true\n"
|
||||
+ "}\n"
|
||||
+ "return true");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a (Args (Pair int i) (Pair int j))\n"
|
||||
+ " (SReturn (EBoolean true)))\n"
|
||||
+ " (SReturn (EBoolean true)))",
|
||||
"def a(int i, int j) {\n"
|
||||
+ " return true\n"
|
||||
+ "}\n"
|
||||
+ "return true");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a (Args (Pair int i) (Pair int j))\n"
|
||||
+ " (SIf (EComp (EVariable i) < (EVariable j)) (SBlock (SReturn (EBoolean true))))\n"
|
||||
+ " (SDeclBlock (SDeclaration int k (EBinary (EVariable i) + (EVariable j))))\n"
|
||||
+ " (SReturn (EVariable k)))\n"
|
||||
+ " (SReturn (EBoolean true)))",
|
||||
"def a(int i, int j) {\n"
|
||||
+ " if (i < j) {\n"
|
||||
+ " return true\n"
|
||||
+ " }\n"
|
||||
+ " int k = i + j;\n"
|
||||
+ " return k\n"
|
||||
+ "}\n"
|
||||
+ "return true");
|
||||
assertToString(
|
||||
"(SSource\n"
|
||||
+ " (SFunction def a\n"
|
||||
+ " (SReturn (EBoolean true)))\n"
|
||||
+ " (SFunction def b\n"
|
||||
+ " (SReturn (EBoolean false)))\n"
|
||||
+ " (SReturn (EBoolean true)))",
|
||||
"def a() {\n"
|
||||
+ " return true\n"
|
||||
+ "}\n"
|
||||
+ "def b() {\n"
|
||||
+ " return false\n"
|
||||
+ "}\n"
|
||||
+ "return true");
|
||||
}
|
||||
|
||||
public void testSTryAndSCatch() {
|
||||
assertToString(
|
||||
"(SSource (STry (SBlock (SReturn (ENumeric 1)))\n"
|
||||
+ " (SCatch Exception e (SBlock (SReturn (ENumeric 2))))))",
|
||||
"try {\n"
|
||||
+ " return 1\n"
|
||||
+ "} catch (Exception e) {\n"
|
||||
+ " return 2\n"
|
||||
+ "}");
|
||||
assertToString(
|
||||
"(SSource (STry (SBlock\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 1)))\n"
|
||||
+ " (SReturn (ENumeric 1)))\n"
|
||||
+ " (SCatch Exception e (SBlock (SReturn (ENumeric 2))))))",
|
||||
"try {\n"
|
||||
+ " int i = 1;"
|
||||
+ " return 1\n"
|
||||
+ "} catch (Exception e) {\n"
|
||||
+ " return 2\n"
|
||||
+ "}");
|
||||
assertToString(
|
||||
"(SSource (STry (SBlock (SReturn (ENumeric 1)))\n"
|
||||
+ " (SCatch Exception e (SBlock\n"
|
||||
+ " (SDeclBlock (SDeclaration int i (ENumeric 1)))\n"
|
||||
+ " (SReturn (ENumeric 2))))))",
|
||||
"try {\n"
|
||||
+ " return 1\n"
|
||||
+ "} catch (Exception e) {"
|
||||
+ " int i = 1;\n"
|
||||
+ " return 2\n"
|
||||
+ "}");
|
||||
assertToString(
|
||||
"(SSource (STry (SBlock (SReturn (ENumeric 1)))\n"
|
||||
+ " (SCatch NullPointerException e (SBlock (SReturn (ENumeric 2))))\n"
|
||||
+ " (SCatch Exception e (SBlock (SReturn (ENumeric 3))))))",
|
||||
"try {\n"
|
||||
+ " return 1\n"
|
||||
+ "} catch (NullPointerException e) {\n"
|
||||
+ " return 2\n"
|
||||
+ "} catch (Exception e) {\n"
|
||||
+ " return 3\n"
|
||||
+ "}");
|
||||
}
|
||||
|
||||
private void assertToString(String expected, String code) {
|
||||
assertEquals(expected, walk(code).toString());
|
||||
}
|
||||
|
||||
private SSource walk(String code) {
|
||||
CompilerSettings compilerSettings = new CompilerSettings();
|
||||
compilerSettings.setRegexesEnabled(true);
|
||||
try {
|
||||
return Walker.buildPainlessTree(getTestName(), code, compilerSettings, null);
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Failed to compile: " + code, e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue