From 9d7d79f92af2512eb58d98af3a0c8e255ad7f092 Mon Sep 17 00:00:00 2001 From: Clint McKenzie Date: Fri, 10 Jan 2025 17:15:37 -0600 Subject: [PATCH] Added sections for user-added content that won't be overwritten during code regeneration --- .../org/sireum/hamr/codegen/CodeGen.scala | 35 ++-- jvm/src/test | 2 +- .../sireum/hamr/codegen/ros2/Generator.scala | 167 ++++++++++-------- .../hamr/codegen/ros2/Ros2Codegen.scala | 12 +- 4 files changed, 121 insertions(+), 95 deletions(-) diff --git a/jvm/src/main/scala/org/sireum/hamr/codegen/CodeGen.scala b/jvm/src/main/scala/org/sireum/hamr/codegen/CodeGen.scala index 6d736b3..113595c 100644 --- a/jvm/src/main/scala/org/sireum/hamr/codegen/CodeGen.scala +++ b/jvm/src/main/scala/org/sireum/hamr/codegen/CodeGen.scala @@ -121,7 +121,7 @@ object CodeGen { if (~reporter.hasError && runRos2) { val results = Ros2Codegen().run(rmodel, modOptions, aadlTypes, symbolTable, plugins, reporter) if (!reporter.hasError) { - writeOutResources(results.fileResources, reporter) + writeOutResources(results.fileResources, T, reporter) } if (!modOptions.parseableMessages) { reporterIndex = printMessages(reporter.messages, modOptions.verbose, reporterIndex, ISZ()) @@ -133,7 +133,7 @@ object CodeGen { reporter.info(None(), toolName, "Generating Microkit artifacts...") val results = MicrokitCodegen().run(rmodel, modOptions, aadlTypes, symbolTable, plugins, reporter) if (!reporter.hasError) { - writeOutResources(results.resources, reporter) + writeOutResources(results.resources, F, reporter) } if (!modOptions.parseableMessages) { reporterIndex = printMessages(reporter.messages, modOptions.verbose, reporterIndex, ISZ()) @@ -192,7 +192,7 @@ object CodeGen { // doesn't matter what 'o.writeOutResources' is, sergen/slangcheck needs the // resources to be written out if (!wroteOutArsitResources) { - writeOutResources(arsitResources, reporter) + writeOutResources(arsitResources, F, reporter) wroteOutArsitResources = T } @@ -214,7 +214,7 @@ object CodeGen { // doesn't matter what 'o.writeOutResources' is, sergen/slangcheck needs the // resources to be written out if (!wroteOutArsitResources) { - writeOutResources(arsitResources, reporter) + writeOutResources(arsitResources, F, reporter) wroteOutArsitResources = T } @@ -232,7 +232,7 @@ object CodeGen { // doesn't matter what 'o.writeOutResources' is, proyek ive needs the // resources to be written out if (!wroteOutArsitResources) { - writeOutResources(arsitResources, reporter) + writeOutResources(arsitResources, F, reporter) wroteOutArsitResources = T } @@ -272,7 +272,7 @@ object CodeGen { // doesn't matter what 'o.writeOutResources' is, transpiler needs the // resources to be written out if (!wroteOutArsitResources) { - writeOutResources(arsitResources, reporter) + writeOutResources(arsitResources, F, reporter) wroteOutArsitResources = T } @@ -319,10 +319,10 @@ object CodeGen { if (!reporter.hasError && shouldWriteOutResources) { if (!wroteOutArsitResources) { - writeOutResources(arsitResources, reporter) + writeOutResources(arsitResources, F, reporter) wroteOutArsitResources = T } - writeOutResources(actResources, reporter) + writeOutResources(actResources, F, reporter) } reporterIndex = printMessages(reporter.messages, modOptions.verbose, reporterIndex, ISZ()) @@ -436,7 +436,9 @@ object CodeGen { return ret } - def writeOutResources(resources: IS[Z, FileResource], reporter: Reporter): Unit = { + // With invertMarkers enabled, edits made to the existing file within the markers will be carried over into the + // freshly generated file. With it disabled, edits made outside of the markers will be carried over. + def writeOutResources(resources: IS[Z, FileResource], invertMarkers: B, reporter: Reporter): Unit = { def render(i: IResource): String = { val ret: String = { val lineSep: String = if (Os.isWin) "\r\n" else "\n" // ST render uses System.lineSep @@ -477,10 +479,17 @@ object CodeGen { | ${(missingMarkers, "\n")}""" reporter.error(None(), toolName, msg.render) } else { - val replacements: ISZ[(Z, Z, String)] = oldSections.entries.map((oldEntry: (Marker, (Z, Z, String))) => - ((oldEntry._2._1, oldEntry._2._2, newSections.get(oldEntry._1).get._3))) - val content: String = StringUtil.replaceSections(p.read, replacements, reporter) - p.writeOver(content) + if (invertMarkers) { + val replacements: ISZ[(Z, Z, String)] = newSections.entries.map((newEntry: (Marker, (Z, Z, String))) => + ((newEntry._2._1, newEntry._2._2, oldSections.get(newEntry._1).get._3))) + val content: String = StringUtil.replaceSections(newContent, replacements, reporter) + p.writeOver(content) + } else { + val replacements: ISZ[(Z, Z, String)] = oldSections.entries.map((oldEntry: (Marker, (Z, Z, String))) => + ((oldEntry._2._1, oldEntry._2._2, newSections.get(oldEntry._1).get._3))) + val content: String = StringUtil.replaceSections(p.read, replacements, reporter) + p.writeOver(content) + } reporter.info(None(), toolName, s"Wrote and preserved existing content: ${p}") } diff --git a/jvm/src/test b/jvm/src/test index c2f61a1..3a64dc5 160000 --- a/jvm/src/test +++ b/jvm/src/test @@ -1 +1 @@ -Subproject commit c2f61a1be8860ffcdc71b98fb61378bc0405c93a +Subproject commit 3a64dc5ab8a29de4fe9950721ca927f6a6a8b325 diff --git a/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Generator.scala b/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Generator.scala index c4a8142..fbedc9f 100644 --- a/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Generator.scala +++ b/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Generator.scala @@ -3,6 +3,7 @@ package org.sireum.hamr.codegen.ros2 import org.sireum._ +import org.sireum.hamr.codegen.common.containers.Marker import org.sireum.hamr.codegen.common.symbols.{AadlComponent, AadlDataPort, AadlEventDataPort, AadlPort, AadlProcess, AadlSystem, AadlThread, Dispatch_Protocol} import org.sireum.hamr.codegen.common.types.{AadlType, ArrayType, BaseType, EnumType, RecordType} import org.sireum.hamr.ir.Direction @@ -32,6 +33,7 @@ object Generator { // Mutex is used for thread locking in C++ val mutex_name: String = "mutex_" + def genPyLaunchFileName(compNameS: String): String = { // create launch file name val nodeNameT: String = s"${compNameS}${py_launch_file_name_suffix}" @@ -286,10 +288,13 @@ object Generator { // Setup file for node source package // Example: https://github.com/santoslab/ros-examples/blob/main/tempControlcpp_ws/src/tc_cpp_pkg/CMakeLists.txt - def genCppCMakeListsFile(modelName: String, threadComponents: ISZ[AadlThread], hasEnumConverter: B): (ISZ[String], ST) = { + def genCppCMakeListsFile(modelName: String, threadComponents: ISZ[AadlThread], hasEnumConverter: B): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "CMakeLists.txt" + val startMarker: String = "# Additions within these tags will be preserved when re-running Codegen" + val endMarker: String = "# Additions within these tags will be preserved when re-running Codegen" + // build entry point declarations var entry_point_decls: ISZ[ST] = IS() var entry_point_executables: ISZ[String] = IS() @@ -315,6 +320,10 @@ object Generator { |find_package(rclcpp REQUIRED) |${(pkgRequirements, "\n")} | + |${startMarker} + | + |${endMarker} + | |include_directories(include) | |${(entry_point_decls, "\n\n")} @@ -329,15 +338,18 @@ object Generator { val filePath: ISZ[String] = IS("src", top_level_package_nameT, fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, F, IS(Marker(startMarker, endMarker))) } // Setup file for node source package // Example: https://github.com/santoslab/ros-examples/blob/main/tempControlcpp_ws/src/tc_cpp_pkg/package.xml - def genCppPackageFile(modelName: String): (ISZ[String], ST) = { + def genCppPackageFile(modelName: String): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "package.xml" + val startMarker: String = "" + val endMarker: String = "" + val packages: ISZ[String] = IS(s"${top_level_package_nameT}_interfaces") val pkgDependencies: ISZ[ST] = genPackageFilePkgDependencies(packages) @@ -356,6 +368,10 @@ object Generator { | rclcpp | ${(pkgDependencies, "\n")} | + | ${startMarker} + | + | ${endMarker} + | | ament_lint_auto | ament_lint_common | @@ -367,7 +383,7 @@ object Generator { val filePath: ISZ[String] = IS("src", top_level_package_nameT, fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, F, IS(Marker(startMarker, endMarker))) } @@ -375,7 +391,7 @@ object Generator { // L a u n c h File Setup Files //================================================ - def genLaunchCMakeListsFile(modelName: String): (ISZ[String], ST) = { + def genLaunchCMakeListsFile(modelName: String): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "CMakeLists.txt" @@ -399,13 +415,16 @@ object Generator { val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_bringup", fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, T, IS()) } - def genLaunchPackageFile(modelName: String): (ISZ[String], ST) = { + def genLaunchPackageFile(modelName: String): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "package.xml" + val startMarker: String = "" + val endMarker: String = "" + val setupFileBody = st""" | @@ -420,6 +439,10 @@ object Generator { | | ${top_level_package_nameT} | + | ${startMarker} + | + | ${endMarker} + | | ament_lint_auto | ament_lint_common | @@ -431,7 +454,7 @@ object Generator { val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_bringup", fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, F, IS(Marker(startMarker, endMarker))) } @@ -562,32 +585,16 @@ object Generator { // For example, see https://github.com/santoslab/ros-examples/blob/main/tempControl_ws/src/tc_bringup/launch/tc.launch.py // Creates a launch file for each system component in the model def genXmlFormatLaunchFiles(modelName: String, threadComponents: ISZ[AadlThread], - systemComponents: ISZ[AadlSystem]): ISZ[(ISZ[String], ST)] = { + systemComponents: ISZ[AadlSystem]): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { val top_level_package_nameT: String = genCppPackageName(modelName) - var launchFiles: ISZ[(ISZ[String], ST)] = IS() + var launchFiles: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() for (system <- systemComponents) { val fileName = genXmlLaunchFileName(system.identifier) - - val launch_decls: ISZ[ST] = genXmlFormatLaunchDecls(system, top_level_package_nameT) - - -/* - var node_decls: ISZ[ST] = IS() - - for (thread <- threadComponents) { - val threadPath: String = thread.pathAsString(",") - val systemPath: String = system.pathAsString(",") - - if (threadPath.size > systemPath.size && ops.StringOps(threadPath).substring(0, systemPath.size) == systemPath) { - node_decls = node_decls :+ genXmlFormatLaunchNodeDecl(top_level_package_nameT, thread) - } - } -*/ val launchFileBody = st""" | ${(launch_decls, "\n")} @@ -596,7 +603,7 @@ object Generator { val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_bringup", "launch", fileName) - launchFiles = launchFiles :+ (filePath, launchFileBody) + launchFiles = launchFiles :+ (filePath, launchFileBody, T, IS()) } return launchFiles @@ -609,26 +616,26 @@ object Generator { // ROS2 data/message types are defined in a "{package_name}_interfaces" package according to convention // The "Empty" datatype, which has no data fields, is used for event ports - def genMsgFiles(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): ISZ[(ISZ[String], ST)] = { - var msg_files: ISZ[(ISZ[String], ST)] = IS() + def genMsgFiles(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { + var msg_files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() for (datatype <- datatypeMap.entries) { msg_files = msg_files :+ genMsgFile(modelName, datatype._2._1, datatype._2._2) } - msg_files = msg_files :+ (ISZ("src", s"${genCppPackageName(modelName)}_interfaces", "msg", "Empty.msg"), st"") + msg_files = msg_files :+ (ISZ("src", s"${genCppPackageName(modelName)}_interfaces", "msg", "Empty.msg"), st"", T, IS()) return msg_files } - def genMsgFile(modelName: String, datatypeName: String, datatypeContent: ISZ[String]): (ISZ[String], ST) = { + def genMsgFile(modelName: String, datatypeName: String, datatypeContent: ISZ[String]): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileBody = st"${(datatypeContent, "\n")}" val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_interfaces", "msg", s"${datatypeName}.msg") - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } - def genInterfacesCMakeListsFile(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): (ISZ[String], ST) = { + def genInterfacesCMakeListsFile(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "CMakeLists.txt" var msgTypes: ISZ[String] = IS() @@ -660,10 +667,10 @@ object Generator { val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_interfaces", fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, T, IS()) } - def genInterfacesPackageFile(modelName: String): (ISZ[String], ST) = { + def genInterfacesPackageFile(modelName: String): (ISZ[String], ST, B, ISZ[Marker]) = { val top_level_package_nameT: String = genCppPackageName(modelName) val fileName: String = "package.xml" @@ -694,7 +701,7 @@ object Generator { val filePath: ISZ[String] = IS("src", s"${top_level_package_nameT}_interfaces", fileName) - return (filePath, setupFileBody) + return (filePath, setupFileBody, T, IS()) } @@ -1510,7 +1517,8 @@ object Generator { def genCppBaseNodeHeaderFile(packageName: String, component: AadlThread, connectionMap: Map[ISZ[String], ISZ[ISZ[String]]], - datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, reporter: Reporter): (ISZ[String], ST) = { + datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, + reporter: Reporter): (ISZ[String], ST, B, ISZ[Marker]) = { val nodeName = s"${genNodeName(component)}_base" val fileName = genCppNodeSourceHeaderName(nodeName) @@ -1611,9 +1619,9 @@ object Generator { |${(typeIncludes, "\n")} |${(stdIncludes, "\n")} | - |//================================================= - |// D O N O T E D I T T H I S F I L E - |//================================================= + |//======================================================== + |// Re-running Codegen will overwrite changes to this file + |//======================================================== | |class ${nodeName} : public rclcpp::Node |{ @@ -1763,11 +1771,11 @@ object Generator { val filePath: ISZ[String] = IS("src", packageName, "include", packageName, "base_headers", fileName) - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } def genCppBaseNodeCppFile(packageName: String, component: AadlThread, connectionMap: Map[ISZ[String], ISZ[ISZ[String]]], - datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, reporter: Reporter): (ISZ[String], ST) = { + datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, reporter: Reporter): (ISZ[String], ST, B, ISZ[Marker]) = { val nodeName = s"${genNodeName(component)}_base" val fileName = genCppNodeSourceName(nodeName) @@ -1852,9 +1860,9 @@ object Generator { var fileBody = st"""#include "${packageName}/base_headers/${nodeName}${cpp_src_node_header_name_suffix}" | - |//================================================= - |// D O N O T E D I T T H I S F I L E - |//================================================= + |//======================================================== + |// Re-running Codegen will overwrite changes to this file + |//======================================================== | |${nodeName}::${nodeName}() : Node("${genNodeName(component)}") |{ @@ -1972,14 +1980,17 @@ object Generator { val filePath: ISZ[String] = IS("src", packageName, "src", "base_code", fileName) - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } def genCppUserNodeHeaderFile(packageName: String, component: AadlThread, datatypeMap: Map[AadlType, (String, ISZ[String])], - strictAADLMode: B, reporter: Reporter): (ISZ[String], ST) = { + strictAADLMode: B, reporter: Reporter): (ISZ[String], ST, B, ISZ[Marker]) = { val nodeName = genNodeName(component) val fileName = genCppNodeSourceHeaderName(nodeName) + val startMarker: String = "// Additions within these tags will be preserved when re-running Codegen" + val endMarker: String = "// Additions within these tags will be preserved when re-running Codegen" + var subscriptionHandlers: ISZ[ST] = IS() if (isSporadic(component)) { for (p <- component.getPorts()) { @@ -2028,17 +2039,19 @@ object Generator { | //================================================= | // Include any additional declarations here | //================================================= + | ${startMarker} | + | ${endMarker} |}; """ val filePath: ISZ[String] = IS("src", packageName, "include", packageName, "user_headers", fileName) - return (filePath, fileBody) + return (filePath, fileBody, F, IS(Marker(startMarker, endMarker))) } def genCppUserNodeCppFile(packageName: String, component: AadlThread, datatypeMap: Map[AadlType, (String, ISZ[String])], - hasConverterFiles: B, strictAADLMode: B, reporter: Reporter): (ISZ[String], ST) = { + hasConverterFiles: B, strictAADLMode: B, reporter: Reporter): (ISZ[String], ST, B, ISZ[Marker]) = { val nodeName = genNodeName(component) val fileName = genCppNodeSourceName(nodeName) @@ -2072,6 +2085,10 @@ object Generator { val fileBody = st"""${includeFiles} + | + |//=========================================================== + |// This file will not be overwritten when re-running Codegen + |//=========================================================== | |//================================================= |// I n i t i a l i z e E n t r y P o i n t @@ -2091,19 +2108,19 @@ object Generator { val filePath: ISZ[String] = IS("src", packageName, "src", "user_code", fileName) - return (filePath, fileBody) + return (filePath, fileBody, F, IS()) } - def genCppNodeRunnerFile(packageName: String, component: AadlThread): (ISZ[String], ST) = { + def genCppNodeRunnerFile(packageName: String, component: AadlThread): (ISZ[String], ST, B, ISZ[Marker]) = { val nodeName = genNodeName(component) val fileName = genCppNodeRunnerName(nodeName) val fileBody = st"""#include "${packageName}/user_headers/${nodeName}${cpp_src_node_header_name_suffix}" | - |//================================================= - |// D O N O T E D I T T H I S F I L E - |//================================================= + |//======================================================== + |// Re-running Codegen will overwrite changes to this file + |//======================================================== | |${nodeName}::${nodeName}() : ${nodeName}_base() |{ @@ -2127,14 +2144,15 @@ object Generator { val filePath: ISZ[String] = IS("src", packageName, "src", "base_code", fileName) - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } def genCppNodeFiles(modelName: String, threadComponents: ISZ[AadlThread], connectionMap: Map[ISZ[String], ISZ[ISZ[String]]], - datatypeMap: Map[AadlType, (String, ISZ[String])], hasConverterFiles: B, strictAADLMode: B, reporter: Reporter): ISZ[(ISZ[String], ST)] = { + datatypeMap: Map[AadlType, (String, ISZ[String])], hasConverterFiles: B, strictAADLMode: B, + reporter: Reporter): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { val top_level_package_nameT: String = genCppPackageName(modelName) - var cpp_files: ISZ[(ISZ[String], ST)] = IS() + var cpp_files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() for (comp <- threadComponents) { cpp_files = @@ -2153,7 +2171,7 @@ object Generator { } def genCppEnumConverterHeaderFile(packageName: String, enumTypes: ISZ[(String, AadlType)], - strictAADLMode: B): (ISZ[String], ST) = { + strictAADLMode: B): (ISZ[String], ST, B, ISZ[Marker]) = { var includes: ISZ[ST] = IS() var converterHeaders: ISZ[ST] = IS() @@ -2186,7 +2204,7 @@ object Generator { val filePath: ISZ[String] = IS("src", packageName, "include", packageName, "base_headers", "enum_converter.hpp") - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } def genCppEnumConverters(packageName: String, enumTypes: ISZ[(String, AadlType)], strictAADLMode: B): ISZ[ST] = { @@ -2232,20 +2250,24 @@ object Generator { } def genCppEnumConverterFile(packageName: String, enumTypes: ISZ[(String, AadlType)], - strictAADLMode: B): (ISZ[String], ST) = { + strictAADLMode: B): (ISZ[String], ST, B, ISZ[Marker]) = { val fileBody = st"""#include "${packageName}/base_headers/enum_converter.hpp" + | + |//======================================================== + |// Re-running Codegen will overwrite changes to this file + |//======================================================== | |${(genCppEnumConverters(packageName, enumTypes, strictAADLMode), "\n")} """ val filePath: ISZ[String] = IS("src", packageName, "src", "base_code", "enum_converter.cpp") - return (filePath, fileBody) + return (filePath, fileBody, T, IS()) } def genCppEnumConverterFiles(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])], - strictAADLMode: B): ISZ[(ISZ[String], ST)] = { + strictAADLMode: B): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { var enumTypes: ISZ[(String, AadlType)] = IS() for (key <- datatypeMap.keys) { @@ -2262,7 +2284,7 @@ object Generator { return IS() } - var files: ISZ[(ISZ[String], ST)] = IS() + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() val packageName: String = genCppPackageName(modelName) files = files :+ genCppEnumConverterHeaderFile(packageName, enumTypes, strictAADLMode) @@ -2287,10 +2309,9 @@ object Generator { return files } // TODO: Python pkgs - def genPyLaunchPkg(modelName: String, threadComponents: ISZ[AadlThread]): ISZ[(ISZ[String], ST)] = { - var files: ISZ[(ISZ[String], ST)] = IS() + def genPyLaunchPkg(modelName: String, threadComponents: ISZ[AadlThread]): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() - // TODO //files = files :+ genXmlFormatLaunchFile(modelName, threadComponents) files = files :+ genLaunchCMakeListsFile(modelName) files = files :+ genLaunchPackageFile(modelName) @@ -2299,10 +2320,10 @@ object Generator { } def genCppNodePkg(modelName: String, threadComponents: ISZ[AadlThread], connectionMap: Map[ISZ[String], ISZ[ISZ[String]]], - datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, reporter: Reporter): ISZ[(ISZ[String], ST)] = { - var files: ISZ[(ISZ[String], ST)] = ISZ() + datatypeMap: Map[AadlType, (String, ISZ[String])], strictAADLMode: B, reporter: Reporter): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = ISZ() - val converterFiles: ISZ[(ISZ[String], ST)] = genCppEnumConverterFiles(modelName, datatypeMap, strictAADLMode) + val converterFiles: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = genCppEnumConverterFiles(modelName, datatypeMap, strictAADLMode) val hasConverterFiles: B = (converterFiles.size > 0) files = files ++ @@ -2314,8 +2335,8 @@ object Generator { return files } - def genXmlLaunchPkg(modelName: String, threadComponents: ISZ[AadlThread], systemComponents: ISZ[AadlSystem]): ISZ[(ISZ[String], ST)] = { - var files: ISZ[(ISZ[String], ST)] = IS() + def genXmlLaunchPkg(modelName: String, threadComponents: ISZ[AadlThread], systemComponents: ISZ[AadlSystem]): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() files = files ++ genXmlFormatLaunchFiles(modelName, threadComponents, systemComponents) files = files :+ genLaunchCMakeListsFile(modelName) @@ -2326,8 +2347,8 @@ object Generator { // The same datatype package will work regardless of other packages' types // ROS2 data/message types are defined in a "{package_name}_interfaces" package according to convention - def genInterfacesPkg(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): ISZ[(ISZ[String], ST)] = { - var files: ISZ[(ISZ[String], ST)] = IS() + def genInterfacesPkg(modelName: String, datatypeMap: Map[AadlType, (String, ISZ[String])]): ISZ[(ISZ[String], ST, B, ISZ[Marker])] = { + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() files = files ++ genMsgFiles(modelName, datatypeMap) files = files :+ genInterfacesCMakeListsFile(modelName, datatypeMap) diff --git a/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Ros2Codegen.scala b/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Ros2Codegen.scala index 7e66a1c..27be597 100644 --- a/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Ros2Codegen.scala +++ b/shared/src/main/scala/org/sireum/hamr/codegen/ros2/Ros2Codegen.scala @@ -4,7 +4,7 @@ package org.sireum.hamr.codegen.ros2 import org.sireum._ import org.sireum.hamr.codegen.common.CommonUtil -import org.sireum.hamr.codegen.common.containers.FileResource +import org.sireum.hamr.codegen.common.containers.{FileResource, IResource, Marker} import org.sireum.hamr.codegen.common.plugin.Plugin import org.sireum.hamr.codegen.common.symbols.{AadlComponent, AadlSystem, AadlThread, SymbolTable} import org.sireum.hamr.codegen.common.types.{AadlType, AadlTypes, ArrayType, BaseType, EnumType, RecordType} @@ -37,11 +37,11 @@ import org.sireum.ops.ISZOps mapDatatypes(aadlTypes, reporter) - var files: ISZ[(ISZ[String], ST)] = IS() + var files: ISZ[(ISZ[String], ST, B, ISZ[Marker])] = IS() options.ros2NodesLanguage.name match { case "Cpp" => files = Generator.genCppNodePkg(modelName, threadComponents, connectionMap, datatypeMap, options.strictAadlMode, reporter) - case "Python" => files = Generator.genPyNodePkg(modelName, threadComponents, connectionMap, options.strictAadlMode) + //case "Python" => files = Generator.genPyNodePkg(modelName, threadComponents, connectionMap, options.strictAadlMode) case _ => reporter.error(None(), toolName, s"Unknown code type: ${options.ros2NodesLanguage.name}") } @@ -65,11 +65,7 @@ import org.sireum.ops.ISZOps case _ => filePath } - resources = resources :+ ResourceUtil.createResource( - path = absPath, - content = file._2, - overwrite = T - ) + resources = resources :+ IResource(absPath, file._2, file._4, file._3, F, F, F) } return Ros2Results(fileResources = resources)