Commit ce17f304 authored by Nils Kaminski's avatar Nils Kaminski
Browse files

Fix execution order of value events

parent 925b8e12
......@@ -8,6 +8,7 @@ import de.monticore.lang.monticar.generator.Instruction;
import de.monticore.lang.monticar.generator.Method;
import de.monticore.lang.monticar.generator.TargetCodeInstruction;
import de.monticore.lang.monticar.generator.Variable;
import de.monticore.lang.monticar.generator.cpp.instruction.ExecuteDynamicConnects;
import de.monticore.lang.monticar.generator.order.ImplementExecutionOrder;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.logging.Log;
......@@ -45,6 +46,7 @@ public class ExecutionOrderFixer {
newList.addAll(joinInstructions);
newList.addAll(otherInstructions);
fixDynamicInstruction(newList, bluePrintCPP);
fixNextInstruction(newList, bluePrintCPP);
method.setInstructions(newList);
......@@ -66,6 +68,12 @@ public class ExecutionOrderFixer {
}
}
public static void fixDynamicInstruction(List<Instruction> newList, BluePrintCPP bluePrintCPP){
if(bluePrintCPP.getMethod("dynamic").isPresent()){
newList.add(0, new TargetCodeInstruction("dynamic();\n"));
}
}
public static boolean listContainsExecuteInstruction(List<Instruction> list, String name) {
for (Instruction instruction : list) {
if (instruction.isExecuteInstruction()) {
......@@ -115,6 +123,20 @@ public class ExecutionOrderFixer {
if(instruction.isTargetCodeInstruction() && instruction.getTargetLanguageInstruction().equals("next();\n")){
continue;
}
if(instruction.isTargetCodeInstruction() && (instruction instanceof ExecuteDynamicConnects)){
ExecuteDynamicConnects edc = (ExecuteDynamicConnects)instruction;
if(edc.getAfterComponent().isPresent()){
if(!map.containsKey(edc.getAfterComponentName())){
List<Instruction> l = new ArrayList<>();
map.put(edc.getAfterComponentName(),l);
}
map.get(edc.getAfterComponentName()).add(instruction);
continue;
}
}
otherInstructions.add(instruction);
}
}
......
package de.monticore.lang.monticar.generator.cpp.converter;
import alice.tuprolog.Var;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAConnectorInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicConnectorInstanceSymbol;
......@@ -16,8 +18,10 @@ import de.monticore.lang.monticar.generator.cpp.GeneratorCPP;
import de.monticore.lang.monticar.generator.cpp.VariablePortValueChecker;
import de.monticore.lang.monticar.generator.cpp.instruction.ConnectInstructionCPP;
import de.monticore.lang.monticar.generator.cpp.instruction.EventConnectInstructionCPP;
import de.monticore.lang.monticar.generator.cpp.instruction.ExecuteDynamicConnects;
import de.se_rwth.commons.logging.Log;
import javax.swing.plaf.metal.MetalTheme;
import java.util.*;
public class EventConverter {
......@@ -35,7 +39,9 @@ public class EventConverter {
boolean generateCondition = false;
if(event.isDynamicPortConnectionEvent()) {
generateCondition = generateDynamicConnectEvent(event, componentSymbol, executeMethod, bluePrint);
// generateCondition = generateDynamicConnectEvent(event, componentSymbol, executeMethod, bluePrint);
int x = 5/0;
generateCondition = EventDynamicConnectConverter.generateDynamicConnectEvent(event, componentSymbol, executeMethod, bluePrint);
}else{
Log.info("Create connectors for: "+event.getFullName(), "EventConverter");
......@@ -76,74 +82,63 @@ public class EventConverter {
}
return number > 0;
}
protected static boolean generateDynamicConnectEvent(EMADynamicEventHandlerInstanceSymbol event, EMAComponentInstanceSymbol componentSymbol, Method executeMethod, BluePrintCPP bluePrint ) {
List<String> names= new ArrayList<>();
event.getCondition().getConnectPortNames(names);
java.util.Collections.sort(names);
String connectMethodName = "connect_"+String.join("_", names);
if(!bluePrint.getMethod(connectMethodName).isPresent()){
generateConnectMethod(connectMethodName,names, componentSymbol, bluePrint);
}
//TODO generate event body method
String bodyname = "__event_body_"+event.getName().replace("[", "_").replace("]", "_");
Method body = new Method(bodyname, "void");
body.setPublic(false);
body.addInstruction(new TargetCodeInstruction("if("+EventConnectInstructionCPP.getEventNameCPP(event.getName())+"){\n"));
Map<String,List<String>> newPorts = new HashMap<>();
// newPorts.put("_this_", names);
for(String name : names){
body.addInstruction(new TargetCodeInstruction(
String.format("int _%s_dynPortID = __%s_connect_request.front(); __%s_connect_request.pop();\n",
name, name, name)));
}
for (Map.Entry<String,List<String>> entry : newPorts.entrySet()){
for(String port : entry.getValue()){
body.addInstruction(new TargetCodeInstruction("// TODO: "+entry.getKey()+" . "+port+"\n"));
}
}
@Deprecated
protected static boolean generateDynamicConnectEvent(EMADynamicEventHandlerInstanceSymbol event, EMAComponentInstanceSymbol componentSymbol, Method executeMethod, BluePrintCPP bluePrint ) {
body.addInstruction(new TargetCodeInstruction("}\n"));
// EMADynamicComponentInstanceSymbol dynComp = (EMADynamicComponentInstanceSymbol)componentSymbol;
//
// for(EMADynamicConnectorInstanceSymbol connector : event.getConnectorsDynamic()){
// EMADynamicConnectorInstanceSymbol dynConnect = (EMADynamicConnectorInstanceSymbol) connector;
//
//// body.addInstruction(new TargetCodeInstruction(
//// "// connect: "+dynConnect.getSource()+" -> "+dynConnect.getTarget()+"\n"
//// ));
//
// String afterComponent = "";
// String sourceName = dynConnect.getSource();
// String targetName = dynConnect.getTarget();
// EMAPortInstanceSymbol target = dynConnect.getTargetPort();
//
// if(dynConnect.isDynamicSourceNewPort()){
// if(sourceName.contains(".")){
// //TODO target hat eine komponente
// }else{
// sourceName = EMAPortSymbol.getNameWithoutArrayBracketPart(sourceName);
// sourceName = String.format("%s[_%s_dynPortID]", sourceName, sourceName);
// }
// }
//
// if(dynConnect.isDynamicTargetNewPort()){
// if(targetName.contains(".")){
// //TODO target hat eine komponente
// System.out.println("bla bla");
// }else{
// targetName = EMAPortSymbol.getNameWithoutArrayBracketPart(targetName);
// targetName = String.format("%s[_%s_dynPortID]", targetName, targetName);
// }
// }
//
// Optional<VariableType> vt = TypeConverter.getVariableTypeForMontiCarTypeName(target.getTypeReference().getName());
// generateEventDynamicConnectVecotr(vt.get().getTypeNameTargetLanguage(), bluePrint);
//
//
// body.addInstruction(new TargetCodeInstruction(String.format(
//// "// connect: "+sourceName+" - "+targetName+"\n"
// "__dynamic_%s_connect.push_back({%s, &%s, &%s});\n", vt.get().getTypeNameTargetLanguage(), afterComponent, sourceName, targetName
// )));
//
//// executeMethod.addInstruction(new TargetCodeInstruction(
//// "executeDynamicConnects("+afterComponent+");\n"
//// ));
// executeMethod.addInstruction(new ExecuteDynamicConnects(afterComponent));
// }
//
bluePrint.addMethod(body);
return true;
}
protected static void generateConnectMethod(String name,List<String> names, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
Log.info("Create connect method: "+name+"(...)", "EventConverter");
Method method = new Method(name, "bool");
List<String> checks = new ArrayList<>();
for(String n : names ){
Variable v = new Variable();
v.setName(n+"_indexref");
v.setTypeNameTargetLanguage("int*");
method.addParameter(v);
long counter = componentSymbol.getPortInstanceList().stream().filter(p->p.getNameWithoutArrayBracketPart().equals(n)).count();
String inst = String.format("*%s_indexref = dynamicconnect(%d, __%s_connected, &__%s_connect_request);\n", n, counter, n,n);
method.addInstruction(
new TargetCodeInstruction(inst)
);
checks.add(String.format("(*%s_indexref < 0)", n));
}
method.addInstruction(new TargetCodeInstruction(
String.format("if(%s){return false;}\n", String.join(" || ", checks))
));
method.addInstruction(new TargetCodeInstruction("return true;\n"));
bluePrint.addAdditionalIncludeString("DynamicHelper");
bluePrint.addMethod(method);
}
public static void generatePVCNextMethod(BluePrintCPP bluePrint){
......@@ -196,6 +191,10 @@ public class EventConverter {
}
}
//<editor-fold desc="Generate event condition">
protected static String generateEventCondition(EventExpressionSymbol expression, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
......
package de.monticore.lang.monticar.generator.cpp.converter;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicConnectorInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicEventHandlerInstanceSymbol;
import de.monticore.lang.monticar.generator.*;
import de.monticore.lang.monticar.generator.cpp.BluePrintCPP;
import de.monticore.lang.monticar.generator.cpp.instruction.EventConnectInstructionCPP;
import de.monticore.lang.monticar.generator.cpp.instruction.ExecuteDynamicConnects;
import de.se_rwth.commons.logging.Log;
import java.util.*;
public class EventDynamicConnectConverter {
protected static final String DYNPORTID = "_%s_dynPortID";
protected static final String THISCOMPONENTPORTREQUEST = "int "+DYNPORTID+" = __%s_connect_request.front(); __%s_connect_request.pop();\n";
protected static final String DYNPORTIDININSTANCE = "_%s_%s_dynPortID";
protected static final String DYNPORTIDININSTANCEINIT = "int "+DYNPORTIDININSTANCE+" = -1;\n";
public static boolean generateDynamicConnectEvent(EMADynamicEventHandlerInstanceSymbol event, EMAComponentInstanceSymbol componentSymbol, Method executeMethod, BluePrintCPP bluePrint ) {
List<String> names= new ArrayList<>();
event.getCondition().getConnectPortNames(names);
java.util.Collections.sort(names);
Map<String,List<String>> newPortsInstances = getNewPortsOfInstances(event);
generateConnectMethod(names, componentSymbol, bluePrint);
String bodyname = "__event_body_"+event.getName().replace("[", "_").replace("]", "_");
Method body = new Method(bodyname, "void");
body.setPublic(false);
generateDynamicMethod(bluePrint, bodyname);
body.addInstruction(new TargetCodeInstruction("while("+EventConnectInstructionCPP.getEventNameCPP(event.getName())+"()){\n"));
generateHandleConnectRequestsOfQueues(names, body);
generateHandleConnectRequestInInstances(newPortsInstances, body);
generateConnects(event, body, bluePrint, executeMethod);
body.addInstruction(new TargetCodeInstruction("}\n"));
bluePrint.addMethod(body);
return true;
}
protected static void generateConnectMethod(List<String> names, EMAComponentInstanceSymbol componentSymbol, BluePrintCPP bluePrint){
String name = "connect_"+String.join("_", names);
if(bluePrint.getMethod(name).isPresent()){
return;
}
Log.info("Create connect method: "+name+"(...)", "EventConverter");
Method method = new Method(name, "bool");
List<String> checks = new ArrayList<>();
for(String n : names ){
Variable v = new Variable();
v.setName(n+"_indexref");
v.setTypeNameTargetLanguage("int*");
method.addParameter(v);
long counter = componentSymbol.getPortInstanceList().stream().filter(p->p.getNameWithoutArrayBracketPart().equals(n)).count();
String inst = String.format("*%s_indexref = dynamicconnect(%d, __%s_connected, &__%s_connect_request);\n", n, counter, n,n);
method.addInstruction(
new TargetCodeInstruction(inst)
);
checks.add(String.format("(*%s_indexref < 0)", n));
}
method.addInstruction(new TargetCodeInstruction(
String.format("if(%s){return false;}\n", String.join(" || ", checks))
));
method.addInstruction(new TargetCodeInstruction("return true;\n"));
bluePrint.addAdditionalIncludeString("DynamicHelper");
bluePrint.addMethod(method);
}
protected static void generateDynamicMethod(BluePrintCPP bluePrint, String eventBodyName){
Optional<Method> dynamic = bluePrint.getMethod("dynamic");
if(!dynamic.isPresent()){
Method d = new Method("dynamic", "void");
d.setPublic(false);
bluePrint.addMethod(d);
dynamic = Optional.of(d);
}
dynamic.get().addInstruction(new TargetCodeInstruction(eventBodyName+"();\n"));
}
protected static Map<String, List<String>> getNewPortsOfInstances(EMADynamicEventHandlerInstanceSymbol event){
Map<String,List<String>> newPorts = new HashMap<>();
for(EMADynamicConnectorInstanceSymbol connector : event.getConnectorsDynamic()){
Optional<String> comp = connector.getSourceComponentName();
String p;
if( connector.isDynamicSourceNewPort() && comp.isPresent()){
if(!newPorts.containsKey(comp.get())){
newPorts.put(comp.get(), new ArrayList<>());
}
p = EMAPortSymbol.getNameWithoutArrayBracketPart(connector.getSourcePortName());
if(!newPorts.get(comp.get()).contains(p)){
newPorts.get(comp.get()).add(p);
}
}
comp = connector.getTargetComponentName();
if(connector.isDynamicTargetNewPort() && comp.isPresent()){
if(!newPorts.containsKey(comp.get())){
newPorts.put(comp.get(), new ArrayList<>());
}
p = EMAPortSymbol.getNameWithoutArrayBracketPart(connector.getTargetPortName());
if(!newPorts.get(comp.get()).contains(p)){
newPorts.get(comp.get()).add(p);
}
}
}
return newPorts;
}
protected static void generateHandleConnectRequestsOfQueues(List<String> names, Method body){
for(String name : names){
body.addInstruction(new TargetCodeInstruction(
String.format(THISCOMPONENTPORTREQUEST,
name, name, name)));
}
}
protected static void generateHandleConnectRequestInInstances(Map<String, List<String>> newPorts, Method body){
for (Map.Entry<String,List<String>> entry : newPorts.entrySet()){
Collections.sort(entry.getValue());
String inst = entry.getKey()+".connect_"+String.join("_", entry.getValue())+"(";
// for(String port : entry.getValue()){
for(int i = 0; i < entry.getValue().size(); ++i){
body.addInstruction(new TargetCodeInstruction(String.format(
DYNPORTIDININSTANCEINIT, convertName(entry.getKey()), entry.getValue().get(i)
)));
inst = inst + "&"+String.format(DYNPORTIDININSTANCE, convertName(entry.getKey()), entry.getValue().get(i));
if(i < entry.getValue().size()-1){
inst += ", ";
}
}
body.addInstruction(new TargetCodeInstruction(String.format(
"if(!"+inst+")){return ;}\n"
)));
}
}
protected static void generateConnects(EMADynamicEventHandlerInstanceSymbol event, Method body, BluePrintCPP bluePrint, Method executeMethod){
for(EMADynamicConnectorInstanceSymbol connector : event.getConnectorsDynamic()){
Optional<String> afterComponent = Optional.empty();
String sourceName = connector.getSource();
String targetName = connector.getTarget();
EMAPortInstanceSymbol target = connector.getTargetPort();
if(connector.isDynamicSourceNewPort()){
sourceName = generateConnectNameForNewPort(sourceName, connector.getSourceComponentName(), connector.getSourcePortName());
afterComponent = connector.getSourceComponentName();
}
if(connector.isDynamicTargetNewPort()){
targetName = generateConnectNameForNewPort(targetName, connector.getTargetComponentName(), connector.getTargetPortName());
}
Optional<VariableType> vt = TypeConverter.getVariableTypeForMontiCarTypeName(target.getTypeReference().getName());
generateEventDynamicConnectVector(vt.get().getTypeNameTargetLanguage(), bluePrint);
executeMethod.addInstruction(new ExecuteDynamicConnects(afterComponent));
if(!afterComponent.isPresent()){
afterComponent = Optional.of("NULL");
}else{
afterComponent = Optional.of("&"+afterComponent.get());
}
body.addInstruction(new TargetCodeInstruction(String.format(
"__dynamic_%s_connect.push_back({%s, &%s, &%s});\n", vt.get().getTypeNameTargetLanguage(), afterComponent.get(), sourceName, targetName
)));
}
}
protected static void generateEventDynamicConnectVector(String typeName, BluePrint bluePrint){
Optional<Method> execDynConnects = bluePrint.getMethod("executeDynamicConnects");
if(!execDynConnects.isPresent()){
Method m = new Method("executeDynamicConnects", "void");
Variable p = new Variable();
p.setName("afterComponent");
p.setTypeNameTargetLanguage("void*");
m.addParameter(p);
bluePrint.addMethod(m);
execDynConnects = Optional.of(m);
}
String cConnectVarName = "__dynamic_"+typeName+"_connect";
if(!bluePrint.getVariable(cConnectVarName).isPresent()){
Variable vdConnect = new Variable();
vdConnect.setName(cConnectVarName);
vdConnect.setTypeNameTargetLanguage("std::vector<connection<"+typeName+">>");
vdConnect.setPublic(false);
bluePrint.addVariable(vdConnect);
execDynConnects.get().addInstruction(new TargetCodeInstruction(String.format(
"for (std::vector<connection<%s>>::iterator it = __dynamic_%s_connect.begin(); it < __dynamic_%s_connect.end(); ++it) {if(it->afterComponent == afterComponent){*(*it).target = *(*it).source;}}\n",
typeName, typeName,typeName
)));
}
}
protected static String generateConnectNameForNewPort(String allName, Optional<String> componenName, String portName){
String result = "";
if(componenName.isPresent()){
result = String.format("%s["+DYNPORTIDININSTANCE+"]",
EMAPortSymbol.getNameWithoutArrayBracketPart(allName),
convertName(componenName.get()),
EMAPortSymbol.getNameWithoutArrayBracketPart(portName));
}else{
result = EMAPortSymbol.getNameWithoutArrayBracketPart(allName);
result = String.format("%s["+DYNPORTID+"]", result, result);
}
return result;
}
protected static String convertName(String name){
return name.replace("[", "_").replace("]", "_");
}
}
package de.monticore.lang.monticar.generator.cpp.instruction;
import de.monticore.lang.monticar.generator.Instruction;
import java.util.Optional;
public class ExecuteDynamicConnects implements Instruction {
protected Optional<String> afterComponent;
public ExecuteDynamicConnects(){
afterComponent = Optional.empty();
}
public ExecuteDynamicConnects(String after){
afterComponent = Optional.of(after);
}
public ExecuteDynamicConnects(Optional<String> after){
afterComponent = after;
}
@Override
public String getTargetLanguageInstruction() {
if(!afterComponent.isPresent()){
return "executeDynamicConnects(NULL);\n";
}
return "executeDynamicConnects(&"+afterComponent.get()+");\n";
}
@Override
public boolean isConnectInstruction() {
return false;
}
@Override
public boolean isTargetCodeInstruction() {
return true;
}
@Override
public boolean isExecuteInstruction() {
return false;
}
public Optional<String> getAfterComponent() {
return afterComponent;
}
public String getAfterComponentName(){
return afterComponent.orElse("");
}
}
......@@ -4,6 +4,7 @@ import de.ma2cfg.helper.Names;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAConnectorInstanceSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAPortInstanceSymbol;
import de.monticore.lang.embeddedmontiarcdynamic.embeddedmontiarcdynamic._symboltable.instanceStructure.EMADynamicComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.order.nfp.TagExecutionOrderTagSchema.TagExecutionOrderSymbol;
import de.monticore.lang.tagging._symboltable.TaggingResolver;
import de.se_rwth.commons.Splitters;
......@@ -72,8 +73,16 @@ public class ImplementExecutionOrder {
* Then the component B will be stored in 'dependencies' with the ports in1 and in2 of component A.
*/
private static void getDependencies(EMAComponentInstanceSymbol inst) {
Collection<EMAConnectorInstanceSymbol> connectors;
if(inst instanceof EMADynamicComponentInstanceSymbol){
connectors = ((EMADynamicComponentInstanceSymbol)inst).getConnectorInstancesAndEventConnectorInstances();
}else{
connectors = inst.getConnectorInstances();
}
//Log.info(inst.toString()," getDependencies from:");
for (EMAConnectorInstanceSymbol c : inst.getConnectorInstances()) {
for (EMAConnectorInstanceSymbol c : connectors) {
//Log.info(c.toString(),"ConnectorSymbol:");
EMAPortInstanceSymbol pt = connectorTargetPort(inst, c);
EMAPortInstanceSymbol ps = connectorSourcePort(inst, c);
......@@ -193,7 +202,7 @@ public class ImplementExecutionOrder {
ExecutionOrder e = new NonVirtualBlock(s, b);
taggingResolver.addTag(subInst, new TagExecutionOrderSymbol(e));
b += 1;
Collection<EMAConnectorInstanceSymbol> connects = inst.getConnectorInstances().stream()
Collection<EMAConnectorInstanceSymbol> connects = getAllConnectorInstances(inst).stream()
.filter(c -> subInst.getOutgoingPortInstances().contains(connectorSourcePort(inst, c)))
.collect(Collectors.toList());
for (EMAConnectorInstanceSymbol c : connects) {
......@@ -226,7 +235,7 @@ public class ImplementExecutionOrder {
* @param p The source port
*/
private static EMAComponentInstanceSymbol dependencyPortDeletion(TaggingResolver taggingResolver, EMAComponentInstanceSymbol inst, EMAPortInstanceSymbol p) {
Collection<EMAConnectorInstanceSymbol> connects = inst.getConnectorInstances().stream()