com.dragome.compiler.parser.Optimizer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of dragome-bytecode-js-compiler Show documentation
Show all versions of dragome-bytecode-js-compiler Show documentation
Dragome SDK module: bytecode to javascript compiler
package com.dragome.compiler.parser;
import java.util.Iterator;
import java.util.List;
import org.apache.bcel.generic.Type;
import com.dragome.compiler.ast.ASTNode;
import com.dragome.compiler.ast.Assignable;
import com.dragome.compiler.ast.Assignment;
import com.dragome.compiler.ast.Block;
import com.dragome.compiler.ast.Expression;
import com.dragome.compiler.ast.FieldAccess;
import com.dragome.compiler.ast.InfixExpression;
import com.dragome.compiler.ast.MethodDeclaration;
import com.dragome.compiler.ast.NumberLiteral;
import com.dragome.compiler.ast.PStarExpression;
import com.dragome.compiler.ast.PostfixExpression;
import com.dragome.compiler.ast.PrefixExpression;
import com.dragome.compiler.ast.VariableBinding;
import com.dragome.compiler.ast.VariableDeclaration;
public class Optimizer
{
private MethodDeclaration methodDecl;
private List tempDecls;
public Optimizer(MethodDeclaration theMethodDecl, List theTempDecls)
{
methodDecl= theMethodDecl;
tempDecls= theTempDecls;
}
public static Expression negate(Expression expr)
{
PrefixExpression pe= new PrefixExpression();
pe.setOperator(PrefixExpression.NOT);
pe.setOperand(expr);
return pe;
}
public static Expression simplifyBooleanExpression(Expression expr, boolean negate)
{
if (expr instanceof PrefixExpression)
{
PrefixExpression pe= (PrefixExpression) expr;
if (pe.getOperator() != PrefixExpression.NOT)
return expr;
return simplifyBooleanExpression((Expression) pe.getOperand(), !negate);
}
if (expr instanceof InfixExpression && expr.getTypeBinding() == Type.BOOLEAN)
{
InfixExpression in= (InfixExpression) expr;
InfixExpression.Operator op= in.getOperator();
if (negate)
{
op= op.getComplement();
if (op != InfixExpression.Operator.CONDITIONAL_AND && op != InfixExpression.Operator.CONDITIONAL_OR)
negate= false;
}
InfixExpression out= new InfixExpression(op);
out.widen(in);
out.setOperands(simplifyBooleanExpression(in.getLeftOperand(), negate), simplifyBooleanExpression(in.getRightOperand(), negate));
return out;
}
if (negate)
{
PrefixExpression pe= new PrefixExpression();
pe.setOperator(PrefixExpression.NOT);
pe.setOperand(expr);
return pe;
}
return expr;
}
private boolean representSameAssignables(Assignable a, Assignable b)
{
if (!(a instanceof FieldAccess && b instanceof FieldAccess))
return false;
FieldAccess faa= (FieldAccess) a;
FieldAccess fab= (FieldAccess) b;
if (!faa.getName().equals(fab.getName()))
return false;
if (faa.getExpression() instanceof VariableBinding && fab.getExpression() instanceof VariableBinding)
{
VariableBinding vba= (VariableBinding) faa.getExpression();
VariableBinding vbb= (VariableBinding) fab.getExpression();
return vba.getVariableDeclaration() == vbb.getVariableDeclaration();
}
return false;
}
private VariableBinding fetchVariableBinding(Expression expr, VariableDeclaration decl)
{
ASTNode child= expr.getFirstChild();
while (child != null)
{
if (child instanceof VariableBinding && ((VariableBinding) child).getVariableDeclaration() == decl)
return (VariableBinding) child;
VariableBinding vb= fetchVariableBinding((Expression) child, decl);
if (vb != null)
return vb;
child= child.getNextSibling();
}
return null;
}
private PStarExpression.Operator getOp(InfixExpression expr)
{
NumberLiteral nl;
if (expr.getRightOperand() instanceof NumberLiteral)
{
nl= (NumberLiteral) expr.getRightOperand();
}
else
return null;
PStarExpression.Operator op;
if (expr.getOperator() == InfixExpression.Operator.PLUS)
{
op= PStarExpression.INCREMENT;
}
else if (expr.getOperator() == InfixExpression.Operator.MINUS)
{
op= PStarExpression.DECREMENT;
}
else
{
return null;
}
if (NumberLiteral.isOne(nl))
{
}
else if (NumberLiteral.isMinusOne(nl))
{
op= op.complement();
}
else
{
return null;
}
return op;
}
private boolean reduceXCrement(VariableDeclaration decl)
{
Assignment a1= null;
Assignment a2= null;
VariableBinding vb1= null;
VariableBinding vb2= null;
Assignable fa1= null;
Assignable fa2= null;
InfixExpression sum= null;
Iterator iter= decl.vbs.iterator();
while (iter.hasNext())
{
VariableBinding vb= (VariableBinding) iter.next();
if (vb.getParentNode() instanceof Assignment)
{
Assignment a= (Assignment) vb.getParentNode();
if (a.getLeftHandSide() == vb && a.getRightHandSide() instanceof Assignable)
{
vb1= vb;
a1= a;
fa1= (Assignable) a.getRightHandSide();
continue;
}
}
if (vb.getParentNode() instanceof InfixExpression)
{
InfixExpression infix= (InfixExpression) vb.getParentNode();
if (infix.getParentNode() instanceof Assignment)
{
Assignment a= (Assignment) infix.getParentNode();
if (a.getLeftHandSide() instanceof Assignable)
{
vb2= vb;
fa2= (Assignable) a.getLeftHandSide();
a2= a;
sum= infix;
continue;
}
}
}
}
if (a1 == null || a2 == null)
return false;
if (!fa1.isSame(fa2))
return false;
PStarExpression.Operator operator= getOp(sum);
if (operator == null)
return false;
PStarExpression p= new PostfixExpression();
p.setOperand((Expression) fa1);
p.setOperator(operator);
decl.vbs.remove(vb1);
decl.vbs.remove(vb2);
VariableBinding vb= decl.vbs.get(0);
vb.getParentBlock().replaceChild(p, vb);
Block b= a1.getParentBlock();
b.removeChild(a1);
b.removeChild(a2);
return true;
}
private boolean reduceYCrement(VariableDeclaration decl)
{
Assignment a1= null;
Assignment a2= null;
VariableBinding vb1= null;
VariableBinding vb2= null;
Assignable fa1= null;
Assignable fa2= null;
InfixExpression infixExpr= null;
Iterator iter= decl.vbs.iterator();
while (iter.hasNext())
{
VariableBinding vb= (VariableBinding) iter.next();
if (!(vb.getParentNode() instanceof Assignment))
continue;
Assignment a= (Assignment) vb.getParentNode();
if (a.getRightHandSide() == vb && a.getLeftHandSide() instanceof Assignable)
{
vb2= vb;
a2= a;
fa2= (Assignable) a.getLeftHandSide();
continue;
}
if (a.getLeftHandSide() == vb && a.getRightHandSide() instanceof InfixExpression)
{
InfixExpression infix= (InfixExpression) a.getRightHandSide();
if (!(infix.getLeftOperand() instanceof Assignable))
continue;
vb1= vb;
a1= a;
fa1= (Assignable) infix.getLeftOperand();
infixExpr= infix;
continue;
}
}
if (a1 == null || a2 == null)
return false;
if (!fa1.isSame(fa2))
return false;
decl.vbs.remove(vb1);
decl.vbs.remove(vb2);
VariableBinding vb= decl.vbs.get(0);
Expression replacement= null;
PStarExpression.Operator operator= getOp(infixExpr);
if (operator != null)
{
PrefixExpression p= new PrefixExpression();
p.setOperand((Expression) fa1);
p.setOperator(operator);
replacement= p;
}
else
{
InfixExpression.Operator op= infixExpr.getOperator();
Assignment.Operator opp= Assignment.Operator.lookup(op.toString() + '=');
Assignment a= new Assignment(opp);
a.setLeftHandSide((Expression) fa2);
a.setRightHandSide(infixExpr.getRightOperand());
replacement= a;
}
vb.getParentBlock().replaceChild(replacement, vb);
Block b= a1.getParentBlock();
b.removeChild(a1);
b.removeChild(a2);
return true;
}
public void optimize()
{
if (false)
return;
Iterator iter= tempDecls.iterator();
while (iter.hasNext())
{
VariableDeclaration decl= (VariableDeclaration) iter.next();
int count= decl.vbs.size();
if (count == 3)
{
if (reduceXCrement(decl))
{
iter.remove();
methodDecl.removeLocalVariable(decl.getName());
}
else if (reduceYCrement(decl))
{
iter.remove();
methodDecl.removeLocalVariable(decl.getName());
}
}
}
}
}