/* * Copyright (c) 2011, IETR/INSA of Rennes * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the IETR/INSA of Rennes nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ package net.sf.orcc.df.transform; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import net.sf.orcc.df.Action; import net.sf.orcc.df.Actor; import net.sf.orcc.df.Instance; import net.sf.orcc.df.Unit; import net.sf.orcc.df.util.DfVisitor; import net.sf.orcc.ir.Def; import net.sf.orcc.ir.InstCall; import net.sf.orcc.ir.InstLoad; import net.sf.orcc.ir.Procedure; import net.sf.orcc.ir.Use; import net.sf.orcc.ir.Var; import net.sf.orcc.ir.util.AbstractIrVisitor; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.EcoreUtil.Copier; /** * This class defines a transformation that imports objects defined in units. * * @author Matthieu Wipliez * */ public class UnitImporter extends DfVisitor<Procedure> { private Copier copier; private int indexProc; private int indexVar; private Instance instance; public UnitImporter() { this.irVisitor = new InnerIrVisitor(); } private class InnerIrVisitor extends AbstractIrVisitor<Procedure> { @Override public Procedure caseInstCall(InstCall call) { Procedure proc = call.getProcedure(); Procedure procInActor = doSwitch(proc); call.setProcedure(procInActor); return null; } @Override public Procedure caseInstLoad(InstLoad load) { Use use = load.getSource(); Var var = use.getVariable(); if (var.eContainer() instanceof Unit) { final String actorVarName = getCurrentEntityName() + "_" + var.getName(); Var varInActor = actor.getStateVar(actorVarName); if (varInActor == null) { varInActor = (Var) copier.get(var); if (varInActor == null) { varInActor = (Var) copier.copy(var); actor.getStateVars().add(indexVar++, varInActor); varInActor.setName(actorVarName); } } use.setVariable(varInActor); } return null; } @Override public Procedure caseProcedure(Procedure proc) { if (proc.eContainer() instanceof Unit) { final String actorProcName = getCurrentEntityName() + "_" + proc.getName(); Procedure procInActor = (Procedure) copier.get(proc); if (procInActor == null) { procInActor = (Procedure) copier.copy(proc); procInActor.setAttribute("package", getPackage(proc.eContainer())); if (!procInActor.isNative()) { procInActor.setName(actorProcName); } TreeIterator<EObject> it = EcoreUtil.getAllContents(proc, true); while (it.hasNext()) { EObject object = it.next(); if (object instanceof Def) { Def def = (Def) object; Var copyVar = (Var) copier.get(def.getVariable()); Def copyDef = (Def) copier.get(def); copyDef.setVariable(copyVar); } else if (object instanceof Use) { Use use = (Use) object; Var var = use.getVariable(); Var copyVar = (Var) copier.get(var); Use copyUse = (Use) copier.get(use); if (copyVar == null) { // happens for variables loaded from units // handled by caseInstLoad copyUse.setVariable(var); } else { copyUse.setVariable(copyVar); } } else if (object instanceof InstCall) { InstCall innerCall = (InstCall) object; Procedure copyProc = doSwitch(innerCall .getProcedure()); InstCall copyCall = (InstCall) copier .get(innerCall); copyCall.setProcedure(copyProc); } } actor.getProcs().add(indexProc++, procInActor); super.caseProcedure(procInActor); } return procInActor; } else { proc.setAttribute("package", getPackage(proc.eContainer())); super.caseProcedure(proc); return proc; } } } @Override public Procedure caseInstance(Instance instance) { this.instance = instance; final Procedure result = super.caseInstance(instance); this.instance = null; return result; } @Override public Procedure caseActor(Actor actor) { this.actor = actor; this.copier = new EcoreUtil.Copier(); this.indexProc = 0; this.indexVar = 0; List<Procedure> procs = new ArrayList<Procedure>(actor.getProcs()); for (Procedure procedure : procs) { doSwitch(procedure); } for (Action action : actor.getActions()) { doSwitch(action); } for (Action initialize : actor.getInitializes()) { doSwitch(initialize); } return null; } private List<String> getPackage(EObject eObject) { String[] name = { "" }; if (eObject instanceof Actor) { name = ((Actor) eObject).getName().split("\\."); } else if (eObject instanceof Unit) { name = ((Unit) eObject).getName().split("\\."); } return Arrays.asList(name); } private String getCurrentEntityName() { if (instance != null) { return instance.getName(); } else if (actor != null) { return actor.getName(); } else { return ""; } } }