Skip to content

Commit 5f10f0b

Browse files
committed
Рефакторинг
1 parent 08b12ff commit 5f10f0b

File tree

9 files changed

+196
-131
lines changed

9 files changed

+196
-131
lines changed
Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,31 @@
11
package com.annimon.ownlang.parser;
22

3+
import com.annimon.ownlang.parser.ast.Node;
34
import com.annimon.ownlang.parser.ast.Statement;
45
import com.annimon.ownlang.parser.optimization.ConstantFolding;
56
import com.annimon.ownlang.parser.optimization.ConstantPropagation;
67
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
78
import com.annimon.ownlang.parser.optimization.ExpressionSimplification;
9+
import com.annimon.ownlang.parser.optimization.Optimizable;
10+
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
811

912
public final class Optimizer {
1013

11-
public interface Info {
12-
13-
int optimizationsCount();
14-
15-
String summaryInfo();
16-
}
17-
1814
public static Statement optimize(Statement statement, int level) {
1915
if (level == 0) return statement;
20-
21-
final ConstantFolding constantFolding = new ConstantFolding();
22-
final ConstantPropagation constantPropagation = new ConstantPropagation();
23-
final DeadCodeElimination deadCodeElimination = new DeadCodeElimination();
24-
final ExpressionSimplification expressionSimplification = new ExpressionSimplification();
2516

26-
Statement result = statement;
17+
final Optimizable optimization = new SummaryOptimization(new Optimizable[] {
18+
new ConstantFolding(),
19+
new ConstantPropagation(),
20+
new DeadCodeElimination(),
21+
new ExpressionSimplification()
22+
});
23+
24+
Node result = statement;
2725
for (int i = 0; i < level; i++) {
28-
result = (Statement) result.accept(constantFolding, null);
29-
result = (Statement) constantPropagation.visit(result);
30-
result = (Statement) result.accept(deadCodeElimination, null);
31-
result = (Statement) result.accept(expressionSimplification, null);
26+
result = optimization.optimize(result);
3227
}
33-
System.out.print(constantFolding.summaryInfo());
34-
System.out.print(constantPropagation.summaryInfo());
35-
System.out.print(deadCodeElimination.summaryInfo());
36-
System.out.print(expressionSimplification.summaryInfo());
37-
System.out.println();
38-
return result;
28+
System.out.println(optimization.summaryInfo());
29+
return (Statement) result;
3930
}
4031
}

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

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

