Skip to content

Commit 692370e

Browse files
committed
Добавлен оптимизация: объединение инструкций
1 parent 1b9c518 commit 692370e

File tree

3 files changed

+121
-2
lines changed

3 files changed

+121
-2
lines changed

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.annimon.ownlang.parser.optimization.ConstantPropagation;
88
import com.annimon.ownlang.parser.optimization.DeadCodeElimination;
99
import com.annimon.ownlang.parser.optimization.ExpressionSimplification;
10+
import com.annimon.ownlang.parser.optimization.InstructionCombining;
1011
import com.annimon.ownlang.parser.optimization.Optimizable;
1112
import com.annimon.ownlang.parser.optimization.SummaryOptimization;
1213

@@ -19,11 +20,12 @@ public static Statement optimize(Statement statement, int level) {
1920
new ConstantFolding(),
2021
new ConstantPropagation(),
2122
new DeadCodeElimination(),
22-
new ExpressionSimplification()
23+
new ExpressionSimplification(),
24+
new InstructionCombining()
2325
});
2426

2527
Node result = statement;
26-
if (true || level >= 9) {
28+
if (level >= 9) {
2729
int iteration = 0, lastModifications = 0;
2830
do {
2931
lastModifications = optimization.optimizationsCount();
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package com.annimon.ownlang.parser.optimization;
2+
3+
import com.annimon.ownlang.parser.ast.BlockStatement;
4+
import com.annimon.ownlang.parser.ast.Expression;
5+
import com.annimon.ownlang.parser.ast.Node;
6+
import com.annimon.ownlang.parser.ast.PrintStatement;
7+
import com.annimon.ownlang.parser.ast.PrintlnStatement;
8+
import com.annimon.ownlang.parser.ast.Statement;
9+
import com.annimon.ownlang.parser.ast.ValueExpression;
10+
import static com.annimon.ownlang.parser.visitors.VisitorUtils.isConstantValue;
11+
12+
/**
13+
* Performs instruction combining.
14+
*/
15+
public class InstructionCombining extends OptimizationVisitor<Void> implements Optimizable {
16+
17+
private int printCombinedCount;
18+
19+
@Override
20+
public Node optimize(Node node) {
21+
return node.accept(this, null);
22+
}
23+
24+
@Override
25+
public int optimizationsCount() {
26+
return printCombinedCount;
27+
}
28+
29+
@Override
30+
public String summaryInfo() {
31+
if (optimizationsCount() == 0) return "";
32+
final StringBuilder sb = new StringBuilder();
33+
if (printCombinedCount > 0) {
34+
sb.append("\nPrint statement combined: ").append(printCombinedCount);
35+
}
36+
return sb.toString();
37+
}
38+
39+
@Override
40+
public Node visit(BlockStatement s, Void t) {
41+
final int size = s.statements.size();
42+
if (size <= 1) {
43+
return super.visit(s, t);
44+
}
45+
46+
boolean changed = false;
47+
final BlockStatement result = new BlockStatement();
48+
int i;
49+
for (i = 1; i < size; i++) {
50+
Statement s1 = s.statements.get(i - 1);
51+
Statement s2 = s.statements.get(i);
52+
Node n1 = s1.accept(this, t);
53+
Node n2 = s2.accept(this, t);
54+
if (n1 != s1 || n2 != s2) {
55+
changed = true;
56+
}
57+
final Node combined = tryCombine(n1, n2);
58+
if (combined == null) {
59+
result.add((Statement) n1);
60+
} else {
61+
changed = true;
62+
result.add(consumeStatement(combined));
63+
i++;
64+
}
65+
}
66+
if (i == size) {
67+
// Last node
68+
Statement s2 = s.statements.get(size - 1);
69+
Node n2 = s2.accept(this, t);
70+
if (n2 != s2) {
71+
changed = true;
72+
}
73+
result.add((Statement) n2);
74+
}
75+
if (changed) {
76+
return result;
77+
}
78+
return super.visit(s, t);
79+
}
80+
81+
private Node tryCombine(Node n1, Node n2) {
82+
final int n1Type;
83+
if (n1 instanceof PrintStatement) n1Type = 1;
84+
else if (n1 instanceof PrintlnStatement) n1Type = 2;
85+
else n1Type = 0;
86+
87+
final int n2Type;
88+
if (n2 instanceof PrintStatement) n2Type = 1;
89+
else if (n2 instanceof PrintlnStatement) n2Type = 2;
90+
else n2Type = 0;
91+
92+
if (n1Type != 0 && n2Type != 0) {
93+
final Expression e1 = (n1Type == 1)
94+
? ((PrintStatement) n1).expression
95+
: ((PrintlnStatement) n1).expression;
96+
final Expression e2 = (n2Type == 1)
97+
? ((PrintStatement) n2).expression
98+
: ((PrintlnStatement) n2).expression;
99+
if (isConstantValue(e1) && isConstantValue(e2)) {
100+
String s1 = e1.eval().asString();
101+
if (n1Type == 2) s1 += System.lineSeparator();
102+
String s2 = e2.eval().asString();
103+
if (n2Type == 2) s2 += System.lineSeparator();
104+
printCombinedCount++;
105+
return new PrintStatement(new ValueExpression(s1 + s2));
106+
}
107+
}
108+
return null;
109+
}
110+
}

src/com/annimon/ownlang/parser/visitors/VisitorUtils.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ public static boolean isValueAsInt(Node node, int valueToCheck) {
5656
return value.asInt() == valueToCheck;
5757
}
5858

59+
public static boolean isConstantValue(Node node) {
60+
if (!isValue(node)) return false;
61+
62+
final int type = ((ValueExpression) node).value.type();
63+
return ( (type == Types.NUMBER) || (type == Types.STRING) );
64+
}
65+
5966
public static boolean isSameVariables(Node n1, Node n2) {
6067
if (isVariable(n1) && isVariable(n2)) {
6168
final VariableExpression v1 = (VariableExpression) n1;

0 commit comments

Comments
 (0)