blob: 206f57524155a2e440b624a05a74fa14be8a9f8b [file] [log] [blame]
/*
* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.test.lib.jittester.visitors;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors;
import jdk.test.lib.jittester.BinaryOperator;
import jdk.test.lib.jittester.Block;
import jdk.test.lib.jittester.Break;
import jdk.test.lib.jittester.CastOperator;
import jdk.test.lib.jittester.CatchBlock;
import jdk.test.lib.jittester.Continue;
import jdk.test.lib.jittester.Declaration;
import jdk.test.lib.jittester.IRNode;
import jdk.test.lib.jittester.If;
import jdk.test.lib.jittester.Initialization;
import jdk.test.lib.jittester.Literal;
import jdk.test.lib.jittester.LocalVariable;
import jdk.test.lib.jittester.NonStaticMemberVariable;
import jdk.test.lib.jittester.Nothing;
import jdk.test.lib.jittester.Operator;
import jdk.test.lib.jittester.OperatorKind;
import jdk.test.lib.jittester.PrintVariables;
import jdk.test.lib.jittester.ProductionParams;
import jdk.test.lib.jittester.Statement;
import jdk.test.lib.jittester.StaticMemberVariable;
import jdk.test.lib.jittester.Switch;
import jdk.test.lib.jittester.Symbol;
import jdk.test.lib.jittester.TernaryOperator;
import jdk.test.lib.jittester.Throw;
import jdk.test.lib.jittester.TryCatchBlock;
import jdk.test.lib.jittester.Type;
import jdk.test.lib.jittester.TypeList;
import jdk.test.lib.jittester.UnaryOperator;
import jdk.test.lib.jittester.VariableBase;
import jdk.test.lib.jittester.VariableDeclaration;
import jdk.test.lib.jittester.VariableDeclarationBlock;
import jdk.test.lib.jittester.VariableInfo;
import jdk.test.lib.jittester.arrays.ArrayCreation;
import jdk.test.lib.jittester.arrays.ArrayElement;
import jdk.test.lib.jittester.arrays.ArrayExtraction;
import jdk.test.lib.jittester.classes.ClassDefinitionBlock;
import jdk.test.lib.jittester.classes.Interface;
import jdk.test.lib.jittester.classes.Klass;
import jdk.test.lib.jittester.classes.MainKlass;
import jdk.test.lib.jittester.functions.ArgumentDeclaration;
import jdk.test.lib.jittester.functions.ConstructorDefinition;
import jdk.test.lib.jittester.functions.ConstructorDefinitionBlock;
import jdk.test.lib.jittester.functions.Function;
import jdk.test.lib.jittester.functions.FunctionDeclaration;
import jdk.test.lib.jittester.functions.FunctionDeclarationBlock;
import jdk.test.lib.jittester.functions.FunctionDefinition;
import jdk.test.lib.jittester.functions.FunctionDefinitionBlock;
import jdk.test.lib.jittester.functions.FunctionInfo;
import jdk.test.lib.jittester.functions.FunctionRedefinition;
import jdk.test.lib.jittester.functions.FunctionRedefinitionBlock;
import jdk.test.lib.jittester.functions.Return;
import jdk.test.lib.jittester.functions.StaticConstructorDefinition;
import jdk.test.lib.jittester.loops.CounterInitializer;
import jdk.test.lib.jittester.loops.CounterManipulator;
import jdk.test.lib.jittester.loops.DoWhile;
import jdk.test.lib.jittester.loops.For;
import jdk.test.lib.jittester.loops.Loop;
import jdk.test.lib.jittester.loops.LoopingCondition;
import jdk.test.lib.jittester.loops.While;
import jdk.test.lib.jittester.types.TypeArray;
import jdk.test.lib.jittester.types.TypeKlass;
import jdk.test.lib.jittester.utils.FixedTrees;
import jdk.test.lib.jittester.utils.PrintingUtils;
public class JavaCodeVisitor implements Visitor<String> {
public static String funcAttributes(FunctionInfo fi) {
String attrs = attributes(fi);
if (fi.isSynchronized()) {
attrs += "synchronized ";
}
return attrs;
}
public static String attributes(Symbol s) {
String attrs = "";
if (s.isPrivate()) {
attrs += "private ";
}
if (s.isProtected()) {
attrs += "protected ";
}
if (s.isPublic()) {
attrs += "public ";
}
if (s.isFinal()) {
attrs += "final ";
}
if (s.isStatic()) {
attrs += "static ";
}
return attrs;
}
private String operatorToJaveCode(OperatorKind operationKind) {
switch (operationKind) {
case COMPOUND_ADD:
return "+=";
case COMPOUND_SUB:
return "-=";
case COMPOUND_MUL:
return "*=";
case COMPOUND_DIV:
return "/=";
case COMPOUND_MOD:
return "%=";
case COMPOUND_AND:
return "&=";
case COMPOUND_OR:
return "|=";
case COMPOUND_XOR:
return "^=";
case COMPOUND_SHR:
return ">>=";
case COMPOUND_SHL:
return "<<=";
case COMPOUND_SAR:
return ">>>=";
case ASSIGN:
return "=";
case OR:
return "||";
case BIT_OR:
return "|";
case BIT_XOR:
return "^";
case AND:
return "&&";
case BIT_AND:
return "&";
case EQ:
return "==";
case NE:
return "!=";
case GT:
return ">";
case LT:
return "<";
case GE:
return ">=";
case LE:
return "<=";
case SHR:
return ">>";
case SHL:
return "<<";
case SAR:
return ">>>";
case ADD:
case STRADD:
return "+";
case SUB:
return "-";
case MUL:
return "*";
case DIV:
return "/";
case MOD:
return "%";
case NOT:
return "!";
case BIT_NOT:
return "~";
case UNARY_PLUS:
return "+";
case UNARY_MINUS:
return "-";
case PRE_DEC:
case POST_DEC:
return "--";
case PRE_INC:
case POST_INC:
return "++";
default:
throw new IllegalArgumentException("Unkown operator kind " + operationKind);
}
}
private String expressionToJavaCode(Operator t, IRNode p, Operator.Order o) {
String result;
try {
if ((o == Operator.Order.LEFT && ((Operator) p).getPriority() < t.getPriority())
|| (o == Operator.Order.RIGHT && ((Operator) p).getPriority() <= t.getPriority())) {
result = "(" + p.accept(this)+ ")";
} else {
result = p.accept(this);
}
} catch (Exception e) {
result = p.accept(this);
}
return result;
}
@Override
public String visit(ArgumentDeclaration node) {
VariableInfo vi = node.variableInfo;
return attributes(vi) + vi.type.accept(this) + " " + vi.name;
}
@Override
public String visit(ArrayCreation node) {
Type arrayElemType = node.getArrayType().type;
String type = arrayElemType.accept(this);
String name = node.getVariable().getName();
StringBuilder code = new StringBuilder()
.append(node.getVariable().accept(this))
.append(";\n")
.append(PrintingUtils.align(node.getParent().getLevel()))
.append(name)
.append(" = new ")
.append(type);
code.append(node.getChildren().stream()
.map(p -> p.accept(this))
.collect(Collectors.joining("][", "[", "]")));
code.append(";\n");
if (!TypeList.isBuiltIn(arrayElemType)) {
code.append(PrintingUtils.align(node.getParent().getLevel()))
.append("java.util.Arrays.fill(")
.append(name)
.append(", new ")
.append(type)
.append("());\n");
}
return code.toString();
}
@Override
public String visit(ArrayElement node) {
IRNode array = node.getChild(0);
StringBuilder code = new StringBuilder();
if (array instanceof VariableBase || array instanceof Function) {
code.append(array.accept(this));
} else {
code.append("(")
.append(array.accept(this))
.append(")");
}
code.append(node.getChildren().stream()
.skip(1)
.map(c -> c.accept(this))
.collect(Collectors.joining("][", "[", "]")));
return code.toString();
}
@Override
public String visit(ArrayExtraction node) {
IRNode array = node.getChild(0);
StringBuilder code = new StringBuilder();
if (array instanceof VariableBase || array instanceof Function) {
code.append(array.accept(this));
} else {
code.append("(")
.append(array.accept(this))
.append(")");
}
code.append(node.getChildren().stream()
.skip(1)
.map(c -> c.accept(this))
.collect(Collectors.joining("][", "[", "]")));
return code.toString();
}
@Override
public String visit(BinaryOperator node) {
IRNode left = node.getChild(Operator.Order.LEFT.ordinal());
IRNode right = node.getChild(Operator.Order.RIGHT.ordinal());
if (left == null || right == null) {
return "null";
}
return expressionToJavaCode(node, left, Operator.Order.LEFT)
+ " " + operatorToJaveCode(node.getOperationKind()) + " "
+ expressionToJavaCode(node, right, Operator.Order.RIGHT);
}
@Override
public String visit(Block node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
String s = i.accept(this);
if (!s.isEmpty()) {
int level = node.getLevel();
if (i instanceof Block) {
code.append(PrintingUtils.align(level + 1))
.append("{\n")
.append(s)
.append(PrintingUtils.align(level + 1))
.append("}");
} else {
code.append(PrintingUtils.align(level + 1))
.append(s);
}
code.append(addComplexityInfo(i));
code.append("\n");
}
}
return code.toString();
}
private String addComplexityInfo(IRNode node) {
if (ProductionParams.printComplexity.value()) {
return " /* " + node.complexity() + " */";
}
return "";
}
@Override
public String visit(Break node) {
return "break;";
}
@Override
public String visit(CastOperator node) {
return "(" + node.getResultType().accept(this)+ ")"
+ expressionToJavaCode(node, node.getChild(0), Operator.Order.LEFT);
}
@Override
public String visit(ClassDefinitionBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append("\n")
.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append("\n");
}
return code.toString();
}
@Override
public String visit(ConstructorDefinition node) {
String args = node.getChildren().stream()
.skip(1)
.map(c -> c.accept(this))
.collect(Collectors.joining(", "));
IRNode body = node.getChild(0);
StringBuilder code = new StringBuilder();
code.append(funcAttributes(node.getFunctionInfo()))
.append(node.getFunctionInfo().name)
.append("(")
.append(args)
.append(")\n")
.append(PrintingUtils.align(node.getLevel() + 1))
.append("{\n")
.append(body != null ? body.accept(this) : "")
.append(PrintingUtils.align(node.getLevel() + 1))
.append("}");
return code.toString();
}
@Override
public String visit(ConstructorDefinitionBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append("\n")
.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append(addComplexityInfo(i))
.append("\n");
}
return code.toString();
}
@Override
public String visit(Continue node) {
return "continue;";
}
@Override
public String visit(CounterInitializer node) {
VariableInfo vi = node.getVariableInfo();
return vi.type.accept(this) + " " + vi.name + " = " + node.getChild(0).accept(this)+ ";";
}
@Override
public String visit(CounterManipulator node) {
return node.getChild(0).accept(this);
}
@Override
public String visit(Declaration node) {
return node.getChild(0).accept(this)+ ";";
}
@Override
public String visit(DoWhile node) {
IRNode header = node.getChild(DoWhile.DoWhilePart.HEADER.ordinal());
IRNode body1 = node.getChild(DoWhile.DoWhilePart.BODY1.ordinal());
IRNode body2 = node.getChild(DoWhile.DoWhilePart.BODY2.ordinal());
StringBuilder code = new StringBuilder();
Loop loop = node.getLoop();
int level = node.getLevel();
code.append(loop.initialization.accept(this))
.append("\n")
.append(header.accept(this))
.append(PrintingUtils.align(level))
.append("do\n")
.append(PrintingUtils.align(level))
.append("{\n")
.append(body1.accept(this))
.append(PrintingUtils.align(level + 1))
.append(loop.manipulator.accept(this))
.append(";\n")
.append(body2.accept(this))
.append(PrintingUtils.align(level))
.append("} while (")
.append(loop.condition.accept(this))
.append(");");
return code.toString();
}
@Override
public String visit(For node) {
IRNode header = node.getChild(For.ForPart.HEADER.ordinal());
IRNode statement1 = node.getChild(For.ForPart.STATEMENT1.ordinal());
IRNode statement2 = node.getChild(For.ForPart.STATEMENT2.ordinal());
IRNode body1 = node.getChild(For.ForPart.BODY1.ordinal());
IRNode body2 = node.getChild(For.ForPart.BODY2.ordinal());
IRNode body3 = node.getChild(For.ForPart.BODY3.ordinal());
Loop loop = node.getLoop();
StringBuilder code = new StringBuilder();
int level = node.getLevel();
code.append(loop.initialization.accept(this))
.append("\n")
.append(header.accept(this))
.append(PrintingUtils.align(level))
.append("for (")
.append(statement1.accept(this))
.append("; ")
.append(loop.condition.accept(this))
.append("; ")
.append(statement2.accept(this))
.append(")\n")
.append(PrintingUtils.align(level))
.append("{\n")
.append(body1.accept(this))
.append(PrintingUtils.align(level + 1))
.append(loop.manipulator.accept(this))
.append(";\n")
.append(body2.accept(this))
.append(body3.accept(this))
.append(PrintingUtils.align(level))
.append("}");
return code.toString();
}
@Override
public String visit(Function node) {
FunctionInfo value = node.getValue();
String nameAndArgs = value.name + "("
+ node.getChildren().stream()
.skip(value.isStatic() || value.isConstructor() ? 0 : 1)
.map(c -> c.accept(this))
.collect(Collectors.joining(", "))
+ ")";
String prefix = "";
if (value.isStatic()) {
if(!node.getOwner().equals(value.owner)) {
prefix = value.owner.getName() + ".";
}
} else if (value.isConstructor()) {
prefix = "new ";
} else {
IRNode object = node.getChild(0);
String objectString = object.accept(this);
if (!objectString.equals("this")) {
if (object instanceof VariableBase || object instanceof Function
|| object instanceof Literal) {
prefix = objectString + ".";
} else {
prefix = "(" + objectString + ")" + ".";
}
}
}
return prefix + nameAndArgs;
}
@Override
public String visit(FunctionDeclaration node) {
String args = node.getChildren().stream()
.map(c -> c.accept(this))
.collect(Collectors.joining(", "));
FunctionInfo functionInfo = node.getFunctionInfo();
return (functionInfo.owner.isInterface() ? "" : "abstract ")
+ funcAttributes(functionInfo) + functionInfo.type.accept(this)+ " "
+ functionInfo.name + "(" + args + ");";
}
@Override
public String visit(FunctionDeclarationBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append(addComplexityInfo(i))
.append("\n");
}
return code.toString();
}
@Override
public String visit(FunctionDefinition node) {
String args = node.getChildren().stream()
.skip(2)
.map(c -> c.accept(this))
.collect(Collectors.joining(", "));
IRNode body = node.getChild(0);
IRNode ret = node.getChild(1);
FunctionInfo functionInfo = node.getFunctionInfo();
return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n"
+ PrintingUtils.align(node.getLevel() + 1) + "{\n"
+ body.accept(this)
+ (ret != null ? PrintingUtils.align(node.getLevel() + 2) + ret.accept(this) + "\n" : "")
+ PrintingUtils.align(node.getLevel() + 1) + "}\n";
}
@Override
public String visit(FunctionDefinitionBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append("\n")
.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append(addComplexityInfo(i))
.append("\n");
}
return code.toString();
}
@Override
public String visit(FunctionRedefinition node) {
String args = node.getChildren().stream()
.skip(2)
.map(c -> c.accept(this))
.collect(Collectors.joining(", "));
IRNode body = node.getChild(0);
IRNode ret = node.getChild(1);
int level = node.getLevel();
FunctionInfo functionInfo = node.getFunctionInfo();
return funcAttributes(functionInfo) + functionInfo.type.accept(this) + " " + functionInfo.name + "(" + args + ")" + "\n"
+ PrintingUtils.align(level + 1) + "{\n"
+ body.accept(this)
+ (ret != null ? PrintingUtils.align(level + 2) + ret.accept(this) + "\n" : "")
+ PrintingUtils.align(level + 1) + "}";
}
@Override
public String visit(FunctionRedefinitionBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append("\n")
.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append(addComplexityInfo(i))
.append("\n");
}
return code.toString();
}
@Override
public String visit(If node) {
int level = node.getLevel();
String thenBlockString = PrintingUtils.align(level) + "{\n"
+ node.getChild(If.IfPart.THEN.ordinal()).accept(this)
+ PrintingUtils.align(level) + "}";
String elseBlockString = null;
if (node.getChild(If.IfPart.ELSE.ordinal()) != null) {
elseBlockString = PrintingUtils.align(level) + "{\n"
+ node.getChild(If.IfPart.ELSE.ordinal()).accept(this)
+ PrintingUtils.align(level) + "}";
}
return "if (" + node.getChild(If.IfPart.CONDITION.ordinal()).accept(this)+ ")\n"
+ thenBlockString + (elseBlockString != null ? "\n"
+ PrintingUtils.align(level) + "else\n" + elseBlockString : "");
}
@Override
public String visit(Initialization node) {
VariableInfo vi = node.getVariableInfo();
return attributes(vi) + vi.type.accept(this)+ " " + vi.name + " = "
+ node.getChild(0).accept(this);
}
@Override
public String visit(Interface node) {
return "interface " + node.getName() + (node.getParentKlass() != null ? " extends "
+ node.getParentKlass().getName() : "") + " {\n"
+ (node.getChildren().size() > 0 ? node.getChild(0).accept(this) : "")
+ "}\n";
}
@Override
public String visit(Klass node) {
TypeKlass thisKlass = node.getThisKlass();
String r = (ProductionParams.enableStrictFP.value() ? "strictfp " : "")
+ (thisKlass.isFinal() ? "final " : "")
+ (thisKlass.isAbstract() ? "abstract " : "")
+ "class " + node.getName()
+ (node.getParentKlass() != null && !node.getParentKlass().equals(TypeList.OBJECT)
? " extends " + node.getParentKlass().getName() : "");
List<TypeKlass> interfaces = node.getInterfaces();
r += interfaces.stream()
.map(Type::getName)
.collect(Collectors.joining(", ", (interfaces.isEmpty() ? "" : " implements "), ""));
IRNode dataMembers = node.getChild(Klass.KlassPart.DATA_MEMBERS.ordinal());
IRNode constructors = node.getChild(Klass.KlassPart.CONSTRUCTORS.ordinal());
IRNode redefinedFunctions = node.getChild(Klass.KlassPart.REDEFINED_FUNCTIONS.ordinal());
IRNode overridenFunctions = node.getChild(Klass.KlassPart.OVERRIDEN_FUNCTIONS.ordinal());
IRNode memberFunctions = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS.ordinal());
IRNode memberFunctionDecls = node.getChild(Klass.KlassPart.MEMBER_FUNCTIONS_DECLARATIONS.ordinal());
IRNode printVariables = node.getChild(Klass.KlassPart.PRINT_VARIABLES.ordinal());
r += " {\n"
+ (dataMembers != null ? (dataMembers.accept(this)+ "\n") : "")
+ (constructors != null ? (constructors.accept(this)+ "\n") : "")
+ (redefinedFunctions != null ? (redefinedFunctions.accept(this)+ "\n") : "")
+ (overridenFunctions != null ? (overridenFunctions.accept(this)+ "\n") : "")
+ (memberFunctionDecls != null ? (memberFunctionDecls.accept(this)+ "\n") : "")
+ (memberFunctions != null ? (memberFunctions.accept(this)+ "\n") : "")
+ printVariables.accept(this)
+ "}\n";
return r;
}
@Override
public String visit(Literal node) {
Type resultType = node.getResultType();
Object value = node.getValue();
if (resultType.equals(TypeList.LONG)) {
return value.toString() + "L";
}
if (resultType.equals(TypeList.FLOAT)) {
return String.format((Locale) null,
"%EF",
Double.parseDouble(value.toString()));
}
if (resultType.equals(TypeList.DOUBLE)) {
return String.format((Locale) null,
"%E",
Double.parseDouble(value.toString()));
}
if (resultType.equals(TypeList.CHAR)) {
if ((Character) value == '\\') {
return "\'" + "\\\\" + "\'";
} else {
return "\'" + value.toString() + "\'";
}
}
if (resultType.equals(TypeList.SHORT)) {
return "(short) " + value.toString();
}
if (resultType.equals(TypeList.BYTE)) {
return "(byte) " + value.toString();
}
if (resultType.equals(TypeList.STRING)) {
// TOOD handle other non-printable
return "\"" + value.toString().replace("\n", "\\n") + "\"";
}
return value.toString();
}
@Override
public String visit(LocalVariable node) {
return node.getVariableInfo().name;
}
@Override
public String visit(LoopingCondition node) {
return node.getCondition().accept(this);
}
@Override
public String visit(MainKlass node) {
String name = node.getName();
IRNode dataMembers = node.getChild(MainKlass.MainKlassPart.DATA_MEMBERS.ordinal());
IRNode memberFunctions = node.getChild(MainKlass.MainKlassPart.MEMBER_FUNCTIONS.ordinal());
IRNode testFunction = node.getChild(MainKlass.MainKlassPart.TEST_FUNCTION.ordinal());
IRNode printVariables = node.getChild(MainKlass.MainKlassPart.PRINT_VARIABLES.ordinal());
return (ProductionParams.enableStrictFP.value() ? "strictfp " : "")
+ "public class " + name + " {\n"
+ dataMembers.accept(this)+ "\n"
+ (memberFunctions != null ? memberFunctions.accept(this): "") + "\n"
+ " private void test()\n"
+ " {\n"
+ testFunction.accept(this)
+ " }" + addComplexityInfo(testFunction) + "\n"
+ printVariables.accept(this)
+ "}\n\n";
}
@Override
public String visit(NonStaticMemberVariable node) {
IRNode object = node.getChild(0);
String objectString = object.accept(this);
VariableInfo value = node.getVariableInfo();
if (objectString.equals("this")) {
return value.name;
} else {
if (object instanceof VariableBase || object instanceof Function || object instanceof Literal) {
return objectString + "." + value.name;
} else {
return "(" + objectString + ")" + "." + value.name;
}
}
}
@Override
public String visit(Nothing node) {
return "";
}
@Override
public String visit(PrintVariables node) {
return FixedTrees.printVariablesAsFunction(node).accept(this);
}
@Override
public String visit(Return node) {
return "return " + node.getExpression().accept(this) + ";";
}
@Override
public String visit(Throw node) {
return "throw " + node.getThowable().accept(this) + ";";
}
@Override
public String visit(Statement node) {
return node.getChild(0).accept(this)+ (node.isSemicolonNeeded() ? ";" : "");
}
@Override
public String visit(StaticConstructorDefinition node) {
IRNode body = node.getChild(0);
return "static {\n"
+ (body != null ? body.accept(this): "")
+ PrintingUtils.align(node.getLevel()) + "}";
}
@Override
public String visit(StaticMemberVariable node) {
IRNode owner = node.getOwner();
VariableInfo info = node.getVariableInfo();
if (owner.equals(info.owner)) {
return info.name;
} else {
return info.owner.getName() + "." + info.name;
}
}
@Override
public String visit(Switch node) {
int level = node.getLevel();
int caseBlockIdx = node.getCaseBlockIndex();
String cases = "";
for (int i = 0; i < caseBlockIdx - 1; ++i) {
cases += PrintingUtils.align(level + 1);
if (node.getChild(i + 1) instanceof Nothing) {
cases += "default:\n";
} else {
cases += "case " + node.getChild(i + 1).accept(this)+ ":\n";
}
cases += node.getChild(i + caseBlockIdx).accept(this)+ "\n";
}
return "switch (" + node.getChild(0).accept(this)+ ")\n"
+ PrintingUtils.align(level) + "{\n"
+ cases
+ PrintingUtils.align(level) + "}";
}
@Override
public String visit(TernaryOperator node) {
IRNode conditionalExp = node.getChild(TernaryOperator.TernaryPart.CONDITION.ordinal());
IRNode leftExp = node.getChild(TernaryOperator.TernaryPart.TRUE.ordinal());
IRNode rightExp = node.getChild(TernaryOperator.TernaryPart.FALSE.ordinal());
if (Objects.isNull(conditionalExp) || Objects.isNull(leftExp) || Objects.isNull(rightExp)) {
return "null";
}
return expressionToJavaCode(node, conditionalExp, Operator.Order.RIGHT) + " ? "
+ expressionToJavaCode(node, leftExp, Operator.Order.RIGHT) + " : "
+ expressionToJavaCode(node, rightExp, Operator.Order.RIGHT);
}
@Override
public String visit(Type node) {
return node.getName();
}
@Override
public String visit(TypeArray node) {
String r = node.getType().accept(this);
for (int i = 0; i < node.getDimensions(); i++) {
r += "[]";
}
return r;
}
@Override
public String visit(UnaryOperator node) {
IRNode exp = node.getChild(0);
if (node.isPrefix()) {
return operatorToJaveCode(node.getOperationKind())
+ (exp instanceof Operator ? " " : "")
+ expressionToJavaCode(node, exp, Operator.Order.LEFT);
} else {
return expressionToJavaCode(node, exp, Operator.Order.RIGHT)
+ (exp instanceof Operator ? " " : "")
+ operatorToJaveCode(node.getOperationKind());
}
}
@Override
public String visit(VariableDeclaration node) {
VariableInfo vi = node.getVariableInfo();
return attributes(vi) + vi.type.accept(this)+ " " + vi.name;
}
@Override
public String visit(VariableDeclarationBlock node) {
StringBuilder code = new StringBuilder();
for (IRNode i : node.getChildren()) {
code.append(PrintingUtils.align(node.getLevel()))
.append(i.accept(this))
.append(addComplexityInfo(i))
.append("\n");
}
return code.toString();
}
@Override
public String visit(While node) {
IRNode header = node.getChild(While.WhilePart.HEADER.ordinal());
IRNode body1 = node.getChild(While.WhilePart.BODY1.ordinal());
IRNode body2 = node.getChild(While.WhilePart.BODY2.ordinal());
IRNode body3 = node.getChild(While.WhilePart.BODY3.ordinal());
int level = node.getLevel();
Loop loop = node.getLoop();
return loop.initialization.accept(this)+ "\n"
+ header.accept(this)
+ PrintingUtils.align(level) + "while (" + loop.condition.accept(this)+ ")\n"
+ PrintingUtils.align(level) + "{\n"
+ body1.accept(this)
+ PrintingUtils.align(level + 1) + loop.manipulator.accept(this)+ ";\n"
+ body2.accept(this)
+ body3.accept(this)
+ PrintingUtils.align(level) + "}";
}
@Override
public String visit(CatchBlock node) {
StringBuilder result = new StringBuilder();
int level = node.getLevel();
result.append(PrintingUtils.align(level)).append("catch(");
result.append(node.throwables.get(0).accept(this));
for (int i = 1; i < node.throwables.size(); i++) {
result.append(" | ").append(node.throwables.get(i).accept(this));
}
result.append(" ex) {\n");
result.append(node.getChild(0).accept(this));
result.append(PrintingUtils.align(level)).append("}\n");
return result.toString();
}
@Override
public String visit(TryCatchBlock node) {
StringBuilder result = new StringBuilder();
List<? extends IRNode> childs = node.getChildren();
IRNode body = childs.get(0);
IRNode finallyBody = childs.get(1);
int level = node.getLevel();
result.append("try {\n")
.append(body.accept(this)).append("\n")
.append(PrintingUtils.align(level))
.append("}\n");
for (int i = 2; i < childs.size(); i++) {
result.append(childs.get(i).accept(this));
}
if (finallyBody != null) {
String finallyContent = finallyBody.accept(this);
if (!finallyContent.isEmpty()) {
result.append(PrintingUtils.align(level)).append("finally {\n")
.append(finallyContent).append("\n")
.append(PrintingUtils.align(level)).append("}\n");
}
}
return result.toString();
}
}