package generators; import java.util.ArrayList; import java.util.List; import code.ast.CompilationUnit; import code.ast.FieldDeclaration; import code.ast.ImportDeclaration; import code.ast.MethodDeclaration; import code.ast.TypeDeclaration; import code.ast.VariableDeclaration; import models.algebra.Expression; import models.algebra.Parameter; import models.algebra.Term; import models.algebra.Type; import models.algebra.Variable; import models.dataConstraintModel.DataConstraintModel; public class JavaSpecific implements ILanguageSpecific { public static final Type typeVoid = new Type("Void", "void"); public static final String self = "this"; @Override public CompilationUnit newCompilationUnit(TypeDeclaration component) { CompilationUnit cu = new CompilationUnit(component); cu.addImport(new ImportDeclaration("java.util.*")); return cu; } @Override public TypeDeclaration newTypeDeclaration(String typeName) { return new TypeDeclaration(typeName); } @Override public VariableDeclaration newVariableDeclaration(Type type, String varName) { return new VariableDeclaration(type, varName); } @Override public MethodDeclaration newMethodDeclaration(String methodName, Type returnType) { if (returnType == null) { returnType = typeVoid; } return new MethodDeclaration(methodName, returnType); } @Override public MethodDeclaration newMethodDeclaration(String methodName, boolean isConstructor, Type returnType, List<VariableDeclaration> parameters) { if (returnType == null) { returnType = typeVoid; } return new MethodDeclaration(methodName, isConstructor, returnType, parameters); } @Override public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName) { return new FieldDeclaration(fieldType, fieldName); } @Override public FieldDeclaration newFieldDeclaration(Type fieldType, String fieldName, String fieldInitializer) { return new FieldDeclaration(fieldType, fieldName, fieldInitializer); } @Override public Type newListType(String compTypeName) { return new Type("List", "ArrayList<>", "List<" + compTypeName + ">", DataConstraintModel.typeList); } @Override public Type newMapType(Type keyType, String valueTypeName) { return new Type("Map", "HashMap<>", "Map<" + keyType.getImplementationTypeName() + ", " + valueTypeName + ">", DataConstraintModel.typeMap); } @Override public Type newTupleType(List<Type> componentTypes) { String implTypeName = "AbstractMap.SimpleEntry<>"; String interfaceTypeName = "Map.Entry<$x>"; if (componentTypes.size() >= 2) { implTypeName = implTypeName.replace("$x", getImplementationTypeName(componentTypes.get(0)) + "$x"); interfaceTypeName = interfaceTypeName.replace("$x", getInterfaceTypeName(componentTypes.get(0)) + "$x"); for (Type argType : componentTypes.subList(1, componentTypes.size() - 1)) { implTypeName = implTypeName.replace("$x", ", AbstractMap.SimpleEntry<" + getImplementationTypeName(argType) + "$x>"); interfaceTypeName = interfaceTypeName.replace("$x", ", Map.Entry<" + getInterfaceTypeName(argType) + "$x>"); } implTypeName = implTypeName.replace("$x", ", " + getImplementationTypeName(componentTypes.get(componentTypes.size() - 1))); interfaceTypeName = interfaceTypeName.replace("$x", ", " + getInterfaceTypeName(componentTypes.get(componentTypes.size() - 1))); } Type newTupleType = new Type("Tuple", implTypeName, interfaceTypeName, DataConstraintModel.typeTuple); return newTupleType; } @Override public String getVariableDeclaration(String typeName, String varName) { return typeName + " " + varName; } @Override public String getFieldInitializer(Type type, Expression initialValue) { String initializer = null; if (initialValue != null) { initializer = initialValue.toImplementation(new String[] {""}); } else if (type != null) { if (DataConstraintModel.typeList.isAncestorOf(type)) { initializer = "new " + type.getImplementationTypeName() + "()"; } else if (DataConstraintModel.typeMap.isAncestorOf(type)) { initializer = "new " + type.getImplementationTypeName() + "()"; } } return initializer; } @Override public boolean declareField() { return true; } @Override public String getFieldAccessor(String fieldName) { return self + "." + fieldName; } @Override public String getMethodInvocation(String methodName) { return self + "." + methodName + "()"; } @Override public String getMethodInvocation(String methodName, List<String> parameters) { if (parameters == null) return getMethodInvocation( methodName); String invocation = self + "." + methodName + "("; if (parameters.size() > 0) { for (int i = 0; i < parameters.size(); i++) { if (i < parameters.size() - 1) { invocation += parameters.get(i) + ", "; } else { invocation += parameters.get(i); } } } invocation += ")"; return invocation; } @Override public String getMethodInvocation(String receiverName, String methodName) { return receiverName + "." + methodName + "()"; } @Override public String getMethodInvocation(String receiverName, String methodName, List<String> parameters) { if (parameters == null) return getMethodInvocation(receiverName, methodName); String invocation = receiverName + "." + methodName + "("; if (parameters.size() > 0) { for (int i = 0; i < parameters.size(); i++) { if (i < parameters.size() - 1) { invocation += parameters.get(i) + ", "; } else { invocation += parameters.get(i); } } } invocation += ")"; return invocation; } @Override public String getConstructorInvocation(String componentName, List<String> parameters) { String invocation = "new " + componentName + "("; if (parameters.size() > 0) { for (int i = 0; i < parameters.size(); i++) { if (i < parameters.size() - 1) { invocation += parameters.get(i) + ", "; } else { invocation += parameters.get(i); } } } invocation += ")"; return invocation; } @Override public String getReturnStatement(String returnValue) { return "return " + returnValue; } @Override public String getIfStatement(Term condition, String block) { return "if (" + condition.toImplementation(new String[] {})+ ") {\n" + "\t" + block.replace("\n", "\n\t") + "\n}"; } @Override public String toComponentName(String name) { return name.substring(0, 1).toUpperCase() + name.substring(1); } @Override public String toVariableName(String name) { return name.substring(0, 1).toLowerCase() + name.substring(1); } @Override public String getMainComponentName() { return "Main"; } @Override public String getAssignment() { return " = "; } @Override public String getStatementDelimiter() { return ";"; } @Override public String getStringDelimiter() { return "\""; } @Override public String getTupleGet(String tupleExp, int idx, int length) { Expression t = new Variable(tupleExp, DataConstraintModel.typeTuple); for (int i = 0; i < idx; i++) { Term next = new Term(DataConstraintModel.snd); next.addChild(t); t = next; } if (idx < length - 1) { Term last = new Term(DataConstraintModel.fst); last.addChild(t); t = last; } return t.toImplementation(new String[]{}); } @Override public String getDecomposedTuple(String tupleExp, VariableDeclaration tupleVar, List<VariableDeclaration> vars) { String statements = ""; statements += getVariableDeclaration(tupleVar.getType().getInterfaceTypeName(), tupleVar.getName()) + getAssignment() + tupleExp + getStatementDelimiter(); for (int i = 0; i < vars.size(); i++) { VariableDeclaration var = vars.get(i); statements += "\n" + getVariableDeclaration(var.getType().getInterfaceTypeName(), var.getName()) + getAssignment() + getTupleGet(tupleVar.getName(), i, vars.size()) + getStatementDelimiter(); } return statements; } @Override public boolean isValueType(Type type) { if (type == DataConstraintModel.typeInt || type == DataConstraintModel.typeLong || type == DataConstraintModel.typeFloat || type == DataConstraintModel.typeDouble || type == DataConstraintModel.typeBoolean) { return true; } return false; } @Override public boolean isVoidType(Type type) { if (type == typeVoid) { return true; } return false; } private String getImplementationTypeName(Type type) { if (type == null) return "Object"; String wrapperType = DataConstraintModel.getWrapperType(type); if (wrapperType != null) return wrapperType; return type.getImplementationTypeName(); } private String getInterfaceTypeName(Type type) { if (type == null) return "Object"; String wrapperType = DataConstraintModel.getWrapperType(type); if (wrapperType != null) return wrapperType; return type.getInterfaceTypeName(); } }