package org.overture.codegen.traces; import java.util.List; import org.apache.log4j.Logger; import org.overture.ast.lex.Dialect; import org.overture.codegen.ir.INode; import org.overture.codegen.ir.IRConstants; 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.declarations.ANamedTraceDeclIR; import org.overture.codegen.ir.declarations.SClassDeclIR; import org.overture.codegen.ir.expressions.AIdentifierVarExpIR; import org.overture.codegen.ir.expressions.ATypeArgExpIR; import org.overture.codegen.ir.statements.ABlockStmIR; import org.overture.codegen.ir.statements.APlainCallStmIR; 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.AVoidTypeIR; import org.overture.codegen.trans.IterationVarPrefixes; import org.overture.codegen.trans.assistants.TransAssistantIR; import org.overture.codegen.trans.iterator.ILanguageIterator; import org.overture.config.Settings; public class TracesTrans extends DepthFirstAnalysisAdaptor { protected TransAssistantIR transAssistant; protected IterationVarPrefixes iteVarPrefixes; protected ILanguageIterator langIterator; protected ICallStmToStringMethodBuilder toStringBuilder; protected TraceNames tracePrefixes; private List<INode> cloneFreeNodes; private Logger log = Logger.getLogger(this.getClass().getName()); public TracesTrans(TransAssistantIR transAssistant, IterationVarPrefixes iteVarPrefixes, TraceNames tracePrefixes, ILanguageIterator langIterator, ICallStmToStringMethodBuilder toStringBuilder, List<INode> cloneFreeNodes) { this.transAssistant = transAssistant; this.iteVarPrefixes = iteVarPrefixes; this.langIterator = langIterator; this.toStringBuilder = toStringBuilder; this.tracePrefixes = tracePrefixes; this.cloneFreeNodes = cloneFreeNodes; } @Override public void caseANamedTraceDeclIR(ANamedTraceDeclIR node) throws AnalysisException { if (!transAssistant.getInfo().getSettings().generateTraces()) { return; } TraceSupportedAnalysis supportedAnalysis = new TraceSupportedAnalysis(node); if (!traceIsSupported(supportedAnalysis)) { transAssistant.getInfo().addTransformationWarning(node, supportedAnalysis.getReason()); return; } ADefaultClassDeclIR enclosingClass = node.getAncestor(ADefaultClassDeclIR.class); if (enclosingClass != null) { enclosingClass.getMethods().add(consTraceMethod(node)); } else { log.error("Class enclosing trace could not be found so the generated trace could not be added as a method to the corresponding class"); } } private boolean traceIsSupported(TraceSupportedAnalysis supportedAnalysis) { try { supportedAnalysis.run(); } catch (AnalysisException e) { log.error("Could not determine if a trace could be code generated"); e.printStackTrace(); return false; } return !supportedAnalysis.isUnsupported(); } private AMethodDeclIR consTraceMethod(ANamedTraceDeclIR node) throws AnalysisException { AClassTypeIR testAccType = transAssistant.consClassType(tracePrefixes.testAccumulatorClassName()); AMethodTypeIR methodType = new AMethodTypeIR(); methodType.setResult(new AVoidTypeIR()); methodType.getParams().add(testAccType); AFormalParamLocalParamIR instanceParam = new AFormalParamLocalParamIR(); instanceParam.setType(testAccType.clone()); instanceParam.setPattern(transAssistant.getInfo().getPatternAssistant().consIdPattern(tracePrefixes.traceMethodParamName())); AMethodDeclIR traceMethod = new AMethodDeclIR(); traceMethod.setTag(new TraceMethodTag()); traceMethod.getFormalParams().add(instanceParam); traceMethod.setImplicit(false); traceMethod.setAbstract(false); traceMethod.setAccess(IRConstants.PUBLIC); traceMethod.setBody(consTraceMethodBody(node)); traceMethod.setIsConstructor(false); traceMethod.setStatic(Settings.dialect == Dialect.VDM_SL); traceMethod.setMethodType(methodType); traceMethod.setName(getTraceName(node) + "_" + tracePrefixes.runTraceMethodName()); return traceMethod; } private SStmIR buildTestExecutionStms(AIdentifierVarExpIR nodeVar, String traceEnclosingClassName) { AExternalTypeIR utilsType = new AExternalTypeIR(); utilsType.setName(tracePrefixes.traceNodeNodeClassName()); APlainCallStmIR executeTestsCall = new APlainCallStmIR(); executeTestsCall.setClassType(utilsType); executeTestsCall.setName(tracePrefixes.executeTestsMethodName()); executeTestsCall.setType(new AVoidTypeIR()); ATypeArgExpIR typeArg = new ATypeArgExpIR(); typeArg.setType(transAssistant.consClassType(traceEnclosingClassName)); executeTestsCall.getArgs().add(nodeVar.clone()); if (Settings.dialect != Dialect.VDM_SL) { executeTestsCall.getArgs().add(typeArg); } executeTestsCall.getArgs().add(transAssistant.getInfo().getExpAssistant().consIdVar(tracePrefixes.traceMethodParamName(), transAssistant.consClassType(tracePrefixes.testAccumulatorClassName()))); executeTestsCall.getArgs().add(transAssistant.getInfo().getExpAssistant().consIdVar(tracePrefixes.storeVarName(), transAssistant.consClassType(tracePrefixes.storeClassName()))); return executeTestsCall; } private SStmIR consTraceMethodBody(ANamedTraceDeclIR node) throws AnalysisException { StoreAssistant storeAssist = new StoreAssistant(tracePrefixes, transAssistant); String traceEnclosingClass = getClassName(node); TraceStmBuilder stmBuilder = consStmBuilder(storeAssist, traceEnclosingClass); SStmIR regModules = registerOtherModules(traceEnclosingClass, storeAssist); TraceNodeData nodeData = stmBuilder.buildFromDeclTerms(node.getTerms()); ABlockStmIR stms = new ABlockStmIR(); stms.getLocalDefs().add(transAssistant.consClassVarDeclDefaultCtor(tracePrefixes.storeClassName(), tracePrefixes.storeVarName())); stms.getLocalDefs().add(transAssistant.consClassVarDeclDefaultCtor(tracePrefixes.idGeneratorClassName(), tracePrefixes.idGeneratorVarName())); if (regModules != null) { stms.getStatements().add(regModules); } stms.getStatements().add(nodeData.getStms()); stms.getStatements().add(buildTestExecutionStms(nodeData.getNodeVar(), getClassName(node))); return stms; } public TraceStmBuilder consStmBuilder(StoreAssistant storeAssist, String traceEnclosingClass) { return new TraceStmBuilder(this, traceEnclosingClass, storeAssist); } private SStmIR registerOtherModules(String encClass, StoreAssistant storeAssist) { // Static registration of other modules if (Settings.dialect == Dialect.VDM_PP && transAssistant.getInfo().getClasses().size() == 1) { return null; } ABlockStmIR regBlock = new ABlockStmIR(); regBlock.setScoped(true); for (SClassDeclIR c : transAssistant.getInfo().getClasses()) { if (Settings.dialect == Dialect.VDM_PP && c.getName().equals(encClass)) { /** * There is no need to register the instance of the enclosing class. This is handled by the * TraceNode.executeTests method */ continue; } String idConstName = transAssistant.getInfo().getTempVarNameGen().nextVarName(tracePrefixes.idConstNamePrefix()); regBlock.getLocalDefs().add(storeAssist.consIdConstDecl(idConstName)); AClassTypeIR classType = transAssistant.consClassType(c.getName()); ATypeArgExpIR classArg = new ATypeArgExpIR(); classArg.setType(classType.clone()); regBlock.getStatements().add(storeAssist.consStoreRegistration(idConstName, classArg, true)); } return regBlock; } private String getTraceName(ANamedTraceDeclIR node) { String methodName = getClassName(node); for (int i = 0; i < node.getPathname().size(); i++) { methodName += "_" + node.getPathname().get(i).getName(); } return methodName; } public String getClassName(ANamedTraceDeclIR trace) { if (trace != null) { ADefaultClassDeclIR enclosingClass = trace.getAncestor(ADefaultClassDeclIR.class); if (enclosingClass != null) { return enclosingClass.getName(); } } log.error("Could not find class declaration enclosing the trace node " + trace); return null; } public TransAssistantIR getTransAssist() { return transAssistant; } public IterationVarPrefixes getIteVarPrefixes() { return iteVarPrefixes; } public TraceNames getTracePrefixes() { return tracePrefixes; } public ILanguageIterator getLangIterator() { return langIterator; } public ICallStmToStringMethodBuilder getToStringBuilder() { return toStringBuilder; } public List<INode> getCloneFreeNodes() { return cloneFreeNodes; } }