package org.overture.codegen.trans; import java.util.LinkedList; import org.apache.log4j.Logger; import org.overture.codegen.ir.ITempVarGen; import org.overture.codegen.ir.SExpIR; import org.overture.codegen.ir.SMultipleBindIR; import org.overture.codegen.ir.SPatternIR; import org.overture.codegen.ir.STypeIR; import org.overture.codegen.ir.analysis.AnalysisException; import org.overture.codegen.ir.analysis.DepthFirstAnalysisAdaptor; import org.overture.codegen.ir.patterns.ASeqMultipleBindIR; import org.overture.codegen.ir.patterns.ASetMultipleBindIR; import org.overture.codegen.ir.statements.ABlockStmIR; import org.overture.codegen.ir.statements.ALetBeStStmIR; import org.overture.codegen.ir.types.AUnknownTypeIR; import org.overture.codegen.ir.utils.AHeaderLetBeStIR; import org.overture.codegen.trans.assistants.TransAssistantIR; import org.overture.codegen.trans.iterator.ILanguageIterator; import org.overture.codegen.trans.let.LetBeStStrategy; public class LetBeStTrans extends DepthFirstAnalysisAdaptor { private TransAssistantIR transAssistant; private ILanguageIterator langIterator; private IterationVarPrefixes iteVarPrefixes; private Logger log = Logger.getLogger(this.getClass().getName()); public LetBeStTrans(TransAssistantIR transAssistant, ILanguageIterator langIterator, IterationVarPrefixes iteVarPrefixes) { this.transAssistant = transAssistant; this.langIterator = langIterator; this.iteVarPrefixes = iteVarPrefixes; } @Override public void caseALetBeStStmIR(ALetBeStStmIR node) throws AnalysisException { AHeaderLetBeStIR header = node.getHeader(); if (!(header.getBinding() instanceof ASetMultipleBindIR || header.getBinding() instanceof ASeqMultipleBindIR)) { transAssistant.getInfo().addTransformationWarning(node.getHeader().getBinding(), "This transformation only works for 'let be st' " + "statements with with multiple set binds and not multiple type binds in '" + this.getClass().getSimpleName() + "'"); return; } SExpIR suchThat = header.getSuchThat(); SMultipleBindIR binding = node.getHeader().getBinding(); STypeIR setSeqType; if (binding instanceof ASetMultipleBindIR) { ASetMultipleBindIR sb = (ASetMultipleBindIR) binding; setSeqType = sb.getSet().getType().clone(); } else if (binding instanceof ASeqMultipleBindIR) { ASeqMultipleBindIR sb = (ASeqMultipleBindIR) binding; setSeqType = sb.getSeq().getType().clone(); } else { log.error("Expected multiple set bind or multiple sequence bind. Got: " + binding); setSeqType = new AUnknownTypeIR(); // The closest we get setSeqType.setSourceNode(binding.getSourceNode()); } ITempVarGen tempVarNameGen = transAssistant.getInfo().getTempVarNameGen(); LetBeStStrategy strategy = new LetBeStStrategy(transAssistant, suchThat, setSeqType.clone(), langIterator, tempVarNameGen, iteVarPrefixes); if (transAssistant.hasEmptySet(binding)) { transAssistant.cleanUpBinding(binding); node.setStatement(new ABlockStmIR()); } LinkedList<SPatternIR> patterns = binding.getPatterns(); ABlockStmIR outerBlock = transAssistant.consIterationBlock(patterns, getCol(binding), tempVarNameGen, strategy, iteVarPrefixes); // Only the statement of the let be st statement is added to the outer block statements. // We obtain the equivalent functionality of the remaining part of the let be st statement // from the transformation in the outer block outerBlock.getStatements().add(node.getStatement()); // Replace the let be st statement with the transformation transAssistant.replaceNodeWithRecursively(node, outerBlock, this); outerBlock.setScoped(transAssistant.getInfo().getStmAssistant().isScoped(outerBlock)); } private SExpIR getCol(SMultipleBindIR binding) { if (binding instanceof ASetMultipleBindIR) { return ((ASetMultipleBindIR) binding).getSet(); } else if (binding instanceof ASeqMultipleBindIR) { return ((ASeqMultipleBindIR) binding).getSeq(); } else { log.error("Expected multiple set bind or multiple sequence bind. Got: " + binding); return null; } } }