Удаление неиспользуемых переменных, исправлена возможная ошибка приведения типа

This commit is contained in:
Victor 2016-06-26 12:57:20 +03:00
parent 46349bdd36
commit 1b9c5187f6
4 changed files with 76 additions and 19 deletions

View File

@ -1,5 +1,6 @@
package com.annimon.ownlang.parser; package com.annimon.ownlang.parser;
import com.annimon.ownlang.Console;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.ast.Statement;
import com.annimon.ownlang.parser.optimization.ConstantFolding; import com.annimon.ownlang.parser.optimization.ConstantFolding;
@ -22,10 +23,20 @@ public final class Optimizer {
}); });
Node result = statement; Node result = statement;
if (true || level >= 9) {
int iteration = 0, lastModifications = 0;
do {
lastModifications = optimization.optimizationsCount();
result = optimization.optimize(result);
iteration++;
} while (lastModifications != optimization.optimizationsCount());
Console.print("Performs " + iteration + " optimization iterations");
} else {
for (int i = 0; i < level; i++) { for (int i = 0; i < level; i++) {
result = optimization.optimize(result); result = optimization.optimize(result);
} }
System.out.println(optimization.summaryInfo()); }
Console.println(optimization.summaryInfo());
return (Statement) result; return (Statement) result;
} }
} }

View File

