diff --git a/src/com/annimon/ownlang/parser/Optimizer.java b/src/com/annimon/ownlang/parser/Optimizer.java index 3fc8580..43628cf 100644 --- a/src/com/annimon/ownlang/parser/Optimizer.java +++ b/src/com/annimon/ownlang/parser/Optimizer.java @@ -1,5 +1,6 @@ package com.annimon.ownlang.parser; +import com.annimon.ownlang.Console; import com.annimon.ownlang.parser.ast.Node; import com.annimon.ownlang.parser.ast.Statement; import com.annimon.ownlang.parser.optimization.ConstantFolding; @@ -22,10 +23,20 @@ public final class Optimizer { }); Node result = statement; - for (int i = 0; i < level; i++) { - result = optimization.optimize(result); + 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++) { + result = optimization.optimize(result); + } } - System.out.println(optimization.summaryInfo()); + Console.println(optimization.summaryInfo()); return (Statement) result; } } diff --git a/src/com/annimon/ownlang/parser/ast/ExprStatement.java b/src/com/annimon/ownlang/parser/ast/ExprStatement.java index f70ace4..30700ee 100644 --- a/src/com/annimon/ownlang/parser/ast/ExprStatement.java +++ b/src/com/annimon/ownlang/parser/ast/ExprStatement.java @@ -1,11 +1,13 @@ package com.annimon.ownlang.parser.ast; +import com.annimon.ownlang.lib.Value; + /** * Wrapper for expressions, which can be used as statements. * * @author aNNiMON */ -public final class ExprStatement implements Statement { +public final class ExprStatement implements Expression, Statement { public final Expression expr; @@ -17,6 +19,11 @@ public final class ExprStatement implements Statement { public void execute() { expr.eval(); } + + @Override + public Value eval() { + return expr.eval(); + } @Override public void accept(Visitor visitor) { diff --git a/src/com/annimon/ownlang/parser/optimization/DeadCodeElimination.java b/src/com/annimon/ownlang/parser/optimization/DeadCodeElimination.java index 97b928e..206f979 100644 --- a/src/com/annimon/ownlang/parser/optimization/DeadCodeElimination.java +++ b/src/com/annimon/ownlang/parser/optimization/DeadCodeElimination.java @@ -1,17 +1,23 @@ 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.IfStatement; import com.annimon.ownlang.parser.ast.Node; 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 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.isVariable; +import java.util.Map; /** * Performs dead code elimination. */ -public class DeadCodeElimination extends OptimizationVisitor implements Optimizable { +public class DeadCodeElimination extends OptimizationVisitor> implements Optimizable { private int ifStatementEliminatedCount; private int ternaryExpressionEliminatedCount; @@ -19,7 +25,8 @@ public class DeadCodeElimination extends OptimizationVisitor implements Op @Override public Node optimize(Node node) { - return node.accept(this, null); + final Map variableInfos = VariablesGrabber.getInfo(node); + return node.accept(this, variableInfos); } @Override @@ -45,7 +52,7 @@ public class DeadCodeElimination extends OptimizationVisitor implements Op } @Override - public Node visit(IfStatement s, Void t) { + public Node visit(IfStatement s, Map t) { if (isValue(s.expression)) { ifStatementEliminatedCount++; // true statement @@ -62,7 +69,7 @@ public class DeadCodeElimination extends OptimizationVisitor implements Op } @Override - public Node visit(TernaryExpression s, Void t) { + public Node visit(TernaryExpression s, Map t) { if (isValue(s.condition)) { ternaryExpressionEliminatedCount++; if (s.condition.eval().asInt() != 0) { @@ -74,11 +81,32 @@ public class DeadCodeElimination extends OptimizationVisitor implements Op } @Override - public Node visit(WhileStatement s, Void t) { + public Node visit(WhileStatement s, Map t) { if (isValueAsInt(s.condition, 0)) { whileStatementEliminatedCount++; return new ExprStatement(s.condition); } return super.visit(s, t); } + + @Override + public Node visit(AssignmentExpression s, Map 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); + } + } } diff --git a/src/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java b/src/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java index 51983c0..fcd2c5c 100644 --- a/src/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java +++ b/src/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java @@ -53,7 +53,11 @@ public abstract class OptimizationVisitor implements ResultVisitor { if (node != statement) { changed = true; } - result.add((Statement) node); + if (node instanceof Statement) { + result.add((Statement) node); + } else if (node instanceof Expression) { + result.add(new ExprStatement((Expression) node)); + } } if (changed) { return result; @@ -103,7 +107,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node condition = s.condition.accept(this, t); final Node statement = s.statement.accept(this, t); if (condition != s.condition || statement != s.statement) { - return new DoWhileStatement((Expression) condition, (Statement) statement); + return new DoWhileStatement((Expression) condition, consumeStatement(statement)); } return s; } @@ -125,8 +129,8 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node statement = s.statement.accept(this, t); if (initialization != s.initialization || termination != s.termination || increment != s.increment || statement != s.statement) { - return new ForStatement((Statement) initialization, - (Expression) termination, (Statement) increment, (Statement) statement); + return new ForStatement(consumeStatement(initialization), + (Expression) termination, consumeStatement(increment), consumeStatement(statement)); } return s; } @@ -136,7 +140,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node container = s.container.accept(this, t); final Node body = s.body.accept(this, t); 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; } @@ -146,7 +150,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node container = s.container.accept(this, t); final Node body = s.body.accept(this, t); 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; } @@ -155,7 +159,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { public Node visit(FunctionDefineStatement s, T t) { final Node body = s.body.accept(this, t); if (body != s.body) { - return new FunctionDefineStatement(s.name, s.arguments, (Statement) body); + return new FunctionDefineStatement(s.name, s.arguments, consumeStatement(body)); } return s; } @@ -203,7 +207,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { elseStatement = null; } 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; } @@ -244,7 +248,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node patternResult = pattern.result.accept(this, t); if (patternResult != pattern.result) { changed = true; - pattern.result = (Statement) patternResult; + pattern.result = consumeStatement(patternResult); } patterns.add(pattern); } @@ -316,7 +320,7 @@ public abstract class OptimizationVisitor implements ResultVisitor { final Node condition = s.condition.accept(this, t); final Node statement = s.statement.accept(this, t); if (condition != s.condition || statement != s.statement) { - return new WhileStatement((Expression) condition, (Statement) statement); + return new WhileStatement((Expression) condition, consumeStatement(statement)); } return s; } @@ -329,4 +333,11 @@ public abstract class OptimizationVisitor implements ResultVisitor { } return s; } + + protected Statement consumeStatement(Node node) { + if (node instanceof Statement) { + return (Statement) node; + } + return new ExprStatement((Expression) node); + } }