Search in sources :

Example 11 with LiteralNode

use of org.mvel2.ast.LiteralNode in project mvel by mvel.

the class ExpressionCompiler method compileReduce.

private boolean compileReduce(int opCode, ASTLinkedList astBuild) {
    switch(arithmeticFunctionReduction(opCode)) {
        case OP_TERMINATE:
            /**
             * The reduction failed because we encountered a non-literal,
             * so we must now back out and cleanup.
             */
            stk.xswap_op();
            astBuild.addTokenNode(new LiteralNode(stk.pop(), pCtx));
            astBuild.addTokenNode((OperatorNode) splitAccumulator.pop(), verify(pCtx, (ASTNode) splitAccumulator.pop()));
            return false;
        case OP_OVERFLOW:
            /**
             * Back out completely, pull everything back off the stack and add the instructions
             * to the output payload as they are.
             */
            LiteralNode rightValue = new LiteralNode(stk.pop(), pCtx);
            OperatorNode operator = new OperatorNode((Integer) stk.pop(), expr, st, pCtx);
            astBuild.addTokenNode(new LiteralNode(stk.pop(), pCtx), operator);
            astBuild.addTokenNode(rightValue, (OperatorNode) splitAccumulator.pop());
            astBuild.addTokenNode(verify(pCtx, (ASTNode) splitAccumulator.pop()));
            return false;
        case OP_NOT_LITERAL:
            ASTNode tkLA2 = (ASTNode) stk.pop();
            Integer tkOp2 = (Integer) stk.pop();
            astBuild.addTokenNode(new LiteralNode(getStackValueResult(), pCtx));
            astBuild.addTokenNode(new OperatorNode(tkOp2, expr, st, pCtx), verify(pCtx, tkLA2));
            return false;
    }
    return true;
}
Also used : LiteralNode(org.mvel2.ast.LiteralNode) ASTNode(org.mvel2.ast.ASTNode) OperatorNode(org.mvel2.ast.OperatorNode)

Example 12 with LiteralNode

use of org.mvel2.ast.LiteralNode in project mvel by mvel.

the class CompilerTools method finalizePayload.

/**
 * Finalize the payload, by reducing any stack-based-operations to dedicated nodes where possible.
 *
 * @param astLinkedList          - AST to be optimized.
 * @param secondPassOptimization - perform a second pass optimization to optimize boolean expressions.
 * @param pCtx                    - The parser context
 * @return optimized AST
 */
