use of org.mvel2.ast.ASTNode 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;
}
use of org.mvel2.ast.ASTNode in project mvel by mvel.
the class CompiledExpression method toString.
public String toString() {
StringBuilder appender = new StringBuilder();
ASTNode node = firstNode;
while (node != null) {
appender.append(node).append(";\n");
node = node.nextASTNode;
}
return appender.toString();
}
use of org.mvel2.ast.ASTNode 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.ASTNode in project mvel by mvel.
the class ASTBinaryTree method buildTree.
public static ASTBinaryTree buildTree(ASTIterator input) {
ASTIterator iter = new ASTLinkedList(input.firstNode());
ASTBinaryTree tree = new ASTBinaryTree(iter.nextNode());
while (iter.hasMoreNodes()) {
ASTNode node = iter.nextNode();
if (node instanceof EndOfStatement) {
if (iter.hasMoreNodes())
tree = new ASTBinaryTree(iter.nextNode());
} else {
tree = tree.append(node);
}
}
return tree;
}
use of org.mvel2.ast.ASTNode in project mvel by mvel.
the class ASTLinkedList method finish.
public void finish() {
reset();
ASTNode last = null;
ASTNode curr;
while (hasMoreNodes()) {
if ((curr = nextNode()).isDiscard()) {
if (last == null) {
last = firstASTNode = nextNode();
} else {
last.nextASTNode = nextNode();
}
continue;
}
if (!hasMoreNodes())
break;
last = curr;
}
this.last = last;
reset();
}
Aggregations