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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,24 @@ object FinalizeTypeDefs
yield if (t1 != t2) a.assignType(node -> t2) else a
}

override def defAliasTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
val symbol = Symbol.AliasType(aNode)
def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) = {
val node = aNode._2
val data = node.data
// Get the type of this node as an alias type A
val aliasType @ Type.AliasType(_, _) = a.typeMap(node.id)
for {
referencedType <- TypeVisitor.ty(a, aliasType.aliasType)
aliasType1 <- Right(aliasType.copy(aliasType = referencedType))
} yield {
// Update A in the type map
a.assignType(node -> aliasType1)
}
}
visitIfNeeded(symbol, visitor)(a, aNode)
}

override def defArrayAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) = {
val symbol = Symbol.Array(aNode)
def visitor(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) = {
Expand Down Expand Up @@ -177,6 +195,10 @@ object FinalizeTypeDefs

override def default(a: Analysis, t: Type) = Right(t)

override def aliasType(a: Analysis, t: Type.AliasType) =
for (a <- defAliasTypeAnnotatedNode(a, t.node))
yield a.typeMap(t.node._2.id)

override def array(a: Analysis, t: Type.Array) =
for (a <- defArrayAnnotatedNode(a, t.node))
yield a.typeMap(t.node._2.id)
Expand Down
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
197 changes: 197 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,197 @@
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)
// Here we can assume that all symbols referenced with be numeric primitives (U/I[8-64] or F32/F64)
// ..or an alias to one of those types.
// We already are including `FpConfig.h` as part of the system headers so we only have to handle the
// alias case.
def getIncludeFiles(sym: Symbol): Option[String] = {
val name = s.getName(sym)
for {
fileName <- sym match {
case Symbol.AliasType(_) => Some(ComputeCppFiles.FileNames.getAliasType(name))
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.concat(
List(getHppIncludes),
wrapInNamespaces(namespaceIdentList, List(getHppDefinition))
)
}

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

private def getHPPCPPGuard: CppDoc.Member = {
linesMember(addBlankPrefix(lines(
"""extern "C" {""")
))
}

private def getHPPCloseCPPGuard: CppDoc.Member = {
linesMember(addBlankPrefix(lines(
"""}""")
))
}

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 systemHHeaders = List(
"FpConfig.h"
).map(CppWriter.systemHeaderString).map(line)

val standardHeaders = List(
"Fw/Types/BasicTypes.h",
).map(CppWriter.headerString)

val symbolHeaders = writeHIncludeDirectives(s, aNode)
val headers = (standardHeaders ++ symbolHeaders).distinct.sorted.map(line)
linesMember(List.concat(
addBlankPrefix(systemHHeaders),
addBlankPrefix(headers)
))
}

private def getHppIncludes: CppDoc.Member.Lines = {
val systemHppHeaders = List(
"FpConfig.hpp"
).map(CppWriter.systemHeaderString).map(line)

val standardHeaders = List(
aliasType.aliasType match {
case Type.String(_) => "Fw/Types/String.hpp"
case _ => "Fw/Types/BasicTypes.h"
},
).map(CppWriter.headerString)
val symbolHeaders = writeHppIncludeDirectives(s, aNode)
val headers = standardHeaders ++ symbolHeaders
linesMember(List.concat(
addBlankPrefix(systemHppHeaders),
addBlankPrefix(headers.distinct.sorted.map(line))
))
}

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

supportedCHeader match {
case true => linesMember(
// Include the C definition of the type alias
// This is using a `typedef`
addBlankPrefix(lines(
s"""|extern "C" {
|${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
Loading