Skip to content

Commit dcc943f

Browse files
committed
Добавлена оптимизация: упрощение выражений
1 parent 1aef2c9 commit dcc943f

File tree

2 files changed

+150
-0
lines changed

2 files changed

+150
-0
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.annimon.ownlang.parser.ast.Statement;
44
import com.annimon.ownlang.parser.visitors.ConstantFolding;
55
import com.annimon.ownlang.parser.visitors.DeadCodeElimination;
6+
import com.annimon.ownlang.parser.visitors.ExpressionSimplification;
67

78
public final class Optimizer {
89

@@ -18,14 +19,17 @@ public static Statement optimize(Statement statement, int level) {
1819

1920
final ConstantFolding constantFolding = new ConstantFolding();
2021
final DeadCodeElimination deadCodeElimination = new DeadCodeElimination();
22+
final ExpressionSimplification expressionSimplification = new ExpressionSimplification();
2123

2224
Statement result = statement;
2325
for (int i = 0; i < level; i++) {
2426
result = (Statement) result.accept(constantFolding, null);
2527
result = (Statement) result.accept(deadCodeElimination, null);
28+
result = (Statement) result.accept(expressionSimplification, null);
2629
}
2730
System.out.print(constantFolding.summaryInfo());
2831
System.out.print(deadCodeElimination.summaryInfo());
32+
System.out.print(expressionSimplification.summaryInfo());
2933
System.out.println();
3034
return result;
3135
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package com.annimon.ownlang.parser.visitors;
2+
3+
import com.annimon.ownlang.lib.NumberValue;
4+
import com.annimon.ownlang.lib.Types;
5+
import com.annimon.ownlang.lib.Value;
6+
import com.annimon.ownlang.parser.Optimizer;
7+
import com.annimon.ownlang.parser.ast.BinaryExpression;
8+
import com.annimon.ownlang.parser.ast.ConditionalExpression;
9+
import com.annimon.ownlang.parser.ast.Node;
10+
import com.annimon.ownlang.parser.ast.UnaryExpression;
11+
import com.annimon.ownlang.parser.ast.ValueExpression;
12+
import com.annimon.ownlang.parser.ast.VariableExpression;
13+
14+
/**
15+
* Performs expression simplification.
16+
*/
17+
public class ExpressionSimplification extends OptimizationVisitor<Void> implements Optimizer.Info {
18+
19+
private int simplificationsCount;
20+
21+
public ExpressionSimplification() {
22+
simplificationsCount = 0;
23+
}
24+
25+
@Override
26+
public int optimizationsCount() {
27+
return simplificationsCount;
28+
}
29+
30+
@Override
31+
public String summaryInfo() {
32+
if (optimizationsCount() == 0) return "";
33+
final StringBuilder sb = new StringBuilder();
34+
if (simplificationsCount > 0) {
35+
sb.append("\nExpression simplifications: ").append(simplificationsCount);
36+
}
37+
return sb.toString();
38+
}
39+
40+
@Override
41+
public Node visit(BinaryExpression s, Void t) {
42+
// operations with 0
43+
final boolean expr1IsZero = isIntegerValue(s.expr1, 0);
44+
if (expr1IsZero || isIntegerValue(s.expr2, 0)) {
45+
switch (s.operation) {
46+
case ADD:
47+
// 0 + x2 to x2, x1 + 0 to x1
48+
simplificationsCount++;
49+
return expr1IsZero ? s.expr2 : s.expr1;
50+
51+
case SUBTRACT:
52+
simplificationsCount++;
53+
if (expr1IsZero) {
54+
// 0 - x2 to -x2
55+
return new UnaryExpression(UnaryExpression.Operator.NEGATE, s.expr2);
56+
}
57+
// x1 - 0 to x1
58+
return s.expr1;
59+
60+
case MULTIPLY:
61+
// 0 * x2 to 0, x1 * 0 to 0
62+
simplificationsCount++;
63+
return new ValueExpression(0);
64+
65+
case DIVIDE:
66+
// 0 / x2 to 0
67+
if (expr1IsZero) {
68+
simplificationsCount++;
69+
return new ValueExpression(0);
70+
}
71+
break;
72+
}
73+
}
74+
75+
// operations with 1
76+
final boolean expr1IsOne = isIntegerValue(s.expr1, 1);
77+
if (expr1IsOne || isIntegerValue(s.expr2, 1)) {
78+
switch (s.operation) {
79+
case MULTIPLY:
80+
// 1 * x2 to x2, x1 * 1 to x1
81+
simplificationsCount++;
82+
return expr1IsOne ? s.expr2 : s.expr1;
83+
84+
case DIVIDE:
85+
// x1 / 1 to x1
86+
if (!expr1IsOne) {
87+
simplificationsCount++;
88+
return s.expr1;
89+
}
90+
break;
91+
}
92+
}
93+
94+
// x1 / -1 to -x1
95+
if (isIntegerValue(s.expr2, -1)) {
96+
simplificationsCount++;
97+
return new UnaryExpression(UnaryExpression.Operator.NEGATE, s.expr1);
98+
}
99+
100+
// x - x to 0
101+
if (isSameVariables(s.expr1, s.expr2) && s.operation == BinaryExpression.Operator.SUBTRACT) {
102+
simplificationsCount++;
103+
return new ValueExpression(0);
104+
}
105+
106+
return super.visit(s, t);
107+
}
108+
109+
@Override
110+
public Node visit(ConditionalExpression s, Void t) {
111+
if (isIntegerValue(s.expr1, 0) && s.operation == ConditionalExpression.Operator.AND) {
112+
// 0 && x2 to 0
113+
simplificationsCount++;
114+
return new ValueExpression(0);
115+
}
116+
if (isIntegerValue(s.expr1, 1) && s.operation == ConditionalExpression.Operator.OR) {
117+
// 1 || x2 to 1
118+
simplificationsCount++;
119+
return new ValueExpression(1);
120+
}
121+
return super.visit(s, t);
122+
}
123+
124+
125+
private boolean isIntegerValue(Node node, int valueToCheck) {
126+
if (!(node instanceof ValueExpression)) return false;
127+
128+
final Value value = ((ValueExpression) node).value;
129+
if (value.type() != Types.NUMBER) return false;
130+
131+
final Number number = ((NumberValue) value).raw();
132+
if ( (number instanceof Integer) || (number instanceof Short) || (number instanceof Byte)) {
133+
return number.intValue() == valueToCheck;
134+
}
135+
return false;
136+
}
137+
138+
private boolean isSameVariables(Node n1, Node n2) {
139+
if ( (n1 instanceof VariableExpression) && (n2 instanceof VariableExpression) ) {
140+
final VariableExpression v1 = (VariableExpression) n1;
141+
final VariableExpression v2 = (VariableExpression) n2;
142+
return v1.name.equals(v2.name);
143+
}
144+
return false;
145+
}
146+
}

0 commit comments

Comments
 (0)