Search in sources :

Example 1 with FunctionRef

use of org.elasticsearch.painless.FunctionRef in project elasticsearch by elastic.

the class ECapturingFunctionRef method analyze.

@Override
void analyze(Locals variables) {
    captured = variables.getVariable(location, variable);
    if (expected == null) {
        if (captured.type.sort == Definition.Sort.DEF) {
            // dynamic implementation
            defPointer = "D" + variable + "." + call + ",1";
        } else {
            // typed implementation
            defPointer = "S" + captured.type.name + "." + call + ",1";
        }
        actual = Definition.getType("String");
    } else {
        defPointer = null;
        // static case
        if (captured.type.sort != Definition.Sort.DEF) {
            try {
                ref = new FunctionRef(expected, captured.type.name, call, 1);
            } catch (IllegalArgumentException e) {
                throw createError(e);
            }
        }
        actual = expected;
    }
}
Also used : FunctionRef(org.elasticsearch.painless.FunctionRef)

Example 2 with FunctionRef

use of org.elasticsearch.painless.FunctionRef 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 FunctionRef

use of org.elasticsearch.painless.FunctionRef in project elasticsearch by elastic.

the class EFunctionRef method analyze.

@Override
void analyze(Locals locals) {
    if (expected == null) {
        ref = null;
        actual = Definition.getType("String");
        defPointer = "S" + type + "." + call + ",0";
    } else {
        defPointer = null;
        try {
            if ("this".equals(type)) {
                // user's own function
                Method interfaceMethod = expected.struct.getFunctionalMethod();
                if (interfaceMethod == null) {
                    throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + "to [" + expected.name + "], not a functional interface");
                }
                Method implMethod = locals.getMethod(new MethodKey(call, interfaceMethod.arguments.size()));
                if (implMethod == null) {
                    throw new IllegalArgumentException("Cannot convert function reference [" + type + "::" + call + "] " + "to [" + expected.name + "], function not found");
                }
                ref = new FunctionRef(expected, interfaceMethod, implMethod, 0);
            } else {
                // whitelist lookup
                ref = new FunctionRef(expected, type, call, 0);
            }
        } catch (IllegalArgumentException e) {
            throw createError(e);
        }
        actual = expected;
    }
}
Also used : Method(org.elasticsearch.painless.Definition.Method) MethodKey(org.elasticsearch.painless.Definition.MethodKey) FunctionRef(org.elasticsearch.painless.FunctionRef)

Aggregations

FunctionRef (org.elasticsearch.painless.FunctionRef)3 Method (org.elasticsearch.painless.Definition.Method)2 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 MethodKey (org.elasticsearch.painless.Definition.MethodKey)1 Type (org.elasticsearch.painless.Definition.Type)1 Variable (org.elasticsearch.painless.Locals.Variable)1