Skip to content

Commit f6d6398

Browse files
committed
Finish Emitter
1 parent fddafed commit f6d6398

File tree

1 file changed

+241
-15
lines changed

1 file changed

+241
-15
lines changed

src/pgdp/minijava/Emitter.java

Lines changed: 241 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,49 @@
11
package pgdp.minijava;
22

3+
import pgdp.minijava.ast.SyntaxTreeNode;
4+
35
import java.util.ArrayList;
46
import java.util.HashMap;
57
import java.util.List;
68
import java.util.Map;
79

810
public class Emitter {
11+
private static int whileLoops = 0;
12+
private static int ifStatements = 0;
13+
914
private Emitter() {
1015

1116
}
1217

1318
public static String emit(SyntaxTreeNode node) {
1419
Map<String, Integer> variableMap = generateVariableMap(node, new HashMap<>());
15-
return emitCode(node, variableMap);
20+
whileLoops = 0;
21+
ifStatements = 0;
22+
var temp = emitCode(node, variableMap).trim();
23+
if(!temp.endsWith("\nHALT")) {
24+
temp += "\nHALT";
25+
}
26+
temp = cleanUpResult(temp).trim();
27+
return temp;
28+
}
29+
30+
private static String cleanUpResult(String in) {
31+
List<String> lines = in.lines().toList();
32+
ArrayList<String> newLines = new ArrayList<>();
33+
if(lines.size() != 0) {
34+
newLines.add(lines.get(0));
35+
}
36+
for (int i = 1; i < lines.size(); i++) {
37+
var current = lines.get(i);
38+
var prev = lines.get(i - 1);
39+
if(current.startsWith("ALLOC") && prev.startsWith("ALLOC")) {
40+
newLines.remove(prev);
41+
newLines.add("ALLOC " + (Integer.parseInt(current.substring(6)) + Integer.parseInt(prev.substring(6))));
42+
} else {
43+
newLines.add(current);
44+
}
45+
}
46+
return newLines.stream().reduce("", (s, s2) -> s + "\n" + s2);
1647
}
1748

1849
private static Map<String, Integer> generateVariableMap(SyntaxTreeNode node, Map<String, Integer> variableMap) {
@@ -32,7 +63,7 @@ private static Map<String, Integer> generateVariableMap(SyntaxTreeNode node, Map
3263
}
3364
}
3465
}
35-
} else if(child.getType() == SyntaxTreeNode.Type.NAME) {
66+
} else if(child.getType() == SyntaxTreeNode.Type.NAME && (i != 1 && node.getType() != SyntaxTreeNode.Type.FUNCCALL)) {
3667
if(!(variableMap.containsKey(child.getValue()) || out.containsKey(child.getValue()))) {
3768
throw new IllegalStateException(child.getValue() + " hasn't been defined in this context");
3869
}
@@ -55,34 +86,229 @@ private static String emitCode(SyntaxTreeNode node, Map<String, Integer> variabl
5586
return switch (node.getType()) {
5687
case PROGRAM -> emitProgram(node, variableMap);
5788
case DECL -> emitDeclaration(node, variableMap);
58-
case NAME -> null;
59-
case NUMBER -> null;
60-
case BOOL -> null;
61-
case EXPR -> null;
62-
case COND -> null;
63-
case COMP -> null;
64-
case TYPE -> null;
65-
case STMT -> null;
89+
//case BOOL -> null;
90+
//case NAME -> null;
91+
//case NUMBER -> null;
92+
//case TYPE -> null;
93+
//case EXPR -> emitExpression(node, variableMap);
94+
//case COND -> null;
95+
//case COMP -> null;
96+
case STMT -> emitStatement(node, variableMap);
6697
case LABEL -> emitLabel(node, variableMap);
67-
case SYMBOL -> null;
68-
case FUNCCALL -> null;
98+
//case SYMBOL -> null;
99+
case FUNCCALL -> emitFunctionCall(node, variableMap);
100+
//case ASS -> emitAssignment(node, variableMap);
101+
default -> throw new IllegalStateException("Not a statement!");
69102
};
70103
}
71104

72105
private static String emitProgram(SyntaxTreeNode node, Map<String, Integer> variableMap) {
73106
StringBuilder out = new StringBuilder();
74107
for (int i = 0; i < node.getNumberChildren(); i++) {
75108
SyntaxTreeNode child = node.getChild(i);
76-
out.append(emitCode(child, variableMap)).append("\n");
109+
out.append(emitCode(child, variableMap));
77110
}
78111
return out.toString();
79112
}
80113

81114
private static String emitLabel(SyntaxTreeNode node, Map<String, Integer> variableMap) {
82-
return node.toString() + ":";
115+
return node.getValue() + ":\n";
83116
}
84117

85118
private static String emitDeclaration(SyntaxTreeNode node, Map<String, Integer> variableMap) {
86-
return "";
119+
boolean[] vars = new boolean[variableMap.size()];
120+
int variables = 0;
121+
boolean readValue = false;
122+
String value = "";
123+
for (int j = 0; j < node.getNumberChildren(); j++) {
124+
SyntaxTreeNode child = node.getChild(j);
125+
if(child.getType() == SyntaxTreeNode.Type.NAME){
126+
variables++;
127+
vars[variableMap.get(child.getValue())] = true;
128+
}
129+
if(child.getType() == SyntaxTreeNode.Type.SYMBOL && child.getValue().equals("=")) {
130+
readValue = true;
131+
}
132+
if(readValue){
133+
if(child.getType() == SyntaxTreeNode.Type.EXPR){
134+
value = emitExpression(child, variableMap);
135+
} else if(child.getType() == SyntaxTreeNode.Type.COND) {
136+
value = emitCondition(child, variableMap);
137+
} else {
138+
throw new IllegalStateException("Expected value!");
139+
}
140+
}
141+
}
142+
StringBuilder out = new StringBuilder();
143+
out.append("ALLOC ").append(variables).append("\n");
144+
if(readValue) {
145+
for (int i = 0; i < vars.length; i++) {
146+
if(vars[i]) {
147+
out.append(value).append("STORE ").append(i).append("\n");
148+
}
149+
}
150+
}
151+
return out.toString();
152+
}
153+
154+
private static String emitExpression(SyntaxTreeNode node, Map<String, Integer> variableMap) {
155+
SyntaxTreeNode next = node.getChild(0);
156+
if(next.getType() == SyntaxTreeNode.Type.NUMBER) {
157+
return "CONST " + next.getValue() + "\n";
158+
}
159+
if(next.getType() == SyntaxTreeNode.Type.NAME) {
160+
return "LOAD " + variableMap.get(next.getValue()) + "\n";
161+
}
162+
if(next.getType() == SyntaxTreeNode.Type.SYMBOL) {
163+
if(next.getValue().equals("(")) {
164+
return emitExpression(node.getChild(1), variableMap);
165+
}
166+
if(next.getValue().equals("-")) {
167+
return emitExpression(node.getChild(1), variableMap) + "NEG\n";
168+
}
169+
throw new IllegalStateException("Unexpected symbol " + next.getValue());
170+
}
171+
if(next.getType() == SyntaxTreeNode.Type.EXPR) {
172+
return emitExpression(next, variableMap) + emitExpression(node.getChild(2), variableMap) + emitOperator(node.getChild(1), variableMap);
173+
}
174+
if(next.getType() == SyntaxTreeNode.Type.FUNCCALL) {
175+
return emitFunctionCall(next, variableMap);
176+
}
177+
if(next.getType() == SyntaxTreeNode.Type.COND) {
178+
return emitCondition(next, variableMap);
179+
}
180+
throw new IllegalStateException("Couldn't resolve expression");
181+
}
182+
183+
private static String emitStatement(SyntaxTreeNode node, Map<String, Integer> variableMap) {
184+
SyntaxTreeNode next = node.getChild(0);
185+
if(next.getType() == SyntaxTreeNode.Type.SYMBOL) {
186+
if(next.getValue().equals(";")) {
187+
System.err.println("Unnecessary Semicolon detected");
188+
return "";
189+
}
190+
if(next.getValue().equals("{")) {
191+
StringBuilder out = new StringBuilder();
192+
for (int i = 1; i < node.getNumberChildren() - 1; i++) {
193+
out.append(emitCode(node.getChild(i), variableMap));
194+
}
195+
return out.toString();
196+
}
197+
if(next.getValue().equals("return")) {
198+
return "HALT\n";
199+
}
200+
if(next.getValue().equals("while")) {
201+
var start = "while" + whileLoops + ":\n" + emitCondition(node.getChild(2), variableMap) + "FJUMP whileEnd" + whileLoops +"\n";
202+
var end = "JUMP " + "while" + whileLoops + "\nwhileEnd" + whileLoops +":\n";
203+
whileLoops++;
204+
return start + emitCode(node.getChild(4), variableMap) + end;
205+
}
206+
if(next.getValue().equals("if")) {
207+
var currentIfs = ifStatements++;
208+
var start = emitCondition(node.getChild(2), variableMap) + "FJUMP else" + currentIfs + "\n";
209+
var temp = start + emitCode(node.getChild(4), variableMap);
210+
var end = "else" + currentIfs + ":\n";
211+
if(node.getNumberChildren() > 5) {
212+
var middle = "JUMP ifend" + currentIfs + "\n" + end;
213+
end = "ifend" + currentIfs +":\n";
214+
temp += middle + emitCode(node.getChild(6), variableMap);
215+
}
216+
temp += end;
217+
return temp;
218+
}
219+
throw new IllegalStateException("Unexpected symbol " + next.getValue());
220+
}
221+
if(next.getType() == SyntaxTreeNode.Type.LABEL) {
222+
return emitLabel(next, variableMap) + emitCode(node.getChild(2), variableMap);
223+
}
224+
if(next.getType() == SyntaxTreeNode.Type.ASS) {
225+
return emitAssignment(next, variableMap);
226+
}
227+
if(next.getType() == SyntaxTreeNode.Type.FUNCCALL) {
228+
return emitFunctionCall(next, variableMap);
229+
}
230+
throw new IllegalStateException("Unexpected symbol " + next.getValue());
231+
}
232+
233+
private static String emitAssignment(SyntaxTreeNode node, Map<String, Integer> variableMap) {
234+
SyntaxTreeNode next = node.getChild(0);
235+
int pos = variableMap.get(next.getValue());
236+
String store = "STORE " + pos;
237+
return emitExpression(node.getChild(2), variableMap) + store + "\n";
238+
}
239+
240+
private static String emitFunctionCall(SyntaxTreeNode node, Map<String, Integer> variableMap) {
241+
SyntaxTreeNode next = node.getChild(0);
242+
if(next.getValue().equals("write")) {
243+
return emitExpression(node.getChild(2), variableMap) + "WRITE\n";
244+
}
245+
if(next.getValue().equals("readInt")) {
246+
return "READ\n";
247+
}
248+
throw new UnsupportedOperationException("This compiler does not support CALL and RET");
249+
}
250+
251+
private static String emitOperator(SyntaxTreeNode node, Map<String, Integer> variableMap) {
252+
return switch (node.getValue()) {
253+
case "+" -> "ADD\n";
254+
case "-" -> "SUB\n";
255+
case "*" -> "MUL\n";
256+
case "/" -> "DIV\n";
257+
case "%" -> "MOD\n";
258+
default -> throw new IllegalStateException();
259+
};
260+
}
261+
262+
private static String emitCondition(SyntaxTreeNode node, Map<String, Integer> variableMap) {
263+
SyntaxTreeNode next = node.getChild(0);
264+
if(next.getType() == SyntaxTreeNode.Type.BOOL) {
265+
if(next.getValue().equals("true")) {
266+
return "TRUE\n";
267+
}
268+
if(next.getValue().equals("false")) {
269+
return "FALSE\n";
270+
}
271+
throw new IllegalStateException("Unexpected non bool value detected as bool!");
272+
}
273+
274+
if(next.getType() == SyntaxTreeNode.Type.SYMBOL) {
275+
if(next.getValue().equals("(")) {
276+
return emitCondition(node.getChild(1), variableMap);
277+
}
278+
if(next.getValue().equals("!")) {
279+
return emitExpression(node.getChild(1), variableMap) + "NOT\n";
280+
}
281+
throw new IllegalStateException("Unexpected symbol " + next.getValue());
282+
}
283+
if(next.getType() == SyntaxTreeNode.Type.COND) {
284+
return emitCondition(next, variableMap) + emitCondition(node.getChild(2), variableMap) + emitBoolOperator(node.getChild(1), variableMap);
285+
}
286+
if(next.getType() == SyntaxTreeNode.Type.EXPR) {
287+
if(node.getNumberChildren() == 1) {
288+
return emitExpression(next, variableMap);
289+
}
290+
return emitExpression(next, variableMap) + emitExpression(node.getChild(2), variableMap) + emitComparator(node.getChild(1), variableMap);
291+
}
292+
throw new IllegalStateException();
293+
}
294+
295+
private static String emitComparator(SyntaxTreeNode node, Map<String, Integer> variableMap) {
296+
return switch (node.getValue()) {
297+
case "==" -> "EQ\n";
298+
case "!=" -> "NEQ\n";
299+
case "<" -> "LESS\n";
300+
case "<=" -> "LEQ\n";
301+
case ">" -> "LEQ\nNOT\n";
302+
case ">=" -> "LESS\nNOT\n";
303+
default -> throw new IllegalStateException();
304+
};
305+
}
306+
307+
private static String emitBoolOperator(SyntaxTreeNode node, Map<String, Integer> variableMap) {
308+
return switch (node.getValue()) {
309+
case "&&", "&" -> "AND\n";
310+
case "||", "|" -> "OR\n";
311+
default -> throw new IllegalStateException();
312+
};
87313
}
88314
}

0 commit comments

Comments
 (0)