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;
}
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);
}
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;
}
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();
}
Aggregations