Search in sources :

Example 6 with BinaryOperation

use of org.mvel2.ast.BinaryOperation in project drools by kiegroup.

the class ConditionAnalyzer method analyzeSingleCondition.

private SingleCondition analyzeSingleCondition(ASTNode node, boolean isNegated) {
    SingleCondition condition = new SingleCondition(isNegated);
    if (node instanceof BinaryOperation) {
        BinaryOperation binaryOperation = (BinaryOperation) node;
        condition.left = analyzeNode(binaryOperation.getLeft());
        condition.operation = BooleanOperator.fromMvelOpCode(binaryOperation.getOperation());
        condition.right = analyzeNode(binaryOperation.getRight());
    } else if (node instanceof RegExMatch) {
        condition.left = analyzeNode(node);
        condition.operation = BooleanOperator.MATCHES;
        RegExMatch regExNode = (RegExMatch) node;
        Pattern pattern = regExNode.getPattern();
        if (pattern != null) {
            condition.right = new FixedExpression(String.class, pattern.pattern());
        } else {
            condition.right = analyzeNode(((ExecutableAccessor) regExNode.getPatternStatement()).getNode());
        }
    } else if (node instanceof Contains) {
        condition.left = analyzeNode(((Contains) node).getFirstStatement());
        condition.operation = BooleanOperator.CONTAINS;
        condition.right = analyzeNode(((Contains) node).getSecondStatement());
    } else if (node instanceof Soundslike) {
        condition.left = analyzeNode(((Soundslike) node).getStatement());
        condition.operation = BooleanOperator.SOUNDSLIKE;
        condition.right = analyzeNode(((Soundslike) node).getSoundslike());
    } else if (node instanceof Instance) {
        condition.left = analyzeNode(((Instance) node).getStatement());
        condition.operation = BooleanOperator.INSTANCEOF;
        condition.right = analyzeNode(((Instance) node).getClassStatement());
    } else {
        condition.left = analyzeNode(node);
    }
    return condition;
}
Also used : Pattern(java.util.regex.Pattern) RegExMatch(org.mvel2.ast.RegExMatch) Soundslike(org.mvel2.ast.Soundslike) Instance(org.mvel2.ast.Instance) BinaryOperation(org.mvel2.ast.BinaryOperation) Contains(org.mvel2.ast.Contains)

Example 7 with BinaryOperation

use of org.mvel2.ast.BinaryOperation in project drools by kiegroup.

the class ConditionAnalyzer method analyzeNode.

