package org.overture.codegen.traces;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.overture.ast.lex.Dialect;
import org.overture.codegen.ir.ITempVarGen;
import org.overture.codegen.ir.SExpIR;
import org.overture.codegen.ir.SPatternIR;
import org.overture.codegen.ir.SStmIR;
import org.overture.codegen.ir.STypeIR;
import org.overture.codegen.ir.analysis.AnalysisException;
import org.overture.codegen.ir.declarations.AVarDeclIR;
import org.overture.codegen.ir.expressions.AIdentifierVarExpIR;
import org.overture.codegen.ir.patterns.AIdentifierPatternIR;
import org.overture.codegen.ir.statements.ABlockStmIR;
import org.overture.codegen.ir.statements.ACallObjectExpStmIR;
import org.overture.codegen.ir.statements.AContinueStmIR;
import org.overture.codegen.ir.statements.AIfStmIR;
import org.overture.codegen.ir.statements.ALocalPatternAssignmentStmIR;
import org.overture.codegen.ir.types.ASetSetTypeIR;
import org.overture.codegen.ir.types.SSetTypeIR;
import org.overture.codegen.trans.DeclarationTag;
import org.overture.codegen.trans.IterationVarPrefixes;
import org.overture.codegen.trans.assistants.TransAssistantIR;
import org.overture.codegen.trans.iterator.ILanguageIterator;
import org.overture.codegen.trans.let.LetBeStStrategy;
import org.overture.config.Settings;
public class TraceLetBeStStrategy extends LetBeStStrategy
{
protected TraceNodeData nodeData;
protected AVarDeclIR altTests;
protected AIdentifierPatternIR id;
protected TraceNames tracePrefixes;
protected StoreAssistant storeAssistant;
protected Map<String, String> idConstNameMap;
protected TraceStmBuilder builder;
private Logger log = Logger.getLogger(this.getClass().getSimpleName());
public TraceLetBeStStrategy(TransAssistantIR transAssistant,
SExpIR suchThat, SSetTypeIR setType, ILanguageIterator langIterator,
ITempVarGen tempGen, IterationVarPrefixes iteVarPrefixes,
StoreAssistant storeAssistant, Map<String, String> idConstNameMap,
TraceNames tracePrefixes, AIdentifierPatternIR id,
AVarDeclIR altTests, TraceNodeData nodeData,
TraceStmBuilder builder)
{
super(transAssistant, suchThat, setType, langIterator, tempGen, iteVarPrefixes);
this.storeAssistant = storeAssistant;
this.idConstNameMap = idConstNameMap;
this.tracePrefixes = tracePrefixes;
this.id = id;
this.altTests = altTests;
this.nodeData = nodeData;
this.builder = builder;
}
@Override
public List<AVarDeclIR> getOuterBlockDecls(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns) throws AnalysisException
{
STypeIR elementType = transAssist.getElementType(setSeqType);
for (SPatternIR id : patterns)
{
AVarDeclIR decl = transAssist.getInfo().getDeclAssistant().consLocalVarDecl(elementType.clone(), id.clone(), transAssist.getInfo().getExpAssistant().consUndefinedExp());
decl.setFinal(true);
decls.add(decl);
}
return packDecl(altTests);
}
@Override
public List<SStmIR> getPreForLoopStms(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns, SPatternIR pattern)
{
return null;
}
@Override
public SExpIR getForLoopCond(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns, SPatternIR pattern)
throws AnalysisException
{
return langIterator.getForLoopCond(setVar, patterns, pattern);
}
@Override
public DeclarationTag consDeclarationTag()
{
return new DeclarationTag(false, successVarDecl);
}
@Override
public AVarDeclIR getNextElementDeclared(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns, SPatternIR pattern)
throws AnalysisException
{
AVarDeclIR nextElementDecl = decls.get(count++);
tagNextElementDeclared(nextElementDecl);
nextElementDecl.setExp(langIterator.consNextElementCall(setVar));
return nextElementDecl;
}
@Override
public ALocalPatternAssignmentStmIR getNextElementAssigned(
AIdentifierVarExpIR setVar, List<SPatternIR> patterns,
SPatternIR pattern) throws AnalysisException
{
return null;
}
@Override
public List<SStmIR> getForLoopStms(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns, SPatternIR pattern)
{
ABlockStmIR block = new ABlockStmIR();
if (suchThat != null)
{
AIfStmIR ifStm = new AIfStmIR();
ifStm.setIfExp(transAssist.getInfo().getExpAssistant().negate(suchThat.clone()));
ifStm.setThenStm(new AContinueStmIR());
block.getStatements().add(ifStm);
}
AVarDeclIR nextElementDecl = decls.get(count - 1);
IdentifierPatternCollector idCollector = new IdentifierPatternCollector();
idCollector.setTopNode(nextElementDecl);
PatternTypeFinder typeFinder = new PatternTypeFinder(transAssist.getInfo());
if (setVar.getType() instanceof ASetSetTypeIR)
{
STypeIR elemType = ((ASetSetTypeIR) setVar.getType()).getSetOf();
try
{
nextElementDecl.getPattern().apply(typeFinder, elemType);
} catch (AnalysisException e)
{
log.error("Unexpectected problem occurred when trying to determine the type of pattern "
+ nextElementDecl.getPattern());
e.printStackTrace();
}
} else
{
log.error("Expected set type. Got: " + setVar.getType());
}
List<AIdentifierVarExpIR> traceVars = new LinkedList<>();
for (AIdentifierPatternIR idToReg : idCollector.findOccurences())
{
if (Settings.dialect != Dialect.VDM_SL)
{
String idConstName = idConstNameMap.get(idToReg.getName());
block.getStatements().add(transAssist.wrap(storeAssistant.consIdConstDecl(idConstName)));
storeAssistant.appendStoreRegStms(block, idToReg.getName(), idConstName, false);
}
traceVars.add(this.transAssist.getInfo().getExpAssistant().consIdVar(idToReg.getName(), PatternTypeFinder.getType(typeFinder, idToReg)));
}
block.getStatements().add(nodeData.getStms());
STypeIR instanceType = altTests.getType().clone();
AIdentifierVarExpIR subject = nodeData.getNodeVar();
for (int i = traceVars.size() - 1; i >= 0; i--)
{
block.getStatements().add(builder.consAddTraceVarCall(subject, traceVars.get(i)));
}
// E.g. alternatives_2.add(apply_1)
ACallObjectExpStmIR addCall = transAssist.consInstanceCallStm(instanceType, id.getName(), tracePrefixes.addMethodName(), subject);
block.getStatements().add(addCall);
return packStm(block);
}
@Override
public List<SStmIR> getPostOuterBlockStms(AIdentifierVarExpIR setVar,
List<SPatternIR> patterns)
{
return null;
}
}