1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24 package jdk.test.lib.jittester.visitors;
25
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Objects;
29 import java.util.stream.Collectors;
30 import jdk.test.lib.jittester.BinaryOperator;
31 import jdk.test.lib.jittester.Block;
32 import jdk.test.lib.jittester.Break;
33 import jdk.test.lib.jittester.CastOperator;
34 import jdk.test.lib.jittester.CatchBlock;
35 import jdk.test.lib.jittester.Continue;
36 import jdk.test.lib.jittester.Declaration;
37 import jdk.test.lib.jittester.IRNode;
38 import jdk.test.lib.jittester.If;
39 import jdk.test.lib.jittester.Initialization;
40 import jdk.test.lib.jittester.Literal;
41 import jdk.test.lib.jittester.LocalVariable;
42 import jdk.test.lib.jittester.NonStaticMemberVariable;
43 import jdk.test.lib.jittester.Nothing;
44 import jdk.test.lib.jittester.Operator;
45 import jdk.test.lib.jittester.OperatorKind;
46 import jdk.test.lib.jittester.PrintVariables;
47 import jdk.test.lib.jittester.ProductionParams;
48 import jdk.test.lib.jittester.Statement;
49 import jdk.test.lib.jittester.StaticMemberVariable;
50 import jdk.test.lib.jittester.Switch;
51 import jdk.test.lib.jittester.Symbol;
52 import jdk.test.lib.jittester.TernaryOperator;
53 import jdk.test.lib.jittester.Throw;
54 import jdk.test.lib.jittester.TryCatchBlock;
55 import jdk.test.lib.jittester.Type;
56 import jdk.test.lib.jittester.TypeList;
57 import jdk.test.lib.jittester.UnaryOperator;
58 import jdk.test.lib.jittester.VariableBase;
59 import jdk.test.lib.jittester.VariableDeclaration;
60 import jdk.test.lib.jittester.VariableDeclarationBlock;
61 import jdk.test.lib.jittester.VariableInfo;
62 import jdk.test.lib.jittester.arrays.ArrayCreation;
63 import jdk.test.lib.jittester.arrays.ArrayElement;
64 import jdk.test.lib.jittester.arrays.ArrayExtraction;
65 import jdk.test.lib.jittester.classes.ClassDefinitionBlock;
66 import jdk.test.lib.jittester.classes.Interface;
67 import jdk.test.lib.jittester.classes.Klass;
68 import jdk.test.lib.jittester.classes.MainKlass;
69 import jdk.test.lib.jittester.functions.ArgumentDeclaration;
70 import jdk.test.lib.jittester.functions.ConstructorDefinition;
71 import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock;
72 import jdk.test.lib.jittester.functions.Function;
73 import jdk.test.lib.jittester.functions.FunctionDeclaration;
74 import jdk.test.lib.jittester.functions.FunctionDeclarationBlock;
75 import jdk.test.lib.jittester.functions.FunctionDefinition;
76 import jdk.test.lib.jittester.functions.FunctionDefinitionBlock;
77 import jdk.test.lib.jittester.functions.FunctionInfo;
78 import jdk.test.lib.jittester.functions.FunctionRedefinition;
79 import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock;
80 import jdk.test.lib.jittester.functions.Return;
81 import jdk.test.lib.jittester.functions.StaticConstructorDefinition;
82 import jdk.test.lib.jittester.loops.CounterInitializer;
83 import jdk.test.lib.jittester.loops.CounterManipulator;
84 import jdk.test.lib.jittester.loops.DoWhile;
85 import jdk.test.lib.jittester.loops.For;
86 import jdk.test.lib.jittester.loops.Loop;
87 import jdk.test.lib.jittester.loops.LoopingCondition;
88 import jdk.test.lib.jittester.loops.While;
89 import jdk.test.lib.jittester.types.TypeArray;
90 import jdk.test.lib.jittester.types.TypeKlass;
91 import jdk.test.lib.jittester.utils.FixedTrees;
92 import jdk.test.lib.jittester.utils.PrintingUtils;
93
94 public class JavaCodeVisitor implements Visitor<String> {
95
96 public static String funcAttributes(FunctionInfo fi) {
97 String attrs = attributes(fi);
98 if (fi.isSynchronized()) {
99 attrs += "synchronized ";
100 }
101 return attrs;
102 }
103
104 public static String attributes(Symbol s) {
105 String attrs = "";
106 if (s.isPrivate()) {
107 attrs += "private ";
108 }
109 if (s.isProtected()) {
110 attrs += "protected ";
111 }
112 if (s.isPublic()) {
113 attrs += "public ";
114 }
115 if (s.isFinal()) {
116 attrs += "final ";
117 }
118 if (s.isStatic()) {
119 attrs += "static ";
120 }
121 return attrs;
122 }
123
124 private String operatorToJaveCode(OperatorKind operationKind) {
125 switch (operationKind) {
126 case COMPOUND_ADD:
127 return "+=";
128 case COMPOUND_SUB:
129 return "-=";
130 case COMPOUND_MUL:
131 return "*=";
132 case COMPOUND_DIV:
133 return "/=";
134 case COMPOUND_MOD:
135 return "%=";
136 case COMPOUND_AND:
137 return "&=";
138 case COMPOUND_OR:
139 return "|=";
140 case COMPOUND_XOR:
141 return "^=";
142 case COMPOUND_SHR:
143 return ">>=";
144 case COMPOUND_SHL:
145 return "<<=";
146 case COMPOUND_SAR:
147 return ">>>=";
148 case ASSIGN:
149 return "=";
150 case OR:
151 return "||";
152 case BIT_OR:
153 return "|";
154 case BIT_XOR:
155 return "^";
156 case AND:
157 return "&&";
158 case BIT_AND:
159 return "&";
160 case EQ:
161 return "==";
162 case NE:
163 return "!=";
164 case GT:
165 return ">";
166 case LT:
167 return "<";
168 case GE:
169 return ">=";
170 case LE:
171 return "<=";
172 case SHR:
173 return ">>";
174 case SHL:
175 return "<<";
176 case SAR:
177 return ">>>";
178 case ADD:
179 case STRADD:
180 return "+";
181 case SUB:
182 return "-";
183 case MUL:
184 return "*";
185 case DIV:
186 return "/";
187 case MOD:
188 return "%";
189 case NOT:
190 return "!";
191 case BIT_NOT:
192 return "~";
193 case UNARY_PLUS:
194 return "+";
195 case UNARY_MINUS:
196 return "-";
197 case PRE_DEC:
198 case POST_DEC:
199 return "--";
200 case PRE_INC:
201 case POST_INC:
202 return "++";
203 default:
204 throw new IllegalArgumentException("Unkown operator kind " + operationKind);
205 }
206 }
207
208 private String expressionToJavaCode(Operator t, IRNode p, Operator.Order o) {
209 String result;
210 try {
211 if ((o == Operator.Order.LEFT && ((Operator) p).getPriority() < t.getPriority())
212 || (o == Operator.Order.RIGHT && ((Operator) p).getPriority() <= t.getPriority())) {
213 result = "(" + p.accept(this)+ ")";
214 } else {
215 result = p.accept(this);
216 }
217 } catch (Exception e) {
218 result = p.accept(this);
219 }
220 return result;
221 }
222
223 @Override
224 public String visit(ArgumentDeclaration node) {
225 VariableInfo vi = node.variableInfo;
226 return attributes(vi) + vi.type.accept(this) + " " + vi.name;
227 }
228
229 @Override
230 public String visit(ArrayCreation node) {
231 Type arrayElemType = node.getArrayType().type;
232 String type = arrayElemType.accept(this);
233 String name = node.getVariable().getName();
234 StringBuilder code = new StringBuilder()
235 .append(node.getVariable().accept(this))
236 .append(";\n")
237 .append(PrintingUtils.align(node.getParent().getLevel()))
238 .append(name)
239 .append(" = new ")
240 .append(type);
241 code.append(node.getChildren().stream()
242 .map(p -> p.accept(this))
243 .collect(Collectors.joining("][", "[", "]")));
244 code.append(";\n");
245 if (!TypeList.isBuiltIn(arrayElemType)) {
246 code.append(PrintingUtils.align(node.getParent().getLevel()))
247 .append("java.util.Arrays.fill(")
248 .append(name)
249 .append(", new ")
250 .append(type)
251 .append("());\n");
252 }
253 return code.toString();
254 }
255
256 @Override
257 public String visit(ArrayElement node) {
258 IRNode array = node.getChild(0);
259 StringBuilder code = new StringBuilder();
260 if (array instanceof VariableBase || array instanceof Function) {
261 code.append(array.accept(this));
262 } else {
263 code.append("(")
264 .append(array.accept(this))
265 .append(")");
266 }
267 code.append(node.getChildren().stream()
268 .skip(1)
269 .map(c -> c.accept(this))
270 .collect(Collectors.joining("][", "[", "]")));
271 return code.toString();
272 }
273
274 @Override
275 public String visit(ArrayExtraction node) {
276 IRNode array = node.getChild(0);
277 StringBuilder code = new StringBuilder();
278 if (array instanceof VariableBase || array instanceof Function) {
279 code.append(array.accept(this));
280 } else {
281 code.append("(")
282 .append(array.accept(this))
283 .append(")");
284 }
285 code.append(node.getChildren().stream()
286 .skip(1)
287 .map(c -> c.accept(this))
288 .collect(Collectors.joining("][", "[", "]")));
289 return code.toString();
290 }
291
292 @Override
293 public String visit(BinaryOperator node) {
294 IRNode left = node.getChild(Operator.Order.LEFT.ordinal());
295 IRNode right = node.getChild(Operator.Order.RIGHT.ordinal());
296 if (left == null || right == null) {
297 return "null";
298 }
299 return expressionToJavaCode(node, left, Operator.Order.LEFT)
300 + " " + operatorToJaveCode(node.getOperationKind()) + " "
301 + expressionToJavaCode(node, right, Operator.Order.RIGHT);
302 }
303
304 @Override
305 public String visit(Block node) {
306 StringBuilder code = new StringBuilder();
307 for (IRNode i : node.getChildren()) {
308 String s = i.accept(this);
309 if (!s.isEmpty()) {
310 int level = node.getLevel();
311 if (i instanceof Block) {
312 code.append(PrintingUtils.align(level + 1))
313 .append("{\n")
314 .append(s)
315 .append(PrintingUtils.align(level + 1))
316 .append("}");
317 } else {
318 code.append(PrintingUtils.align(level + 1))
319 .append(s);
320 }
321 code.append(addComplexityInfo(i));
322 code.append("\n");
323 }
324 }
325 return code.toString();
326 }
327
328 private String addComplexityInfo(IRNode node) {
329 if (ProductionParams.printComplexity.value()) {
330 return " /* " + node.complexity() + " */";
331 }
332 return "";
333 }
334
335 @Override
336 public String visit(Break node) {
337 return "break;";
338 }
339
340 @Override
341 public String visit(CastOperator node) {
342 return "(" + node.getResultType().accept(this)+ ")"
343 + expressionToJavaCode(node, node.getChild(0), Operator.Order.LEFT);
344 }
345
346 @Override
347 public String visit(ClassDefinitionBlock node) {
348 StringBuilder code = new StringBuilder();
349 for (IRNode i : node.getChildren()) {
350 code.append("\n")
351 .append(PrintingUtils.align(node.getLevel()))
352 .append(i.accept(this))
353 .append("\n");
354 }
355
356 return code.toString();
357 }
358
359 @Override
360 public String visit(ConstructorDefinition node) {
361 String args = node.getChildren().stream()
362 .skip(1)
363 .map(c -> c.accept(this))
364 .collect(Collectors.joining(", "));
365 IRNode body = node.getChild(0);
366 StringBuilder code = new StringBuilder();
367 code.append(funcAttributes(node.getFunctionInfo()))
368 .append(node.getFunctionInfo().name)
369 .append("(")
370 .append(args)
371 .append(")\n")
372 .append(PrintingUtils.align(node.getLevel() + 1))
373 .append("{\n")
374 .append(body != null ? body.accept(this) : "")
375 .append(PrintingUtils.align(node.getLevel() + 1))
376 .append("}");
377 return code.toString();
378 }
379
380 @Override
381 public String visit(ConstructorDefinitionBlock node) {
382 StringBuilder code = new StringBuilder();
383 for (IRNode i : node.getChildren()) {
384 code.append("\n")
385 .append(PrintingUtils.align(node.getLevel()))
386 .append(i.accept(this))
387 .append(addComplexityInfo(i))
388 .append("\n");
389 }
390 return code.toString();
391 }
392
393 @Override
394 public String visit(Continue node) {
395 return "continue;";
396 }
397
398 @Override
399 public String visit(CounterInitializer node) {
400 VariableInfo vi = node.getVariableInfo();
401 return vi.type.accept(this) + " " + vi.name + " = " + node.getChild(0).accept(this)+ ";";
402 }
403
404 @Override
405 public String visit(CounterManipulator node) {
406 return node.getChild(0).accept(this);
407 }
408
409 @Override
410 public String visit(Declaration node) {
411 return node.getChild(0).accept(this)+ ";";
412 }
413
414 @Override
415 public String visit(DoWhile node) {
416 IRNode header = node.getChild(DoWhile.DoWhilePart.HEADER.ordinal());
417 IRNode body1 = node.getChild(DoWhile.DoWhilePart.BODY1.ordinal());
418 IRNode body2 = node.getChild(DoWhile.DoWhilePart.BODY2.ordinal());
419 StringBuilder code = new StringBuilder();
420 Loop loop = node.getLoop();
421 int level = node.getLevel();
422 code.append(loop.initialization.accept(this))
423 .append("\n")
424 .append(header.accept(this))
425 .append(PrintingUtils.align(level))
426 .append("do\n")
427 .append(PrintingUtils.align(level))
428 .append("{\n")
429 .append(body1.accept(this))
430 .append(PrintingUtils.align(level + 1))
431 .append(loop.manipulator.accept(this))
432 .append(";\n")
433 .append(body2.accept(this))
434 .append(PrintingUtils.align(level))
435 .append("} while (")
436 .append(loop.condition.accept(this))
437 .append(");");
438 return code.toString();
439 }
440
441 @Override
442 public String visit(For node) {
443 IRNode header = node.getChild(For.ForPart.HEADER.ordinal());
444 IRNode statement1 = node.getChild(For.ForPart.STATEMENT1.ordinal());
445 IRNode statement2 = node.getChild(For.ForPart.STATEMENT2.ordinal());
446 IRNode body1 = node.getChild(For.ForPart.BODY1.ordinal());
447 IRNode body2 = node.getChild(For.ForPart.BODY2.ordinal());
448 IRNode body3 = node.getChild(For.ForPart.BODY3.ordinal());
449 Loop loop = node.getLoop();
450 StringBuilder code = new StringBuilder();
451 int level = node.getLevel();
452 code.append(loop.initialization.accept(this))
453 .append("\n")
454 .append(header.accept(this))
455 .append(PrintingUtils.align(level))
456 .append("for (")
457 .append(statement1.accept(this))
458 .append("; ")
459 .append(loop.condition.accept(this))
460 .append("; ")
461 .append(statement2.accept(this))
462 .append(")\n")
463 .append(PrintingUtils.align(level))
464 .append("{\n")
465 .append(body1.accept(this))
466 .append(PrintingUtils.align(level + 1))
467 .append(loop.manipulator.accept(this))
468 .append(";\n")
469 .append(body2.accept(this))
470 .append(body3.accept(this))
471 .append(PrintingUtils.align(level))
472 .append("}");
473 return code.toString();
474 }
475
476 @Override
477 public String visit(Function node) {
478 FunctionInfo value = node.getValue();
479 String nameAndArgs = value.name + "("
480 + node.getChildren().stream()
481 .skip(value.isStatic() || value.isConstructor() ? 0 : 1)
482 .map(c -> c.accept(this))
483 .collect(Collectors.joining(", "))
484 + ")";
485 String prefix = "";
486 if (value.isStatic()) {
487 if(!node.getOwner().equals(value.owner)) {
488 prefix = value.owner.getName() + ".";
489 }
490 } else if (value.isConstructor()) {
491 prefix = "new ";
492 } else {
493 IRNode object = node.getChild(0);
494 String objectString = object.accept(this);
495 if (!objectString.equals("this")) {
496 if (object instanceof VariableBase || object instanceof Function
497 || object instanceof Literal) {
498 prefix = objectString + ".";
499 } else {
500 prefix = "(" + objectString + ")" + ".";
501 }
502 }
503 }
504 return prefix + nameAndArgs;
505 }
506
507 @Override
508 public String visit(FunctionDeclaration node) {
509 String args = node.getChildren().stream()
510 .map(c -> c.accept(this))
511 .collect(Collectors.joining(", "));
512
513 FunctionInfo functionInfo = node.getFunctionInfo();
514 return (functionInfo.owner.isInterface() ? "" : "abstract ")
515 + funcAttributes(functionInfo) + functionInfo.type.accept(this)+ " "
516 + functionInfo.name + "(" + args + ");";
517 }
518
519 @Override
520 public String visit(FunctionDeclarationBlock node) {
521 StringBuilder code = new StringBuilder();
522 for (IRNode i : node.getChildren()) {
523 code.append(PrintingUtils.align(node.getLevel()))
524 .append(i.accept(this))
525 .append(addComplexityInfo(i))
526 .append("\n");
527 }
528 return code.toString();
529 }
530
531 @Override
532 public String visit(FunctionDefinition node) {
533 String args = node.getChildren().stream()
534 .skip(2)
535 .map(c -> c.accept(this))
536 .collect(Collectors.joining(", "));
537 IRNode body = node.getChild(0);
538 IRNode ret = node.getChild(1);
539 FunctionInfo functionInfo = node.getFunctionInfo();
540 return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n"
541 + PrintingUtils.align(node.getLevel() + 1) + "{\n"
542 + body.accept(this)
543 + (ret != null ? PrintingUtils.align(node.getLevel() + 2) + ret.accept(this) + "\n" : "")
544 + PrintingUtils.align(node.getLevel() + 1) + "}\n";
545 }
546
547 @Override
548 public String visit(FunctionDefinitionBlock node) {
549 StringBuilder code = new StringBuilder();
550 for (IRNode i : node.getChildren()) {
551 code.append("\n")
552 .append(PrintingUtils.align(node.getLevel()))
553 .append(i.accept(this))
554 .append(addComplexityInfo(i))
555 .append("\n");
556 }
557 return code.toString();
558 }
559
560 @Override
561 public String visit(FunctionRedefinition node) {
562 String args = node.getChildren().stream()
563 .skip(2)
564 .map(c -> c.accept(this))
565 .collect(Collectors.joining(", "));
566
567 IRNode body = node.getChild(0);
568 IRNode ret = node.getChild(1);
569 int level = node.getLevel();
570 FunctionInfo functionInfo = node.getFunctionInfo();
571 return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n"
572 + PrintingUtils.align(level + 1) + "{\n"
573 + body.accept(this)
574 + (ret != null ? PrintingUtils.align(level + 2) + ret.accept(this) + "\n" : "")
575 + PrintingUtils.align(level + 1) + "}";
576 }
577
578 @Override
579 public String visit(FunctionRedefinitionBlock node) {
580 StringBuilder code = new StringBuilder();
581 for (IRNode i : node.getChildren()) {
582 code.append("\n")
583 .append(PrintingUtils.align(node.getLevel()))
584 .append(i.accept(this))
585 .append(addComplexityInfo(i))
586 .append("\n");
587 }
588 return code.toString();
589 }
590
591 @Override
592 public String visit(If node) {
593 int level = node.getLevel();
594 String thenBlockString = PrintingUtils.align(level) + "{\n"
595 + node.getChild(If.IfPart.THEN.ordinal()).accept(this)
596 + PrintingUtils.align(level) + "}";
597
598 String elseBlockString = null;
599 if (node.getChild(If.IfPart.ELSE.ordinal()) != null) {
600 elseBlockString = PrintingUtils.align(level) + "{\n"
601 + node.getChild(If.IfPart.ELSE.ordinal()).accept(this)
602 + PrintingUtils.align(level) + "}";
603 }
604
605 return "if (" + node.getChild(If.IfPart.CONDITION.ordinal()).accept(this)+ ")\n"
606 + thenBlockString + (elseBlockString != null ? "\n"
607 + PrintingUtils.align(level) + "else\n" + elseBlockString : "");
608 }
609
610 @Override
611 public String visit(Initialization node) {
612 VariableInfo vi = node.getVariableInfo();
613 return attributes(vi) + vi.type.accept(this)+ " " + vi.name + " = "
614 + node.getChild(0).accept(this);
615 }
616
617 @Override
618 public String visit(Interface node) {
619 return "interface " + node.getName() + (node.getParentKlass() != null ? " extends "
620 + node.getParentKlass().getName() : "") + " {\n"
621 + (node.getChildren().size() > 0 ? node.getChild(0).accept(this) : "")
622 + "}\n";
623 }
624
625 @Override
626 public String visit(Klass node) {
627 TypeKlass thisKlass = node.getThisKlass();
628 String r = (ProductionParams.enableStrictFP.value() ? "strictfp " : "")
629 + (thisKlass.isFinal() ? "final " : "")
630 + (thisKlass.isAbstract() ? "abstract " : "")
631 + "class " + node.getName()
632 + (node.getParentKlass() != null && !node.getParentKlass().equals(TypeList.OBJECT)
633 ? " extends " + node.getParentKlass().getName() : "");
634 List<TypeKlass> interfaces = node.getInterfaces();
635 r += interfaces.stream()
636 .map(Type::getName)
637 .collect(Collectors.joining(", ", (interfaces.isEmpty() ? "" : " implements "), ""));
638 IRNode dataMembers = node.getChild(Klass.KlassPart.DATA_MEMBERS.ordinal());
639 IRNode constructors = node.getChild(Klass.KlassPart.CONSTRUCTORS.ordinal());
640 IRNode redefinedFunctions = node.getChild(Klass.KlassPart.REDEFINED_FUNCTIONS.ordinal());
641 IRNode overridenFunctions = node.getChild(Klass.KlassPart.OVERRIDEN_FUNCTIONS.ordinal());
642 IRNode memberFunctions = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS.ordinal());
643 IRNode memberFunctionDecls = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS_DECLARATIONS.ordinal());
644 IRNode printVariables = node.getChild(Klass.KlassPart.PRINT_VARIABLES.ordinal());
645 r += " {\n"
646 + (dataMembers != null ? (dataMembers.accept(this)+ "\n") : "")
647 + (constructors != null ? (constructors.accept(this)+ "\n") : "")
648 + (redefinedFunctions != null ? (redefinedFunctions.accept(this)+ "\n") : "")
649 + (overridenFunctions != null ? (overridenFunctions.accept(this)+ "\n") : "")
650 + (memberFunctionDecls != null ? (memberFunctionDecls.accept(this)+ "\n") : "")
651 + (memberFunctions != null ? (memberFunctions.accept(this)+ "\n") : "")
652 + printVariables.accept(this)
653 + "}\n";
654 return r;
655 }
656
657 @Override
658 public String visit(Literal node) {
659 Type resultType = node.getResultType();
660 Object value = node.getValue();
661 if (resultType.equals(TypeList.LONG)) {
662 return value.toString() + "L";
663 }
664 if (resultType.equals(TypeList.FLOAT)) {
665 return String.format((Locale) null,
666 "%EF",
667 Double.parseDouble(value.toString()));
668 }
669 if (resultType.equals(TypeList.DOUBLE)) {
670 return String.format((Locale) null,
671 "%E",
672 Double.parseDouble(value.toString()));
673 }
674 if (resultType.equals(TypeList.CHAR)) {
675 if ((Character) value == '\\') {
676 return "\'" + "\\\\" + "\'";
677 } else {
678 return "\'" + value.toString() + "\'";
679 }
680 }
681 if (resultType.equals(TypeList.SHORT)) {
682 return "(short) " + value.toString();
683 }
684 if (resultType.equals(TypeList.BYTE)) {
685 return "(byte) " + value.toString();
686 }
687 if (resultType.equals(TypeList.STRING)) {
688 // TOOD handle other non-printable
689 return "\"" + value.toString().replace("\n", "\\n") + "\"";
690 }
691 return value.toString();
692 }
693
694 @Override
695 public String visit(LocalVariable node) {
696 return node.getVariableInfo().name;
697 }
698
699 @Override
700 public String visit(LoopingCondition node) {
701 return node.getCondition().accept(this);
702 }
703
704 @Override
705 public String visit(MainKlass node) {
706 String name = node.getName();
707 IRNode dataMembers = node.getChild(MainKlass.MainKlassPart.DATA_MEMBERS.ordinal());
708 IRNode memberFunctions = node.getChild(MainKlass.MainKlassPart.MEMBER_FUNCTIONS.ordinal());
709 IRNode testFunction = node.getChild(MainKlass.MainKlassPart.TEST_FUNCTION.ordinal());
710 IRNode printVariables = node.getChild(MainKlass.MainKlassPart.PRINT_VARIABLES.ordinal());
711
712 return (ProductionParams.enableStrictFP.value() ? "strictfp " : "")
713 + "public class " + name + " {\n"
714 + dataMembers.accept(this)+ "\n"
715 + (memberFunctions != null ? memberFunctions.accept(this): "") + "\n"
716 + " private void test()\n"
717 + " {\n"
718 + testFunction.accept(this)
719 + " }" + addComplexityInfo(testFunction) + "\n"
720 + printVariables.accept(this)
721 + "}\n\n";
722 }
723
724 @Override
725 public String visit(NonStaticMemberVariable node) {
726 IRNode object = node.getChild(0);
727 String objectString = object.accept(this);
728 VariableInfo value = node.getVariableInfo();
729 if (objectString.equals("this")) {
730 return value.name;
731 } else {
732 if (object instanceof VariableBase || object instanceof Function || object instanceof Literal) {
733 return objectString + "." + value.name;
734 } else {
735 return "(" + objectString + ")" + "." + value.name;
736 }
737 }
738 }
739
740 @Override
741 public String visit(Nothing node) {
742 return "";
743 }
744
745 @Override
746 public String visit(PrintVariables node) {
747 return FixedTrees.printVariablesAsFunction(node).accept(this);
748 }
749
750 @Override
751 public String visit(Return node) {
752 return "return " + node.getExpression().accept(this) + ";";
753 }
754
755 @Override
756 public String visit(Throw node) {
757 return "throw " + node.getThowable().accept(this) + ";";
758 }
759
760 @Override
761 public String visit(Statement node) {
762 return node.getChild(0).accept(this)+ (node.isSemicolonNeeded() ? ";" : "");
763 }
764
765 @Override
766 public String visit(StaticConstructorDefinition node) {
767 IRNode body = node.getChild(0);
768 return "static {\n"
769 + (body != null ? body.accept(this): "")
770 + PrintingUtils.align(node.getLevel()) + "}";
771 }
772
773 @Override
774 public String visit(StaticMemberVariable node) {
775 IRNode owner = node.getOwner();
776 VariableInfo info = node.getVariableInfo();
777 if (owner.equals(info.owner)) {
778 return info.name;
779 } else {
780 return info.owner.getName() + "." + info.name;
781 }
782 }
783
784 @Override
785 public String visit(Switch node) {
786 int level = node.getLevel();
787 int caseBlockIdx = node.getCaseBlockIndex();
788 String cases = "";
789 for (int i = 0; i < caseBlockIdx - 1; ++i) {
790 cases += PrintingUtils.align(level + 1);
791 if (node.getChild(i + 1) instanceof Nothing) {
792 cases += "default:\n";
793 } else {
794 cases += "case " + node.getChild(i + 1).accept(this)+ ":\n";
795 }
796
797 cases += node.getChild(i + caseBlockIdx).accept(this)+ "\n";
798 }
799 return "switch (" + node.getChild(0).accept(this)+ ")\n"
800 + PrintingUtils.align(level) + "{\n"
801 + cases
802 + PrintingUtils.align(level) + "}";
803 }
804
805 @Override
806 public String visit(TernaryOperator node) {
807 IRNode conditionalExp = node.getChild(TernaryOperator.TernaryPart.CONDITION.ordinal());
808 IRNode leftExp = node.getChild(TernaryOperator.TernaryPart.TRUE.ordinal());
809 IRNode rightExp = node.getChild(TernaryOperator.TernaryPart.FALSE.ordinal());
810 if (Objects.isNull(conditionalExp) || Objects.isNull(leftExp) || Objects.isNull(rightExp)) {
811 return "null";
812 }
813 return expressionToJavaCode(node, conditionalExp, Operator.Order.RIGHT) + " ? "
814 + expressionToJavaCode(node, leftExp, Operator.Order.RIGHT) + " : "
815 + expressionToJavaCode(node, rightExp, Operator.Order.RIGHT);
816 }
817
818 @Override
819 public String visit(Type node) {
820 return node.getName();
821 }
822
823 @Override
824 public String visit(TypeArray node) {
825 String r = node.getType().accept(this);
826 for (int i = 0; i < node.getDimensions(); i++) {
827 r += "[]";
828 }
829 return r;
830 }
831
832 @Override
833 public String visit(UnaryOperator node) {
834 IRNode exp = node.getChild(0);
835 if (node.isPrefix()) {
836 return operatorToJaveCode(node.getOperationKind())
837 + (exp instanceof Operator ? " " : "")
838 + expressionToJavaCode(node, exp, Operator.Order.LEFT);
839 } else {
840 return expressionToJavaCode(node, exp, Operator.Order.RIGHT)
841 + (exp instanceof Operator ? " " : "")
842 + operatorToJaveCode(node.getOperationKind());
843 }
844 }
845
846 @Override
847 public String visit(VariableDeclaration node) {
848 VariableInfo vi = node.getVariableInfo();
849 return attributes(vi) + vi.type.accept(this)+ " " + vi.name;
850 }
851
852 @Override
853 public String visit(VariableDeclarationBlock node) {
854 StringBuilder code = new StringBuilder();
855 for (IRNode i : node.getChildren()) {
856 code.append(PrintingUtils.align(node.getLevel()))
857 .append(i.accept(this))
858 .append(addComplexityInfo(i))
859 .append("\n");
860 }
861 return code.toString();
862 }
863
864 @Override
865 public String visit(While node) {
866 IRNode header = node.getChild(While.WhilePart.HEADER.ordinal());
867 IRNode body1 = node.getChild(While.WhilePart.BODY1.ordinal());
868 IRNode body2 = node.getChild(While.WhilePart.BODY2.ordinal());
869 IRNode body3 = node.getChild(While.WhilePart.BODY3.ordinal());
870 int level = node.getLevel();
871 Loop loop = node.getLoop();
872 return loop.initialization.accept(this)+ "\n"
873 + header.accept(this)
874 + PrintingUtils.align(level) + "while (" + loop.condition.accept(this)+ ")\n"
875 + PrintingUtils.align(level) + "{\n"
876 + body1.accept(this)
877 + PrintingUtils.align(level + 1) + loop.manipulator.accept(this)+ ";\n"
878 + body2.accept(this)
879 + body3.accept(this)
880 + PrintingUtils.align(level) + "}";
881 }
882
883 @Override
884 public String visit(CatchBlock node) {
885 StringBuilder result = new StringBuilder();
886 int level = node.getLevel();
887 result.append(PrintingUtils.align(level)).append("catch(");
888 result.append(node.throwables.get(0).accept(this));
889 for (int i = 1; i < node.throwables.size(); i++) {
890 result.append(" | ").append(node.throwables.get(i).accept(this));
891 }
892 result.append(" ex) {\n");
893 result.append(node.getChild(0).accept(this));
894 result.append(PrintingUtils.align(level)).append("}\n");
895 return result.toString();
896 }
897
898 @Override
899 public String visit(TryCatchBlock node) {
900 StringBuilder result = new StringBuilder();
901 List<? extends IRNode> childs = node.getChildren();
902 IRNode body = childs.get(0);
903 IRNode finallyBody = childs.get(1);
904 int level = node.getLevel();
905 result.append("try {\n")
906 .append(body.accept(this)).append("\n")
907 .append(PrintingUtils.align(level))
908 .append("}\n");
909 for (int i = 2; i < childs.size(); i++) {
910 result.append(childs.get(i).accept(this));
911 }
912 if (finallyBody != null) {
913 String finallyContent = finallyBody.accept(this);
914 if (!finallyContent.isEmpty()) {
915 result.append(PrintingUtils.align(level)).append("finally {\n")
916 .append(finallyContent).append("\n")
917 .append(PrintingUtils.align(level)).append("}\n");
918 }
919 }
920 return result.toString();
921 }
922 }