11package pgdp .minijava ;
22
3+ import pgdp .minijava .ast .SyntaxTreeNode ;
4+
35import java .util .ArrayList ;
46import java .util .HashMap ;
57import java .util .List ;
68import java .util .Map ;
79
810public 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 ("\n HALT" )) {
24+ temp += "\n HALT" ;
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 + "\n whileEnd" + 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\n NOT\n " ;
302+ case ">=" -> "LESS\n NOT\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