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.HashSet; 27 import java.util.Iterator; 28 import java.util.List; 29 import java.util.Locale; 30 import java.util.Objects; 31 import java.util.stream.Collectors; 32 import jdk.test.lib.jittester.BinaryOperator; 33 import jdk.test.lib.jittester.Block; 34 import jdk.test.lib.jittester.Break; 35 import jdk.test.lib.jittester.CastOperator; 36 import jdk.test.lib.jittester.CatchBlock; 37 import jdk.test.lib.jittester.Continue; 38 import jdk.test.lib.jittester.Declaration; 39 import jdk.test.lib.jittester.IRNode; 40 import jdk.test.lib.jittester.If; 41 import jdk.test.lib.jittester.Initialization; 42 import jdk.test.lib.jittester.Literal; 43 import jdk.test.lib.jittester.LocalVariable; 44 import jdk.test.lib.jittester.LogicOperator; 45 import jdk.test.lib.jittester.NonStaticMemberVariable; 46 import jdk.test.lib.jittester.Nothing; 47 import jdk.test.lib.jittester.Operator; 48 import jdk.test.lib.jittester.PrintVariables; 49 import jdk.test.lib.jittester.ProductionParams; 50 import jdk.test.lib.jittester.Statement; 51 import jdk.test.lib.jittester.StaticMemberVariable; 52 import jdk.test.lib.jittester.Switch; 53 import jdk.test.lib.jittester.Symbol; 54 import jdk.test.lib.jittester.TernaryOperator; 55 import jdk.test.lib.jittester.Throw; 56 import jdk.test.lib.jittester.TryCatchBlock; 57 import jdk.test.lib.jittester.Type; 58 import jdk.test.lib.jittester.TypeList; 59 import jdk.test.lib.jittester.UnaryOperator; 60 import jdk.test.lib.jittester.VariableBase; 61 import jdk.test.lib.jittester.VariableDeclaration; 62 import jdk.test.lib.jittester.VariableDeclarationBlock; 63 import jdk.test.lib.jittester.VariableInfo; 64 import jdk.test.lib.jittester.arrays.ArrayCreation; 65 import jdk.test.lib.jittester.arrays.ArrayElement; 66 import jdk.test.lib.jittester.arrays.ArrayExtraction; 67 import jdk.test.lib.jittester.classes.ClassDefinitionBlock; 68 import jdk.test.lib.jittester.classes.Interface; 69 import jdk.test.lib.jittester.classes.Klass; 70 import jdk.test.lib.jittester.classes.MainKlass; 71 import jdk.test.lib.jittester.functions.ArgumentDeclaration; 72 import jdk.test.lib.jittester.functions.ConstructorDefinition; 73 import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock; 74 import jdk.test.lib.jittester.functions.Function; 75 import jdk.test.lib.jittester.functions.FunctionDeclaration; 76 import jdk.test.lib.jittester.functions.FunctionDeclarationBlock; 77 import jdk.test.lib.jittester.functions.FunctionDefinition; 78 import jdk.test.lib.jittester.functions.FunctionDefinitionBlock; 79 import jdk.test.lib.jittester.functions.FunctionInfo; 80 import jdk.test.lib.jittester.functions.FunctionRedefinition; 81 import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock; 82 import jdk.test.lib.jittester.functions.Return; 83 import jdk.test.lib.jittester.functions.StaticConstructorDefinition; 84 import jdk.test.lib.jittester.loops.CounterInitializer; 85 import jdk.test.lib.jittester.loops.CounterManipulator; 86 import jdk.test.lib.jittester.loops.DoWhile; 87 import jdk.test.lib.jittester.loops.For; 88 import jdk.test.lib.jittester.loops.Loop; 89 import jdk.test.lib.jittester.loops.LoopingCondition; 90 import jdk.test.lib.jittester.loops.While; 91 import jdk.test.lib.jittester.types.TypeArray; 92 import jdk.test.lib.jittester.types.TypeByte; 93 import jdk.test.lib.jittester.types.TypeKlass; 94 import jdk.test.lib.jittester.types.TypeChar; 95 import jdk.test.lib.jittester.types.TypeDouble; 96 import jdk.test.lib.jittester.types.TypeFloat; 97 import jdk.test.lib.jittester.types.TypeLong; 98 import jdk.test.lib.jittester.types.TypeShort; 99 import jdk.test.lib.jittester.utils.PrintingUtils; 100 101 public class JavaCodeVisitor implements Visitor<String> { 102 103 public static String funcAttributes(FunctionInfo fi) { 104 String attrs = attributes(fi); 105 if (fi.isSynchronized()) { 106 attrs += "synchronized "; 107 } 108 return attrs; 109 } 110 111 public static String attributes(Symbol s) { 112 String attrs = ""; 113 if (s.isPrivate()) { 114 attrs += "private "; 115 } 116 if (s.isProtected()) { 117 attrs += "protected "; 118 } 119 if (s.isPublic()) { 120 attrs += "public "; 121 } 122 if (s.isFinal()) { 123 attrs += "final "; 124 } 125 if (s.isStatic()) { 126 attrs += "static "; 127 } 128 return attrs; 129 } 130 131 public String expressionToJavaCode(Operator t, IRNode p, Operator.Order o) { 132 String result; 133 try { 134 if ((o == Operator.Order.LEFT && ((Operator) p).getPriority() < t.getPriority()) 135 || (o == Operator.Order.RIGHT && ((Operator) p).getPriority() <= t.getPriority())) { 136 result = "(" + p.accept(this)+ ")"; 137 } else { 138 result = p.accept(this); 139 } 140 } catch (Exception e) { 141 result = p.accept(this); 142 } 143 return result; 144 } 145 146 @Override 147 public String visit(ArgumentDeclaration node) { 148 VariableInfo vi = node.variableInfo; 149 return attributes(vi) + vi.type.accept(this) + " " + vi.name; 150 } 151 152 @Override 153 public String visit(ArrayCreation node) { 154 Type arrayType = node.getArrayType(); 155 String type = arrayType.accept(this); 156 String name = node.getVariable().getName(); 157 StringBuilder code = new StringBuilder() 158 .append(node.getVariable().accept(this)) 159 .append(";\n") 160 .append(PrintingUtils.align(node.getParent().getLevel())) 161 .append(name) 162 .append(" = new ") 163 .append(type); 164 code.append(node.getChildren().stream() 165 .map(p -> p.accept(this)) 166 .collect(Collectors.joining("][", "[", "]"))); 167 code.append(";\n"); 168 if (!TypeList.isBuiltIn(arrayType)) { 169 code.append(PrintingUtils.align(node.getParent().getLevel())) 170 .append("java.util.Arrays.fill(") 171 .append(name) 172 .append(", new ") 173 .append(type) 174 .append("());\n"); 175 } 176 return code.toString(); 177 } 178 179 @Override 180 public String visit(ArrayElement node) { 181 IRNode array = node.getChild(0); 182 StringBuilder code = new StringBuilder(); 183 if (array instanceof VariableBase || array instanceof Function) { 184 code.append(array.accept(this)); 185 } else { 186 code.append("(") 187 .append(array.accept(this)) 188 .append(")"); 189 } 190 code.append(node.getChildren().stream() 191 .skip(1) 192 .map(c -> c.accept(this)) 193 .collect(Collectors.joining("][", "[", "]"))); 194 return code.toString(); 195 } 196 197 @Override 198 public String visit(ArrayExtraction node) { 199 IRNode array = node.getChild(0); 200 StringBuilder code = new StringBuilder(); 201 if (array instanceof VariableBase || array instanceof Function) { 202 code.append(array.accept(this)); 203 } else { 204 code.append("(") 205 .append(array.accept(this)) 206 .append(")"); 207 } 208 code.append(node.getChildren().stream() 209 .skip(1) 210 .map(c -> c.accept(this)) 211 .collect(Collectors.joining("][", "[", "]"))); 212 return code.toString(); 213 } 214 215 @Override 216 public String visit(BinaryOperator node) { 217 IRNode left = node.getChild(Operator.Order.LEFT.ordinal()); 218 IRNode right = node.getChild(Operator.Order.RIGHT.ordinal()); 219 if (left == null || right == null) { 220 return "null"; 221 } 222 return expressionToJavaCode(node, left, Operator.Order.LEFT) 223 + " " + node.getOperationCode() + " " 224 + expressionToJavaCode(node, right, Operator.Order.RIGHT); 225 } 226 227 @Override 228 public String visit(Block node) { 229 StringBuilder code = new StringBuilder(); 230 for (IRNode i : node.getChildren()) { 231 String s = i.accept(this); 232 if (!s.isEmpty()) { 233 int level = node.getLevel(); 234 if (i instanceof Block) { 235 code.append(PrintingUtils.align(level + 1)) 236 .append("{\n") 237 .append(s) 238 .append(PrintingUtils.align(level + 1)) 239 .append("}"); 240 } else { 241 code.append(PrintingUtils.align(level + 1)) 242 .append(s); 243 } 244 code.append(addComplexityInfo(i)); 245 code.append("\n"); 246 } 247 } 248 return code.toString(); 249 } 250 251 private String addComplexityInfo(IRNode node) { 252 if (ProductionParams.printComplexity.value()) { 253 return " /* " + node.complexity() + " */"; 254 } 255 return ""; 256 } 257 258 @Override 259 public String visit(Break node) { 260 return "break;"; 261 } 262 263 @Override 264 public String visit(CastOperator node) { 265 return "(" + node.getResultType().accept(this)+ ")" 266 + expressionToJavaCode(node, node.getChild(0), Operator.Order.LEFT); 267 } 268 269 @Override 270 public String visit(ClassDefinitionBlock node) { 271 StringBuilder code = new StringBuilder(); 272 for (IRNode i : node.getChildren()) { 273 code.append("\n") 274 .append(PrintingUtils.align(node.getLevel())) 275 .append(i.accept(this)) 276 .append("\n"); 277 } 278 279 return code.toString(); 280 } 281 282 @Override 283 public String visit(ConstructorDefinition node) { 284 String args = node.getChildren().stream() 285 .skip(1) 286 .map(c -> c.accept(this)) 287 .collect(Collectors.joining(", ")); 288 IRNode body = node.getChild(0); 289 StringBuilder code = new StringBuilder(); 290 code.append(funcAttributes(node.getFunctionInfo())) 291 .append(node.getFunctionInfo().name) 292 .append("(") 293 .append(args) 294 .append(")\n") 295 .append(PrintingUtils.align(node.getLevel() + 1)) 296 .append("{\n") 297 .append(body != null ? body.accept(this) : "") 298 .append(PrintingUtils.align(node.getLevel() + 1)) 299 .append("}"); 300 return code.toString(); 301 } 302 303 @Override 304 public String visit(ConstructorDefinitionBlock node) { 305 StringBuilder code = new StringBuilder(); 306 for (IRNode i : node.getChildren()) { 307 code.append("\n") 308 .append(PrintingUtils.align(node.getLevel())) 309 .append(i.accept(this)) 310 .append(addComplexityInfo(i)) 311 .append("\n"); 312 } 313 return code.toString(); 314 } 315 316 @Override 317 public String visit(Continue node) { 318 return "continue;"; 319 } 320 321 @Override 322 public String visit(CounterInitializer node) { 323 VariableInfo vi = node.get(); 324 return vi.type.accept(this) + " " + vi.name + " = " + node.getChild(0).accept(this)+ ";"; 325 } 326 327 @Override 328 public String visit(CounterManipulator node) { 329 return node.getChild(0).accept(this); 330 } 331 332 @Override 333 public String visit(Declaration node) { 334 return node.getChild(0).accept(this)+ ";"; 335 } 336 337 @Override 338 public String visit(DoWhile node) { 339 IRNode header = node.getChild(DoWhile.DoWhilePart.HEADER.ordinal()); 340 IRNode body1 = node.getChild(DoWhile.DoWhilePart.BODY1.ordinal()); 341 IRNode body2 = node.getChild(DoWhile.DoWhilePart.BODY2.ordinal()); 342 StringBuilder code = new StringBuilder(); 343 Loop loop = node.getLoop(); 344 int level = node.getLevel(); 345 code.append(loop.initialization.accept(this)) 346 .append("\n") 347 .append(header.accept(this)) 348 .append(PrintingUtils.align(level)) 349 .append("do\n") 350 .append(PrintingUtils.align(level)) 351 .append("{\n") 352 .append(body1.accept(this)) 353 .append(PrintingUtils.align(level + 1)) 354 .append(loop.manipulator.accept(this)) 355 .append(";\n") 356 .append(body2.accept(this)) 357 .append(PrintingUtils.align(level)) 358 .append("} while (") 359 .append(loop.condition.accept(this)) 360 .append(");"); 361 return code.toString(); 362 } 363 364 @Override 365 public String visit(For node) { 366 IRNode header = node.getChild(For.ForPart.HEADER.ordinal()); 367 IRNode statement1 = node.getChild(For.ForPart.STATEMENT1.ordinal()); 368 IRNode statement2 = node.getChild(For.ForPart.STATEMENT2.ordinal()); 369 IRNode body1 = node.getChild(For.ForPart.BODY1.ordinal()); 370 IRNode body2 = node.getChild(For.ForPart.BODY2.ordinal()); 371 IRNode body3 = node.getChild(For.ForPart.BODY3.ordinal()); 372 Loop loop = node.getLoop(); 373 StringBuilder code = new StringBuilder(); 374 int level = node.getLevel(); 375 code.append(loop.initialization.accept(this)) 376 .append("\n") 377 .append(header.accept(this)) 378 .append(PrintingUtils.align(level)) 379 .append("for (") 380 .append(statement1.accept(this)) 381 .append("; ") 382 .append(loop.condition.accept(this)) 383 .append("; ") 384 .append(statement2.accept(this)) 385 .append(")\n") 386 .append(PrintingUtils.align(level)) 387 .append("{\n") 388 .append(body1.accept(this)) 389 .append(PrintingUtils.align(level + 1)) 390 .append(loop.manipulator.accept(this)) 391 .append(";\n") 392 .append(body2.accept(this)) 393 .append(body3.accept(this)) 394 .append(PrintingUtils.align(level)) 395 .append("}"); 396 return code.toString(); 397 } 398 399 @Override 400 public String visit(Function node) { 401 FunctionInfo value = node.getValue(); 402 String nameAndArgs = value.name + "(" 403 + node.getChildren().stream() 404 .skip(value.isStatic() || value.isConstructor() ? 0 : 1) 405 .map(c -> c.accept(this)) 406 .collect(Collectors.joining(", ")) 407 + ")"; 408 String prefix = ""; 409 if (value.isStatic()) { 410 if(!node.getKlass().equals(value.klass)) { 411 prefix = value.klass.getName() + "."; 412 } 413 } else if (value.isConstructor()) { 414 prefix = "new "; 415 } else { 416 IRNode object = node.getChild(0); 417 String objectString = object.accept(this); 418 if (!objectString.equals("this")) { 419 if (object instanceof VariableBase || object instanceof Function 420 || object instanceof Literal) { 421 prefix = objectString + "."; 422 } else { 423 prefix = "(" + objectString + ")" + "."; 424 } 425 } 426 } 427 return prefix + nameAndArgs; 428 } 429 430 @Override 431 public String visit(FunctionDeclaration node) { 432 String args = node.getChildren().stream() 433 .map(c -> c.accept(this)) 434 .collect(Collectors.joining(", ")); 435 436 FunctionInfo functionInfo = node.getFunctionInfo(); 437 return (functionInfo.klass.isInterface() ? "" : "abstract ") 438 + funcAttributes(functionInfo) + functionInfo.type.accept(this)+ " " 439 + functionInfo.name + "(" + args + ");"; 440 } 441 442 @Override 443 public String visit(FunctionDeclarationBlock node) { 444 StringBuilder code = new StringBuilder(); 445 for (IRNode i : node.getChildren()) { 446 code.append(PrintingUtils.align(node.getLevel())) 447 .append(i.accept(this)) 448 .append(addComplexityInfo(i)) 449 .append("\n"); 450 } 451 return code.toString(); 452 } 453 454 @Override 455 public String visit(FunctionDefinition node) { 456 String args = node.getChildren().stream() 457 .skip(2) 458 .map(c -> c.accept(this)) 459 .collect(Collectors.joining(", ")); 460 IRNode body = node.getChild(0); 461 IRNode ret = node.getChild(1); 462 FunctionInfo functionInfo = node.getFunctionInfo(); 463 return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n" 464 + PrintingUtils.align(node.getLevel() + 1) + "{\n" 465 + body.accept(this) 466 + (ret != null ? PrintingUtils.align(node.getLevel() + 2) + ret.accept(this) + "\n" : "") 467 + PrintingUtils.align(node.getLevel() + 1) + "}"; 468 } 469 470 @Override 471 public String visit(FunctionDefinitionBlock node) { 472 StringBuilder code = new StringBuilder(); 473 for (IRNode i : node.getChildren()) { 474 code.append("\n") 475 .append(PrintingUtils.align(node.getLevel())) 476 .append(i.accept(this)) 477 .append(addComplexityInfo(i)) 478 .append("\n"); 479 } 480 return code.toString(); 481 } 482 483 @Override 484 public String visit(FunctionRedefinition node) { 485 String args = node.getChildren().stream() 486 .map(c -> c.accept(this)) 487 .collect(Collectors.joining(", ")); 488 489 IRNode body = node.getChild(0); 490 IRNode ret = node.getChild(1); 491 int level = node.getLevel(); 492 FunctionInfo functionInfo = node.getFunctionInfo(); 493 return funcAttributes(functionInfo) + functionInfo.type + " " + functionInfo.name + "(" + args + ")" + "\n" 494 + PrintingUtils.align(level + 1) + "{\n" 495 + body 496 + (ret != null ? PrintingUtils.align(level + 2) + ret + "\n" : "") 497 + PrintingUtils.align(level + 1) + "}"; 498 } 499 500 @Override 501 public String visit(FunctionRedefinitionBlock node) { 502 StringBuilder code = new StringBuilder(); 503 for (IRNode i : node.getChildren()) { 504 code.append("\n") 505 .append(PrintingUtils.align(node.getLevel())) 506 .append(i.accept(this)) 507 .append(addComplexityInfo(i)) 508 .append("\n"); 509 } 510 return code.toString(); 511 } 512 513 @Override 514 public String visit(If node) { 515 int level = node.getLevel(); 516 String thenBlockString = PrintingUtils.align(level) + "{\n" 517 + node.getChild(If.IfPart.THEN.ordinal()).accept(this) 518 + PrintingUtils.align(level) + "}"; 519 520 String elseBlockString = null; 521 if (node.getChild(If.IfPart.ELSE.ordinal()) != null) { 522 elseBlockString = PrintingUtils.align(level) + "{\n" 523 + node.getChild(If.IfPart.ELSE.ordinal()).accept(this) 524 + PrintingUtils.align(level) + "}"; 525 } 526 527 return "if (" + node.getChild(If.IfPart.CONDITION.ordinal()).accept(this)+ ")\n" 528 + thenBlockString + (elseBlockString != null ? "\n" 529 + PrintingUtils.align(level) + "else\n" + elseBlockString : ""); 530 } 531 532 @Override 533 public String visit(Initialization node) { 534 VariableInfo vi = node.getVariableInfo(); 535 return attributes(vi) + vi.type.accept(this)+ " " + vi.name + " = " 536 + node.getChild(0).accept(this); 537 } 538 539 @Override 540 public String visit(Interface node) { 541 return "interface " + node.getName() + (node.getParentKlass() != null ? " extends " 542 + node.getParentKlass().getName() : "") + " {\n" 543 + (node.getChildren().size() > 0 ? node.getChild(0).accept(this) : "") 544 + "}\n"; 545 } 546 547 @Override 548 public String visit(Klass node) { 549 TypeKlass thisKlass = node.getThisKlass(); 550 String r = (ProductionParams.enableStrictFP.value() ? "strictfp " : "") 551 + (thisKlass.isFinal() ? "final " : "") 552 + (thisKlass.isAbstract() ? "abstract " : "") 553 + "class " + node.getName() 554 + (node.getParentKlass()!= null ? " extends " + node.getParentKlass().getName() : ""); 555 List<TypeKlass> interfaces = node.getInterfaces(); 556 r += interfaces.stream() 557 .map(c -> c.getName()) 558 .collect(Collectors.joining(", ", (interfaces.isEmpty() ? "" : " implements "), "")); 559 IRNode dataMembers = node.getChild(Klass.KlassPart.DATA_MEMBERS.ordinal()); 560 IRNode constructors = node.getChild(Klass.KlassPart.CONSTRUCTORS.ordinal()); 561 IRNode redefinedFunctions = node.getChild(Klass.KlassPart.REDEFINED_FUNCTIONS.ordinal()); 562 IRNode overridenFunctions = node.getChild(Klass.KlassPart.OVERRIDEN_FUNCTIONS.ordinal()); 563 IRNode memberFunctions = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS.ordinal()); 564 IRNode memberFunctionDecls = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS_DECLARATIONS.ordinal()); 565 IRNode printVariables = node.getChild(Klass.KlassPart.PRINT_VARIABLES.ordinal()); 566 r += " {\n" 567 + (dataMembers != null ? (dataMembers.accept(this)+ "\n") : "") 568 + (constructors != null ? (constructors.accept(this)+ "\n") : "") 569 + (redefinedFunctions != null ? (redefinedFunctions.accept(this)+ "\n") : "") 570 + (overridenFunctions != null ? (overridenFunctions.accept(this)+ "\n") : "") 571 + (memberFunctionDecls != null ? (memberFunctionDecls.accept(this)+ "\n") : "") 572 + (memberFunctions != null ? (memberFunctions.accept(this)+ "\n") : "") 573 + " public String toString()\n" 574 + " {\n" 575 + printVariables.accept(this) 576 + " }\n" 577 + "}\n"; 578 return r; 579 } 580 581 @Override 582 public String visit(Literal node) { 583 Type resultType = node.getResultType(); 584 Object value = node.getValue(); 585 if (resultType.equals(new TypeLong())) { 586 return value.toString() + "L"; 587 } 588 if (resultType.equals(new TypeFloat())) { 589 return String.format((Locale) null, 590 "%." + ProductionParams.floatingPointPrecision.value() + "EF", 591 Double.parseDouble(value.toString())); 592 } 593 if (resultType.equals(new TypeDouble())) { 594 return String.format((Locale) null, 595 "%." + 2 * ProductionParams.floatingPointPrecision.value() + "E", 596 Double.parseDouble(value.toString())); 597 } 598 if (resultType.equals(new TypeChar())) { 599 if (((Character) value).charValue() == '\\') { 600 return "\'" + "\\\\" + "\'"; 601 } else { 602 return "\'" + value.toString() + "\'"; 603 } 604 } 605 if (resultType.equals(new TypeShort())) { 606 return "(short) " + value.toString(); 607 } 608 if (resultType.equals(new TypeByte())) { 609 return "(byte) " + value.toString(); 610 } 611 return value.toString(); 612 } 613 614 @Override 615 public String visit(LocalVariable node) { 616 return node.get().name; 617 } 618 619 @Override 620 public String visit(LogicOperator node) { 621 throw new UnsupportedOperationException("Not supported yet."); 622 } 623 624 @Override 625 public String visit(LoopingCondition node) { 626 return node.getCondition().accept(this); 627 } 628 629 @Override 630 public String visit(MainKlass node) { 631 String name = node.getName(); 632 IRNode dataMembers = node.getChild(MainKlass.MainKlassPart.DATA_MEMBERS.ordinal()); 633 IRNode memberFunctions = node.getChild(MainKlass.MainKlassPart.MEMBER_FUNCTIONS.ordinal()); 634 IRNode testFunction = node.getChild(MainKlass.MainKlassPart.TEST_FUNCTION.ordinal()); 635 IRNode printVariables = node.getChild(MainKlass.MainKlassPart.PRINT_VARIABLES.ordinal()); 636 String executeFunction = " public static String execute()\n" 637 + " {\n" 638 + " try {\n" 639 + " " + name + " t = new " + name + "();\n" 640 + " try { t.test(); }\n" 641 + " catch(Throwable e) { }\n" 642 + " try { return t.toString(); }\n" 643 + " catch (Throwable e) { return \"Error during result conversion to String\"; }\n" 644 + " } catch (Throwable e) { return \"Error during test execution\"; }\n" 645 + " }\n"; 646 String mainFunction = " public static void main(String[] args)\n" 647 + " {\n" 648 + " try {\n" 649 + " " + name + " t = new " + name + "();\n" 650 + " try {\n" 651 + " for (int i = 0; i < 150000; ++i) {\n" 652 + " t.test();\n" 653 + " }\n" 654 + " }\n" 655 + " catch(Throwable e) { e.printStackTrace(); }\n" 656 + " try { System.out.println(t); }\n" 657 + " catch(Throwable e) { e.printStackTrace();}\n" 658 + " } catch (Throwable e) { e.printStackTrace(); }\n" 659 + " }\n"; 660 String printerClass = " static class Printer\n" 661 + " {\n" 662 + " public static String print(boolean arg) { return String.valueOf(arg); }\n" 663 + " public static String print(byte arg) { return String.valueOf(arg); }\n" 664 + " public static String print(short arg) { return String.valueOf(arg); }\n" 665 + " public static String print(char arg) { return String.valueOf((int)arg); }\n" 666 + " public static String print(int arg) { return String.valueOf(arg); }\n" 667 + " public static String print(long arg) { return String.valueOf(arg); }\n" 668 + " public static String print(float arg) { return String.valueOf(arg); }\n" 669 + " public static String print(double arg) { return String.valueOf(arg); }\n" 670 + "\n" 671 + "\n" 672 + " public static String print(Object arg)\n" 673 + " {\n" 674 + " return print_r(new java.util.Stack(), arg);\n" 675 + " }\n" 676 + "\n" 677 + " private static String print_r(java.util.Stack visitedObjects, Object arg)\n" 678 + " {\n" 679 + " String result = \"\";\n" 680 + " if (arg == null)\n" 681 + " result += \"null\";\n" 682 + " else\n" 683 + " if (arg.getClass().isArray())\n" 684 + " {\n" 685 + " for (int i = 0; i < visitedObjects.size(); i++)\n" 686 + " if (visitedObjects.elementAt(i) == arg) return \"<recursive>\";\n" 687 + "\n" 688 + " visitedObjects.push(arg);\n" 689 + "\n" 690 + " final String delimiter = \", \";\n" 691 + " result += \"[\";\n" 692 + "\n" 693 + " if (arg instanceof Object[])\n" 694 + " {\n" 695 + " Object[] array = (Object[]) arg;\n" 696 + " for (int i = 0; i < array.length; i++)\n" 697 + " {\n" 698 + " result += print_r(visitedObjects, array[i]);\n" 699 + " if (i < array.length - 1) result += delimiter;\n" 700 + " }\n" 701 + " }\n" 702 + " else\n" 703 + " if (arg instanceof boolean[])\n" 704 + " {\n" 705 + " boolean[] array = (boolean[]) arg;\n" 706 + " for (int i = 0; i < array.length; i++)\n" 707 + " {\n" 708 + " result += print(array[i]);\n" 709 + " if (i < array.length - 1) result += delimiter;\n" 710 + " }\n" 711 + " }\n" 712 + " else\n" 713 + " if (arg instanceof byte[])\n" 714 + " {\n" 715 + " byte[] array = (byte[]) arg;\n" 716 + " for (int i = 0; i < array.length; i++)\n" 717 + " {\n" 718 + " result += print(array[i]);\n" 719 + " if (i < array.length - 1) result += delimiter;\n" 720 + " }\n" 721 + " }\n" 722 + " else\n" 723 + " if (arg instanceof short[])\n" 724 + " {\n" 725 + " short[] array = (short[]) arg;\n" 726 + " for (int i = 0; i < array.length; i++)\n" 727 + " {\n" 728 + " result += print(array[i]);\n" 729 + " if (i < array.length - 1) result += delimiter;\n" 730 + " }\n" 731 + " }\n" 732 + " else\n" 733 + " if (arg instanceof char[])\n" 734 + " {\n" 735 + " char[] array = (char[]) arg;\n" 736 + " for (int i = 0; i < array.length; i++)\n" 737 + " {\n" 738 + " result += print(array[i]);\n" 739 + " if (i < array.length - 1) result += delimiter;\n" 740 + " }\n" 741 + " }\n" 742 + " else\n" 743 + " if (arg instanceof int[])\n" 744 + " {\n" 745 + " int[] array = (int[]) arg;\n" 746 + " for (int i = 0; i < array.length; i++)\n" 747 + " {\n" 748 + " result += print(array[i]);\n" 749 + " if (i < array.length - 1) result += delimiter;\n" 750 + " }\n" 751 + " }\n" 752 + " else\n" 753 + " if (arg instanceof long[])\n" 754 + " {\n" 755 + " long[] array = (long[]) arg;\n" 756 + " for (int i = 0; i < array.length; i++)\n" 757 + " {\n" 758 + " result += print(array[i]);\n" 759 + " if (i < array.length - 1) result += delimiter;\n" 760 + " }\n" 761 + " }\n" 762 + " else\n" 763 + " if (arg instanceof float[])\n" 764 + " {\n" 765 + " float[] array = (float[]) arg;\n" 766 + " for (int i = 0; i < array.length; i++)\n" 767 + " {\n" 768 + " result += print(array[i]);\n" 769 + " if (i < array.length - 1) result += delimiter;\n" 770 + " }\n" 771 + " }\n" 772 + " else\n" 773 + " if (arg instanceof double[])\n" 774 + " {\n" 775 + " double[] array = (double[]) arg;\n" 776 + " for (int i = 0; i < array.length; i++)\n" 777 + " {\n" 778 + " result += print(array[i]);\n" 779 + " if (i < array.length - 1) result += delimiter;\n" 780 + " }\n" 781 + " }\n" 782 + "\n" 783 + " result += \"]\";\n" 784 + " visitedObjects.pop();\n" 785 + "\n" 786 + " } else\n" 787 + " {\n" 788 + " result += arg.toString();\n" 789 + " }\n" 790 + "\n" 791 + " return result;\n" 792 + " }\n" 793 + " }\n"; 794 795 return (ProductionParams.enableStrictFP.value() ? "strictfp " : "") 796 + "public class " + name + " {\n" 797 + dataMembers.accept(this)+ "\n" 798 + (memberFunctions != null ? memberFunctions.accept(this): "") + "\n" 799 + executeFunction 800 + "\n" 801 + mainFunction 802 + "\n" 803 + " private void test()\n" 804 + " {\n" 805 + testFunction.accept(this) 806 + " }" + addComplexityInfo(testFunction) + "\n" 807 + " public String toString()\n" 808 + " {\n" 809 + printVariables.accept(this) 810 + " }\n" 811 + printerClass 812 + "}\n\n"; 813 } 814 815 @Override 816 public String visit(NonStaticMemberVariable node) { 817 IRNode object = node.getChild(0); 818 String objectString = object.accept(this); 819 VariableInfo value = node.getValue(); 820 if (objectString.equals("this")) { 821 return value.name; 822 } else { 823 if (object instanceof VariableBase || object instanceof Function || object instanceof Literal) { 824 return objectString + "." + value.name; 825 } else { 826 return "(" + objectString + ")" + "." + value.name; 827 } 828 } 829 } 830 831 @Override 832 public String visit(Nothing node) { 833 return ""; 834 } 835 836 @Override 837 public String visit(PrintVariables node) { 838 int level = node.getLevel(); 839 List<Symbol> vars = node.getVars(); 840 StringBuilder result = new StringBuilder() 841 .append(PrintingUtils.align(level)) 842 .append("String result = \"[\\n\";\n"); 843 if (!vars.isEmpty()) { 844 for (int i = 0; i < vars.size(); i++) { 845 Symbol v = vars.get(i); 846 result.append(PrintingUtils.align(level)) 847 .append("result += \"").append(v.klass.getName()) 848 .append(".") 849 .append(v.name) 850 .append(" = \"; ") 851 .append("result += ") 852 .append(node.getPrinterName()) 853 .append(".print(") 854 .append(v.name) 855 .append(");\n") 856 .append(PrintingUtils.align(level)); 857 if (i < vars.size() - 1) { 858 result.append("result += \"\\n\";"); 859 } else { 860 result.append("result += \"\";"); 861 } 862 result.append("\n"); 863 } 864 } 865 result.append(PrintingUtils.align(level)) 866 .append("result += \"\\n]\";\n") 867 .append(PrintingUtils.align(level)) 868 .append("return result;\n"); 869 return result.toString(); 870 } 871 872 @Override 873 public String visit(Return node) { 874 return "return " + node.getExpression().accept(this) + ";"; 875 } 876 877 @Override 878 public String visit(Throw node) { 879 return "throw " + node.getThowable().accept(this) + ";"; 880 } 881 882 @Override 883 public String visit(Statement node) { 884 return node.getChild(0).accept(this)+ (node.isSemicolonNeeded() ? ";" : ""); 885 } 886 887 @Override 888 public String visit(StaticConstructorDefinition node) { 889 IRNode body = node.getChild(0); 890 return "static {\n" 891 + (body != null ? body.accept(this): "") 892 + PrintingUtils.align(node.getLevel()) + "}"; 893 } 894 895 @Override 896 public String visit(StaticMemberVariable node) { 897 IRNode klass = node.getKlass(); 898 VariableInfo value = node.get(); 899 if (klass.equals(value.klass)) { 900 return value.name; 901 } else { 902 return value.klass.getName() + "." + value.name; 903 } 904 } 905 906 @Override 907 public String visit(Switch node) { 908 int level = node.getLevel(); 909 int caseBlockIdx = node.getCaseBlockIndex(); 910 String cases = ""; 911 for (int i = 0; i < caseBlockIdx - 1; ++i) { 912 cases += PrintingUtils.align(level + 1); 913 if (node.getChild(i + 1) != null) { 914 cases += "case " + node.getChild(i + 1).accept(this)+ ":\n"; 915 } else { 916 cases += "default:\n"; 917 } 918 919 cases += node.getChild(i + caseBlockIdx).accept(this)+ "\n"; 920 } 921 return "switch (" + node.getChild(0).accept(this)+ ")\n" 922 + PrintingUtils.align(level) + "{\n" 923 + cases 924 + PrintingUtils.align(level) + "}"; 925 } 926 927 @Override 928 public String visit(TernaryOperator node) { 929 IRNode conditionalExp = node.getChild(TernaryOperator.TernaryPart.CONDITION.ordinal()); 930 IRNode leftExp = node.getChild(TernaryOperator.TernaryPart.TRUE.ordinal()); 931 IRNode rightExp = node.getChild(TernaryOperator.TernaryPart.FALSE.ordinal()); 932 if (Objects.isNull(conditionalExp) || Objects.isNull(leftExp) || Objects.isNull(rightExp)) { 933 return "null"; 934 } 935 return expressionToJavaCode(node, conditionalExp, Operator.Order.RIGHT) + " ? " 936 + expressionToJavaCode(node, leftExp, Operator.Order.RIGHT) + " : " 937 + expressionToJavaCode(node, rightExp, Operator.Order.RIGHT); 938 } 939 940 @Override 941 public String visit(Type node) { 942 return node.getName(); 943 } 944 945 @Override 946 public String visit(TypeArray node) { 947 String r = node.getType().accept(this); 948 for (int i = 0; i < node.getDimensions(); i++) { 949 r += "[]"; 950 } 951 return r; 952 } 953 954 @Override 955 public String visit(UnaryOperator node) { 956 IRNode exp = node.getChild(0); 957 if (node.isPrefix()) { 958 return node.getOperatorText() + (exp instanceof Operator ? " " : "") 959 + expressionToJavaCode(node, exp, Operator.Order.LEFT); 960 } else { 961 return expressionToJavaCode(node, exp, Operator.Order.RIGHT) 962 + (exp instanceof Operator ? " " : "") + node.getOperatorText(); 963 } 964 } 965 966 @Override 967 public String visit(VariableDeclaration node) { 968 VariableInfo vi = node.getVariableInfo(); 969 return attributes(vi) + vi.type.accept(this)+ " " + vi.name; 970 } 971 972 @Override 973 public String visit(VariableDeclarationBlock node) { 974 StringBuilder code = new StringBuilder(); 975 for (IRNode i : node.getChildren()) { 976 code.append(PrintingUtils.align(node.getLevel())) 977 .append(i.accept(this)) 978 .append(addComplexityInfo(i)) 979 .append("\n"); 980 } 981 return code.toString(); 982 } 983 984 @Override 985 public String visit(While node) { 986 IRNode header = node.getChild(While.WhilePart.HEADER.ordinal()); 987 IRNode body1 = node.getChild(While.WhilePart.BODY1.ordinal()); 988 IRNode body2 = node.getChild(While.WhilePart.BODY2.ordinal()); 989 IRNode body3 = node.getChild(While.WhilePart.BODY3.ordinal()); 990 int level = node.getLevel(); 991 Loop loop = node.getLoop(); 992 return loop.initialization.accept(this)+ "\n" 993 + header.accept(this) 994 + PrintingUtils.align(level) + "while (" + loop.condition.accept(this)+ ")\n" 995 + PrintingUtils.align(level) + "{\n" 996 + body1.accept(this) 997 + PrintingUtils.align(level + 1) + loop.manipulator.accept(this)+ ";\n" 998 + body2.accept(this) 999 + body3.accept(this) 1000 + PrintingUtils.align(level) + "}"; 1001 } 1002 1003 @Override 1004 public String visit(CatchBlock node) { 1005 StringBuilder result = new StringBuilder(); 1006 int level = node.getLevel(); 1007 result.append(PrintingUtils.align(level)).append("catch("); 1008 result.append(node.throwables.get(0).accept(this)); 1009 for (int i = 1; i < node.throwables.size(); i++) { 1010 result.append(" | ").append(node.throwables.get(i).accept(this)); 1011 } 1012 result.append(" ex) {\n"); 1013 result.append(node.getChild(0).accept(this)); 1014 result.append(PrintingUtils.align(level)).append("}\n"); 1015 return result.toString(); 1016 } 1017 1018 @Override 1019 public String visit(TryCatchBlock node) { 1020 StringBuilder result = new StringBuilder(); 1021 List<? extends IRNode> childs = node.getChildren(); 1022 IRNode body = childs.get(0); 1023 IRNode finallyBody = childs.get(1); 1024 int level = node.getLevel(); 1025 result.append("try {\n") 1026 .append(body.accept(this)).append("\n") 1027 .append(PrintingUtils.align(level)).append("}\n"); 1028 for (int i = 2; i < childs.size(); i++) { 1029 result.append(childs.get(i).accept(this)); 1030 } 1031 if (finallyBody != null) { 1032 result.append(PrintingUtils.align(level)).append("finally {\n") 1033 .append(finallyBody.accept(this)).append("\n") 1034 .append(PrintingUtils.align(level)).append("}\n"); 1035 } 1036 return result.toString(); 1037 } 1038 }