-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathConstFoldingVisitor.java
126 lines (95 loc) · 4.15 KB
/
ConstFoldingVisitor.java
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
118
119
120
121
122
123
124
125
126
package pt.up.fe.comp.ollir.optimization.optimizers;
import pt.up.fe.comp.analysis.table.AstNode;
import pt.up.fe.comp.jmm.ast.AJmmVisitor;
import pt.up.fe.comp.jmm.ast.JmmNode;
import pt.up.fe.comp.jmm.ast.JmmNodeImpl;
public class ConstFoldingVisitor extends AJmmVisitor<String, Boolean> {
public ConstFoldingVisitor() {
setDefaultVisit(this::defaultVisit);
addVisit(AstNode.BIN_OP, this::binOpVisit);
addVisit(AstNode.NOT, this::notVisit);
}
public Boolean defaultVisit(JmmNode jmmNode, String dummy) {
boolean changes = false;
for (JmmNode child : jmmNode.getChildren()) {
changes = visit(child) || changes;
}
return changes;
}
private Boolean notVisit(JmmNode notNode, String dummy) {
boolean changes = visit(notNode.getJmmChild(0));
JmmNode child = notNode.getJmmChild(0);
if (child.getKind().equals(AstNode.BOOL)) {
String value = child.get("value");
JmmNode literalNode = new JmmNodeImpl(AstNode.BOOL);
literalNode.put("col", notNode.get("col"));
literalNode.put("line", notNode.get("line"));
if (value.equals("true")) {
literalNode.put("value", "false");
} else {
literalNode.put("value", "true");
}
notNode.replace(literalNode);
return true;
}
return changes;
}
private Boolean binOpVisit(JmmNode binOpNode, String dummy) {
JmmNode leftNode = binOpNode.getJmmChild(0);
JmmNode rightNode = binOpNode.getJmmChild(1);
boolean changes = visit(leftNode);
changes = visit(rightNode) || changes;
// NOTE: these might be different than the previous ones
leftNode = binOpNode.getJmmChild(0);
rightNode = binOpNode.getJmmChild(1);
boolean hasBoolOperands = leftNode.getKind().equals(AstNode.BOOL) && rightNode.getKind().equals(AstNode.BOOL);
boolean hasIntOperands = leftNode.getKind().equals(AstNode.INT_LITERAL) && rightNode.getKind().equals(AstNode.INT_LITERAL);
// shortcut evaluation on '&&'
if (binOpNode.get("op").equals("and") && leftNode.getKind().equals(AstNode.BOOL)) {
// true && x => x
if (leftNode.get("value").equals("true")) {
binOpNode.replace(rightNode);
return true;
// false && x => false
} else if (leftNode.get("value").equals("false")) {
binOpNode.replace(leftNode);
return true;
}
// bin op folding
} else if (hasBoolOperands || hasIntOperands) {
String value = ConstFoldingVisitor.parseBinOp(binOpNode.get("op"), leftNode.get("value"), rightNode.get("value"));
JmmNode literalNode;
if (value.equals("true") || value.equals("false")) {
literalNode = new JmmNodeImpl(AstNode.BOOL);
} else {
literalNode = new JmmNodeImpl(AstNode.INT_LITERAL);
}
literalNode.put("value", value);
literalNode.put("col", binOpNode.get("col"));
literalNode.put("line", binOpNode.get("line"));
binOpNode.replace(literalNode);
return true;
}
return changes;
}
public static String parseBinOp(String op, String lhs, String rhs) {
if (op.equals("and")) {
if (lhs.equals("true") && rhs.equals("true")) {
return "true";
} else {
return "false";
}
} else {
int lhsInt = Integer.parseInt(lhs);
int rhsInt = Integer.parseInt(rhs);
return switch (op) {
case "addition" -> String.valueOf(lhsInt + rhsInt);
case "subtraction" -> String.valueOf(lhsInt - rhsInt);
case "multiplication" -> String.valueOf(lhsInt * rhsInt);
case "division" -> String.valueOf(lhsInt / rhsInt);
case "lessThan" -> (lhsInt < rhsInt) ? "true" : "false";
default -> throw new IllegalStateException("Unexpected value: " + op);
};
}
}
}