Search in sources :

Example 1 with Variable

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);
}
Also used : Variable(org.elasticsearch.painless.Locals.Variable) Label(org.objectweb.asm.Label)

Example 2 with Variable

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;
    }
}
Also used : Variable(org.elasticsearch.painless.Locals.Variable) ArrayList(java.util.ArrayList) Method(org.elasticsearch.painless.Definition.Method) Type(org.elasticsearch.painless.Definition.Type) HashSet(java.util.HashSet) FunctionRef(org.elasticsearch.painless.FunctionRef)

Example 3 with Variable

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());
}
Also used : Variable(org.elasticsearch.painless.Locals.Variable) Location(org.elasticsearch.painless.Location)

Example 4 with Variable

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());
}
Also used : Variable(org.elasticsearch.painless.Locals.Variable) Location(org.elasticsearch.painless.Location)

Example 5 with Variable

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);
    }
}
Also used : Type(org.elasticsearch.painless.Definition.Type) Variable(org.elasticsearch.painless.Locals.Variable)

Aggregations

Variable (org.elasticsearch.painless.Locals.Variable)6 Type (org.elasticsearch.painless.Definition.Type)2 Location (org.elasticsearch.painless.Location)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Method (org.elasticsearch.painless.Definition.Method)1 FunctionRef (org.elasticsearch.painless.FunctionRef)1 Label (org.objectweb.asm.Label)1