package org.overture.codegen.mojocg.util; import java.util.Map; import org.apache.maven.plugin.logging.Log; import org.overture.codegen.ir.SPatternIR; import org.overture.codegen.ir.SStmIR; 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.patterns.AIdentifierPatternIR; import org.overture.codegen.ir.statements.APlainCallStmIR; import org.overture.codegen.ir.types.AExternalTypeIR; import org.overture.codegen.trans.assistants.TransAssistantIR; public class DelegateTrans extends DepthFirstAnalysisAdaptor { private static final String FALLBACK_PARAM_NAME_PREFIX = "_param_"; private Map<String, String> delegateMap; private TransAssistantIR assist; private Log log; public DelegateTrans(Map<String, String> buidDelegateMap, TransAssistantIR assist, Log log) { this.delegateMap = buidDelegateMap; this.assist = assist; this.log = log; } @Override public void caseADefaultClassDeclIR(ADefaultClassDeclIR node) throws AnalysisException { if (isBridgeClass(node)) { for (AMethodDeclIR m : node.getMethods()) { if (isDelegateCall(m.getBody())) { log.debug("Updating " + node.getName() + "." + m.getName() + " to use delegate method " + getFullDelegateName(node) + "." + m.getName()); assist.replaceNodeWith(m.getBody(), consDelegateCall(node.getName(), m)); } } } } private boolean isBridgeClass(ADefaultClassDeclIR node) { return delegateMap.containsKey(node.getName()); } private String getFullDelegateName(ADefaultClassDeclIR node) { return delegateMap.get(node.getName()); } private boolean isDelegateCall(SStmIR body) { DelegateSearch search = new DelegateSearch(); if (body != null) { try { body.apply(search); return search.isDelegateCall(); } catch (AnalysisException e) { e.printStackTrace(); log.error("Unexpected error encountered when checking " + "if method is a delegate call: " + e.getMessage()); } } return false; } private APlainCallStmIR consDelegateCall(String className, AMethodDeclIR m) { AExternalTypeIR delegateType = new AExternalTypeIR(); delegateType.setName(delegateMap.get(className)); APlainCallStmIR call = new APlainCallStmIR(); call.setClassType(delegateType); call.setIsStatic(m.getStatic()); call.setName(m.getName()); call.setSourceNode(m.getBody().getSourceNode()); call.setTag(m.getBody().getTag()); call.setType(m.getMethodType().getResult().clone()); for (int i = 0; i < m.getFormalParams().size(); i++) { AFormalParamLocalParamIR param = m.getFormalParams().get(i); SPatternIR pattern = param.getPattern(); String argName = null; if (pattern instanceof AIdentifierPatternIR) { argName = ((AIdentifierPatternIR) pattern).getName(); } else { // Should not happen... argName = FALLBACK_PARAM_NAME_PREFIX + i; } call.getArgs().add(assist.getInfo().getExpAssistant().consIdVar(argName, param.getType().clone())); } return call; } }