33
import com.annimon.ownlang.exceptions.OperationIsNotSupportedException;
4-
import com.annimon.ownlang.parser.Optimizer;
54
import com.annimon.ownlang.parser.ast.BinaryExpression;
65
import com.annimon.ownlang.parser.ast.ConditionalExpression;
76
import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
@@ -15,7 +14,7 @@
1514
/**
1615
* Performs constant folding optimization.
1716
*/
18-
public class ConstantFolding extends OptimizationVisitor<Void> implements Optimizer.Info {
17+
public class ConstantFolding extends OptimizationVisitor<Void> implements Optimizable {
1918

2019
private static final Set<String> OPERATORS = VisitorUtils.operators();
2120

@@ -29,6 +28,11 @@ public ConstantFolding() {
2928
overloadedOperators = new HashSet<>();
3029
}
3130

31+
@Override
32+
public Node optimize(Node node) {
33+
return node.accept(this, null);
34+
}
35+
3236
@Override
3337
public int optimizationsCount() {
3438
return binaryExpressionFoldingCount

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

Lines changed: 26 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,16 @@
22

33
import com.annimon.ownlang.lib.Types;
44
import com.annimon.ownlang.lib.Value;
5-
import com.annimon.ownlang.parser.Optimizer;
6-
import com.annimon.ownlang.parser.ast.Argument;
7-
import com.annimon.ownlang.parser.ast.AssignmentExpression;
8-
import com.annimon.ownlang.parser.ast.DestructuringAssignmentStatement;
9-
import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
10-
import com.annimon.ownlang.parser.ast.MatchExpression;
115
import com.annimon.ownlang.parser.ast.Node;
12-
import com.annimon.ownlang.parser.ast.Statement;
136
import com.annimon.ownlang.parser.ast.ValueExpression;
147
import com.annimon.ownlang.parser.ast.VariableExpression;
15-
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isValue;
16-
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isVariable;
178
import java.util.HashMap;
189
import java.util.Map;
1910

2011
/**
2112
* Performs constant propagation.
2213
*/
23-
public class ConstantPropagation implements Optimizer.Info {
14+
public class ConstantPropagation extends OptimizationVisitor<Map<String, Value>> implements Optimizable {
2415

2516
private final Map<String, Integer> propagatedVariables;
2617

@@ -29,27 +20,10 @@ public ConstantPropagation() {
2920
}
3021

3122
@Override
32-
public int optimizationsCount() {
33-
return propagatedVariables.size();
34-
}
35-
36-
@Override
37-
public String summaryInfo() {
38-
if (optimizationsCount() == 0) return "";
39-
final StringBuilder sb = new StringBuilder();
40-
if (propagatedVariables.size() > 0) {
41-
sb.append("\nConstant propagations: ").append(propagatedVariables.size());
42-
for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) {
43-
sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue());
44-
}
45-
}
46-
return sb.toString();
47-
}
48-
49-
public Node visit(Statement s) {
23+
public Node optimize(Node node) {
5024
final Map<String, VariableInfo> variables = new HashMap<>();
5125
// Find variables
52-
s.accept(new VariablesGrabber(), variables);
26+
node.accept(new VariablesGrabber(), variables);
5327
// Filter only string/number values with 1 modification
5428
final Map<String, Value> candidates = new HashMap<>();
5529
for (Map.Entry<String, VariableInfo> e : variables.entrySet()) {
@@ -64,87 +38,37 @@ public Node visit(Statement s) {
6438
}
6539
}
6640
// Replace VariableExpression with ValueExpression
67-
return s.accept(new VariablesPropagator(), candidates);
41+
return node.accept(this, candidates);
6842
}
6943

70-
private class VariablesGrabber extends OptimizationVisitor<Map<String, VariableInfo>> {
71-
72-
@Override
73-
public Node visit(AssignmentExpression s, Map<String, VariableInfo> t) {
74-
if (!isVariable((Node)s.target)) {
75-
return super.visit(s, t);
76-
}
77-
78-
final String variableName = ((VariableExpression) s.target).name;
79-
final VariableInfo var = variableInfo(t, variableName);
80-
81-
if (s.operation == null && isValue(s.expression)) {
82-
var.value = ((ValueExpression) s.expression).value;
83-
}
84-
t.put(variableName, var);
85-
return super.visit(s, t);
86-
}
87-
88-
@Override
89-
public Node visit(DestructuringAssignmentStatement s, Map<String, VariableInfo> t) {
90-
for (String variableName : s.variables) {
91-
if (variableName == null) continue;
92-
t.put(variableName, variableInfo(t, variableName));
93-
}
94-
return super.visit(s, t);
95-
}
96-
97-
@Override
98-
public Node visit(FunctionDefineStatement s, Map<String, VariableInfo> t) {
99-
for (Argument argument : s.arguments) {
100-
final String variableName = argument.getName();
101-
t.put(variableName, variableInfo(t, variableName));
102-
}
103-
return super.visit(s, t);
104-
}
105-
106-
@Override
107-
public Node visit(MatchExpression s, Map<String, VariableInfo> t) {
108-
// no visit match expression
109-
return s;
110-
}
111-
112-
private VariableInfo variableInfo(Map<String, VariableInfo> t, final String variableName) {
113-
final VariableInfo var;
114-
if (t.containsKey(variableName)) {
115-
var = t.get(variableName);
116-
var.modifications++;
117-
} else {
118-
var = new VariableInfo();
119-
var.modifications = 1;
120-
}
121-
return var;
122-
}
44+
@Override
45+
public int optimizationsCount() {
46+
return propagatedVariables.size();
12347
}
12448

125-
private class VariablesPropagator extends OptimizationVisitor<Map<String, Value>> {
126-
127-
@Override
128-
public Node visit(VariableExpression s, Map<String, Value> t) {
129-
if (t.containsKey(s.name)) {
130-
if (!propagatedVariables.containsKey(s.name)) {
131-
propagatedVariables.put(s.name, 1);
132-
} else {
133-
propagatedVariables.put(s.name, 1 + propagatedVariables.get(s.name));
134-
}
135-
return new ValueExpression(t.get(s.name));
49+
@Override
50+
public String summaryInfo() {
51+
if (optimizationsCount() == 0) return "";
52+
final StringBuilder sb = new StringBuilder();
53+
if (propagatedVariables.size() > 0) {
54+
sb.append("\nConstant propagations: ").append(propagatedVariables.size());
55+
for (Map.Entry<String, Integer> e : propagatedVariables.entrySet()) {
56+
sb.append("\n ").append(e.getKey()).append(": ").append(e.getValue());
13657
}
137-
return super.visit(s, t);
13858
}
59+
return sb.toString();
13960
}
14061

141-
private static class VariableInfo {
142-
Value value;
143-
int modifications;
144-
145-
@Override
146-
public String toString() {
147-
return (value == null ? "?" : value) + " (" + modifications + " mods)";
62+
@Override
63+
public Node visit(VariableExpression s, Map<String, Value> t) {
64+
if (t.containsKey(s.name)) {
65+
if (!propagatedVariables.containsKey(s.name)) {
66+
propagatedVariables.put(s.name, 1);
67+
} else {
68+
propagatedVariables.put(s.name, 1 + propagatedVariables.get(s.name));
69+
}
70+
return new ValueExpression(t.get(s.name));
14871
}
72+
return super.visit(s, t);
14973
}
15074
}

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

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

3-
import com.annimon.ownlang.parser.Optimizer;
43
import com.annimon.ownlang.parser.ast.ExprStatement;
54
import com.annimon.ownlang.parser.ast.IfStatement;
65
import com.annimon.ownlang.parser.ast.Node;
@@ -12,12 +11,17 @@
1211
/**
1312
* Performs dead code elimination.
1413
*/
15-
public class DeadCodeElimination extends OptimizationVisitor<Void> implements Optimizer.Info {
14+
public class DeadCodeElimination extends OptimizationVisitor<Void> implements Optimizable {
1615

1716
private int ifStatementEliminatedCount;
1817
private int ternaryExpressionEliminatedCount;
1918
private int whileStatementEliminatedCount;
2019

20+
@Override
21+
public Node optimize(Node node) {
22+
return node.accept(this, null);
23+
}
24+
2125
@Override
2226
public int optimizationsCount() {
2327
return ifStatementEliminatedCount + ternaryExpressionEliminatedCount

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

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

3-
import com.annimon.ownlang.parser.Optimizer;
43
import com.annimon.ownlang.parser.ast.BinaryExpression;
54
import com.annimon.ownlang.parser.ast.ConditionalExpression;
65
import com.annimon.ownlang.parser.ast.FunctionDefineStatement;
@@ -16,7 +15,7 @@
1615
/**
1716
* Performs expression simplification.
1817
*/
19-
public class ExpressionSimplification extends OptimizationVisitor<Void> implements Optimizer.Info {
18+
public class ExpressionSimplification extends OptimizationVisitor<Void> implements Optimizable {
2019

2120
private static final Set<String> OPERATORS = VisitorUtils.operators();
2221

@@ -29,6 +28,11 @@ public ExpressionSimplification() {
2928
overloadedOperators = new HashSet<>();
3029
}
3130

31+
@Override
32+
public Node optimize(Node node) {
33+
return node.accept(this, null);
34+
}
35+
3236
@Override
3337
public int optimizationsCount() {
3438
return simplificationsCount;
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.annimon.ownlang.parser.optimization;
2+
3+
import com.annimon.ownlang.parser.ast.Node;
4+
5+
public interface Optimizable {
6+
7+
Node optimize(Node node);
8+
9+
int optimizationsCount();
10+
11+
String summaryInfo();
12+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package com.annimon.ownlang.parser.optimization;
2+
3+
import com.annimon.ownlang.parser.ast.Node;
4+
5+
public final class SummaryOptimization implements Optimizable {
6+
7+
private final Optimizable[] optimizations;
8+
9+
public SummaryOptimization(Optimizable[] optimizations) {
10+
this.optimizations = optimizations;
11+
}
12+
13+
@Override
14+
public Node optimize(Node node) {
15+
for (Optimizable optimization : optimizations) {
16+
node = optimization.optimize(node);
17+
}
18+
return node;
19+
}
20+
21+
@Override
22+
public int optimizationsCount() {
23+
int count = 0;
24+
for (Optimizable optimization : optimizations) {
25+
count += optimization.optimizationsCount();
26+
}
27+
return count;
28+
}
29+
30+
@Override
31+
public String summaryInfo() {
32+
final StringBuilder sb = new StringBuilder();
33+
for (Optimizable optimization : optimizations) {
34+
sb.append(optimization.summaryInfo());
35+
}
36+
return sb.toString();
37+
}
38+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.annimon.ownlang.parser.optimization;
2+
3+
import com.annimon.ownlang.lib.Value;
4+
5+
public final class VariableInfo {
6+
public Value value;
7+
public int modifications;
8+
9+
@Override
10+
public String toString() {
11+
return (value == null ? "?" : value) + " (" + modifications + " mods)";
12+
}
13+
}

0 commit comments

Comments
 (0)