public static ASTLinkedList finalizePayload(ASTLinkedList astLinkedList, boolean secondPassOptimization, ParserContext pCtx) {
    ASTLinkedList optimizedAst = new ASTLinkedList();
    ASTNode tk, tkOp, tkOp2;
    /**
     * Re-process the AST and optimize it.
     */
    while (astLinkedList.hasMoreNodes()) {
        if ((tk = astLinkedList.nextNode()).getFields() == -1) {
            optimizedAst.addTokenNode(tk);
        } else if (astLinkedList.hasMoreNodes()) {
            if ((tkOp = astLinkedList.nextNode()).getFields() == -1) {
                optimizedAst.addTokenNode(tk, tkOp);
            } else if (tkOp.isOperator() && tkOp.getOperator() < 21) {
                int op = tkOp.getOperator();
                int op2;
                if (op == -1) {
                    throw new CompileException("illegal use of operator: " + tkOp.getName(), tkOp.getExpr(), tk.getStart());
                }
                ASTNode tk2 = astLinkedList.nextNode();
                BinaryOperation bo;
                if (tk.getEgressType() == Integer.class && tk2.getEgressType() == Integer.class) {
                    bo = boOptimize(op, tk, tk2, pCtx);
                } else {
                    /**
                     * Let's see if we can simply the expression more.
                     */
                    bo = null;
                    boolean inv = tkOp.isOperator(Operator.SUB);
                    boolean reduc = tk.isLiteral() && isReductionOpportunity(tkOp, tk2);
                    boolean p_inv = false;
                    while (reduc) {
                        ASTNode oper = astLinkedList.nextNode();
                        ASTNode rightNode = astLinkedList.nextNode();
                        if (rightNode == null)
                            break;
                        Object val = new BinaryOperation(oper.getOperator(), inv ? new LiteralNode(signNumber(tk2.getLiteralValue()), pCtx) : tk2, rightNode, pCtx).getReducedValueAccelerated(null, null, null);
                        if (!astLinkedList.hasMoreNodes() && BlankLiteral.INSTANCE.equals(val)) {
                            optimizedAst.addTokenNode(tk);
                            continue;
                        }
                        reduc = astLinkedList.hasMoreNodes() && (reducacbleOperator(astLinkedList.peekNode().getOperator())) && astLinkedList.peekNext().isLiteral();
                        if (inv)
                            p_inv = true;
                        inv = false;
                        if (!reduc) {
                            bo = new BinaryOperation(tkOp.getOperator(), tk, new LiteralNode(p_inv ? signNumber(val) : val, pCtx), pCtx);
                        } else {
                            tk2 = new LiteralNode(val, pCtx);
                        }
                    }
                    if (bo == null)
                        bo = new BinaryOperation(op, tk, tk2, pCtx);
                }
                tkOp2 = null;
                /**
                 * If we have a chain of math/comparitive operators then we fill them into the tree
                 * right here.
                 */
                while (astLinkedList.hasMoreNodes() && (tkOp2 = astLinkedList.nextNode()).isOperator() && tkOp2.getFields() != -1 && (op2 = tkOp2.getOperator()) != -1 && op2 < 21) {
                    if (PTABLE[op2] > PTABLE[op]) {
                        BinaryOperation newRightBo = boOptimize(op2, bo.getRightMost(), astLinkedList.nextNode(), pCtx);
                        if (isIntOptimizationviolation(bo, newRightBo)) {
                            // Oops! We optimized the node based on the assumed right node type but it gets replaced
                            bo = new BinaryOperation(bo.getOperation(), bo.getLeft(), newRightBo, pCtx);
                        } else {
                            bo.setRightMost(newRightBo);
                        }
                    } else if (bo.getOperation() != op2 && PTABLE[op] == PTABLE[op2]) {
                        if (PTABLE[bo.getOperation()] == PTABLE[op2]) {
                            // bo = new BinaryOperation(op2, bo, astLinkedList.nextNode(), pCtx);
                            bo = boOptimize(op2, bo, astLinkedList.nextNode(), pCtx);
                        } else {
                            tk2 = astLinkedList.nextNode();
                            if (isIntOptimizationviolation(bo, tk2)) {
                                bo = new BinaryOperation(bo.getOperation(), bo.getLeft(), bo.getRight(), pCtx);
                            }
                            bo.setRight(new BinaryOperation(op2, bo.getRight(), tk2, pCtx));
                        }
                    } else if (PTABLE[bo.getOperation()] >= PTABLE[op2]) {
                        bo = new BinaryOperation(op2, bo, astLinkedList.nextNode(), pCtx);
                    } else {
                        tk2 = astLinkedList.nextNode();
                        if (isIntOptimizationviolation(bo, tk2)) {
                            bo = new BinaryOperation(bo.getOperation(), bo.getLeft(), bo.getRight(), pCtx);
                        }
                        bo.setRight(new BinaryOperation(op2, bo.getRight(), tk2, pCtx));
                    }
                    op = op2;
                    tkOp = tkOp2;
                }
                if (tkOp2 != null && tkOp2 != tkOp) {
                    optimizeOperator(tkOp2.getOperator(), bo, tkOp2, astLinkedList, optimizedAst, pCtx);
                } else {
                    optimizedAst.addTokenNode(bo);
                }
            } else if (tkOp.isOperator()) {
                optimizeOperator(tkOp.getOperator(), tk, tkOp, astLinkedList, optimizedAst, pCtx);
            } else if (!tkOp.isAssignment() && !tkOp.isOperator() && tk.getLiteralValue() instanceof Class) {
                optimizedAst.addTokenNode(new DeclTypedVarNode(tkOp.getName(), tkOp.getExpr(), tkOp.getStart(), tk.getOffset(), (Class) tk.getLiteralValue(), 0, pCtx));
            } else if (tkOp.isAssignment() && tk.getLiteralValue() instanceof Class) {
                tk.discard();
                optimizedAst.addTokenNode(tkOp);
            } else if (astLinkedList.hasMoreNodes() && tkOp.getLiteralValue() instanceof Class && astLinkedList.peekNode().isAssignment()) {
                tkOp.discard();
                optimizedAst.addTokenNode(tk, astLinkedList.nextNode());
            } else {
                astLinkedList.back();
                optimizedAst.addTokenNode(tk);
            }
        } else {
            optimizedAst.addTokenNode(tk);
        }
    }
    if (secondPassOptimization) {
        /**
         * Perform a second pass optimization for boolean conditions.
         */
        (astLinkedList = optimizedAst).reset();
        optimizedAst = new ASTLinkedList();
        while (astLinkedList.hasMoreNodes()) {
            if ((tk = astLinkedList.nextNode()).getFields() == -1) {
                optimizedAst.addTokenNode(tk);
            } else if (astLinkedList.hasMoreNodes()) {
                if ((tkOp = astLinkedList.nextNode()).getFields() == -1) {
                    optimizedAst.addTokenNode(tk, tkOp);
                } else if (tkOp.isOperator() && (tkOp.getOperator() == Operator.AND || tkOp.getOperator() == Operator.OR)) {
                    tkOp2 = null;
                    BooleanNode bool;
                    if (tkOp.getOperator() == Operator.AND) {
                        bool = new And(tk, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                    } else {
                        bool = new Or(tk, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                    }
                    while (astLinkedList.hasMoreNodes() && (tkOp2 = astLinkedList.nextNode()).isOperator() && (tkOp2.isOperator(Operator.AND) || tkOp2.isOperator(Operator.OR))) {
                        if ((tkOp = tkOp2).getOperator() == Operator.AND) {
                            bool.setRightMost(new And(bool.getRightMost(), astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx));
                        } else {
                            bool = new Or(bool, astLinkedList.nextNode(), pCtx.isStrongTyping(), pCtx);
                        }
                    }
                    optimizedAst.addTokenNode(bool);
                    if (tkOp2 != null && tkOp2 != tkOp) {
                        optimizedAst.addTokenNode(tkOp2);
                    }
                } else {
                    optimizedAst.addTokenNode(tk, tkOp);
                }
            } else {
                optimizedAst.addTokenNode(tk);
            }
        }
    }
    return optimizedAst;
}
Also used : Or(org.mvel2.ast.Or) BinaryOperation(org.mvel2.ast.BinaryOperation) BooleanNode(org.mvel2.ast.BooleanNode) LiteralNode(org.mvel2.ast.LiteralNode) And(org.mvel2.ast.And) DeclTypedVarNode(org.mvel2.ast.DeclTypedVarNode) ASTNode(org.mvel2.ast.ASTNode) CompileException(org.mvel2.CompileException)

Aggregations

LiteralNode (org.mvel2.ast.LiteralNode)11 CompileException (org.mvel2.CompileException)6 ASTNode (org.mvel2.ast.ASTNode)6 NewObjectNode (org.mvel2.ast.NewObjectNode)4 OperatorNode (org.mvel2.ast.OperatorNode)4 Union (org.mvel2.ast.Union)4 ExecutableStatement (org.mvel2.compiler.ExecutableStatement)4 And (org.mvel2.ast.And)3 BinaryOperation (org.mvel2.ast.BinaryOperation)3 BooleanNode (org.mvel2.ast.BooleanNode)3 Negation (org.mvel2.ast.Negation)3 Or (org.mvel2.ast.Or)3 Sign (org.mvel2.ast.Sign)3 TypeCast (org.mvel2.ast.TypeCast)3 ExecutableLiteral (org.mvel2.compiler.ExecutableLiteral)3 ParserContext (org.mvel2.ParserContext)2 DeclTypedVarNode (org.mvel2.ast.DeclTypedVarNode)2 DeepOperativeAssignmentNode (org.mvel2.ast.DeepOperativeAssignmentNode)2 Substatement (org.mvel2.ast.Substatement)2 Accessor (org.mvel2.compiler.Accessor)2