package org.overture.codegen.vdm2java; import java.util.LinkedList; import java.util.List; import org.overture.ast.util.ClonableString; import org.overture.codegen.ir.IRInfo; import org.overture.codegen.ir.SExpIR; import org.overture.codegen.ir.STypeIR; import org.overture.codegen.ir.declarations.ADefaultClassDeclIR; import org.overture.codegen.ir.declarations.AFieldDeclIR; import org.overture.codegen.ir.declarations.AMethodDeclIR; import org.overture.codegen.ir.expressions.AApplyExpIR; import org.overture.codegen.ir.expressions.AEqualsBinaryExpIR; import org.overture.codegen.ir.expressions.AExternalExpIR; import org.overture.codegen.ir.expressions.AIdentifierVarExpIR; import org.overture.codegen.ir.expressions.AInstanceofExpIR; import org.overture.codegen.ir.expressions.ANewExpIR; import org.overture.codegen.ir.expressions.ASuperVarExpIR; import org.overture.codegen.ir.name.ATypeNameIR; import org.overture.codegen.ir.statements.AAssignToExpStmIR; import org.overture.codegen.ir.statements.ABlockStmIR; import org.overture.codegen.ir.statements.AIfStmIR; import org.overture.codegen.ir.statements.AReturnStmIR; import org.overture.codegen.ir.types.ABoolBasicTypeIR; import org.overture.codegen.ir.types.AClassTypeIR; import org.overture.codegen.ir.types.AExternalTypeIR; import org.overture.codegen.ir.types.AMethodTypeIR; import org.overture.codegen.ir.types.AObjectTypeIR; import org.overture.codegen.trans.assistants.TransAssistantIR; public class JavaQuoteValueCreator extends JavaClassCreatorBase { public static final String JAVA_QUOTE_NAME_SUFFIX = "Quote"; private static final String GET_INSTANCE_METHOD = "getInstance"; private static final String HASH_CODE_METHOD = "hashCode"; private static final String INSTANCE_FIELD = "instance"; private static final String HASHCODE_FIELD = "hc"; private static final String EQUALS_METHOD_PARAM = "obj"; private IRInfo info; private TransAssistantIR transAssistant; public JavaQuoteValueCreator(IRInfo info, TransAssistantIR transformationAssistant) { this.info = info; this.transAssistant = transformationAssistant; } public ADefaultClassDeclIR consQuoteValue(String quoteClassName, String quoteName, String userCodePackage) { quoteClassName = quoteClassName + JavaQuoteValueCreator.JAVA_QUOTE_NAME_SUFFIX; ADefaultClassDeclIR decl = new ADefaultClassDeclIR(); decl.setAbstract(false); decl.setAccess(IJavaConstants.PUBLIC); decl.setName(quoteClassName); decl.setStatic(false); // The package where the quotes are put is userCode.quotes String quotePackage = consQuotePackage(userCodePackage); decl.setPackage(quotePackage); decl.getFields().add(consHashcodeField()); decl.getFields().add(consInstanceField(quoteClassName)); decl.getMethods().add(consQuoteCtor(quoteClassName)); decl.getMethods().add(consGetInstanceMethod(quoteClassName)); decl.getMethods().add(consHashcodeMethod()); decl.getMethods().add(consEqualsMethod(quoteClassName)); decl.getMethods().add(consToStringMethod(quoteName)); List<ClonableString> imports = new LinkedList<>(); imports.add(new ClonableString(JavaCodeGen.RUNTIME_IMPORT)); decl.setDependencies(imports); return decl; } public static String consQuotePackage(String userCodePackage) { if (JavaCodeGenUtil.isValidJavaPackage(userCodePackage)) { return userCodePackage + "." + JavaCodeGen.JAVA_QUOTES_PACKAGE; } else { return JavaCodeGen.JAVA_QUOTES_PACKAGE; } } public static String fullyQualifiedQuoteName(String userCodePackage, String vdmValueName) { return consQuotePackage(userCodePackage) + "." + vdmValueName + JAVA_QUOTE_NAME_SUFFIX; } private AFieldDeclIR consHashcodeField() { AExternalTypeIR fieldType = new AExternalTypeIR(); fieldType.setName(IJavaConstants.INT); AFieldDeclIR field = new AFieldDeclIR(); field.setAccess(IJavaConstants.PRIVATE); field.setVolatile(false); field.setFinal(false); field.setStatic(true); field.setName(HASHCODE_FIELD); field.setType(fieldType); field.setInitial(consZero()); return field; } private AFieldDeclIR consInstanceField(String name) { AClassTypeIR quoteClassType = new AClassTypeIR(); quoteClassType.setName(name); AFieldDeclIR field = new AFieldDeclIR(); field.setAccess(IJavaConstants.PRIVATE); field.setVolatile(false); field.setFinal(false); field.setStatic(true); field.setName(INSTANCE_FIELD); field.setType(quoteClassType); field.setInitial(info.getExpAssistant().consNullExp()); return field; } private AMethodDeclIR consQuoteCtor(String name) { AExternalTypeIR fieldType = new AExternalTypeIR(); fieldType.setName(IJavaConstants.INT); AIdentifierVarExpIR hashcodeVar = transAssistant.getInfo().getExpAssistant().consIdVar(HASHCODE_FIELD, fieldType); AEqualsBinaryExpIR hashcodeCompare = new AEqualsBinaryExpIR(); hashcodeCompare.setType(new ABoolBasicTypeIR()); hashcodeCompare.setLeft(hashcodeVar); hashcodeCompare.setRight(consZero()); AIdentifierVarExpIR hashCodeId = transAssistant.getInfo().getExpAssistant().consIdVar(HASHCODE_FIELD, consFieldType()); AMethodTypeIR hashCodeMethodType = new AMethodTypeIR(); hashCodeMethodType.setResult(consFieldType()); ASuperVarExpIR superVar = new ASuperVarExpIR(); superVar.setName(HASH_CODE_METHOD); superVar.setType(hashCodeMethodType); superVar.setIsLambda(false); superVar.setIsLocal(false); AApplyExpIR superCall = new AApplyExpIR(); superCall.setType(consFieldType()); superCall.setRoot(superVar); AAssignToExpStmIR assignHashcode = new AAssignToExpStmIR(); assignHashcode.setTarget(hashCodeId); assignHashcode.setExp(superCall); AIfStmIR hashcodeCheck = new AIfStmIR(); hashcodeCheck.setIfExp(hashcodeCompare); hashcodeCheck.setThenStm(assignHashcode); ABlockStmIR body = new ABlockStmIR(); body.getStatements().add(hashcodeCheck); AClassTypeIR quoteClassType = new AClassTypeIR(); quoteClassType.setName(name); AMethodTypeIR constructorType = new AMethodTypeIR(); constructorType.setResult(quoteClassType); AMethodDeclIR ctor = consDefaultCtorSignature(name); ctor.setMethodType(constructorType); ctor.setBody(body); return ctor; } private AMethodDeclIR consGetInstanceMethod(String name) { AClassTypeIR quoteClassType = new AClassTypeIR(); quoteClassType.setName(name); AIdentifierVarExpIR instanceVar = transAssistant.getInfo().getExpAssistant().consIdVar(INSTANCE_FIELD, quoteClassType); AEqualsBinaryExpIR nullCompare = new AEqualsBinaryExpIR(); nullCompare.setType(new ABoolBasicTypeIR()); nullCompare.setLeft(instanceVar); nullCompare.setRight(info.getExpAssistant().consNullExp()); AIdentifierVarExpIR instanceId = transAssistant.getInfo().getExpAssistant().consIdVar(INSTANCE_FIELD, quoteClassType.clone()); ATypeNameIR typeName = new ATypeNameIR(); typeName.setDefiningClass(null); typeName.setName(name); ANewExpIR newQuote = new ANewExpIR(); newQuote.setName(typeName); newQuote.setType(quoteClassType); AAssignToExpStmIR assignInstance = new AAssignToExpStmIR(); assignInstance.setTarget(instanceId); assignInstance.setExp(newQuote); AIfStmIR ensureInstance = new AIfStmIR(); ensureInstance.setIfExp(nullCompare); ensureInstance.setThenStm(assignInstance); AReturnStmIR returnInstance = new AReturnStmIR(); returnInstance.setExp(instanceVar.clone()); ABlockStmIR body = new ABlockStmIR(); body.getStatements().add(ensureInstance); body.getStatements().add(returnInstance); AMethodTypeIR methodType = new AMethodTypeIR(); methodType.setResult(quoteClassType.clone()); AMethodDeclIR getInstanceMethod = new AMethodDeclIR(); getInstanceMethod.setImplicit(false); getInstanceMethod.setAbstract(false); getInstanceMethod.setAccess(IJavaConstants.PUBLIC); getInstanceMethod.setIsConstructor(false); getInstanceMethod.setName(GET_INSTANCE_METHOD); getInstanceMethod.setStatic(true); getInstanceMethod.setMethodType(methodType); getInstanceMethod.setBody(body); return getInstanceMethod; } private AMethodDeclIR consHashcodeMethod() { AIdentifierVarExpIR hashCodeVar = transAssistant.getInfo().getExpAssistant().consIdVar(HASHCODE_FIELD, consFieldType()); AReturnStmIR returnHashCode = new AReturnStmIR(); returnHashCode.setExp(hashCodeVar); AMethodDeclIR hashCodeMethod = consHashcodeMethodSignature(); ABlockStmIR body = new ABlockStmIR(); body.getStatements().add(returnHashCode); hashCodeMethod.setBody(body); return hashCodeMethod; } private AMethodDeclIR consEqualsMethod(String name) { AIdentifierVarExpIR paramVar = transAssistant.getInfo().getExpAssistant().consIdVar(EQUALS_METHOD_PARAM, new AObjectTypeIR()); AClassTypeIR quoteClass = new AClassTypeIR(); quoteClass.setName(name); AInstanceofExpIR instanceCheck = new AInstanceofExpIR(); instanceCheck.setType(new ABoolBasicTypeIR()); instanceCheck.setExp(paramVar); instanceCheck.setCheckedType(quoteClass); AReturnStmIR checkReturned = new AReturnStmIR(); checkReturned.setExp(instanceCheck); AMethodDeclIR equalsMethod = consEqualMethodSignature(EQUALS_METHOD_PARAM); ABlockStmIR body = new ABlockStmIR(); body.getStatements().add(checkReturned); equalsMethod.setBody(body); return equalsMethod; } private AMethodDeclIR consToStringMethod(String name) { SExpIR stringLit = info.getExpAssistant().consStringLiteral("<" + name + ">", false); AReturnStmIR returnStr = new AReturnStmIR(); returnStr.setExp(stringLit); AMethodDeclIR toStringMethod = consToStringSignature(); ABlockStmIR body = new ABlockStmIR(); body.getStatements().add(returnStr); toStringMethod.setBody(body); return toStringMethod; } private STypeIR consFieldType() { AExternalTypeIR fieldType = new AExternalTypeIR(); fieldType.setName(IJavaConstants.INT); return fieldType; } private AExternalExpIR consZero() { AExternalExpIR zero = new AExternalExpIR(); zero.setType(consFieldType()); zero.setTargetLangExp("0"); return zero; } }