Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ object ComputeGeneratedFiles {
/** Computes autocoded files (XML, C++ and JSON Dictionary) */
def getAutocodeFiles(tul: List[Ast.TransUnit]): Result.Result[List[String]] =
for {
// Perform analysis only up to the point we need
a <- enterSymbols(tul)
a <- CheckUses.visitList(a, tul, CheckUses.transUnit)
Comment thread
bocchino marked this conversation as resolved.
_ <- CheckUseDefCycles.visitList(a, tul, CheckUseDefCycles.transUnit)
a <- CheckTypeUses.visitList(a, tul, CheckTypeUses.transUnit)

xmlFiles <- getXmlFiles(a, tul)
cppFiles <- getAutocodeCppFiles(a, tul)
dictFiles <- getDictionaryJsonFiles(a, tul)
Expand Down
188 changes: 188 additions & 0 deletions compiler/lib/src/main/scala/codegen/CppWriter/AliasCppWriter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
package fpp.compiler.codegen

import fpp.compiler.analysis._
import fpp.compiler.ast._
import fpp.compiler.util._

/** Writes out C++/C headers for type alias definitions */
case class AliasCppWriter (
s: CppWriterState,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
) extends CppWriterUtils {

private val node = aNode._2

private val data = node.data

private val symbol = Symbol.AliasType(aNode)

private val name = s.getName(symbol)

private val fileName = ComputeCppFiles.FileNames.getAliasType(name)

private val aliasType @ Type.AliasType(_, _) = s.a.typeMap(node.id)

private val namespaceIdentList = s.getNamespaceIdentList(symbol)

private val typeCppWriter = TypeCppWriter(s, "Fw::String")

private val supportedCHeader = s.isTypeSupportedInC(aliasType)

private def writeHppIncludeDirectives(
s: CppWriterState,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
): List[String] = {
val Right(a) = UsedSymbols.defAliasTypeAnnotatedNode(s.a, aNode)
s.writeIncludeDirectives(a.usedSymbolSet)
}

private def writeHIncludeDirectives(
s: CppWriterState,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
): List[String] = {
val Right(a) = UsedSymbols.defAliasTypeAnnotatedNode(s.a, aNode)
def getIncludeFiles(sym: Symbol): Option[String] = {
val name = s.getName(sym)
for {
fileName <- sym match {
case Symbol.AliasType(_) => Some(ComputeCppFiles.FileNames.getAliasType(name))
case Symbol.AbsType(node) =>
if s.isBuiltInType(name) then Some("FppConfig") else None
case _ => None
}
}
yield s.getIncludePath(sym, fileName, "h")
}

a.usedSymbolSet.map(getIncludeFiles).filter(_.isDefined).map(_.get).map(CppWriterState.headerString).toList
}

def writeHpp: CppDoc = {
val includeGuard = s.includeGuardFromQualifiedName(symbol, fileName, "HPP")
CppWriter.createCppDoc(
s"$name alias",
fileName,
includeGuard,
getHppMembers,
s.toolName,
"hpp"
)
}

def writeH: Option[CppDoc] = {
if (!supportedCHeader) {
return None
}

val includeGuard = s.includeGuardFromQualifiedName(symbol, fileName, "H")
Some(CppWriter.createCppDoc(
s"$name alias",
fileName,
includeGuard,
getHMembers,
s.toolName,
"h"
))
}

private def getHppMembers: List[CppDoc.Member] = {
List(
Comment thread
Kronos3 marked this conversation as resolved.
Outdated
List(getHppIncludes),
wrapInNamespaces(namespaceIdentList, List(getHppDefinition))
).flatten
}

private def getHMembers: List[CppDoc.Member] = {
List(
getHIncludes,
getHOpenCPPGuard,
getHDefinition,
getHCloseCPPGuard,
)
}

private def getHOpenCPPGuard: CppDoc.Member = {
linesMember(addBlankPrefix(lines(
"""|#ifdef __cplusplus
Comment thread
Kronos3 marked this conversation as resolved.
Outdated
|extern "C" {
|#endif""")
))
}

private def getHCloseCPPGuard: CppDoc.Member = {
linesMember(addBlankPrefix(lines(
"""|#ifdef __cplusplus
|}
|#endif""")
))
}

private def getHIncludes: CppDoc.Member = {
if (!supportedCHeader) {
// C header is not supported, we will generate the definition
// in the C++ header
return linesMember(List())
}

val standardHeaders = List(
"Fw/Types/BasicTypes.h",
).map(CppWriter.headerString)
val symbolHeaders = writeHIncludeDirectives(s, aNode)
val headers = standardHeaders ++ symbolHeaders
linesMember(addBlankPrefix(headers.distinct.sorted.map(line)))
}

private def getHppIncludes: CppDoc.Member.Lines = {
val standardHeaders = List(
aliasType.aliasType match {
case Type.String(_) => "Fw/Types/String.hpp"
case Type.AbsType(node) =>
s.isBuiltInType(node._2._1.name) match {
case true => "FppConfig.hpp"
Comment thread
Kronos3 marked this conversation as resolved.
Outdated
case false => "Fw/Types/BasicTypes.h"
}
case _ => "Fw/Types/BasicTypes.h"
},
).map(CppWriter.headerString)
val symbolHeaders = writeHppIncludeDirectives(s, aNode)
val headers = standardHeaders ++ symbolHeaders
linesMember(addBlankPrefix(headers.distinct.sorted.map(line)))
}

private def getHppDefinition: CppDoc.Member.Lines = {
val name = s.getName(symbol)

supportedCHeader match {
case true => linesMember(addBlankPrefix(lines(
// Include the C definition of the type alias
// This is using a `typedef`
CppWriterState.headerString(s.getIncludePath(symbol, ComputeCppFiles.FileNames.getAliasType(name), "h"))
)))
case false => linesMember(addBlankPrefix(
// Define a C++ only
AnnotationCppWriter.writePreComment(aNode) ++ lines(
s"using $name = ${typeCppWriter.write(aliasType.aliasType)};"
)
))
}
}

private def getHDefinition: CppDoc.Member.Lines = {
val name = s.getName(symbol)
def getTypePRI(ty: Type): String = {
ty match {
case Type.Float(f) => aliasType.aliasType.toString().toLowerCase()
case Type.PrimitiveInt(i) => aliasType.aliasType.toString().toLowerCase()
case _ => typeCppWriter.write(ty)
}
}

val fmtSpec = getTypePRI(aliasType.aliasType)

linesMember(addBlankPrefix(
AnnotationCppWriter.writePreComment(aNode) ++ lines(
s"""|typedef ${typeCppWriter.write(aliasType.aliasType)} $name;
|#define PRI_$name PRI_${fmtSpec}""")
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ case class ArrayCppWriter (
CppDocWriter.writeBannerComment("Constants") ++
addBlankPrefix(
wrapInEnum({
val elementSizes = eltType match {
val elementSizes = eltType.getUnderlyingType match {
case ts: Type.String =>
s"""|//! The string size of each element
|ELEMENT_STRING_SIZE = ${writeStringSize(s, ts)},
Expand Down Expand Up @@ -545,7 +545,7 @@ case class ArrayCppWriter (
CppDocWriter.writeBannerComment("Member variables") ++
List.concat(
addBlankPrefix(
eltType match {
eltType.getUnderlyingType match {
case _: Type.String =>
lines("""|//! The char buffers
|char buffers[SIZE][ELEMENT_BUFFER_SIZE];""".stripMargin)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ import fpp.compiler.util._
/** Writes out C++ for F Prime autocode */
object AutocodeCppWriter extends CppWriter {

override def defAliasTypeAnnotatedNode(
s: State,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
) = {
val node = aNode._2
val data = node.data
val hppDoc = AliasCppWriter(s, aNode).writeHpp
val hDoc = AliasCppWriter(s, aNode).writeH

for {
s <- CppWriter.writeHppFile(s, hppDoc)
s <- hDoc match {
case Some(doc) => CppWriter.writeHppFile(s, doc)
case None => Right(s)
}
} yield s
}

override def defArrayAnnotatedNode(
s: State,
aNode: Ast.Annotated[AstNode[Ast.DefArray]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ case class ComponentDataProducts (
else s"const $typeName&"
}
// Generate the code for computing the size delta
val computeSizeDelta = (t match {
val computeSizeDelta = (t.getUnderlyingType match {
case ts: Type.String =>
val stringSize = writeStringSize(s, ts)
s"""|const FwSizeType stringSize = $stringSize;
Expand All @@ -431,7 +431,7 @@ case class ComponentDataProducts (
}).stripMargin
// Get the expression that does the serialization
// For strings this is a truncated serialization
val serialExpr = t match {
val serialExpr = t.getUnderlyingType match {
case ts: Type.String =>
"elt.serialize(this->m_dataBuffer, stringSize)"
case _ => "this->m_dataBuffer.serialize(elt)"
Expand Down Expand Up @@ -478,7 +478,7 @@ case class ComponentDataProducts (
case _ => s"const ${typeName}*"
}
// Generate the code for computing the size delta
val computeSizeDelta = (t match {
val computeSizeDelta = (t.getUnderlyingType match {
case ts: Type.String =>
val stringSize = writeStringSize(s, ts)
s"""|const FwSizeType stringSize = $stringSize;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ case class ComponentEvents (
eventParamTypeMap(id).map((name, typeName, ty) => {

List.concat(
ty match {
ty.getUnderlyingType match {
case t: Type.String =>
val serialSize = writeStringSize(s, t)
lines(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ case class ComponentInternalStateMachines(
case head :: _ =>
val paramName = head.name
val id = signal.node._2.data.typeName.get.id
val serializeExpr = s.a.typeMap(id) match {
val serializeExpr = s.a.typeMap(id).getUnderlyingType match {
case t: Type.String =>
val serialSize = writeStringSize(s, t)
s"$paramName.serialize(buffer, $serialSize)"
Expand Down Expand Up @@ -635,7 +635,7 @@ case class ComponentInternalStateMachines(
case ((ts, maxStringSize), signal) =>
signal.node._2.data.typeName match {
case Some(tn) =>
s.a.typeMap(tn.id) match {
s.a.typeMap(tn.id).getUnderlyingType match {
case t: Type.String => (
ts + Type.String(None),
maxStringSize.max(getStringSize(s, t))
Expand Down Expand Up @@ -684,13 +684,13 @@ case class ComponentInternalStateMachines(
List.concat(comment, union)
}

private def writeSignalTypeName(t: Type) = t match {
private def writeSignalTypeName(t: Type) = t.getUnderlyingType match {
case t: Type.String => "string"
case _ => TypeCppWriter.getName(s, t)
}

private def writeSignalTypeSize(t: Type): String =
t match {
t.getUnderlyingType match {
case _: Type.String =>
s"Fw::StringBase::STATIC_SERIALIZED_SIZE(${signalStringSize.toString})"
case _ => writeSerializedSizeExpr(s, t, TypeCppWriter.getName(s, t))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ case class ComponentTelemetry (
|"""
),
lines(
channel.channelType match {
channel.channelType.getUnderlyingType match {
case t: Type.String =>
val serialSize = writeStringSize(s, t)
s"Fw::SerializeStatus _stat = arg.serialize(_tlmBuff, FW_MIN(FW_TLM_STRING_MAX_SIZE, $serialSize));"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ case class ComponentHistory(
s"$entryName() :",
lines(
params.map((n, tn, t) => {
t match {
t.getUnderlyingType match {
case ts: Type.String =>
val bufferName = getBufferName(n)
s"$n($bufferName, sizeof $bufferName)"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ abstract class ComponentTestUtils(
case Some(stringRep) => TypeCppWriter.getName(s, t, stringRep)
case None => TypeCppWriter.getName(s, t)
}
t match {
t.getUnderlyingType match {
case t if s.isPrimitive(t, typeName) => s"const $typeName"
case _: Type.String => stringRepOpt match {
case Some(stringRep) => s"const $stringRep&"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ case class ComponentTesterBaseWriter(
cmdFormalParams.map(param => {
val t = s.a.typeMap(param._2.data.typeName.id)
val varName = param._2.data.name
t match {
t.getUnderlyingType match {
case ts: Type.String =>
lines(
s"""|_status = $varName.serialize(buf, FW_CMD_STRING_MAX_SIZE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,26 @@ object ComputeAutocodeCppFiles extends ComputeCppFiles {
aNode: Ast.Annotated[AstNode[Ast.DefConstant]]
) = addMappings(s, ComputeCppFiles.FileNames.getConstants, None)

override def defAliasTypeAnnotatedNode(
s: State,
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
) = {
val node = aNode._2
val name = s.getName(Symbol.AliasType(aNode))
val loc = Locations.get(node.id)
val fileName = ComputeCppFiles.FileNames.getAliasType(name)
val t = s.a.typeMap(node.id)

for {
s <- addHppMapping(s, fileName, Some(loc), "hpp")
// Only add C header if its supported
s <- s.isTypeSupportedInC(t) match {
case true => addHppMapping(s, fileName, Some(loc), "h")
case false => Right(s)
}
} yield s
}

override def defArrayAnnotatedNode(
s: State,
aNode: Ast.Annotated[AstNode[Ast.DefArray]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,13 @@ object ComputeCppFiles {
/** Gets the C++ file name for generated constants */
def getConstants = "FppConstantsAc"

/**
* Gets the filename for the C++ type alias header
* This is also used for the optional C header if the
* alias supports being defined in a C header
*/
def getAliasType(baseName: String) = s"${baseName}AliasAc"

/** Gets the C++ file name for generated arrays */
def getArray(baseName: String) = s"${baseName}ArrayAc"

Expand Down
Loading