@ -1,11 +1,13 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.lib.Value;
/** /**
* Wrapper for expressions, which can be used as statements. * Wrapper for expressions, which can be used as statements.
* *
* @author aNNiMON * @author aNNiMON
*/ */
public final class ExprStatement implements Statement { public final class ExprStatement implements Expression, Statement {
public final Expression expr; public final Expression expr;
@ -18,6 +20,11 @@ public final class ExprStatement implements Statement {
expr.eval(); expr.eval();
} }
@Override
public Value eval() {
return expr.eval();
}
@Override @Override
public void accept(Visitor visitor) { public void accept(Visitor visitor) {
visitor.visit(this); visitor.visit(this);

View File

@ -1,17 +1,23 @@
package com.annimon.ownlang.parser.optimization; package com.annimon.ownlang.parser.optimization;
import com.annimon.ownlang.lib.Types;
import com.annimon.ownlang.parser.ast.AssignmentExpression;
import com.annimon.ownlang.parser.ast.ExprStatement; import com.annimon.ownlang.parser.ast.ExprStatement;
import com.annimon.ownlang.parser.ast.IfStatement; import com.annimon.ownlang.parser.ast.IfStatement;
import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Node;
import com.annimon.ownlang.parser.ast.TernaryExpression; import com.annimon.ownlang.parser.ast.TernaryExpression;
import com.annimon.ownlang.parser.ast.ValueExpression;
import com.annimon.ownlang.parser.ast.VariableExpression;
import com.annimon.ownlang.parser.ast.WhileStatement; import com.annimon.ownlang.parser.ast.WhileStatement;
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue; import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValueAsInt; import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValueAsInt;
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isVariable;
import java.util.Map;
/** /**
* Performs dead code elimination. * Performs dead code elimination.
*/ */
public class DeadCodeElimination extends OptimizationVisitor<Void> implements Optimizable { public class DeadCodeElimination extends OptimizationVisitor<Map<String, VariableInfo>> implements Optimizable {
private int ifStatementEliminatedCount; private int ifStatementEliminatedCount;
private int ternaryExpressionEliminatedCount; private int ternaryExpressionEliminatedCount;
@ -19,7 +25,8 @@ public class DeadCodeElimination extends OptimizationVisitor<Void> implements Op
@Override @Override
public Node optimize(Node node) { public Node optimize(Node node) {
return node.accept(this, null); final Map<String, VariableInfo> variableInfos = VariablesGrabber.getInfo(node);
return node.accept(this, variableInfos);
} }
@Override @Override
@ -45,7 +52,7 @@ public class DeadCodeElimination extends OptimizationVisitor<Void> implements Op
} }
@Override @Override
public Node visit(IfStatement s, Void t) { public Node visit(IfStatement s, Map<String, VariableInfo> t) {
if (isValue(s.expression)) { if (isValue(s.expression)) {
ifStatementEliminatedCount++; ifStatementEliminatedCount++;
// true statement // true statement
@ -62,7 +69,7 @@ public class DeadCodeElimination extends OptimizationVisitor<Void> implements Op
} }
@Override @Override
public Node visit(TernaryExpression s, Void t) { public Node visit(TernaryExpression s, Map<String, VariableInfo> t) {
if (isValue(s.condition)) { if (isValue(s.condition)) {
ternaryExpressionEliminatedCount++; ternaryExpressionEliminatedCount++;
if (s.condition.eval().asInt() != 0) { if (s.condition.eval().asInt() != 0) {
@ -74,11 +81,32 @@ public class DeadCodeElimination extends OptimizationVisitor<Void> implements Op
} }
@Override @Override
public Node visit(WhileStatement s, Void t) { public Node visit(WhileStatement s, Map<String, VariableInfo> t) {
if (isValueAsInt(s.condition, 0)) { if (isValueAsInt(s.condition, 0)) {
whileStatementEliminatedCount++; whileStatementEliminatedCount++;
return new ExprStatement(s.condition); return new ExprStatement(s.condition);
} }
return super.visit(s, t); return super.visit(s, t);
} }
@Override
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
if (!isVariable((Node)s.target)) return super.visit(s, t);
final String variableName = ((VariableExpression) s.target).name;
if (!t.containsKey(variableName)) return super.visit(s, t);
final VariableInfo info = t.get(((VariableExpression) s.target).name);
if (info.modifications != 1 || info.value == null) {
return super.visit(s, t);
}
switch (info.value.type()) {
case Types.NUMBER:
case Types.STRING:
return new ValueExpression(info.value);
default:
return super.visit(s, t);
}
}
} }

View File

@ -53,7 +53,11 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
if (node != statement) { if (node != statement) {
changed = true; changed = true;
} }
if (node instanceof Statement) {
result.add((Statement) node); result.add((Statement) node);
} else if (node instanceof Expression) {
result.add(new ExprStatement((Expression) node));
}
} }
if (changed) { if (changed) {
return result; return result;
@ -103,7 +107,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node condition = s.condition.accept(this, t); final Node condition = s.condition.accept(this, t);
final Node statement = s.statement.accept(this, t); final Node statement = s.statement.accept(this, t);
if (condition != s.condition || statement != s.statement) { if (condition != s.condition || statement != s.statement) {
return new DoWhileStatement((Expression) condition, (Statement) statement); return new DoWhileStatement((Expression) condition, consumeStatement(statement));
} }
return s; return s;
} }
@ -125,8 +129,8 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node statement = s.statement.accept(this, t); final Node statement = s.statement.accept(this, t);
if (initialization != s.initialization || termination != s.termination if (initialization != s.initialization || termination != s.termination
|| increment != s.increment || statement != s.statement) { || increment != s.increment || statement != s.statement) {
return new ForStatement((Statement) initialization, return new ForStatement(consumeStatement(initialization),
(Expression) termination, (Statement) increment, (Statement) statement); (Expression) termination, consumeStatement(increment), consumeStatement(statement));
} }
return s; return s;
} }
@ -136,7 +140,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node container = s.container.accept(this, t); final Node container = s.container.accept(this, t);
final Node body = s.body.accept(this, t); final Node body = s.body.accept(this, t);
if (container != s.container || body != s.body) { if (container != s.container || body != s.body) {
return new ForeachArrayStatement(s.variable, (Expression) container, (Statement) body); return new ForeachArrayStatement(s.variable, (Expression) container, consumeStatement(body));
} }
return s; return s;
} }
@ -146,7 +150,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node container = s.container.accept(this, t); final Node container = s.container.accept(this, t);
final Node body = s.body.accept(this, t); final Node body = s.body.accept(this, t);
if (container != s.container || body != s.body) { if (container != s.container || body != s.body) {
return new ForeachMapStatement(s.key, s.value, (Expression) container, (Statement) body); return new ForeachMapStatement(s.key, s.value, (Expression) container, consumeStatement(body));
} }
return s; return s;
} }
@ -155,7 +159,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
public Node visit(FunctionDefineStatement s, T t) { public Node visit(FunctionDefineStatement s, T t) {
final Node body = s.body.accept(this, t); final Node body = s.body.accept(this, t);
if (body != s.body) { if (body != s.body) {
return new FunctionDefineStatement(s.name, s.arguments, (Statement) body); return new FunctionDefineStatement(s.name, s.arguments, consumeStatement(body));
} }
return s; return s;
} }
@ -203,7 +207,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
elseStatement = null; elseStatement = null;
} }
if (expression != s.expression || ifStatement != s.ifStatement || elseStatement != s.elseStatement) { if (expression != s.expression || ifStatement != s.ifStatement || elseStatement != s.elseStatement) {
return new IfStatement((Expression) expression, (Statement) ifStatement, (Statement) elseStatement); return new IfStatement((Expression) expression, consumeStatement(ifStatement), consumeStatement(elseStatement));
} }
return s; return s;
} }
@ -244,7 +248,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node patternResult = pattern.result.accept(this, t); final Node patternResult = pattern.result.accept(this, t);
if (patternResult != pattern.result) { if (patternResult != pattern.result) {
changed = true; changed = true;
pattern.result = (Statement) patternResult; pattern.result = consumeStatement(patternResult);
} }
patterns.add(pattern); patterns.add(pattern);
} }
@ -316,7 +320,7 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
final Node condition = s.condition.accept(this, t); final Node condition = s.condition.accept(this, t);
final Node statement = s.statement.accept(this, t); final Node statement = s.statement.accept(this, t);
if (condition != s.condition || statement != s.statement) { if (condition != s.condition || statement != s.statement) {
return new WhileStatement((Expression) condition, (Statement) statement); return new WhileStatement((Expression) condition, consumeStatement(statement));
} }
return s; return s;
} }
@ -329,4 +333,11 @@ public abstract class OptimizationVisitor<T> implements ResultVisitor<Node, T> {
} }
return s; return s;
} }
protected Statement consumeStatement(Node node) {
if (node instanceof Statement) {
return (Statement) node;
}
return new ExprStatement((Expression) node);
}
} }