Skip to content

Require Fw Types in dictionary #686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions compiler/lib/src/main/scala/analysis/Analysis.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ case class Analysis(
/** The mapping from type and constant symbols, expressions,
* and type names to their types */
typeMap: Map[AstNode.Id, Type] = Map(),
/** THe mapping from constant symbols and expressions to their values. */
/** The mapping from constant symbols and expressions to their values. */
valueMap: Map[AstNode.Id, Value] = Map(),
/** The set of symbols used. Used during code generation. */
usedSymbolSet: Set[Symbol] = Set(),
Expand All @@ -70,7 +70,11 @@ case class Analysis(
/** The dictionary under construction */
dictionary: Option[Dictionary] = None,
/** The telemetry packet set under construction */
tlmPacketSet: Option[TlmPacketSet] = None
tlmPacketSet: Option[TlmPacketSet] = None,
/** The dictionary generation mode */
dictionaryMode: Boolean = false,
Comment on lines +74 to +75
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's rename this variable to be a predicate:

Suggested change
/** The dictionary generation mode */
dictionaryMode: Boolean = false,
/** Whether a dictionary is needed in code generation */
dictionaryNeeded: Boolean = false,

/** The set of type symbols used by the dictionary */
dictionaryTypeSymbolSet: Set[Symbol] = Set()
) {

/** Gets the qualified name of a symbol */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,33 @@ object CheckUses extends UseAnalyzer {
yield a.copy(nestedScope = a.nestedScope.pop)
}

override def defTopologyAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefTopology]]) = {
a.dictionaryMode match {
case true => {
val impliedTypeUses = List(
"FwChanIdType",
"FwEventIdType",
"FwOpcodeType",
"FwPacketDescriptorType",
"FwTlmPacketizeIdType"
)
val (_, node1, _) = node
val mapping = a.nestedScope.get (NameGroup.Type) _
for {
a <- Result.foldLeft (impliedTypeUses) (a) ((a, t) => {
for {
symbol <- Result.annotateResult(
helpers.getSymbolForName(mapping)(node1.id, t),
s"Dictionary requires type ${t} to be defined.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add another check here to ensure that the type has an integer type as its underlying type. If not, we can return a TypeError saying that an integer type is required.

} yield a.copy(dictionaryTypeSymbolSet = a.dictionaryTypeSymbolSet + symbol)
})
a <- super.defTopologyAnnotatedNode(a, node)
} yield a
}
case false => super.defTopologyAnnotatedNode(a, node)
}
}

override def portUse(a: Analysis, node: AstNode[Ast.QualIdent], use: Name.Qualified) =
helpers.visitQualIdentNode (NameGroup.Port) (a, node)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ final case class DictionaryUsedSymbols(a: Analysis, t: Topology) {

private def getUsedSymbolsForInstance(ci: ComponentInstance) = {
val component = ci.component
val dictionaryTypeSymbols = a.dictionaryTypeSymbolSet
val commandSymbols = getUsedSymbolsForSpecifier(
component.commandMap,
{
Expand Down Expand Up @@ -42,6 +43,7 @@ final case class DictionaryUsedSymbols(a: Analysis, t: Topology) {
container => UsedSymbols.specContainerAnnotatedNode(a, container.aNode)
)
Set.concat(
dictionaryTypeSymbols,
commandSymbols,
eventSymbols,
tlmChannelSymbols,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,7 +546,7 @@ case class DictionaryJsonEncoder(

/** Main interface for the class. JSON Encoding for a complete dictionary */
def dictionaryAsJson: Json = {
/** Split set into individual sets consisting of each symbol type (arrays, enums, structs) */
/** Split set into individual sets consisting of each symbol type (arrays, enums, structs, aliases) */
val typeDefSymbols = splitTypeSymbolSet(dictionary.usedSymbolSet, Set())
/** Convert each dictionary element to JSON and return the complete dictionary JSON */
Json.obj(
Expand Down
7 changes: 6 additions & 1 deletion compiler/lib/src/main/scala/util/Error.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ sealed trait Error {
System.err.println("previous occurrence is here:")
System.err.println(prevLoc)
}

/*** Print the error */
def print: Unit = {
this match {
Expand Down Expand Up @@ -301,11 +301,16 @@ sealed trait Error {
case SemanticError.UseDefCycle(loc, msg) => Error.print (Some(loc)) (msg)
case XmlError.ParseError(file, msg) => Error.printXml (file) (msg)
case XmlError.SemanticError(file, msg) => Error.printXml (file) (msg)
case AnnotatedError(error, note) =>
error.print
System.err.println(s"note: ${note}")
}
}

}

/** Annotated error for including additional notes */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Annotated error for including additional notes */
/** An error with a note */

final case class AnnotatedError(error: Error, note: String) extends Error
/** A syntax error */
final case class SyntaxError(loc: Location, msg: String) extends Error

Expand Down
7 changes: 7 additions & 0 deletions compiler/lib/src/main/scala/util/Result.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ package fpp.compiler.util
object Result {

type Result[T] = Either[Error, T]

/** Wraps error as an AnnotatedError with note */
def annotateResult[A](r: Result[A], note: String): Result[A] =
r match {
case Right(v) => Right(v)
case Left(e: Error) => Left(AnnotatedError(e, note))
}

/** Left fold with a function that returns a result */
def foldLeft[A,B]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ object FPPToDict {
case Nil => List(File.StdIn)
case list => list
}
val a = Analysis(inputFileSet = options.files.toSet)
val a = Analysis(inputFileSet = options.files.toSet, dictionaryMode = true)
val metadata = DictionaryMetadata(
projectVersion=options.projectVersion,
frameworkVersion=options.frameworkVersion,
Expand Down
134 changes: 107 additions & 27 deletions compiler/tools/fpp-to-dict/test/top/BasicDpTopologyDictionary.ref.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,85 @@
"dictionarySpecVersion" : "1.0.0"
},
"typeDefinitions" : [
{
"kind" : "struct",
"qualifiedName" : "FppTest.DpTestComponent.Complex",
"members" : {
"f1" : {
"type" : {
"name" : "FppTest.DpTestComponent.Data",
"kind" : "qualifiedIdentifier"
},
"index" : 0,
"annotation" : "A struct in the struct"
},
"f2" : {
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"index" : 1,
"annotation" : "A simple U32 field"
}
},
"default" : {
"f1" : {
"u16Field" : 0
},
"f2" : 0
},
"annotation" : "Data for a ComplexRecord"
},
{
"kind" : "alias",
"qualifiedName" : "FwTlmPacketizeIdType",
"type" : {
"name" : "U16",
"kind" : "integer",
"size" : 16,
"signed" : false
},
"underlyingType" : {
"name" : "U16",
"kind" : "integer",
"size" : 16,
"signed" : false
}
},
{
"kind" : "alias",
"qualifiedName" : "FwEventIdType",
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"underlyingType" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
}
},
{
"kind" : "alias",
"qualifiedName" : "FwPacketDescriptorType",
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"underlyingType" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
}
},
{
"kind" : "alias",
"qualifiedName" : "FppTest.DpTestComponent.AliasU16",
Expand Down Expand Up @@ -44,35 +123,36 @@
"annotation" : "Data for a DataRecord"
},
{
"kind" : "struct",
"qualifiedName" : "FppTest.DpTestComponent.Complex",
"members" : {
"f1" : {
"type" : {
"name" : "FppTest.DpTestComponent.Data",
"kind" : "qualifiedIdentifier"
},
"index" : 0,
"annotation" : "A struct in the struct"
},
"f2" : {
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"index" : 1,
"annotation" : "A simple U32 field"
}
"kind" : "alias",
"qualifiedName" : "FwOpcodeType",
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"default" : {
"f1" : {
"u16Field" : 0
},
"f2" : 0
"underlyingType" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
}
},
{
"kind" : "alias",
"qualifiedName" : "FwChanIdType",
"type" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
},
"annotation" : "Data for a ComplexRecord"
"underlyingType" : {
"name" : "U32",
"kind" : "integer",
"size" : 32,
"signed" : false
}
}
],
"commands" : [
Expand Down
Loading