package org.overture.codegen.vdm2jml.trans; import java.util.LinkedList; import java.util.List; import org.apache.log4j.Logger; import org.overture.codegen.assistant.DeclAssistantIR; import org.overture.codegen.assistant.ExpAssistantIR; import org.overture.codegen.assistant.PatternAssistantIR; import org.overture.codegen.ir.INode; import org.overture.codegen.ir.ITempVarGen; import org.overture.codegen.ir.SExpIR; 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.AVarDeclIR; import org.overture.codegen.ir.expressions.AFieldExpIR; import org.overture.codegen.ir.expressions.AIdentifierVarExpIR; import org.overture.codegen.ir.expressions.AMapSeqGetExpIR; import org.overture.codegen.ir.expressions.SVarExpIR; import org.overture.codegen.ir.patterns.AIdentifierPatternIR; import org.overture.codegen.ir.statements.AAssignToExpStmIR; import org.overture.codegen.ir.statements.ABlockStmIR; import org.overture.codegen.ir.statements.AMapSeqUpdateStmIR; import org.overture.codegen.trans.assistants.TransAssistantIR; import org.overture.codegen.vdm2jml.JmlGenerator; import org.overture.codegen.vdm2jml.data.StateDesInfo; public class TargetNormaliserTrans extends DepthFirstAnalysisAdaptor { public static final String STATE_DES = "stateDes_"; private JmlGenerator jmlGen; private StateDesInfo stateDesInfo; private Logger log = Logger.getLogger(this.getClass().getName()); public TargetNormaliserTrans(JmlGenerator jmlGen) { this.jmlGen = jmlGen; this.stateDesInfo = new StateDesInfo(); } @Override public void caseAFieldExpIR(AFieldExpIR node) throws AnalysisException { if (!(node.parent() instanceof AAssignToExpStmIR)) { return; } if (!(node.getObject() instanceof SVarExpIR)) { normaliseTarget((AAssignToExpStmIR) node.parent(), node.getObject()); } } @Override public void caseAMapSeqUpdateStmIR(AMapSeqUpdateStmIR node) throws AnalysisException { if (!(node.getCol() instanceof SVarExpIR)) { normaliseTarget(node, node.getCol()); } } private void normaliseTarget(SStmIR node, SExpIR target) { List<AVarDeclIR> varDecls = new LinkedList<AVarDeclIR>(); List<AIdentifierVarExpIR> vars = new LinkedList<AIdentifierVarExpIR>(); SExpIR newTarget = splitTarget(target, varDecls, vars); markAsCloneFree(varDecls); markAsCloneFree(vars); stateDesInfo.addStateDesVars(node, vars); stateDesInfo.addStateDesDecl(node, varDecls); if (varDecls.isEmpty()) { return; } ABlockStmIR replBlock = new ABlockStmIR(); jmlGen.getJavaGen().getTransAssistant().replaceNodeWith(node, replBlock); for (AVarDeclIR var : varDecls) { replBlock.getLocalDefs().add(var); } replBlock.getStatements().add(node); jmlGen.getJavaGen().getTransAssistant().replaceNodeWith(target, newTarget); } private SExpIR splitTarget(SExpIR target, List<AVarDeclIR> varDecls, List<AIdentifierVarExpIR> vars) { DeclAssistantIR dAssist = jmlGen.getJavaGen().getInfo().getDeclAssistant(); PatternAssistantIR pAssist = jmlGen.getJavaGen().getInfo().getPatternAssistant(); ExpAssistantIR eAssist = jmlGen.getJavaGen().getInfo().getExpAssistant(); ITempVarGen nameGen = jmlGen.getJavaGen().getInfo().getTempVarNameGen(); TransAssistantIR tr = jmlGen.getJavaGen().getTransAssistant(); if (target instanceof SVarExpIR) { AIdentifierVarExpIR var = ((AIdentifierVarExpIR) target).clone(); vars.add(var); return var; } else if (target instanceof AMapSeqGetExpIR) { // Utils.mapSeqGet(a.myMap, 1).b AMapSeqGetExpIR get = (AMapSeqGetExpIR) target; SExpIR newCol = splitTarget(get.getCol().clone(), varDecls, vars); tr.replaceNodeWith(get.getCol(), newCol); // Utils.mapSeqGet(tmp_1, 1).b AIdentifierPatternIR id = pAssist.consIdPattern(nameGen.nextVarName(STATE_DES)); AVarDeclIR varDecl = dAssist.consLocalVarDecl(get.getType().clone(), id, get.clone()); varDecls.add(varDecl); // B tmp_2 = Utils.mapSeqGet(tmp_1, 1).b // tmp_2 AIdentifierVarExpIR var = eAssist.consIdVar(id.getName(), get.getType().clone()); vars.add(var); return var; } else if (target instanceof AFieldExpIR) { // a.b.c AFieldExpIR field = (AFieldExpIR) target; SExpIR newObj = splitTarget(field.getObject().clone(), varDecls, vars); tr.replaceNodeWith(field.getObject(), newObj); // tmp_1.c AIdentifierPatternIR id = pAssist.consIdPattern(nameGen.nextVarName(STATE_DES)); AVarDeclIR varDecl = dAssist.consLocalVarDecl(field.getType().clone(), id, field.clone()); varDecls.add(varDecl); // C tmp_2 = tmp1.c AIdentifierVarExpIR var = eAssist.consIdVar(id.getName(), field.getType().clone()); vars.add(var); return var; } else { log.error("Got unexpected target:" + target); return null; } } private void markAsCloneFree(List<? extends INode> nodes) { for (INode v : nodes) { jmlGen.getJavaGen().getJavaFormat().getValueSemantics().addCloneFreeNode(v); } } public StateDesInfo getStateDesInfo() { return stateDesInfo; } }