Commit 15504b17 authored by Evgeny Kusmenko's avatar Evgeny Kusmenko
Browse files

Merge branch 'sim_dev' into 'master'

Library-interface & server-adapter updates

See merge request !54
parents 53a62635 f56b4c00
Pipeline #494528 passed with stage
in 1 minute and 36 seconds
...@@ -25,5 +25,3 @@ buildNumber.properties ...@@ -25,5 +25,3 @@ buildNumber.properties
.project .project
.vscode/ .vscode/
.settings/ .settings/
temp/
\ No newline at end of file
# In order to update the 'shared_cpp' submodule
variables:
GIT_SUBMODULE_STRATEGY: recursive
stages: stages:
- linux - linux
#- windows #- windows
......
[submodule "src/main/resources/shared_cpp"]
path = src/main/resources/shared_cpp
url = ../../simulators/shared_cpp
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
<groupId>de.monticore.lang.monticar</groupId> <groupId>de.monticore.lang.monticar</groupId>
<artifactId>embedded-montiarc-math-generator</artifactId> <artifactId>embedded-montiarc-math-generator</artifactId>
<version>0.4.7</version> <version>0.4.8</version>
<!-- == PROJECT DEPENDENCIES ============================================= --> <!-- == PROJECT DEPENDENCIES ============================================= -->
......
...@@ -14,7 +14,7 @@ import de.monticore.lang.monticar.generator.cmake.CMakeFindModule; ...@@ -14,7 +14,7 @@ import de.monticore.lang.monticar.generator.cmake.CMakeFindModule;
import de.monticore.lang.monticar.generator.cpp.Dynamics.DynamicHelper; import de.monticore.lang.monticar.generator.cpp.Dynamics.DynamicHelper;
import de.monticore.lang.monticar.generator.cpp.Dynamics.EventPortValueCheck; import de.monticore.lang.monticar.generator.cpp.Dynamics.EventPortValueCheck;
import de.monticore.lang.monticar.generator.cpp.converter.*; import de.monticore.lang.monticar.generator.cpp.converter.*;
import de.monticore.lang.monticar.generator.cpp.dynamic_interface.DynamicInterfaceGenerator; import de.monticore.lang.monticar.generator.cpp.dynamic_interface.AdapterGenerator;
import de.monticore.lang.monticar.generator.cpp.loopSolver.CPPEquationSystemHelper; import de.monticore.lang.monticar.generator.cpp.loopSolver.CPPEquationSystemHelper;
import de.monticore.lang.monticar.generator.cpp.loopSolver.EquationSystemComponentInstanceSymbol; import de.monticore.lang.monticar.generator.cpp.loopSolver.EquationSystemComponentInstanceSymbol;
import de.monticore.lang.monticar.generator.cpp.loopSolver.NumericSolverOptions; import de.monticore.lang.monticar.generator.cpp.loopSolver.NumericSolverOptions;
...@@ -49,9 +49,8 @@ public class GeneratorCPP implements EMAMGenerator { ...@@ -49,9 +49,8 @@ public class GeneratorCPP implements EMAMGenerator {
public static GeneratorCPP currentInstance; public static GeneratorCPP currentInstance;
private Path modelsDirPath; private Path modelsDirPath;
private boolean isGenerateTests = false; private boolean isGenerateTests = false;
private boolean genDynamicInterface = false; private boolean genLibraryInterface = false;
private boolean genServerAdapter = false; private boolean genServerAdapter = false;
private boolean genDDCAdapter = false;
private boolean importArmadillo = false; private boolean importArmadillo = false;
private String outputName = ""; private String outputName = "";
private boolean isGenerateServerWrapper = false; private boolean isGenerateServerWrapper = false;
...@@ -391,16 +390,15 @@ public class GeneratorCPP implements EMAMGenerator { ...@@ -391,16 +390,15 @@ public class GeneratorCPP implements EMAMGenerator {
public void generateAdapters(List<FileContent> fileContents, EMAComponentInstanceSymbol component) { public void generateAdapters(List<FileContent> fileContents, EMAComponentInstanceSymbol component) {
if (genDynamicInterface || genServerAdapter || genDDCAdapter) { if (genLibraryInterface || genServerAdapter) {
try { try {
fileContents.addAll( fileContents.addAll(
new DynamicInterfaceGenerator( new AdapterGenerator(
component, component,
cMakeConfig, cMakeConfig,
outputName, outputName,
genDynamicInterface, genLibraryInterface,
genServerAdapter, genServerAdapter
genDDCAdapter
).getFiles() ).getFiles()
); );
} catch (SerializationException | IOException e) { } catch (SerializationException | IOException e) {
...@@ -541,8 +539,8 @@ public class GeneratorCPP implements EMAMGenerator { ...@@ -541,8 +539,8 @@ public class GeneratorCPP implements EMAMGenerator {
isGenerateTests = generateTests; isGenerateTests = generateTests;
} }
public boolean isGenerateDynamicInterface() { public boolean isGenerateLibraryInterface() {
return genDynamicInterface; return genLibraryInterface;
} }
public void setImportArmadillo(boolean doImport) { public void setImportArmadillo(boolean doImport) {
...@@ -553,8 +551,8 @@ public class GeneratorCPP implements EMAMGenerator { ...@@ -553,8 +551,8 @@ public class GeneratorCPP implements EMAMGenerator {
return importArmadillo; return importArmadillo;
} }
public void setGenerateDynamicInterface(boolean gen) { public void setGenerateLibraryInterface(boolean gen) {
genDynamicInterface = gen; genLibraryInterface = gen;
} }
public boolean isGenerateServerAdapter() { public boolean isGenerateServerAdapter() {
...@@ -565,14 +563,6 @@ public class GeneratorCPP implements EMAMGenerator { ...@@ -565,14 +563,6 @@ public class GeneratorCPP implements EMAMGenerator {
genServerAdapter = gen; genServerAdapter = gen;
} }
public boolean isGenerateDDCAdapter() {
return genDDCAdapter;
}
public void setGenerateDDCAdapter(boolean gen) {
genDDCAdapter = gen;
}
public void setOutputName(String name) { public void setOutputName(String name) {
this.outputName = name; this.outputName = name;
} }
......
...@@ -106,9 +106,9 @@ public final class GeneratorCppCli { ...@@ -106,9 +106,9 @@ public final class GeneratorCppCli {
.build(); .build();
public static final Option OPTION_FLAG_DYNAMIC_INTERFACE = Option.builder("di") public static final Option OPTION_FLAG_LIBRARY_INTERFACE = Option.builder()
.longOpt("dyn-interface") .longOpt("library-interface")
.desc("Enable autopilot adapter generation") .desc("Enables the autopilot library-adapter generation")
.hasArg(false) .hasArg(false)
.required(false) .required(false)
.build(); .build();
...@@ -120,13 +120,6 @@ public final class GeneratorCppCli { ...@@ -120,13 +120,6 @@ public final class GeneratorCppCli {
.required(false) .required(false)
.build(); .build();
public static final Option OPTION_FLAG_GEN_DDC_ADAPTER = Option.builder("ddc")
.longOpt("ddc-adapter")
.desc("Generate the DDC adapter for the model")
.hasArg(false)
.required(false)
.build();
public static final Option OPTION_FLAG_CHECK_MODEL_DIR = Option.builder() public static final Option OPTION_FLAG_CHECK_MODEL_DIR = Option.builder()
.longOpt("check-model-dir") .longOpt("check-model-dir")
.desc("optional flag indicating if model dir should be checked for creation of component and stream list") .desc("optional flag indicating if model dir should be checked for creation of component and stream list")
...@@ -266,10 +259,9 @@ public final class GeneratorCppCli { ...@@ -266,10 +259,9 @@ public final class GeneratorCppCli {
options.addOption(OPTION_FLAG_TESTS); options.addOption(OPTION_FLAG_TESTS);
options.addOption(OPTION_FLAG_ARMADILLO); options.addOption(OPTION_FLAG_ARMADILLO);
options.addOption(OPTION_IMPORT_ARMADILLO); options.addOption(OPTION_IMPORT_ARMADILLO);
options.addOption(OPTION_FLAG_DYNAMIC_INTERFACE); options.addOption(OPTION_FLAG_LIBRARY_INTERFACE);
options.addOption(OPTION_OUTPUT_NAME); options.addOption(OPTION_OUTPUT_NAME);
options.addOption(OPTION_FLAG_GEN_TCP_SERVER); options.addOption(OPTION_FLAG_GEN_TCP_SERVER);
options.addOption(OPTION_FLAG_GEN_DDC_ADAPTER);
options.addOption(OPTION_FLAG_CHECK_MODEL_DIR); options.addOption(OPTION_FLAG_CHECK_MODEL_DIR);
options.addOption(OPTION_FLAG_SERVER_WRAPPER); options.addOption(OPTION_FLAG_SERVER_WRAPPER);
options.addOption(OPTION_FLAG_ALGEBRAIC); options.addOption(OPTION_FLAG_ALGEBRAIC);
...@@ -321,9 +313,8 @@ public final class GeneratorCppCli { ...@@ -321,9 +313,8 @@ public final class GeneratorCppCli {
} }
g.setCheckModelDir(cliArgs.hasOption(OPTION_FLAG_CHECK_MODEL_DIR.getLongOpt())); g.setCheckModelDir(cliArgs.hasOption(OPTION_FLAG_CHECK_MODEL_DIR.getLongOpt()));
g.setGenerateServerWrapper(cliArgs.hasOption(OPTION_FLAG_SERVER_WRAPPER.getLongOpt())); g.setGenerateServerWrapper(cliArgs.hasOption(OPTION_FLAG_SERVER_WRAPPER.getLongOpt()));
g.setGenerateDynamicInterface(cliArgs.hasOption(OPTION_FLAG_DYNAMIC_INTERFACE.getLongOpt())); g.setGenerateLibraryInterface(cliArgs.hasOption(OPTION_FLAG_LIBRARY_INTERFACE.getLongOpt()));
g.setGenerateServerAdapter(cliArgs.hasOption(OPTION_FLAG_GEN_TCP_SERVER.getLongOpt())); g.setGenerateServerAdapter(cliArgs.hasOption(OPTION_FLAG_GEN_TCP_SERVER.getLongOpt()));
g.setGenerateDDCAdapter(cliArgs.hasOption(OPTION_FLAG_GEN_DDC_ADAPTER.getLongOpt()));
g.setOutputName(cliArgs.getOptionValue(OPTION_OUTPUT_NAME.getOpt())); g.setOutputName(cliArgs.getOptionValue(OPTION_OUTPUT_NAME.getOpt()));
g.setUseAlgebraicOptimizations(cliArgs.hasOption(OPTION_FLAG_ALGEBRAIC.getLongOpt())); g.setUseAlgebraicOptimizations(cliArgs.hasOption(OPTION_FLAG_ALGEBRAIC.getLongOpt()));
......
...@@ -41,7 +41,7 @@ public final class TypesGeneratorCPP { ...@@ -41,7 +41,7 @@ public final class TypesGeneratorCPP {
} else if (s instanceof EnumDeclarationSymbol) { } else if (s instanceof EnumDeclarationSymbol) {
processEnum((EnumDeclarationSymbol) s); processEnum((EnumDeclarationSymbol) s);
} else { } else {
Log.warn("unknown type symbol: " + s.getFullName()); //Log.warn("unknown type symbol: " + s.getFullName());
} }
} }
......
package de.monticore.lang.monticar.generator.cpp.dynamic_interface;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import de.rwth.montisim.commons.dynamicinterface.*;
import de.rwth.montisim.commons.dynamicinterface.PortInformation.PortType;
import de.rwth.montisim.commons.utils.json.SerializationException;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cmake.CMakeConfig;
import de.monticore.lang.monticar.generator.cpp.FileUtil;
import de.monticore.lang.monticar.generator.cpp.dynamic_interface.ProgramInterfaceResolver.SocketInfo;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstanceSymbol;
/*
Generates the CPP files necessary to build the 'library_interface' or the 'server_adapter' for the ema component.
*/
public class AdapterGenerator {
HashSet<String> fileDependenciesOwnCpp = new HashSet<>();
HashSet<String> fileDependenciesSharedCpp = new HashSet<>();
List<FileContent> files = new ArrayList<>();
ProgramInterfaceResolver interfaceResolver;
public AdapterGenerator(
EMAComponentInstanceSymbol componentSymbol,
CMakeConfig cmake,
String outputName,
boolean genLibInterface,
boolean genServerAdapter
) throws SerializationException, IOException {
if (outputName.length() == 0) outputName = componentSymbol.getName();
// Read the ProgramInterface from the model
interfaceResolver = new ProgramInterfaceResolver();
interfaceResolver.resolve(componentSymbol);
String targetNameWithSerialization = outputName+ "_with_serialization";
String targetNameLib = outputName+ "_lib";
String targetNameServer = outputName+ "_server";
// Generate the serialization code
HashMap<String, Object> serializationTemplateData = new HashMap<>();
serializationTemplateData.put("mainModelName", interfaceResolver.componentName);
serializationTemplateData.put("interfaceDescription", interfaceResolver.progInterfaceString);
serializationTemplateData.put("portCount", interfaceResolver.programInterface.ports.size());
serializationTemplateData.put("isSocket", getIsSocketList());
serializationTemplateData.put("isOutput", getIsOutputList());
new JsonSerializationGenerator(this).generate(serializationTemplateData);
new BinarySerializationGenerator(this).generate(serializationTemplateData);
new PortInitGenerator(this).generate(serializationTemplateData);;
files.add(new FileContent(AllTemplates.generate(AllTemplates.ADAPTER_PROGRAM_H, serializationTemplateData), "program.h"));
files.add(new FileContent(AllTemplates.generate(AllTemplates.ADAPTER_PROGRAM_CPP, serializationTemplateData), "program.cpp"));
addFileDependencySharedCpp("buffer.h");
addFileDependencySharedCpp("buffer.cpp");
addFileDependencySharedCpp("json.h");
addFileDependencySharedCpp("json.cpp");
addFileDependencySharedCpp("printf.h");
addFileDependencySharedCpp("printf.cpp");
addFileDependencySharedCpp("err_out.h");
addFileDependencySharedCpp("err_out.cpp");
// TODO "intermediate target" with serialization code ?
cmake.addCMakeCommandEnd("# A static library around the root EMA component with JSON/Binary serialization functions.");
cmake.addCMakeCommandEnd("add_library("+targetNameWithSerialization+" STATIC program.cpp buffer.cpp json.cpp printf.cpp err_out.cpp)");
cmake.addCMakeCommandEnd("target_include_directories("+targetNameWithSerialization+" PUBLIC ${INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})");
//cmake.addCMakeCommandEnd("target_link_libraries("+targetNameWithSerialization+" PUBLIC ${LIBS} -static-libgcc -static-libstdc++)");
cmake.addCMakeCommandEnd("target_link_libraries("+targetNameWithSerialization+" PRIVATE ${LIBS})");
cmake.addCMakeCommandEnd("target_compile_features("+targetNameWithSerialization+" PUBLIC cxx_std_11)");
cmake.addCMakeCommandEnd("set_target_properties("+targetNameWithSerialization+" PROPERTIES LINKER_LANGUAGE CXX POSITION_INDEPENDENT_CODE ON)");
cmake.addCMakeCommandEnd("");
cmake.addCMakeCommandEnd("");
// Generate the files
if (genLibInterface) {
addFileDependencySharedCpp("library_interface.h");
addFileDependencyOwnCpp("library_interface.cpp");
// CMake
// create shared lib for "library_interface"
cmake.addCMakeCommandEnd("# The library-interface based communication adapter (for the hardware_emulator)");
cmake.addCMakeCommandEnd("add_library("+targetNameLib+" SHARED library_interface.cpp)");
cmake.addCMakeCommandEnd("target_link_libraries("+targetNameLib+" PUBLIC -static-libgcc -static-libstdc++ "+targetNameWithSerialization+")");
cmake.addCMakeCommandEnd("set_target_properties("+targetNameLib+" PROPERTIES LINKER_LANGUAGE CXX POSITION_INDEPENDENT_CODE ON)");
cmake.addCMakeCommandEnd("set_target_properties("+targetNameLib+" PROPERTIES PREFIX \"\")");
// install shared lib
cmake.addCMakeCommandEnd("install(TARGETS "+targetNameLib+" DESTINATION $ENV{DLL_DIR})");
//cmake.addCMakeCommandEnd("export(TARGETS "+outputName+" FILE "+outputName+".cmake)");
cmake.addCMakeCommandEnd("");
}
if (genServerAdapter) {
addFileDependencySharedCpp("network.h");
addFileDependencySharedCpp("network.cpp");
addFileDependencySharedCpp("tcp_protocol.h");
addFileDependencyOwnCpp("server_adapter.h");
addFileDependencySharedCpp("standard_err_out.h");
addFileDependencySharedCpp("standard_err_out.cpp");
addFileDependencyOwnCpp("server_adapter.cpp");
// create adapter executable
cmake.addCMakeCommandEnd("# ServerAdapter for the EMA component");
cmake.addCMakeCommandEnd("add_executable("+targetNameServer+" server_adapter.cpp network.cpp standard_err_out.cpp)");
cmake.addCMakeCommandEnd("target_link_libraries("+targetNameServer+" PUBLIC "+targetNameWithSerialization+")");
cmake.addCMakeCommandEnd("if (CMAKE_HOST_WIN32)");
cmake.addCMakeCommandEnd(" target_link_libraries("+targetNameServer+" PUBLIC ws2_32)");
cmake.addCMakeCommandEnd("endif()");
cmake.addCMakeCommandEnd("");
}
// Add the common file dependencies
for (String f : fileDependenciesOwnCpp) {
files.add(FileUtil.getResourceAsFile("/template/adapters/"+f, f));
}
for (String f : fileDependenciesSharedCpp) {
files.add(FileUtil.getResourceAsFile("/shared_cpp/"+f, f));
}
}
String getIsSocketList() {
String isSocketList = "";
boolean first = true;
for (PortInformation portInfo : interfaceResolver.programInterface.ports) {
if (first) first = false;
else isSocketList += ", ";
isSocketList += portInfo.port_type == PortType.SOCKET ? "true" : "false";
}
return isSocketList;
}
String getIsOutputList() {
String isOutputList = "";
boolean first = true;
for (PortInformation portInfo : interfaceResolver.programInterface.ports) {
if (first) first = false;
else isOutputList += ", ";
isOutputList += portInfo.isOutput() ? "true" : "false";
}
return isOutputList;
}
public List<FileContent> getFiles() {
return files;
}
public void addFileDependencyOwnCpp(String name) {
fileDependenciesOwnCpp.add(name);
}
public void addFileDependencySharedCpp(String name) {
fileDependenciesSharedCpp.add(name);
}
}
package de.monticore.lang.monticar.generator.cpp.dynamic_interface;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import de.monticore.lang.monticar.generator.FileContent;
import de.rwth.montisim.commons.utils.json.SerializationException;
public class DDCCommunication {
static final String BASE_SPACES = " ";
final DynamicInterfaceGenerator gen;
FileBuilder b = new FileBuilder();
public DDCCommunication(DynamicInterfaceGenerator gen) {
this.gen = gen;
throw new IllegalArgumentException("DDCCommunication not implemented yet.");
}
public List<FileContent> generate() throws SerializationException {
List<FileContent> files = new ArrayList<>();
return files;
}
public void getSources(HashSet<String> sources) {
sources.add("ddc_mode.cpp");
}
public void getLibs(HashSet<String> libs) {
libs.add("ddc_load");
}
}
package de.monticore.lang.monticar.generator.cpp.dynamic_interface; package de.monticore.lang.monticar.generator.cpp.dynamic_interface;
import java.util.ArrayList; import de.monticore.lang.monticar.generator.cpp.dynamic_interface.ProgramInterfaceResolver.SocketInfo;
import java.util.HashMap;
import java.util.List;
import de.monticore.lang.monticar.generator.FileContent;
import de.monticore.lang.monticar.generator.cmake.CMakeConfig;
import de.monticore.lang.monticar.generator.cpp.template.AllTemplates;
import de.rwth.montisim.commons.dynamicinterface.*; import de.rwth.montisim.commons.dynamicinterface.*;
import de.rwth.montisim.commons.dynamicinterface.PortInformation.PortDirection;
import de.rwth.montisim.commons.utils.json.SerializationException;
public class JsonCommunication {
static final int BASE_INDENT = 2;
//public static void generateCMake(CMakeConfig cmake,)
final DynamicInterfaceGenerator gen; public class JsonSerializationGenerator extends SerializationGenerator {
FileBuilder b = new FileBuilder();
JsonCommunication(DynamicInterfaceGenerator gen) { JsonSerializationGenerator(AdapterGenerator gen) {
this.gen = gen; super(gen);
} }
public List<FileContent> generate() throws SerializationException { String getType() {
List<FileContent> files = new ArrayList<>(); return "Json";
List<String> getPortCases = new ArrayList<>(); }
List<String> setPortCases = new ArrayList<>();
int i = 0;
for (PortInformation portInfo : gen.programInterface.ports){
if (portInfo.direction == PortDirection.INPUT){
setPortCases.add(generateSetPortCase(i, portInfo));
} else {
getPortCases.add(generateGetPortCase(i, portInfo));
}
++i;
}
HashMap<String, Object> templateData = new HashMap<>();
templateData.put("mainModelName", gen.componentName);
templateData.put("interfaceDescription", gen.progInterfaceString);
templateData.put("getPortCases", getPortCases);
templateData.put("setPortCases", setPortCases);
files.add(new FileContent(AllTemplates.generate(AllTemplates.DYNAMIC_INTERFACE_H, templateData), "dynamic_interface.h"));
files.add(new FileContent(AllTemplates.generate(AllTemplates.DYNAMIC_INTERFACE_CPP, templateData), "dynamic_interface.cpp"));
gen.addCppFileDependency("json.h");
gen.addCppFileDependency("json.cpp");
gen.addCppFileDependency("printf.h");
gen.addCppFileDependency("printf.cpp");
gen.addCppFileDependency("utils.h");
return files; boolean isJson() {
return true;
} }
void generateSocketSetter(PortInformation portInfo) {
public void addCMake(CMakeConfig cmake, String outputName) { SocketInfo sockInf = gen.interfaceResolver.getSocketInfo(portInfo);
// create shared lib int indent = BASE_INDENT+1;
cmake.addCMakeCommandEnd("# The JSON/Dynamic-interface based communication adapter (for the hardware_emulator)");
cmake.addCMakeCommandEnd("add_library("+outputName+" SHARED dynamic_interface.cpp json.cpp printf.cpp)"); b.a(indent, "auto as = reader.stream_array();");
cmake.addCMakeCommandEnd("target_include_directories("+outputName+" PUBLIC ${INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR})"); b.a(indent, "auto it = as.begin();");
cmake.addCMakeCommandEnd("target_link_libraries("+outputName+" PUBLIC ${LIBS} -static-libgcc -static-libstdc++)"); b.a(indent, "auto end = as.end();");
cmake.addCMakeCommandEnd("set_target_properties("+outputName+" PROPERTIES LINKER_LANGUAGE CXX POSITION_INDEPENDENT_CODE ON)"); b.a(indent, "if (!(it != end)) {");
cmake.addCMakeCommandEnd("target_compile_features("+outputName+" PUBLIC cxx_std_11)"); b.a(indent, " throw_error(\"PortIO\", \"Expected IP entry in array\");");
cmake.addCMakeCommandEnd("set_target_properties("+outputName+" PROPERTIES PREFIX \"\")"); b.a(indent, " break;");
// install shared lib b.a(indent, "}");
cmake.addCMakeCommandEnd("install(TARGETS "+outputName+" DESTINATION $ENV{DLL_DIR})"); b.a(indent, "auto ip = reader.get_string().get_json_string();");
//cmake.addCMakeCommandEnd("export(TARGETS "+outputName+" FILE "+outputName+".cmake)"); b.a(indent, "auto id = get_socket_id(ip, %d);", sockInf.array_length);
cmake.addCMakeCommandEnd(""); b.a(indent, "if (id < 0) return;");
} b.a(indent, "auto &target = program_instance.%s[id];", sockInf.input_name);
b.a(indent, "++it;");
public String generateSetPortCase(int id, PortInformation portInfo){ b.a(indent, "if (!(it != end)) {");
b.init(); b.a(indent, " throw_error(\"PortIO\", \"Expected IP entry in array\");");
b.a(indent, " break;");
b.a(BASE_INDENT, "case %d: { // %s", id, portInfo.name); b.a(indent, "}");
generateSetter(portInfo.data_type, BASE_INDENT+1, 1, "program_instance."+portInfo.name); generateSetter(((SimplePacketType) portInfo.data_type).getPayloadType(), indent, 1, "target");
b.a(BASE_INDENT, "} break;");
return b.getContent();