use of org.mvel2.util.ASTLinkedList 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.util.ASTLinkedList 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.util.ASTLinkedList 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();
}
use of org.mvel2.util.ASTLinkedList in project mvel by mvel.
the class DebugTools method determineType.
public static Class determineType(String name, CompiledExpression compiledExpression) {
ASTIterator iter = new ASTLinkedList(compiledExpression.getFirstNode());
ASTNode node;
while (iter.hasMoreNodes()) {
if (name.equals((node = iter.nextNode()).getName()) && node.isAssignment()) {
return node.getEgressType();
}
}
return null;
}
Aggregations