Skip to content

Commit 1b9c518

Browse files
committed
Удаление неиспользуемых переменных, исправлена возможная ошибка приведения типа
1 parent 46349bd commit 1b9c518

File tree

4 files changed

+76
-19
lines changed

4 files changed

+76
-19
lines changed

src/com/annimon/ownlang/parser/Optimizer.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.annimon.ownlang.parser;
22

3+
import com.annimon.ownlang.Console;
34
import com.annimon.ownlang.parser.ast.Node;
45
import com.annimon.ownlang.parser.ast.Statement;
56
import com.annimon.ownlang.parser.optimization.ConstantFolding;
@@ -22,10 +23,20 @@ public static Statement optimize(Statement statement, int level) {
2223
});
2324

2425
Node result = statement;
25-
for (int i = 0; i < level; i++) {
26-
result = optimization.optimize(result);
26+
if (true || level >= 9) {
27+
int iteration = 0, lastModifications = 0;
28+
do {
29+
lastModifications = optimization.optimizationsCount();
30+
result = optimization.optimize(result);
31+
iteration++;
32+
} while (lastModifications != optimization.optimizationsCount());
33+
Console.print("Performs " + iteration + " optimization iterations");
34+
} else {
35+
for (int i = 0; i < level; i++) {
36+
result = optimization.optimize(result);
37+
}
2738
}
28-
System.out.println(optimization.summaryInfo());
39+
Console.println(optimization.summaryInfo());
2940
return (Statement) result;
3041
}
3142
}

src/com/annimon/ownlang/parser/ast/ExprStatement.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
package com.annimon.ownlang.parser.ast;
22

