Skip to content

Commit

Permalink
Remove Sort enum from Painless Definition (elastic#26179)
Browse files Browse the repository at this point in the history
This is step toward making Definition instanceable which is necessary for custom whitelists in different contexts.
  • Loading branch information
jdconrad authored Aug 17, 2017
1 parent 7e76b2a commit 2385878
Show file tree
Hide file tree
Showing 31 changed files with 892 additions and 1,243 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@

import org.apache.lucene.util.Constants;
import org.apache.lucene.util.SetOnce;
import org.elasticsearch.painless.api.Augmentation;

import java.io.InputStream;
import java.io.InputStreamReader;
Expand Down Expand Up @@ -99,72 +98,22 @@ public final class Definition {
public static final Type ARRAY_LIST_TYPE = BUILTINS.getType("ArrayList");
public static final Type HASH_MAP_TYPE = BUILTINS.getType("HashMap");

public enum Sort {
VOID( void.class , Void.class , null , 0 , true , false , false , false ),
BOOL( boolean.class , Boolean.class , null , 1 , true , true , false , true ),
BYTE( byte.class , Byte.class , null , 1 , true , false , true , true ),
SHORT( short.class , Short.class , null , 1 , true , false , true , true ),
CHAR( char.class , Character.class , null , 1 , true , false , true , true ),
INT( int.class , Integer.class , null , 1 , true , false , true , true ),
LONG( long.class , Long.class , null , 2 , true , false , true , true ),
FLOAT( float.class , Float.class , null , 1 , true , false , true , true ),
DOUBLE( double.class , Double.class , null , 2 , true , false , true , true ),

VOID_OBJ( Void.class , null , void.class , 1 , true , false , false , false ),
BOOL_OBJ( Boolean.class , null , boolean.class , 1 , false , true , false , false ),
BYTE_OBJ( Byte.class , null , byte.class , 1 , false , false , true , false ),
SHORT_OBJ( Short.class , null , short.class , 1 , false , false , true , false ),
CHAR_OBJ( Character.class , null , char.class , 1 , false , false , true , false ),
INT_OBJ( Integer.class , null , int.class , 1 , false , false , true , false ),
LONG_OBJ( Long.class , null , long.class , 1 , false , false , true , false ),
FLOAT_OBJ( Float.class , null , float.class , 1 , false , false , true , false ),
DOUBLE_OBJ( Double.class , null , double.class , 1 , false , false , true , false ),

NUMBER( Number.class , null , null , 1 , false , false , false , false ),
STRING( String.class , null , null , 1 , false , false , false , true ),

OBJECT( null , null , null , 1 , false , false , false , false ),
DEF( null , null , null , 1 , false , false , false , false ),
ARRAY( null , null , null , 1 , false , false , false , false );

public final Class<?> clazz;
public final Class<?> boxed;
public final Class<?> unboxed;
public final int size;
public final boolean primitive;
public final boolean bool;
public final boolean numeric;
public final boolean constant;

Sort(final Class<?> clazz, final Class<?> boxed, final Class<?> unboxed, final int size,
final boolean primitive, final boolean bool, final boolean numeric, final boolean constant) {
this.clazz = clazz;
this.boxed = boxed;
this.unboxed = unboxed;
this.size = size;
this.bool = bool;
this.primitive = primitive;
this.numeric = numeric;
this.constant = constant;
}
}

public static final class Type {
public final String name;
public final int dimensions;
public final boolean dynamic;
public final Struct struct;
public final Class<?> clazz;
public final org.objectweb.asm.Type type;
public final Sort sort;

private Type(final String name, final int dimensions, final Struct struct,
final Class<?> clazz, final org.objectweb.asm.Type type, final Sort sort) {
private Type(final String name, final int dimensions, final boolean dynamic,
final Struct struct, final Class<?> clazz, final org.objectweb.asm.Type type) {
this.name = name;
this.dimensions = dimensions;
this.struct = struct;
this.clazz = clazz;
this.type = type;
this.sort = sort;
this.dynamic = dynamic;
}

@Override
Expand Down Expand Up @@ -503,6 +452,62 @@ public Type getType(final Struct struct, final int dimensions) {
return BUILTINS.getTypeInternal(struct, dimensions);
}

public static Type getBoxedType(Type unboxed) {
if (unboxed.clazz == boolean.class) {
return BOOLEAN_OBJ_TYPE;
} else if (unboxed.clazz == byte.class) {
return BYTE_OBJ_TYPE;
} else if (unboxed.clazz == short.class) {
return SHORT_OBJ_TYPE;
} else if (unboxed.clazz == char.class) {
return CHAR_OBJ_TYPE;
} else if (unboxed.clazz == int.class) {
return INT_OBJ_TYPE;
} else if (unboxed.clazz == long.class) {
return LONG_OBJ_TYPE;
} else if (unboxed.clazz == float.class) {
return FLOAT_OBJ_TYPE;
} else if (unboxed.clazz == double.class) {
return DOUBLE_OBJ_TYPE;
}

return unboxed;
}

public static Type getUnboxedType(Type boxed) {
if (boxed.clazz == Boolean.class) {
return BOOLEAN_TYPE;
} else if (boxed.clazz == Byte.class) {
return BYTE_TYPE;
} else if (boxed.clazz == Short.class) {
return SHORT_TYPE;
} else if (boxed.clazz == Character.class) {
return CHAR_TYPE;
} else if (boxed.clazz == Integer.class) {
return INT_TYPE;
} else if (boxed.clazz == Long.class) {
return LONG_TYPE;
} else if (boxed.clazz == Float.class) {
return FLOAT_TYPE;
} else if (boxed.clazz == Double.class) {
return DOUBLE_TYPE;
}

return boxed;
}

public static boolean isConstantType(Type constant) {
return constant.clazz == boolean.class ||
constant.clazz == byte.class ||
constant.clazz == short.class ||
constant.clazz == char.class ||
constant.clazz == int.class ||
constant.clazz == long.class ||
constant.clazz == float.class ||
constant.clazz == double.class ||
constant.clazz == String.class;
}

public RuntimeClass getRuntimeClass(Class<?> clazz) {
return BUILTINS.runtimeMap.get(clazz);
}
Expand Down Expand Up @@ -1136,7 +1141,6 @@ private Type getTypeInternal(Struct struct, int dimensions) {
String name = struct.name;
org.objectweb.asm.Type type = struct.type;
Class<?> clazz = struct.clazz;
Sort sort;

if (dimensions > 0) {
StringBuilder builder = new StringBuilder(name);
Expand All @@ -1158,27 +1162,9 @@ private Type getTypeInternal(Struct struct, int dimensions) {
throw new IllegalArgumentException("The class [" + type.getInternalName() + "]" +
" could not be found to create type [" + name + "].");
}

sort = Sort.ARRAY;
} else if ("def".equals(struct.name)) {
sort = Sort.DEF;
} else {
sort = Sort.OBJECT;

for (Sort value : Sort.values()) {
if (value.clazz == null) {
continue;
}

if (value.clazz.equals(struct.clazz)) {
sort = value;

break;
}
}
}

return new Type(name, dimensions, struct, clazz, type, sort);
return new Type(name, dimensions, "def".equals(name), struct, clazz, type);
}

private int getDimensions(String name) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package org.elasticsearch.painless;

import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Sort;
import org.elasticsearch.painless.Definition.Type;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
Expand Down Expand Up @@ -131,35 +130,39 @@ public void writeLoopCounter(int slot, int count, Location location) {

public void writeCast(final Cast cast) {
if (cast != null) {
if (cast.from.sort == Sort.CHAR && cast.to.sort == Sort.STRING) {
if (cast.from.clazz == char.class && cast.to.clazz == String.class) {
invokeStatic(UTILITY_TYPE, CHAR_TO_STRING);
} else if (cast.from.sort == Sort.STRING && cast.to.sort == Sort.CHAR) {
} else if (cast.from.clazz == String.class && cast.to.clazz == char.class) {
invokeStatic(UTILITY_TYPE, STRING_TO_CHAR);
} else if (cast.unboxFrom != null) {
unbox(cast.unboxFrom.type);
writeCast(cast.from, cast.to);
} else if (cast.unboxTo != null) {
if (cast.from.sort == Sort.DEF) {
if (cast.from.dynamic) {
if (cast.explicit) {
if (cast.to.sort == Sort.BOOL_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN);
else if (cast.to.sort == Sort.BYTE_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_EXPLICIT);
else if (cast.to.sort == Sort.SHORT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_EXPLICIT);
else if (cast.to.sort == Sort.CHAR_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_EXPLICIT);
else if (cast.to.sort == Sort.INT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_EXPLICIT);
else if (cast.to.sort == Sort.LONG_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_EXPLICIT);
else if (cast.to.sort == Sort.FLOAT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_EXPLICIT);
else if (cast.to.sort == Sort.DOUBLE_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_EXPLICIT);
else throw new IllegalStateException("Illegal tree structure.");
if (cast.to.clazz == Boolean.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN);
else if (cast.to.clazz == Byte.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_EXPLICIT);
else if (cast.to.clazz == Short.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_EXPLICIT);
else if (cast.to.clazz == Character.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_EXPLICIT);
else if (cast.to.clazz == Integer.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_EXPLICIT);
else if (cast.to.clazz == Long.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_EXPLICIT);
else if (cast.to.clazz == Float.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_EXPLICIT);
else if (cast.to.clazz == Double.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_EXPLICIT);
else {
throw new IllegalStateException("Illegal tree structure.");
}
} else {
if (cast.to.sort == Sort.BOOL_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN);
else if (cast.to.sort == Sort.BYTE_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_IMPLICIT);
else if (cast.to.sort == Sort.SHORT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_IMPLICIT);
else if (cast.to.sort == Sort.CHAR_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_IMPLICIT);
else if (cast.to.sort == Sort.INT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_IMPLICIT);
else if (cast.to.sort == Sort.LONG_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_IMPLICIT);
else if (cast.to.sort == Sort.FLOAT_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_IMPLICIT);
else if (cast.to.sort == Sort.DOUBLE_OBJ) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_IMPLICIT);
else throw new IllegalStateException("Illegal tree structure.");
if (cast.to.clazz == Boolean.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BOOLEAN);
else if (cast.to.clazz == Byte.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_BYTE_IMPLICIT);
else if (cast.to.clazz == Short.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_SHORT_IMPLICIT);
else if (cast.to.clazz == Character.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_CHAR_IMPLICIT);
else if (cast.to.clazz == Integer.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_INT_IMPLICIT);
else if (cast.to.clazz == Long.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_LONG_IMPLICIT);
else if (cast.to.clazz == Float.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_FLOAT_IMPLICIT);
else if (cast.to.clazz == Double.class) invokeStatic(DEF_UTIL_TYPE, DEF_TO_DOUBLE_IMPLICIT);
else {
throw new IllegalStateException("Illegal tree structure.");
}
}
} else {
writeCast(cast.from, cast.to);
Expand All @@ -182,7 +185,7 @@ private void writeCast(final Type from, final Type to) {
return;
}

if (from.sort.numeric && from.sort.primitive && to.sort.numeric && to.sort.primitive) {
if (from.clazz != boolean.class && from.clazz.isPrimitive() && to.clazz != boolean.class && to.clazz.isPrimitive()) {
cast(from.type, to.type);
} else {
if (!to.clazz.isAssignableFrom(from.clazz)) {
Expand Down Expand Up @@ -238,18 +241,16 @@ public void writeAppendStrings(final Type type) {
}
} else {
// Java 8: push a StringBuilder append
switch (type.sort) {
case BOOL: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_BOOLEAN); break;
case CHAR: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_CHAR); break;
case BYTE:
case SHORT:
case INT: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_INT); break;
case LONG: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_LONG); break;
case FLOAT: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_FLOAT); break;
case DOUBLE: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_DOUBLE); break;
case STRING: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_STRING); break;
default: invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_OBJECT);
}
if (type.clazz == boolean.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_BOOLEAN);
else if (type.clazz == char.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_CHAR);
else if (type.clazz == byte.class ||
type.clazz == short.class ||
type.clazz == int.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_INT);
else if (type.clazz == long.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_LONG);
else if (type.clazz == float.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_FLOAT);
else if (type.clazz == double.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_DOUBLE);
else if (type.clazz == String.class) invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_STRING);
else invokeVirtual(STRINGBUILDER_TYPE, STRINGBUILDER_APPEND_OBJECT);
}
}

Expand Down Expand Up @@ -318,9 +319,7 @@ public void writeDynamicBinaryInstruction(Location location, Type returnType, Ty

/** Writes a static binary instruction */
public void writeBinaryInstruction(Location location, Type type, Operation operation) {
final Sort sort = type.sort;

if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) &&
if ((type.clazz == float.class || type.clazz == double.class) &&
(operation == Operation.LSH || operation == Operation.USH ||
operation == Operation.RSH || operation == Operation.BWAND ||
operation == Operation.XOR || operation == Operation.BWOR)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package org.elasticsearch.painless.node;

import org.elasticsearch.painless.AnalyzerCaster;
import org.elasticsearch.painless.Definition;
import org.elasticsearch.painless.Definition.Cast;
import org.elasticsearch.painless.Definition.Type;
import org.elasticsearch.painless.Locals;
Expand Down Expand Up @@ -157,7 +158,7 @@ AExpression cast(Locals locals) {

return ecast;
} else {
if (expected.sort.constant) {
if (Definition.isConstantType(expected)) {
// For the case where a cast is required, a constant is set,
// and the constant can be immediately cast to the expected type.
// An EConstant replaces this node with the constant cast appropriately
Expand Down
Loading

0 comments on commit 2385878

Please sign in to comment.