private Expression analyzeNode(ASTNode node) {
    node = analyzeRegEx(analyzeSubstatement(node));
    if (node instanceof LiteralNode) {
        LiteralNode literalNode = (LiteralNode) node;
        return new FixedExpression(literalNode.getEgressType(), literalNode.getLiteralValue());
    }
    if (node instanceof BinaryOperation) {
        BinaryOperation op = (BinaryOperation) node;
        return new AritmeticExpression(analyzeNode(op.getLeft()), AritmeticOperator.fromMvelOpCode(op), analyzeNode(op.getRight()));
    }
    if (node instanceof TypeCast) {
        ExecutableStatement statement = ((TypeCast) node).getStatement();
        if (statement instanceof ExecutableAccessor) {
            ExecutableAccessor accessor = (ExecutableAccessor) statement;
            return new CastExpression(node.getEgressType(), analyzeNode(accessor.getNode()));
        } else {
            ExecutableLiteral literal = (ExecutableLiteral) statement;
            return new CastExpression(node.getEgressType(), new FixedExpression(literal.getLiteral()));
        }
    }
    if (node instanceof Union) {
        ASTNode main = ((Union) node).getMain();
        Accessor accessor = node.getAccessor();
        EvaluatedExpression expression = new EvaluatedExpression();
        expression.firstExpression = analyzeNode(main);
        if (accessor instanceof DynamicGetAccessor) {
            AccessorNode accessorNode = (AccessorNode) ((DynamicGetAccessor) accessor).getSafeAccessor();
            expression.addInvocation(analyzeAccessorInvocation(accessorNode, node, null, null));
        } else if (accessor instanceof AccessorNode) {
            AccessorNode accessorNode = (AccessorNode) accessor;
            while (accessorNode != null) {
                expression.addInvocation(analyzeAccessorInvocation(accessorNode, node, null, null));
                accessorNode = accessorNode.getNextNode();
            }
        } else {
            throw new RuntimeException("Unexpected accessor: " + accessor);
        }
        return expression;
    }
    if (node instanceof Sign) {
        ExecutableStatement statement = getFieldValue(Sign.class, "stmt", (Sign) node);
        if (statement instanceof ExecutableAccessor) {
            ExecutableAccessor accessor = (ExecutableAccessor) statement;
            return new AritmeticExpression(new FixedExpression(0), AritmeticOperator.SUB, analyzeNode(accessor.getNode()));
        } else {
            ExecutableLiteral literal = (ExecutableLiteral) statement;
            return new AritmeticExpression(new FixedExpression(0), AritmeticOperator.SUB, new FixedExpression(literal.getLiteral()));
        }
    }
    Accessor accessor = node.getAccessor();
    if (accessor instanceof IndexedVariableAccessor) {
        String variableName = node.getName();
        int dot = variableName.indexOf('.');
        if (dot > 0) {
            variableName = variableName.substring(0, dot);
        }
        Class<?> variableType = getVariableType(variableName);
        return new VariableExpression(variableName, analyzeExpressionNode(((AccessorNode) accessor).getNextNode(), node, variableType), variableType != null ? variableType : node.getEgressType());
    }
    if (accessor == null && node instanceof NewObjectNode) {
        accessor = ((NewObjectNode) node).getNewObjectOptimizer();
    }
    if (accessor instanceof VariableAccessor) {
        VariableAccessor variableAccessor = (VariableAccessor) accessor;
        AccessorNode accessorNode = variableAccessor.getNextNode();
        if (accessorNode == null || !isStaticAccessor(accessorNode)) {
            String variableName = (String) (variableAccessor.getProperty());
            Class<?> variableType = getVariableType(variableName);
            if (variableType != null) {
                return new VariableExpression(variableName, analyzeExpressionNode(accessorNode, node, variableType), variableType);
            } else {
                if (node.getLiteralValue() instanceof ParserContext) {
                    ParserContext pCtx = (ParserContext) node.getLiteralValue();
                    // it's not a variable but a method invocation on this
                    Class<?> thisClass = pCtx.getInputs().get("this");
                    try {
                        return new EvaluatedExpression(new MethodInvocation(thisClass.getMethod(variableName)));
                    } catch (NoSuchMethodException e) {
                        if (node.getEgressType() == Class.class) {
                            // there's no method on this with the given name, check if it is a class literal
                            Class<?> classLiteral = pCtx.getParserConfiguration().getImport(variableName);
                            if (classLiteral != null) {
                                return new FixedExpression(Class.class, classLiteral);
                            }
                        }
                        throw new RuntimeException(e);
                    }
                }
            }
        }
    }
    if (accessor == null) {
        throw new RuntimeException("Null accessor on node: " + node);
    }
    return analyzeNodeAccessor(accessor, node);
}
Also used : BinaryOperation(org.mvel2.ast.BinaryOperation) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) FieldAccessor(org.mvel2.optimizers.impl.refl.nodes.FieldAccessor) StaticVarAccessor(org.mvel2.optimizers.impl.refl.nodes.StaticVarAccessor) ListAccessor(org.mvel2.optimizers.impl.refl.nodes.ListAccessor) ExecutableAccessor(org.mvel2.compiler.ExecutableAccessor) GetterAccessor(org.mvel2.optimizers.impl.refl.nodes.GetterAccessor) DynamicGetAccessor(org.mvel2.optimizers.dynamic.DynamicGetAccessor) ExprValueAccessor(org.mvel2.optimizers.impl.refl.collection.ExprValueAccessor) MapAccessor(org.mvel2.optimizers.impl.refl.nodes.MapAccessor) ThisValueAccessor(org.mvel2.optimizers.impl.refl.nodes.ThisValueAccessor) Accessor(org.mvel2.compiler.Accessor) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) MethodAccessor(org.mvel2.optimizers.impl.refl.nodes.MethodAccessor) VariableAccessor(org.mvel2.optimizers.impl.refl.nodes.VariableAccessor) ConstructorAccessor(org.mvel2.optimizers.impl.refl.nodes.ConstructorAccessor) StaticReferenceAccessor(org.mvel2.optimizers.impl.refl.nodes.StaticReferenceAccessor) ArrayAccessor(org.mvel2.optimizers.impl.refl.nodes.ArrayAccessor) Union(org.mvel2.ast.Union) AccessorNode(org.mvel2.compiler.AccessorNode) DynamicGetAccessor(org.mvel2.optimizers.dynamic.DynamicGetAccessor) ExecutableLiteral(org.mvel2.compiler.ExecutableLiteral) ASTNode(org.mvel2.ast.ASTNode) ExecutableStatement(org.mvel2.compiler.ExecutableStatement) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) VariableAccessor(org.mvel2.optimizers.impl.refl.nodes.VariableAccessor) LiteralNode(org.mvel2.ast.LiteralNode) IndexedVariableAccessor(org.mvel2.optimizers.impl.refl.nodes.IndexedVariableAccessor) NewObjectNode(org.mvel2.ast.NewObjectNode) Sign(org.mvel2.ast.Sign) TypeCast(org.mvel2.ast.TypeCast) ParserContext(org.mvel2.ParserContext)

