Search in sources :

Example 1 with ParseTools.parseMethodOrConstructor

use of org.mvel2.util.ParseTools.parseMethodOrConstructor in project mvel by mvel.

the class ExpressionCompiler method verify.

protected ASTNode verify(ParserContext pCtx, ASTNode tk) {
    if (tk.isOperator() && (tk.getOperator().equals(Operator.AND) || tk.getOperator().equals(Operator.OR))) {
        secondPassOptimization = true;
    }
    if (tk.isDiscard() || tk.isOperator()) {
        return tk;
    } else if (tk.isLiteral()) {
        /**
         * Convert literal values from the default ASTNode to the more-efficient LiteralNode.
         */
        if ((fields & COMPILE_IMMEDIATE) != 0 && tk.getClass() == ASTNode.class) {
            return new LiteralNode(tk.getLiteralValue(), pCtx);
        } else {
            return tk;
        }
    }
    if (verifying) {
        if (tk.isIdentifier()) {
            PropertyVerifier propVerifier = new PropertyVerifier(expr, tk.getStart(), tk.getOffset(), pCtx);
            if (tk instanceof Union) {
                propVerifier.setCtx(((Union) tk).getLeftEgressType());
                tk.setEgressType(returnType = propVerifier.analyze());
            } else {
                tk.setEgressType(returnType = propVerifier.analyze());
                if (propVerifier.isFqcn()) {
                    tk.setAsFQCNReference();
                }
                if (propVerifier.isClassLiteral()) {
                    return new LiteralNode(returnType, pCtx);
                }
                if (propVerifier.isInput()) {
                    pCtx.addInput(tk.getAbsoluteName(), propVerifier.isDeepProperty() ? Object.class : returnType);
                }
                if (!propVerifier.isMethodCall() && !returnType.isEnum() && !pCtx.isOptimizerNotified() && pCtx.isStrongTyping() && !pCtx.isVariableVisible(tk.getAbsoluteName()) && !tk.isFQCN()) {
                    throw new CompileException("no such identifier: " + tk.getAbsoluteName(), expr, tk.getStart());
                }
            }
        } else if (tk.isAssignment()) {
            Assignment a = (Assignment) tk;
            if (a.getAssignmentVar() != null) {
                // pCtx.makeVisible(a.getAssignmentVar());
                PropertyVerifier propVerifier = new PropertyVerifier(a.getAssignmentVar(), pCtx);
                tk.setEgressType(returnType = propVerifier.analyze());
                if (!a.isNewDeclaration() && propVerifier.isResolvedExternally()) {
                    pCtx.addInput(tk.getAbsoluteName(), returnType);
                }
                ExecutableStatement c = (ExecutableStatement) subCompileExpression(expr, tk.getStart(), tk.getOffset(), pCtx);
                if (pCtx.isStrictTypeEnforcement()) {
                    /**
                     * If we're using strict type enforcement, we need to see if this coercion can be done now,
                     * or fail epicly.
                     */
                    if (!returnType.isAssignableFrom(c.getKnownEgressType()) && c.isLiteralOnly()) {
                        if (canConvert(c.getKnownEgressType(), returnType)) {
                            /**
                             * We convert the literal to the proper type.
                             */
                            try {
                                // Don't convert to a literal for DeepOperativeAssignmentNode. Coercion will be done by BinaryOperation
                                if (!(a instanceof DeepOperativeAssignmentNode)) {
                                    a.setValueStatement(new ExecutableLiteral(convert(c.getValue(null, null), returnType)));
                                }
                                return tk;
                            } catch (Exception e) {
                            // fall through.
                            }
                        } else if (returnType.isPrimitive() && unboxPrimitive(c.getKnownEgressType()).equals(returnType)) {
                            /**
                             * We ignore boxed primitive cases, since MVEL does not recognize primitives.
                             */
                            return tk;
                        }
                        throw new CompileException("cannot assign type " + c.getKnownEgressType().getName() + " to " + returnType.getName(), expr, st);
                    }
                }
            }
        } else if (tk instanceof NewObjectNode) {
            // this is a bit of a hack for now.
            NewObjectNode n = (NewObjectNode) tk;
            List<char[]> parms = ParseTools.parseMethodOrConstructor(tk.getNameAsArray());
            if (parms != null) {
                for (char[] p : parms) {
                    MVEL.analyze(p, pCtx);
                }
            }
        }
        returnType = tk.getEgressType();
    }
    if (!tk.isLiteral() && tk.getClass() == ASTNode.class && (tk.getFields() & ASTNode.ARRAY_TYPE_LITERAL) == 0) {
        if (pCtx.isStrongTyping())
            tk.strongTyping();
        tk.storePctx();
        tk.storeInLiteralRegister(pCtx);
    }
    return tk;
}
Also used : Union(org.mvel2.ast.Union) CompileException(org.mvel2.CompileException) Assignment(org.mvel2.ast.Assignment) LiteralNode(org.mvel2.ast.LiteralNode) NewObjectNode(org.mvel2.ast.NewObjectNode) DeepOperativeAssignmentNode(org.mvel2.ast.DeepOperativeAssignmentNode) CompileException(org.mvel2.CompileException)

Aggregations

CompileException (org.mvel2.CompileException)1 Assignment (org.mvel2.ast.Assignment)1 DeepOperativeAssignmentNode (org.mvel2.ast.DeepOperativeAssignmentNode)1 LiteralNode (org.mvel2.ast.LiteralNode)1 NewObjectNode (org.mvel2.ast.NewObjectNode)1 Union (org.mvel2.ast.Union)1