package org.overture.codegen.trans; import java.util.HashMap; import java.util.Map; import org.apache.log4j.Logger; import org.overture.ast.definitions.AExplicitOperationDefinition; import org.overture.ast.definitions.AInheritedDefinition; import org.overture.ast.definitions.PDefinition; import org.overture.ast.definitions.SClassDefinition; import org.overture.ast.node.INode; import org.overture.ast.statements.ACallStm; import org.overture.codegen.ir.IRGeneratedTag; import org.overture.codegen.ir.SExpIR; import org.overture.codegen.ir.SPatternIR; import org.overture.codegen.ir.analysis.AnalysisException; import org.overture.codegen.ir.analysis.DepthFirstAnalysisAdaptor; import org.overture.codegen.ir.declarations.ADefaultClassDeclIR; import org.overture.codegen.ir.declarations.AFormalParamLocalParamIR; import org.overture.codegen.ir.declarations.AMethodDeclIR; import org.overture.codegen.ir.declarations.ASystemClassDeclIR; import org.overture.codegen.ir.expressions.AIdentifierVarExpIR; import org.overture.codegen.ir.patterns.AIdentifierPatternIR; import org.overture.codegen.ir.statements.APlainCallStmIR; import org.overture.codegen.ir.types.AVoidTypeIR; import org.overture.codegen.trans.assistants.TransAssistantIR; public class ConstructorTrans extends DepthFirstAnalysisAdaptor { private TransAssistantIR assist; // To look up object initializer call names private Map<AExplicitOperationDefinition, String> objectInitCallNames; // Object initialization call prefix private String objectInitCallPrefix; private Logger log = Logger.getLogger(this.getClass().getName()); public ConstructorTrans(TransAssistantIR assist, String objectInitCallPrefix) { this.assist = assist; this.objectInitCallPrefix = objectInitCallPrefix; this.objectInitCallNames = new HashMap<AExplicitOperationDefinition, String>(); } @Override public void caseAMethodDeclIR(AMethodDeclIR node) throws AnalysisException { if (node.parent() instanceof ASystemClassDeclIR) { return; } if (node.getIsConstructor()) { String initName = getInitName(node); if (initName == null) { return; } AMethodDeclIR objInitializer = node.clone(); objInitializer.setSourceNode(node.getSourceNode()); objInitializer.setTag(new IRGeneratedTag(getClass().getName())); objInitializer.setName(initName); objInitializer.getMethodType().setResult(new AVoidTypeIR()); objInitializer.setIsConstructor(false); objInitializer.setPreCond(null); objInitializer.setPostCond(null); ADefaultClassDeclIR classCg = node.getAncestor(ADefaultClassDeclIR.class); if (classCg == null) { log.error("Could not find enclosing class of constructor " + node.getName()); return; } classCg.getMethods().addFirst(objInitializer); // Apply transformation recursively objInitializer.apply(this); APlainCallStmIR initCall = new APlainCallStmIR(); initCall.setType(objInitializer.getMethodType().getResult().clone()); initCall.setClassType(null); initCall.setName(initName); for (AFormalParamLocalParamIR param : node.getFormalParams()) { SPatternIR pattern = param.getPattern(); if (pattern instanceof AIdentifierPatternIR) { AIdentifierPatternIR idPattern = (AIdentifierPatternIR) pattern; AIdentifierVarExpIR var = new AIdentifierVarExpIR(); var.setIsLocal(true); var.setType(param.getType().clone()); var.setName(idPattern.getName()); var.setIsLambda(false); var.setSourceNode(pattern.getSourceNode()); initCall.getArgs().add(var); } else { log.error("Expected all parameters to be identifier patterns by now. Got: " + pattern); } } node.setBody(initCall); } if (node.getBody() != null) { node.getBody().apply(this); } } @Override public void caseAPlainCallStmIR(APlainCallStmIR node) throws AnalysisException { String initName = getInitName(node); if (initName == null) { // No 'initName' exists for non-constructor calls return; } APlainCallStmIR callStm = new APlainCallStmIR(); callStm.setType(new AVoidTypeIR()); callStm.setClassType(null); callStm.setName(initName); for (SExpIR a : node.getArgs()) { callStm.getArgs().add(a.clone()); } assist.replaceNodeWith(node, callStm); } public String getObjectInitializerCall(AExplicitOperationDefinition vdmOp) { if (objectInitCallNames.containsKey(vdmOp)) { return objectInitCallNames.get(vdmOp); } else { String enclosingClassName = vdmOp.getAncestor(SClassDefinition.class).getName().getName(); String initName = assist.getInfo().getTempVarNameGen().nextVarName(objectInitCallPrefix + enclosingClassName + "_"); objectInitCallNames.put(vdmOp, initName); return initName; } } private String getInitName(APlainCallStmIR node) { if (node.getSourceNode() != null && node.getSourceNode().getVdmNode() != null) { INode vdmNode = node.getSourceNode().getVdmNode(); if (vdmNode instanceof ACallStm) { ACallStm c = (ACallStm) vdmNode; PDefinition rootDef = c.getRootdef(); while (rootDef instanceof AInheritedDefinition) { rootDef = ((AInheritedDefinition) rootDef).getSuperdef(); } if (rootDef instanceof AExplicitOperationDefinition) { AExplicitOperationDefinition op = (AExplicitOperationDefinition) rootDef; if (op.getIsConstructor()) { return getObjectInitializerCall(op); } } } } return null; } private String getInitName(AMethodDeclIR node) { if (node.getSourceNode() != null && node.getSourceNode().getVdmNode() != null) { INode vdmNode = node.getSourceNode().getVdmNode(); if (vdmNode instanceof AExplicitOperationDefinition) { AExplicitOperationDefinition op = (AExplicitOperationDefinition) vdmNode; return getObjectInitializerCall(op); } } return null; } }