3+
import com.annimon.ownlang.lib.Value;
4+
35
/**
46
* Wrapper for expressions, which can be used as statements.
57
*
68
* @author aNNiMON
79
*/
8-
public final class ExprStatement implements Statement {
10+
public final class ExprStatement implements Expression, Statement {
911

1012
public final Expression expr;
1113

@@ -17,6 +19,11 @@ public ExprStatement(Expression function) {
1719
public void execute() {
1820
expr.eval();
1921
}
22+
23+
@Override
24+
public Value eval() {
25+
return expr.eval();
26+
}
2027

2128
@Override
2229
public void accept(Visitor visitor) {

src/com/annimon/ownlang/parser/optimization/DeadCodeElimination.java

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,32 @@
11
package com.annimon.ownlang.parser.optimization;
22

3+
import com.annimon.ownlang.lib.Types;
4+
import com.annimon.ownlang.parser.ast.AssignmentExpression;
35
import com.annimon.ownlang.parser.ast.ExprStatement;
46
import com.annimon.ownlang.parser.ast.IfStatement;
57
import com.annimon.ownlang.parser.ast.Node;
68
import com.annimon.ownlang.parser.ast.TernaryExpression;
9+
import com.annimon.ownlang.parser.ast.ValueExpression;
10+
import com.annimon.ownlang.parser.ast.VariableExpression;
711
import com.annimon.ownlang.parser.ast.WhileStatement;
812
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
913
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValueAsInt;
14+
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isVariable;
15+
import java.util.Map;
1016

1117
/**
1218
* Performs dead code elimination.
1319
*/
14-
public class DeadCodeElimination extends OptimizationVisitor<Void> implements Optimizable {
20+
public class DeadCodeElimination extends OptimizationVisitor<Map<String, VariableInfo>> implements Optimizable {
1521

1622
private int ifStatementEliminatedCount;
1723
private int ternaryExpressionEliminatedCount;
1824
private int whileStatementEliminatedCount;
1925

2026
@Override
2127
public Node optimize(Node node) {
22-
return node.accept(this, null);
28+
final Map<String, VariableInfo> variableInfos = VariablesGrabber.getInfo(node);
29+
return node.accept(this, variableInfos);
2330
}
2431

2532
@Override
@@ -45,7 +52,7 @@ public String summaryInfo() {
4552
}
4653

4754
@Override
48-
public Node visit(IfStatement s, Void t) {
55+
public Node visit(IfStatement s, Map<String, VariableInfo> t) {
4956
if (isValue(s.expression)) {
5057
ifStatementEliminatedCount++;
5158
// true statement
@@ -62,7 +69,7 @@ public Node visit(IfStatement s, Void t) {
6269
}
6370

6471
@Override
65-
public Node visit(TernaryExpression s, Void t) {
72+
public Node visit(TernaryExpression s, Map<String, VariableInfo> t) {
6673
if (isValue(s.condition)) {
6774
ternaryExpressionEliminatedCount++;
6875
if (s.condition.eval().asInt() != 0) {
@@ -74,11 +81,32 @@ public Node visit(TernaryExpression s, Void t) {
7481
}
7582

7683
@Override
77-
public Node visit(WhileStatement s, Void t) {
84+
public Node visit(WhileStatement s, Map<String, VariableInfo> t) {
7885
if (isValueAsInt(s.condition, 0)) {
7986
whileStatementEliminatedCount++;
8087
return new ExprStatement(s.condition);
8188
}
8289
return super.visit(s, t);
8390
}
91+
92+
@Override
93+
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
94+
if (!isVariable((Node)s.target)) return super.visit(s, t);
95+
96+
final String variableName = ((VariableExpression) s.target).name;
97+
if (!t.containsKey(variableName)) return super.visit(s, t);
98+
99+
final VariableInfo info = t.get(((VariableExpression) s.target).name);
100+
if (info.modifications != 1 || info.value == null) {
101+
return super.visit(s, t);
102+
}
103+
104+
switch (info.value.type()) {
105+
case Types.NUMBER:
106+
case Types.STRING:
107+
return new ValueExpression(info.value);
108+
default:
109+
return super.visit(s, t);
110+
}
111+
}
84112
}

src/com/annimon/ownlang/parser/optimization/OptimizationVisitor.java

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,11 @@ public Node visit(BlockStatement s, T t) {
5353
if (node != statement) {
5454
changed = true;
5555
}
56-
result.add((Statement) node);
56+
if (node instanceof Statement) {
57+
result.add((Statement) node);
58+
} else if (node instanceof Expression) {
59+
result.add(new ExprStatement((Expression) node));
60+
}
5761
}
5862
if (changed) {
5963
return result;
@@ -103,7 +107,7 @@ public Node visit(DoWhileStatement s, T t) {
103107
final Node condition = s.condition.accept(this, t);
104108
final Node statement = s.statement.accept(this, t);
105109
if (condition != s.condition || statement != s.statement) {
106-
return new DoWhileStatement((Expression) condition, (Statement) statement);
110+
return new DoWhileStatement((Expression) condition, consumeStatement(statement));
107111
}
108112
return s;
109113
}
@@ -125,8 +129,8 @@ public Node visit(ForStatement s, T t) {
125129
final Node statement = s.statement.accept(this, t);
126130
if (initialization != s.initialization || termination != s.termination
127131
|| increment != s.increment || statement != s.statement) {
128-
return new ForStatement((Statement) initialization,
129-
(Expression) termination, (Statement) increment, (Statement) statement);
132+
return new ForStatement(consumeStatement(initialization),
133+
(Expression) termination, consumeStatement(increment), consumeStatement(statement));
130134
}
131135
return s;
132136
}
@@ -136,7 +140,7 @@ public Node visit(ForeachArrayStatement s, T t) {
136140
final Node container = s.container.accept(this, t);
137141
final Node body = s.body.accept(this, t);
138142
if (container != s.container || body != s.body) {
139-
return new ForeachArrayStatement(s.variable, (Expression) container, (Statement) body);
143+
return new ForeachArrayStatement(s.variable, (Expression) container, consumeStatement(body));
140144
}
141145
return s;
142146
}
@@ -146,7 +150,7 @@ public Node visit(ForeachMapStatement s, T t) {
146150
final Node container = s.container.accept(this, t);
147151
final Node body = s.body.accept(this, t);
148152
if (container != s.container || body != s.body) {
149-
return new ForeachMapStatement(s.key, s.value, (Expression) container, (Statement) body);
153+
return new ForeachMapStatement(s.key, s.value, (Expression) container, consumeStatement(body));
150154
}
151155
return s;
152156
}
@@ -155,7 +159,7 @@ public Node visit(ForeachMapStatement s, T t) {
155159
public Node visit(FunctionDefineStatement s, T t) {
156160
final Node body = s.body.accept(this, t);
157161
if (body != s.body) {
158-
return new FunctionDefineStatement(s.name, s.arguments, (Statement) body);
162+
return new FunctionDefineStatement(s.name, s.arguments, consumeStatement(body));
159163
}
160164
return s;
161165
}
@@ -203,7 +207,7 @@ public Node visit(IfStatement s, T t) {
203207
elseStatement = null;
204208
}
205209
if (expression != s.expression || ifStatement != s.ifStatement || elseStatement != s.elseStatement) {
206-
return new IfStatement((Expression) expression, (Statement) ifStatement, (Statement) elseStatement);
210+
return new IfStatement((Expression) expression, consumeStatement(ifStatement), consumeStatement(elseStatement));
207211
}
208212
return s;
209213
}
@@ -244,7 +248,7 @@ public Node visit(MatchExpression s, T t) {
244248
final Node patternResult = pattern.result.accept(this, t);
245249
if (patternResult != pattern.result) {
246250
changed = true;
247-
pattern.result = (Statement) patternResult;
251+
pattern.result = consumeStatement(patternResult);
248252
}
249253
patterns.add(pattern);
250254
}
@@ -316,7 +320,7 @@ public Node visit(WhileStatement s, T t) {
316320
final Node condition = s.condition.accept(this, t);
317321
final Node statement = s.statement.accept(this, t);
318322
if (condition != s.condition || statement != s.statement) {
319-
return new WhileStatement((Expression) condition, (Statement) statement);
323+
return new WhileStatement((Expression) condition, consumeStatement(statement));
320324
}
321325
return s;
322326
}
@@ -329,4 +333,11 @@ public Node visit(UseStatement s, T t) {
329333
}
330334
return s;
331335
}
336+
337+
protected Statement consumeStatement(Node node) {
338+
if (node instanceof Statement) {
339+
return (Statement) node;
340+
}
341+
return new ExprStatement((Expression) node);
342+
}
332343
}

0 commit comments

Comments
 (0)