use of org.elasticsearch.painless.Locals.Variable in project elasticsearch by elastic.
the class SSource method write.
@Override
void write(MethodWriter writer, Globals globals) {
// We wrap the whole method in a few try/catches to handle and/or convert other exceptions to ScriptException
Label startTry = new Label();
Label endTry = new Label();
Label startExplainCatch = new Label();
Label startOtherCatch = new Label();
Label endCatch = new Label();
writer.mark(startTry);
if (reserved.getMaxLoopCounter() > 0) {
// if there is infinite loop protection, we do this once:
// int #loop = settings.getMaxLoopCounter()
Variable loop = mainMethod.getVariable(null, Locals.LOOP);
writer.push(reserved.getMaxLoopCounter());
writer.visitVarInsn(Opcodes.ISTORE, loop.getSlot());
}
for (AStatement statement : statements) {
statement.write(writer, globals);
}
if (!methodEscape) {
switch(scriptInterface.getExecuteMethod().getReturnType().getSort()) {
case org.objectweb.asm.Type.VOID:
break;
case org.objectweb.asm.Type.BOOLEAN:
writer.push(false);
break;
case org.objectweb.asm.Type.BYTE:
writer.push(0);
break;
case org.objectweb.asm.Type.SHORT:
writer.push(0);
break;
case org.objectweb.asm.Type.INT:
writer.push(0);
break;
case org.objectweb.asm.Type.LONG:
writer.push(0L);
break;
case org.objectweb.asm.Type.FLOAT:
writer.push(0f);
break;
case org.objectweb.asm.Type.DOUBLE:
writer.push(0d);
break;
default:
writer.visitInsn(Opcodes.ACONST_NULL);
}
writer.returnValue();
}
writer.mark(endTry);
writer.goTo(endCatch);
// This looks like:
// } catch (PainlessExplainError e) {
// throw this.convertToScriptException(e, e.getHeaders())
// }
writer.visitTryCatchBlock(startTry, endTry, startExplainCatch, PAINLESS_EXPLAIN_ERROR_TYPE.getInternalName());
writer.mark(startExplainCatch);
writer.loadThis();
writer.swap();
writer.dup();
writer.invokeVirtual(PAINLESS_EXPLAIN_ERROR_TYPE, PAINLESS_EXPLAIN_ERROR_GET_HEADERS_METHOD);
writer.invokeVirtual(BASE_CLASS_TYPE, CONVERT_TO_SCRIPT_EXCEPTION_METHOD);
writer.throwException();
// This looks like:
// } catch (PainlessError | BootstrapMethodError | OutOfMemoryError | StackOverflowError | Exception e) {
// throw this.convertToScriptException(e, e.getHeaders())
// }
// We *think* it is ok to catch OutOfMemoryError and StackOverflowError because Painless is stateless
writer.visitTryCatchBlock(startTry, endTry, startOtherCatch, PAINLESS_ERROR_TYPE.getInternalName());
writer.visitTryCatchBlock(startTry, endTry, startOtherCatch, BOOTSTRAP_METHOD_ERROR_TYPE.getInternalName());
writer.visitTryCatchBlock(startTry, endTry, startOtherCatch, OUT_OF_MEMORY_ERROR_TYPE.getInternalName());
writer.visitTryCatchBlock(startTry, endTry, startOtherCatch, STACK_OVERFLOW_ERROR_TYPE.getInternalName());
writer.visitTryCatchBlock(startTry, endTry, startOtherCatch, EXCEPTION_TYPE.getInternalName());
writer.mark(startOtherCatch);
writer.loadThis();
writer.swap();
writer.invokeStatic(COLLECTIONS_TYPE, EMPTY_MAP_METHOD);
writer.invokeVirtual(BASE_CLASS_TYPE, CONVERT_TO_SCRIPT_EXCEPTION_METHOD);
writer.throwException();
writer.mark(endCatch);
}
use of org.elasticsearch.painless.Locals.Variable in project elasticsearch by elastic.
the class ELambda method analyze.
@Override
void analyze(Locals locals) {
final Type returnType;
final List<String> actualParamTypeStrs;
Method interfaceMethod;
// inspect the target first, set interface method if we know it.
if (expected == null) {
interfaceMethod = null;
// we don't know anything: treat as def
returnType = Definition.DEF_TYPE;
// don't infer any types
actualParamTypeStrs = paramTypeStrs;
} else {
// we know the method statically, infer return type and any unknown/def types
interfaceMethod = expected.struct.getFunctionalMethod();
if (interfaceMethod == null) {
throw createError(new IllegalArgumentException("Cannot pass lambda to [" + expected.name + "], not a functional interface"));
}
// check arity before we manipulate parameters
if (interfaceMethod.arguments.size() != paramTypeStrs.size())
throw new IllegalArgumentException("Incorrect number of parameters for [" + interfaceMethod.name + "] in [" + expected.clazz + "]");
// for method invocation, its allowed to ignore the return value
if (interfaceMethod.rtn == Definition.VOID_TYPE) {
returnType = Definition.DEF_TYPE;
} else {
returnType = interfaceMethod.rtn;
}
// replace any def types with the actual type (which could still be def)
actualParamTypeStrs = new ArrayList<String>();
for (int i = 0; i < paramTypeStrs.size(); i++) {
String paramType = paramTypeStrs.get(i);
if (paramType.equals(Definition.DEF_TYPE.name)) {
actualParamTypeStrs.add(interfaceMethod.arguments.get(i).name);
} else {
actualParamTypeStrs.add(paramType);
}
}
}
// gather any variables used by the lambda body first.
Set<String> variables = new HashSet<>();
for (AStatement statement : statements) {
statement.extractVariables(variables);
}
// any of those variables defined in our scope need to be captured
captures = new ArrayList<>();
for (String variable : variables) {
if (locals.hasVariable(variable)) {
captures.add(locals.getVariable(location, variable));
}
}
// prepend capture list to lambda's arguments
List<String> paramTypes = new ArrayList<>();
List<String> paramNames = new ArrayList<>();
for (Variable var : captures) {
paramTypes.add(var.type.name);
paramNames.add(var.name);
}
paramTypes.addAll(actualParamTypeStrs);
paramNames.addAll(paramNameStrs);
// desugar lambda body into a synthetic method
desugared = new SFunction(reserved, location, returnType.name, name, paramTypes, paramNames, statements, true);
desugared.generateSignature();
desugared.analyze(Locals.newLambdaScope(locals.getProgramScope(), returnType, desugared.parameters, captures.size(), reserved.getMaxLoopCounter()));
// setup method reference to synthetic method
if (expected == null) {
ref = null;
actual = Definition.getType("String");
defPointer = "Sthis." + name + "," + captures.size();
} else {
defPointer = null;
try {
ref = new FunctionRef(expected, interfaceMethod, desugared.method, captures.size());
} catch (IllegalArgumentException e) {
throw createError(e);
}
actual = expected;
}
}
use of org.elasticsearch.painless.Locals.Variable in project elasticsearch by elastic.
the class NodeToStringTests method testSSubEachArray.
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());
}
use of org.elasticsearch.painless.Locals.Variable in project elasticsearch by elastic.
the class NodeToStringTests method testSSubEachIterable.
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());
}
use of org.elasticsearch.painless.Locals.Variable in project elasticsearch by elastic.
the class SEach method analyze.
@Override
void analyze(Locals locals) {
expression.analyze(locals);
expression.expected = expression.actual;
expression = expression.cast(locals);
final Type type;
try {
type = Definition.getType(this.type);
} catch (IllegalArgumentException exception) {
throw createError(new IllegalArgumentException("Not a type [" + this.type + "]."));
}
locals = Locals.newLocalScope(locals);
Variable variable = locals.addVariable(location, type, name, true);
if (expression.actual.sort == Sort.ARRAY) {
sub = new SSubEachArray(location, variable, expression, block);
} else if (expression.actual.sort == Sort.DEF || Iterable.class.isAssignableFrom(expression.actual.clazz)) {
sub = new SSubEachIterable(location, variable, expression, block);
} else {
throw createError(new IllegalArgumentException("Illegal for each type [" + expression.actual.name + "]."));
}
sub.analyze(locals);
if (block == null) {
throw createError(new IllegalArgumentException("Extraneous for each loop."));
}
block.beginLoop = true;
block.inLoop = true;
block.analyze(locals);
block.statementCount = Math.max(1, block.statementCount);
if (block.loopEscape && !block.anyContinue) {
throw createError(new IllegalArgumentException("Extraneous for loop."));
}
statementCount = 1;
if (locals.hasVariable(Locals.LOOP)) {
sub.loopCounter = locals.getVariable(location, Locals.LOOP);
}
}
Aggregations