Example 8 with BinaryOperation

use of org.mvel2.ast.BinaryOperation 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)

Example 9 with BinaryOperation

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

the class DebugTools method decompile.

private static String decompile(CompiledExpression cExp, boolean nest, DecompileContext context) {
    ASTIterator iter = new ASTLinkedList(cExp.getFirstNode());
    ASTNode tk;
    StringBuffer sbuf = new StringBuffer();
    if (!nest) {
        sbuf.append("Expression Decompile\n-------------\n");
    }
    while (iter.hasMoreNodes()) {
        sbuf.append("(").append(context.node++).append(") ");
        if ((tk = iter.nextNode()) instanceof NestedStatement && ((NestedStatement) tk).getNestedStatement() instanceof CompiledExpression) {
            // noinspection StringConcatenationInsideStringBufferAppend
            sbuf.append("NEST [" + tk.getClass().getSimpleName() + "]: { " + tk.getName() + " }\n");
            sbuf.append(decompile((CompiledExpression) ((NestedStatement) tk).getNestedStatement(), true, context));
        }
        if (tk instanceof Substatement && ((Substatement) tk).getStatement() instanceof CompiledExpression) {
            // noinspection StringConcatenationInsideStringBufferAppend
            sbuf.append("NEST [" + tk.getClass().getSimpleName() + "]: { " + tk.getName() + " }\n");
            sbuf.append(decompile((CompiledExpression) ((Substatement) tk).getStatement(), true, context));
        } else // }
        if (tk.isDebuggingSymbol()) {
            // noinspection StringConcatenationInsideStringBufferAppend
            sbuf.append("DEBUG_SYMBOL :: " + tk.toString());
        } else if (tk.isLiteral()) {
            sbuf.append("LITERAL :: ").append(tk.getLiteralValue()).append("'");
        } else if (tk.isOperator()) {
            sbuf.append("OPERATOR [").append(getOperatorName(tk.getOperator())).append("]: ").append(tk.getName());
            if (tk.isOperator(Operator.END_OF_STMT))
                sbuf.append("\n");
        } else if (tk.isIdentifier()) {
            sbuf.append("REFERENCE :: ").append(tk.getClass().getSimpleName()).append(":").append(tk.getName());
        } else if (tk instanceof BinaryOperation) {
            BinaryOperation bo = (BinaryOperation) tk;
            sbuf.append("OPERATION [" + getOperatorName(bo.getOperation()) + "] {").append(bo.getLeft().getName()).append("} {").append(bo.getRight().getName()).append("}");
        } else {
            // noinspection StringConcatenationInsideStringBufferAppend
            sbuf.append("NODE [" + tk.getClass().getSimpleName() + "] :: " + tk.getName());
        }
        sbuf.append("\n");
    }
    sbuf.append("==END==");
    return sbuf.toString();
}
Also used : NestedStatement(org.mvel2.ast.NestedStatement) BinaryOperation(org.mvel2.ast.BinaryOperation) ASTLinkedList(org.mvel2.util.ASTLinkedList) ASTNode(org.mvel2.ast.ASTNode) ASTIterator(org.mvel2.util.ASTIterator) Substatement(org.mvel2.ast.Substatement) CompiledExpression(org.mvel2.compiler.CompiledExpression)

Aggregations

BinaryOperation (org.mvel2.ast.BinaryOperation)7 ASTNode (org.mvel2.ast.ASTNode)5 LiteralNode (org.mvel2.ast.LiteralNode)4 NewObjectNode (org.mvel2.ast.NewObjectNode)3 Union (org.mvel2.ast.Union)3 Pattern (java.util.regex.Pattern)2 CompileException (org.mvel2.CompileException)2 ParserContext (org.mvel2.ParserContext)2 Contains (org.mvel2.ast.Contains)2 Instance (org.mvel2.ast.Instance)2 NestedStatement (org.mvel2.ast.NestedStatement)2 RegExMatch (org.mvel2.ast.RegExMatch)2 Sign (org.mvel2.ast.Sign)2 Soundslike (org.mvel2.ast.Soundslike)2 Substatement (org.mvel2.ast.Substatement)2 TypeCast (org.mvel2.ast.TypeCast)2 Accessor (org.mvel2.compiler.Accessor)2 AccessorNode (org.mvel2.compiler.AccessorNode)2 CompiledExpression (org.mvel2.compiler.CompiledExpression)2 ExecutableAccessor (org.mvel2.compiler.ExecutableAccessor)2