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 24package jdk.test.lib.jittester.visitors; 25 26import java.util.List; 27import java.util.Locale; 28import java.util.Objects; 29import java.util.stream.Collectors; 30import jdk.test.lib.jittester.BinaryOperator; 31import jdk.test.lib.jittester.Block; 32import jdk.test.lib.jittester.Break; 33import jdk.test.lib.jittester.CastOperator; 34import jdk.test.lib.jittester.CatchBlock; 35import jdk.test.lib.jittester.Continue; 36import jdk.test.lib.jittester.Declaration; 37import jdk.test.lib.jittester.IRNode; 38import jdk.test.lib.jittester.If; 39import jdk.test.lib.jittester.Initialization; 40import jdk.test.lib.jittester.Literal; 41import jdk.test.lib.jittester.LocalVariable; 42import jdk.test.lib.jittester.NonStaticMemberVariable; 43import jdk.test.lib.jittester.Nothing; 44import jdk.test.lib.jittester.Operator; 45import jdk.test.lib.jittester.OperatorKind; 46import jdk.test.lib.jittester.PrintVariables; 47import jdk.test.lib.jittester.ProductionParams; 48import jdk.test.lib.jittester.Statement; 49import jdk.test.lib.jittester.StaticMemberVariable; 50import jdk.test.lib.jittester.Switch; 51import jdk.test.lib.jittester.Symbol; 52import jdk.test.lib.jittester.TernaryOperator; 53import jdk.test.lib.jittester.Throw; 54import jdk.test.lib.jittester.TryCatchBlock; 55import jdk.test.lib.jittester.Type; 56import jdk.test.lib.jittester.TypeList; 57import jdk.test.lib.jittester.UnaryOperator; 58import jdk.test.lib.jittester.VariableBase; 59import jdk.test.lib.jittester.VariableDeclaration; 60import jdk.test.lib.jittester.VariableDeclarationBlock; 61import jdk.test.lib.jittester.VariableInfo; 62import jdk.test.lib.jittester.arrays.ArrayCreation; 63import jdk.test.lib.jittester.arrays.ArrayElement; 64import jdk.test.lib.jittester.arrays.ArrayExtraction; 65import jdk.test.lib.jittester.classes.ClassDefinitionBlock; 66import jdk.test.lib.jittester.classes.Interface; 67import jdk.test.lib.jittester.classes.Klass; 68import jdk.test.lib.jittester.classes.MainKlass; 69import jdk.test.lib.jittester.functions.ArgumentDeclaration; 70import jdk.test.lib.jittester.functions.ConstructorDefinition; 71import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock; 72import jdk.test.lib.jittester.functions.Function; 73import jdk.test.lib.jittester.functions.FunctionDeclaration; 74import jdk.test.lib.jittester.functions.FunctionDeclarationBlock; 75import jdk.test.lib.jittester.functions.FunctionDefinition; 76import jdk.test.lib.jittester.functions.FunctionDefinitionBlock; 77import jdk.test.lib.jittester.functions.FunctionInfo; 78import jdk.test.lib.jittester.functions.FunctionRedefinition; 79import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock; 80import jdk.test.lib.jittester.functions.Return; 81import jdk.test.lib.jittester.functions.StaticConstructorDefinition; 82import jdk.test.lib.jittester.loops.CounterInitializer; 83import jdk.test.lib.jittester.loops.CounterManipulator; 84import jdk.test.lib.jittester.loops.DoWhile; 85import jdk.test.lib.jittester.loops.For; 86import jdk.test.lib.jittester.loops.Loop; 87import jdk.test.lib.jittester.loops.LoopingCondition; 88import jdk.test.lib.jittester.loops.While; 89import jdk.test.lib.jittester.types.TypeArray; 90import jdk.test.lib.jittester.types.TypeKlass; 91import jdk.test.lib.jittester.utils.FixedTrees; 92import jdk.test.lib.jittester.utils.PrintingUtils; 93 94public 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} 923