-
Notifications
You must be signed in to change notification settings - Fork 35
Expand file tree
/
Copy pathExpressionSimplifier.java
More file actions
117 lines (101 loc) · 4.83 KB
/
ExpressionSimplifier.java
File metadata and controls
117 lines (101 loc) · 4.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package liquidjava.rj_language.opt;
import liquidjava.rj_language.ast.BinaryExpression;
import liquidjava.rj_language.ast.Expression;
import liquidjava.rj_language.ast.LiteralBoolean;
import liquidjava.rj_language.opt.derivation_node.BinaryDerivationNode;
import liquidjava.rj_language.opt.derivation_node.DerivationNode;
import liquidjava.rj_language.opt.derivation_node.ValDerivationNode;
public class ExpressionSimplifier {
/**
* Simplifies an expression by applying constant propagation, constant folding and removing redundant conjuncts
* Returns a derivation node representing the tree of simplifications applied
*/
public static ValDerivationNode simplify(Expression exp) {
ValDerivationNode fixedPoint = simplifyToFixedPoint(null, exp);
return simplifyValDerivationNode(fixedPoint);
}
/**
* Recursively applies propagation and folding until the expression stops changing (fixed point) Stops early if the
* expression simplifies to 'true', which means we've simplified too much
*/
private static ValDerivationNode simplifyToFixedPoint(ValDerivationNode current, Expression prevExp) {
// apply propagation and folding
ValDerivationNode prop = ConstantPropagation.propagate(prevExp, current);
ValDerivationNode fold = ConstantFolding.fold(prop);
ValDerivationNode simplified = simplifyValDerivationNode(fold);
Expression currExp = simplified.getValue();
// fixed point reached
if (current != null && currExp.equals(current.getValue())) {
return current;
}
// continue simplifying
return simplifyToFixedPoint(simplified, simplified.getValue());
}
/**
* Recursively simplifies the derivation tree by removing redundant conjuncts
*/
private static ValDerivationNode simplifyValDerivationNode(ValDerivationNode node) {
Expression value = node.getValue();
DerivationNode origin = node.getOrigin();
// binary expression with &&
if (value instanceof BinaryExpression binExp && "&&".equals(binExp.getOperator())) {
ValDerivationNode leftSimplified;
ValDerivationNode rightSimplified;
if (origin instanceof BinaryDerivationNode binOrigin) {
leftSimplified = simplifyValDerivationNode(binOrigin.getLeft());
rightSimplified = simplifyValDerivationNode(binOrigin.getRight());
} else {
leftSimplified = simplifyValDerivationNode(new ValDerivationNode(binExp.getFirstOperand(), null));
rightSimplified = simplifyValDerivationNode(new ValDerivationNode(binExp.getSecondOperand(), null));
}
// check if either side is redundant
if (isRedundant(leftSimplified.getValue()))
return rightSimplified;
if (isRedundant(rightSimplified.getValue()))
return leftSimplified;
// collapse identical sides (x && x => x)
if (leftSimplified.getValue().equals(rightSimplified.getValue())) {
return leftSimplified;
}
// collapse symmetric equalities (e.g. x == y && y == x => x == y)
if (isSymmetricEquality(leftSimplified.getValue(), rightSimplified.getValue())) {
return leftSimplified;
}
// return the conjunction with simplified children
Expression newValue = new BinaryExpression(leftSimplified.getValue(), "&&", rightSimplified.getValue());
DerivationNode newOrigin = new BinaryDerivationNode(leftSimplified, rightSimplified, "&&");
return new ValDerivationNode(newValue, newOrigin);
}
// no simplification
return node;
}
private static boolean isSymmetricEquality(Expression left, Expression right) {
if (left instanceof BinaryExpression b1 && "==".equals(b1.getOperator()) && right instanceof BinaryExpression b2
&& "==".equals(b2.getOperator())) {
Expression l1 = b1.getFirstOperand();
Expression r1 = b1.getSecondOperand();
Expression l2 = b2.getFirstOperand();
Expression r2 = b2.getSecondOperand();
return l1.equals(r2) && r1.equals(l2);
}
return false;
}
/**
* Checks if an expression is redundant (e.g. true or x == x)
*/
private static boolean isRedundant(Expression exp) {
// true
if (exp instanceof LiteralBoolean && exp.isBooleanTrue()) {
return true;
}
// x == x
if (exp instanceof BinaryExpression binExp) {
if ("==".equals(binExp.getOperator())) {
Expression left = binExp.getFirstOperand();
Expression right = binExp.getSecondOperand();
return left.equals(right);
}
}
return false;
}
}