mirror of
https://github.com/nasa/fpp.git
synced 2025-12-11 03:05:32 -06:00
Merge branch 'main' into event-throttle-users-guide
This commit is contained in:
commit
ab572348d0
@ -2,8 +2,30 @@
|
||||
|
||||
== Requirements
|
||||
|
||||
* A Unix environment, such as Linux, Mac OS, or the Windows Subsystem for Linux.
|
||||
* The https://www.scala-sbt.org[Simple Build Tool (sbt)] for Scala.
|
||||
. A Unix environment, such as Linux, Mac OS, or the Windows Subsystem for Linux.
|
||||
|
||||
. The https://www.scala-sbt.org[Simple Build Tool (sbt)] for Scala.
|
||||
|
||||
. Version 11 of the Java Development Kit (JDK).
|
||||
If you have a different version of Java installed on your system, then
|
||||
you can do the following:
|
||||
|
||||
.. Install version 11 of the JDK.
|
||||
For example, in MacPorts you can run
|
||||
+
|
||||
[source,bash]
|
||||
----
|
||||
% sudo port install openjdk11-graalvm
|
||||
----
|
||||
|
||||
.. Set the environment variable `JAVA_HOME` to the home directory associated
|
||||
with the installation.
|
||||
For example, on Mac OS:
|
||||
+
|
||||
[source,bash]
|
||||
----
|
||||
% export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk11-graalvm/Contents/Home
|
||||
----
|
||||
|
||||
== Installing
|
||||
|
||||
@ -117,7 +139,7 @@ For example, on Mac OS:
|
||||
+
|
||||
[source,bash]
|
||||
----
|
||||
% export GRAALVM_JAVA_HOME=Library/Java/JavaVirtualMachines/openjdk11-graalvm/Contents/Home
|
||||
% export GRAALVM_JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk11-graalvm/Contents/Home
|
||||
----
|
||||
|
||||
. Run `sudo $GRAALVM_JAVA_HOME/bin/gu install native-image`
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
{
|
||||
"name":"[Lio.circe.Encoder;"
|
||||
},
|
||||
{
|
||||
"name":"[Ljava.io.File;"
|
||||
},
|
||||
{
|
||||
"name":"[Ljava.lang.String;"
|
||||
},
|
||||
@ -1259,42 +1262,6 @@
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1909",
|
||||
"fields":[{"name":"0bitmap$1769"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1910",
|
||||
"fields":[{"name":"0bitmap$1768"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1911",
|
||||
"fields":[{"name":"0bitmap$1760"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1912",
|
||||
"fields":[{"name":"0bitmap$1761"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1913",
|
||||
"fields":[{"name":"0bitmap$1762"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1914",
|
||||
"fields":[{"name":"0bitmap$1763"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1915",
|
||||
"fields":[{"name":"0bitmap$1764"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1916",
|
||||
"fields":[{"name":"0bitmap$1765"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1917",
|
||||
"fields":[{"name":"0bitmap$1766"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$1918",
|
||||
"fields":[{"name":"0bitmap$1767"}]
|
||||
},
|
||||
{
|
||||
"name":"fpp.compiler.codegen.AnalysisJsonEncoder$$anon$192",
|
||||
"fields":[{"name":"0bitmap$183"}]
|
||||
|
||||
@ -22,7 +22,7 @@ case class Analysis(
|
||||
/** The set of files included when parsing input */
|
||||
includedFileSet: Set[File] = Set(),
|
||||
/** A map from pairs (spec loc kind, qualified name) to spec locs. */
|
||||
locationSpecifierMap: Map[(Ast.SpecLoc.Kind, Name.Qualified), Ast.SpecLoc] = Map(),
|
||||
locationSpecifierMap: Map[(Ast.SpecLoc.Kind, Name.Qualified), AstNode[Ast.SpecLoc]] = Map(),
|
||||
/** A list of unqualified names representing the enclosing scope names,
|
||||
* with the innermost name at the head of the list. For exapmle, inside
|
||||
* module B where B is inside A and A is at the top level, the module name
|
||||
@ -80,7 +80,9 @@ case class Analysis(
|
||||
/** Whether dictionary generation is required */
|
||||
dictionaryGeneration: Boolean = false,
|
||||
/** The mapping from nodes to implied uses */
|
||||
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map()
|
||||
impliedUseMap: Map[AstNode.Id, ImpliedUse.Uses] = Map(),
|
||||
/** The set of symbols defined with a dictionary specifier */
|
||||
dictionarySymbolSet: Set[Symbol] = Set()
|
||||
) {
|
||||
|
||||
/** Gets the qualified name of a symbol */
|
||||
@ -394,6 +396,9 @@ case class Analysis(
|
||||
s"\n\n${Locations.get(id)}\nbecause this type is not displayable$reason"
|
||||
}
|
||||
this.typeMap(id) match {
|
||||
case a: Type.AliasType =>
|
||||
val id = a.node._2.data.typeName.id
|
||||
getElementReason(id)
|
||||
case a: Type.Array =>
|
||||
val id = a.node._2.data.eltType.id
|
||||
getElementReason(id)
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
package fpp.compiler.analysis
|
||||
|
||||
import fpp.compiler.ast._
|
||||
import fpp.compiler.util._
|
||||
|
||||
/** Check dictionary definitions */
|
||||
object CheckDictionaryDefs
|
||||
extends Analyzer
|
||||
with ModuleAnalyzer
|
||||
{
|
||||
|
||||
def checkConstantDef(a: Analysis, s: Symbol.Constant) =
|
||||
if !s.isDictionaryDef
|
||||
then Right(a)
|
||||
else
|
||||
val id = s.getNodeId
|
||||
val t = a.typeMap(id)
|
||||
def result =
|
||||
val a1 = a.copy(dictionarySymbolSet = a.dictionarySymbolSet + s)
|
||||
Right(a1)
|
||||
def error =
|
||||
val loc = Locations.get(id)
|
||||
val msg = "dictionary constant must have a numeric, Boolean, string, or enum type"
|
||||
Left(SemanticError.InvalidType(loc, msg))
|
||||
t match
|
||||
case _: Type.String | Type.Boolean | _: Type.Enum => result
|
||||
case _ => if t.isNumeric then result else error
|
||||
|
||||
def checkTypeDef(a: Analysis, s: Symbol) =
|
||||
if s.isDictionaryDef
|
||||
then
|
||||
for {
|
||||
_ <- a.checkDisplayableType(
|
||||
s.getNodeId,
|
||||
"dictionary type is not displayable"
|
||||
)
|
||||
} yield a.copy(dictionarySymbolSet = a.dictionarySymbolSet + s)
|
||||
else Right(a)
|
||||
|
||||
override def defAliasTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) =
|
||||
checkTypeDef(a, Symbol.AliasType(aNode))
|
||||
|
||||
override def defArrayAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) =
|
||||
checkTypeDef(a, Symbol.Array(aNode))
|
||||
|
||||
override def defEnumAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefEnum]]) =
|
||||
checkTypeDef(a, Symbol.Enum(aNode))
|
||||
|
||||
override def defStructAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefStruct]]) =
|
||||
checkTypeDef(a, Symbol.Struct(aNode))
|
||||
|
||||
override def defConstantAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefConstant]]) =
|
||||
checkConstantDef(a, Symbol.Constant(aNode))
|
||||
|
||||
}
|
||||
@ -33,9 +33,10 @@ object CheckSemantics {
|
||||
_ <- CheckComponentInstanceDefs.checkIdRanges(a)
|
||||
a <- CheckStateMachineDefs.visitList(a, tul, CheckStateMachineDefs.transUnit)
|
||||
a <- CheckTopologyDefs.visitList(a, tul, CheckTopologyDefs.transUnit)
|
||||
a <- ConstructDictionaryMap.visitList(a, tul, ConstructDictionaryMap.transUnit)
|
||||
a <- BuildSpecLocMap.visitList(a, tul, BuildSpecLocMap.transUnit)
|
||||
a <- CheckSpecLocs.visitList(a, tul, CheckSpecLocs.transUnit)
|
||||
a <- CheckDictionaryDefs.visitList(a, tul, CheckDictionaryDefs.transUnit)
|
||||
a <- ConstructDictionaryMap.visitList(a, tul, ConstructDictionaryMap.transUnit)
|
||||
}
|
||||
yield a
|
||||
}
|
||||
|
||||
@ -9,58 +9,116 @@ object CheckSpecLocs
|
||||
with ModuleAnalyzer
|
||||
{
|
||||
|
||||
override def defAbsTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAbsType]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Type, name, node)
|
||||
}
|
||||
override def defAbsTypeAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefAbsType]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.AbsType(aNode))
|
||||
|
||||
override def defArrayAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefArray]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Type, name, node)
|
||||
}
|
||||
override def defAliasTypeAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.AliasType(aNode))
|
||||
|
||||
override def defConstantAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefConstant]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Constant, name, node)
|
||||
}
|
||||
override def defArrayAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefArray]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.Array(aNode))
|
||||
|
||||
override def defEnumAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefEnum]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Type, name, node)
|
||||
}
|
||||
override def defComponentAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefComponent]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Component, Symbol.Component(aNode))
|
||||
|
||||
override def defPortAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefPort]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Port, name, node)
|
||||
}
|
||||
override def defComponentInstanceAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefComponentInstance]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.ComponentInstance, Symbol.ComponentInstance(aNode))
|
||||
|
||||
override def defStructAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefStruct]]) = {
|
||||
val (_, node, _) = aNode
|
||||
val name = node.data.name
|
||||
checkSpecLoc(a, Ast.SpecLoc.Type, name, node)
|
||||
}
|
||||
override def defConstantAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefConstant]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Constant, Symbol.Constant(aNode))
|
||||
|
||||
private def checkSpecLoc[T](
|
||||
override def defEnumAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefEnum]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.Enum(aNode))
|
||||
|
||||
override def defInterfaceAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefInterface]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Interface, Symbol.Interface(aNode))
|
||||
|
||||
override def defPortAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefPort]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Port, Symbol.Port(aNode))
|
||||
|
||||
override def defStructAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefStruct]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Type, Symbol.Struct(aNode))
|
||||
|
||||
override def defTopologyAnnotatedNode(
|
||||
a: Analysis,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefTopology]]
|
||||
) = checkSpecLoc(a, Ast.SpecLoc.Topology, Symbol.Topology(aNode))
|
||||
|
||||
private def checkSpecLoc(
|
||||
a: Analysis,
|
||||
kind: Ast.SpecLoc.Kind,
|
||||
name: Name.Unqualified,
|
||||
node: AstNode[T]
|
||||
symbol: Symbol
|
||||
) = for {
|
||||
a <- checkPath(a, kind, symbol)
|
||||
a <- checkDictionarySpecifier(a, kind, symbol)
|
||||
} yield a
|
||||
|
||||
private def checkPath[T](
|
||||
a: Analysis,
|
||||
kind: Ast.SpecLoc.Kind,
|
||||
symbol: Symbol
|
||||
): Result = {
|
||||
val name = symbol.getUnqualifiedName
|
||||
val id = symbol.getNodeId
|
||||
val qualifiedName = Name.Qualified(a.scopeNameList.reverse, name)
|
||||
val actualLoc = Locations.get(node.id).tuLocation
|
||||
val actualLoc = Locations.get(id).tuLocation
|
||||
a.locationSpecifierMap.get((kind, qualifiedName)) match {
|
||||
case Some(specLoc) => {
|
||||
case Some(node) => {
|
||||
val specLoc = node.data
|
||||
val specifierLoc = Locations.get(specLoc.file.id)
|
||||
val specifiedJavaPath = specifierLoc.getRelativePath(specLoc.file.data)
|
||||
val specifiedJavaPath =
|
||||
specifierLoc.getRelativePath(specLoc.file.data)
|
||||
val specifiedPath = File.Path(specifiedJavaPath).toString
|
||||
val actualPath = actualLoc.file.toString
|
||||
if (specifiedPath == actualPath) Right(a)
|
||||
else Left(SemanticError.IncorrectSpecLoc(specifierLoc, specifiedPath, actualLoc))
|
||||
else Left(
|
||||
SemanticError.IncorrectLocationPath(
|
||||
specifierLoc,
|
||||
specifiedPath,
|
||||
actualLoc
|
||||
)
|
||||
)
|
||||
}
|
||||
case None => Right(a)
|
||||
}
|
||||
}
|
||||
|
||||
private def checkDictionarySpecifier(
|
||||
a: Analysis,
|
||||
kind: Ast.SpecLoc.Kind,
|
||||
symbol: Symbol
|
||||
) = {
|
||||
val name = a.getQualifiedName(symbol)
|
||||
val id = symbol.getNodeId
|
||||
val defLoc = Locations.get(id)
|
||||
a.locationSpecifierMap.get((kind, name)) match {
|
||||
case Some(node) => {
|
||||
val specifierLoc = Locations.get(node.id)
|
||||
if symbol.isDictionaryDef == node.data.isDictionaryDef
|
||||
then Right(a)
|
||||
else Left(
|
||||
SemanticError.IncorrectDictionarySpecifier(specifierLoc, defLoc)
|
||||
)
|
||||
}
|
||||
case None => Right(a)
|
||||
}
|
||||
|
||||
@ -17,14 +17,34 @@ object BuildSpecLocMap extends ModuleAnalyzer {
|
||||
val key = (spec.kind, qualifiedName)
|
||||
a.locationSpecifierMap.get(key) match {
|
||||
case None => {
|
||||
val map = a.locationSpecifierMap + (key -> spec)
|
||||
val map = a.locationSpecifierMap + (key -> specNode)
|
||||
Right(a.copy(locationSpecifierMap = map))
|
||||
}
|
||||
case Some(spec1) =>
|
||||
for { _ <- checkPathConsistency(spec, spec1) } yield a
|
||||
case Some(specNode1) =>
|
||||
for {
|
||||
_ <- checkPathConsistency(spec, specNode1.data)
|
||||
_ <- checkDictionarySpecifierConsistency(specNode, specNode1)
|
||||
} yield a
|
||||
}
|
||||
}
|
||||
|
||||
private def checkDictionarySpecifierConsistency(
|
||||
specNode1: AstNode[Ast.SpecLoc],
|
||||
specNode2: AstNode[Ast.SpecLoc]
|
||||
): Result.Result[Unit] = {
|
||||
val spec1 = specNode1.data
|
||||
val spec2 = specNode2.data
|
||||
if(spec1.isDictionaryDef == spec2.isDictionaryDef) then
|
||||
Right(())
|
||||
else
|
||||
Left(
|
||||
SemanticError.InconsistentDictionarySpecifier(
|
||||
Locations.get(specNode1.id),
|
||||
Locations.get(specNode2.id),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private def checkPathConsistency(
|
||||
spec1: Ast.SpecLoc,
|
||||
spec2: Ast.SpecLoc
|
||||
@ -34,7 +54,7 @@ object BuildSpecLocMap extends ModuleAnalyzer {
|
||||
if (path1 == path2)
|
||||
Right(())
|
||||
else Left(
|
||||
SemanticError.InconsistentSpecLoc(
|
||||
SemanticError.InconsistentLocationPath(
|
||||
Locations.get(spec1.file.id),
|
||||
path1,
|
||||
Locations.get(spec2.file.id),
|
||||
|
||||
@ -23,6 +23,7 @@ object ComputeDependencies {
|
||||
a <- BuildSpecLocMap.visitList(a, tul, BuildSpecLocMap.transUnit)
|
||||
a <- ConstructImpliedUseMap.visitList(a, tul, ConstructImpliedUseMap.transUnit)
|
||||
a <- MapUsesToLocs.visitList(a, tul, MapUsesToLocs.transUnit)
|
||||
a <- Right(addDictionaryDependencies(a))
|
||||
}
|
||||
yield {
|
||||
val includedFileSet = a.includedFileSet
|
||||
@ -31,4 +32,16 @@ object ComputeDependencies {
|
||||
}
|
||||
}
|
||||
|
||||
// Adds the dictionary dependencies to the dependency file set
|
||||
private def addDictionaryDependencies(a: Analysis) = {
|
||||
val dfs = a.locationSpecifierMap.foldLeft (a.dependencyFileSet) {
|
||||
case (s, (_, node)) => {
|
||||
if node.data.isDictionaryDef
|
||||
then s + Locations.get(node.data.file.id).file
|
||||
else s
|
||||
}
|
||||
}
|
||||
a.copy(dependencyFileSet = dfs)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ object MapUsesToLocs extends BasicUseAnalyzer {
|
||||
nameList match {
|
||||
case Nil => None
|
||||
case head :: tail => a.locationSpecifierMap.get((kind, head)) match {
|
||||
case specLoc @ Some(_) => specLoc
|
||||
case opt @ Some(_) => opt.map(_.data)
|
||||
case None => findLocation(tail)
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,39 +9,47 @@ final case class DictionaryUsedSymbols(a: Analysis, t: Topology) {
|
||||
d.copy(usedSymbolSet = getUsedSymbolSet)
|
||||
|
||||
private def getUsedSymbolSet: Set[Symbol] =
|
||||
t.instanceMap.keys.toSet.flatMap(getUsedSymbolsForInstance) ++
|
||||
a.getImpliedUses(ImpliedUse.Kind.Type, t.aNode._2.id).map(iu => a.useDefMap(iu.id)) ++
|
||||
a.getImpliedUses(ImpliedUse.Kind.Constant, t.aNode._2.id).map(iu => a.useDefMap(iu.id))
|
||||
val kinds = Set(ImpliedUse.Kind.Type, ImpliedUse.Kind.Constant)
|
||||
val impliedUses = kinds.flatMap(
|
||||
k => a.getImpliedUses(k, t.aNode._2.id).map(iu => a.useDefMap(iu.id))
|
||||
)
|
||||
val ss = Set.concat(
|
||||
t.instanceMap.keys.toSet.flatMap(getUsedSymbolsForInstance),
|
||||
impliedUses,
|
||||
a.dictionarySymbolSet
|
||||
)
|
||||
UsedSymbols.resolveUses(a, ss)
|
||||
|
||||
private def getUsedSymbolsForInstance(ci: ComponentInstance) = {
|
||||
val component = ci.component
|
||||
val a1 = a.copy(usedSymbolSet = Set())
|
||||
val commandSymbols = getUsedSymbolsForSpecifier(
|
||||
component.commandMap,
|
||||
{
|
||||
case Command.NonParam(aNode, _) =>
|
||||
UsedSymbols.specCommandAnnotatedNode(a, aNode)
|
||||
UsedSymbols.specCommandAnnotatedNode(a1, aNode)
|
||||
case _ => Right(a.copy(usedSymbolSet = Set()))
|
||||
}
|
||||
)
|
||||
val eventSymbols = getUsedSymbolsForSpecifier(
|
||||
component.eventMap,
|
||||
event => UsedSymbols.specEventAnnotatedNode(a, event.aNode)
|
||||
event => UsedSymbols.specEventAnnotatedNode(a1, event.aNode)
|
||||
)
|
||||
val tlmChannelSymbols = getUsedSymbolsForSpecifier(
|
||||
component.tlmChannelMap,
|
||||
channel => UsedSymbols.specTlmChannelAnnotatedNode(a, channel.aNode)
|
||||
channel => UsedSymbols.specTlmChannelAnnotatedNode(a1, channel.aNode)
|
||||
)
|
||||
val paramSymbols = getUsedSymbolsForSpecifier(
|
||||
component.paramMap,
|
||||
param => UsedSymbols.specParamAnnotatedNode(a, param.aNode)
|
||||
param => UsedSymbols.specParamAnnotatedNode(a1, param.aNode)
|
||||
)
|
||||
val recordSymbols = getUsedSymbolsForSpecifier(
|
||||
component.recordMap,
|
||||
record => UsedSymbols.specRecordAnnotatedNode(a, record.aNode)
|
||||
record => UsedSymbols.specRecordAnnotatedNode(a1, record.aNode)
|
||||
)
|
||||
val containerSymbols = getUsedSymbolsForSpecifier(
|
||||
component.containerMap,
|
||||
container => UsedSymbols.specContainerAnnotatedNode(a, container.aNode)
|
||||
container => UsedSymbols.specContainerAnnotatedNode(a1, container.aNode)
|
||||
)
|
||||
Set.concat(
|
||||
commandSymbols,
|
||||
@ -57,11 +65,11 @@ final case class DictionaryUsedSymbols(a: Analysis, t: Topology) {
|
||||
map: Map[BigInt, Specifier],
|
||||
usedSymbols: Specifier => Result.Result[Analysis]
|
||||
): Set[Symbol] =
|
||||
map.values.toSet.flatMap {
|
||||
map.values.toSet.flatMap (
|
||||
specifier => {
|
||||
val Right(a) = usedSymbols(specifier)
|
||||
UsedSymbols.resolveUses(a, a.usedSymbolSet)
|
||||
a.usedSymbolSet
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
@ -4,7 +4,9 @@ import fpp.compiler.ast._
|
||||
import fpp.compiler.util._
|
||||
|
||||
/** A data structure that represents a definition */
|
||||
sealed trait Symbol extends SymbolInterface
|
||||
sealed trait Symbol extends SymbolInterface {
|
||||
def isDictionaryDef = false
|
||||
}
|
||||
|
||||
object Symbol {
|
||||
|
||||
@ -13,10 +15,12 @@ object Symbol {
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
final case class AliasType(node: Ast.Annotated[AstNode[Ast.DefAliasType]]) extends Symbol {
|
||||
override def isDictionaryDef = node._2.data.isDictionaryDef
|
||||
override def getNodeId = node._2.id
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
final case class Array(node: Ast.Annotated[AstNode[Ast.DefArray]]) extends Symbol {
|
||||
override def isDictionaryDef = node._2.data.isDictionaryDef
|
||||
override def getNodeId = node._2.id
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
@ -29,10 +33,12 @@ object Symbol {
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
final case class Constant(node: Ast.Annotated[AstNode[Ast.DefConstant]]) extends Symbol {
|
||||
override def isDictionaryDef = node._2.data.isDictionaryDef
|
||||
override def getNodeId = node._2.id
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
final case class Enum(node: Ast.Annotated[AstNode[Ast.DefEnum]]) extends Symbol {
|
||||
override def isDictionaryDef = node._2.data.isDictionaryDef
|
||||
override def getNodeId = node._2.id
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
@ -57,6 +63,7 @@ object Symbol {
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
final case class Struct(node: Ast.Annotated[AstNode[Ast.DefStruct]]) extends Symbol {
|
||||
override def isDictionaryDef = node._2.data.isDictionaryDef
|
||||
override def getNodeId = node._2.id
|
||||
override def getUnqualifiedName = node._2.data.name
|
||||
}
|
||||
|
||||
@ -189,7 +189,6 @@ object Type {
|
||||
case class AliasType(
|
||||
/** The AST node giving the definition */
|
||||
node: Ast.Annotated[AstNode[Ast.DefAliasType]],
|
||||
|
||||
/** Type that this typedef points to */
|
||||
aliasType: Type
|
||||
) extends Type {
|
||||
|
||||
@ -3,9 +3,38 @@ package fpp.compiler.analysis
|
||||
import fpp.compiler.ast.*
|
||||
import fpp.compiler.util.*
|
||||
|
||||
/** Compute used symbols */
|
||||
/**
|
||||
* Compute used symbols
|
||||
*
|
||||
* There are two forms of resolution:
|
||||
*
|
||||
* 1. Shallow resolution (don't follow uses from uses). This is used to
|
||||
* generate header files. You get this by calling a visitor method
|
||||
* of UsedSymbols.
|
||||
*
|
||||
* 2. Deep resolution (follow uses from uses). This is used to generate
|
||||
* dictionary symbols. You get this by calling UsedSymbols.resolveUses.
|
||||
*/
|
||||
object UsedSymbols extends UseAnalyzer {
|
||||
|
||||
// When resolving uses, if the default value of an enum definition is an enum
|
||||
// constant, then don't visit it. In this case the symbol is ignored (for
|
||||
// shallow resolution) or converted to a use of this enum (for deep resolution).
|
||||
// So it adds nothing to the resolution.
|
||||
override def defEnumAnnotatedNode(a: Analysis, node: Ast.Annotated[AstNode[Ast.DefEnum]]) = {
|
||||
val (_, node1, _) = node
|
||||
val data = node1.data
|
||||
for
|
||||
a <- opt(typeNameNode)(a, data.typeName)
|
||||
a <- visitList(a, data.constants, defEnumConstantAnnotatedNode)
|
||||
a <- node._2.data.default match
|
||||
case Some(en) => a.useDefMap(en.id) match
|
||||
case _: Symbol.EnumConstant => Right(a)
|
||||
case _ => opt(exprNode)(a, data.default)
|
||||
case None => Right(a)
|
||||
yield a
|
||||
}
|
||||
|
||||
override def componentUse(
|
||||
a: Analysis,
|
||||
node: AstNode[Ast.QualIdent],
|
||||
@ -55,14 +84,30 @@ object UsedSymbols extends UseAnalyzer {
|
||||
) = addSymbol(a, node)
|
||||
|
||||
private def addSymbol[T](a: Analysis, node: AstNode[T]) = {
|
||||
// We could convert enum constant symbols to enum symbols here.
|
||||
// This would convert E.A to a use of E in shallow resolution.
|
||||
// Currently we don't do this, because we convert E.A to a numeric
|
||||
// constant in the generated code, so we don't need the dependency
|
||||
// on E.
|
||||
val symbol = a.useDefMap(node.id)
|
||||
Right(a.copy(usedSymbolSet = a.usedSymbolSet + symbol))
|
||||
}
|
||||
|
||||
/** Resolves used symbols recursively */
|
||||
/** Deep resolution of used symbols
|
||||
* Replaces uses of enum constants with uses of the corresponding enums */
|
||||
def resolveUses(a: Analysis, ss: Set[Symbol]): Set[Symbol] = {
|
||||
// When resolving uses, convert an enum constant symbol to the corresponding
|
||||
// enum symbol. For example, the use E.A becomes a use of E. This is what
|
||||
// we want, because E provides the definition of E.A.
|
||||
def resolveEnumConstant(s: Symbol) =
|
||||
s match
|
||||
case Symbol.EnumConstant(node) =>
|
||||
val t @ Type.Enum(enumNode, _, _) = a.typeMap(node._2.id)
|
||||
Symbol.Enum(enumNode)
|
||||
case _ => s
|
||||
// Helper function for recursive resolution
|
||||
val a1: Analysis = a.copy(usedSymbolSet = Set())
|
||||
def helper(s: Symbol): Set[Symbol] = {
|
||||
def resolveNode(s: Symbol): Set[Symbol] = {
|
||||
val Right(a2) = s match {
|
||||
case Symbol.AbsType(node) => defAbsTypeAnnotatedNode(a1, node)
|
||||
case Symbol.AliasType(node) => defAliasTypeAnnotatedNode(a1, node)
|
||||
@ -79,9 +124,9 @@ object UsedSymbols extends UseAnalyzer {
|
||||
case Symbol.Struct(node) => defStructAnnotatedNode(a1, node)
|
||||
case Symbol.Topology(node) => defTopologyAnnotatedNode(a1, node)
|
||||
}
|
||||
a2.usedSymbolSet.flatMap(helper) + s
|
||||
a2.usedSymbolSet.flatMap(resolveNode) + resolveEnumConstant(s)
|
||||
}
|
||||
ss.flatMap(helper)
|
||||
ss.flatMap(resolveNode)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -78,7 +78,8 @@ object Ast {
|
||||
/* Aliased type definition */
|
||||
final case class DefAliasType(
|
||||
name: Ident,
|
||||
typeName: AstNode[TypeName]
|
||||
typeName: AstNode[TypeName],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
|
||||
/* Array definition */
|
||||
@ -87,7 +88,8 @@ object Ast {
|
||||
size: AstNode[Expr],
|
||||
eltType: AstNode[TypeName],
|
||||
default: Option[AstNode[Expr]],
|
||||
format: Option[AstNode[String]]
|
||||
format: Option[AstNode[String]],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
|
||||
/** Component definition */
|
||||
@ -112,14 +114,19 @@ object Ast {
|
||||
)
|
||||
|
||||
/** Constant definition */
|
||||
final case class DefConstant(name: Ident, value: AstNode[Expr])
|
||||
final case class DefConstant(
|
||||
name: Ident,
|
||||
value: AstNode[Expr],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
|
||||
/** Enum definition */
|
||||
final case class DefEnum(
|
||||
name: Ident,
|
||||
typeName: Option[AstNode[TypeName]],
|
||||
constants: List[Annotated[AstNode[DefEnumConstant]]],
|
||||
default: Option[AstNode[Expr]]
|
||||
default: Option[AstNode[Expr]],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
|
||||
/** Enum constant definition */
|
||||
@ -279,7 +286,8 @@ object Ast {
|
||||
final case class DefStruct(
|
||||
name: Ident,
|
||||
members: List[Annotated[AstNode[StructTypeMember]]],
|
||||
default: Option[AstNode[Expr]]
|
||||
default: Option[AstNode[Expr]],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
|
||||
/** Expression */
|
||||
@ -578,7 +586,8 @@ object Ast {
|
||||
final case class SpecLoc(
|
||||
kind: SpecLoc.Kind,
|
||||
symbol: AstNode[QualIdent],
|
||||
file: AstNode[String]
|
||||
file: AstNode[String],
|
||||
isDictionaryDef: Boolean
|
||||
)
|
||||
object SpecLoc {
|
||||
/** Location specifier kind */
|
||||
|
||||
@ -11,18 +11,16 @@ trait AstVisitor {
|
||||
|
||||
def defAbsTypeAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefAbsType]]): Out = default(in)
|
||||
|
||||
def defAliasTypeAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefAliasType]]): Out = default(in)
|
||||
|
||||
def defActionAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefAction]]): Out = default(in)
|
||||
|
||||
def defAliasTypeAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefAliasType]]): Out = default(in)
|
||||
|
||||
def defArrayAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefArray]]): Out = default(in)
|
||||
|
||||
def defChoiceAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefChoice]]): Out = default(in)
|
||||
|
||||
def defComponentAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefComponent]]): Out = default(in)
|
||||
|
||||
def defInterfaceAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefInterface]]): Out = default(in)
|
||||
|
||||
def defComponentInstanceAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefComponentInstance]]): Out = default(in)
|
||||
|
||||
def defConstantAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefConstant]]): Out = default(in)
|
||||
@ -31,6 +29,8 @@ trait AstVisitor {
|
||||
|
||||
def defGuardAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefGuard]]): Out = default(in)
|
||||
|
||||
def defInterfaceAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefInterface]]): Out = default(in)
|
||||
|
||||
def defModuleAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefModule]]): Out = default(in)
|
||||
|
||||
def defPortAnnotatedNode(in: In, node: Ast.Annotated[AstNode[Ast.DefPort]]): Out = default(in)
|
||||
|
||||
@ -16,7 +16,7 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
in: Unit,
|
||||
aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]): Out = {
|
||||
val (_, node, _) = aNode
|
||||
lines("def alias type") ++ (
|
||||
prefixWithDictionary("def alias type", node.data.isDictionaryDef) ++ (
|
||||
ident(node.data.name) ++
|
||||
typeNameNode(node.data.typeName)
|
||||
).map(indentIn)
|
||||
@ -49,7 +49,7 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines("def array") ++
|
||||
prefixWithDictionary("def array", data.isDictionaryDef) ++
|
||||
List.concat(
|
||||
ident(data.name),
|
||||
addPrefix("size", exprNode) (data.size),
|
||||
@ -128,8 +128,10 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines("def constant") ++
|
||||
(ident(data.name) ++ exprNode(data.value)).map(indentIn)
|
||||
prefixWithDictionary("def constant", data.isDictionaryDef) ++ (
|
||||
ident(data.name) ++
|
||||
exprNode(data.value)
|
||||
).map(indentIn)
|
||||
}
|
||||
|
||||
override def defEnumAnnotatedNode(
|
||||
@ -138,7 +140,7 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines("def enum") ++
|
||||
prefixWithDictionary("def enum", data.isDictionaryDef) ++
|
||||
List.concat(
|
||||
ident(data.name),
|
||||
linesOpt(typeNameNode, data.typeName),
|
||||
@ -229,7 +231,7 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines("def struct") ++
|
||||
prefixWithDictionary("def struct", data.isDictionaryDef) ++
|
||||
(
|
||||
ident(data.name) ++
|
||||
data.members.flatMap(annotateNode(structTypeMember)) ++
|
||||
@ -949,4 +951,9 @@ object AstWriter extends AstVisitor with LineUtils {
|
||||
|
||||
private def visibility(v: Ast.Visibility) = v.toString
|
||||
|
||||
private def prefixWithDictionary(s: String, isDictionaryDef: Boolean) =
|
||||
if isDictionaryDef then
|
||||
lines(s"dictionary $s")
|
||||
else
|
||||
lines(s)
|
||||
}
|
||||
|
||||
@ -124,7 +124,7 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines(s"type ${ident(data.name)} = ").
|
||||
lines(prefixWithDictionary(s"type ${ident(data.name)} = ", data.isDictionaryDef)).
|
||||
join("") (typeNameNode(data.typeName))
|
||||
}
|
||||
|
||||
@ -153,7 +153,7 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines(s"array ${ident(data.name)} = [").
|
||||
lines(prefixWithDictionary(s"array ${ident(data.name)} = [", data.isDictionaryDef)).
|
||||
join ("") (exprNode(data.size)).
|
||||
join ("] ") (typeNameNode(data.eltType)).
|
||||
joinOpt (data.default) (" default ") (exprNode).
|
||||
@ -223,7 +223,8 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines(s"constant ${ident(data.name)}").join (" = ") (exprNode(data.value))
|
||||
lines(prefixWithDictionary(s"constant ${ident(data.name)}", data.isDictionaryDef)).
|
||||
join (" = ") (exprNode(data.value))
|
||||
}
|
||||
|
||||
override def defEnumAnnotatedNode(
|
||||
@ -232,7 +233,7 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines(s"enum ${ident(data.name)}").
|
||||
lines(prefixWithDictionary(s"enum ${ident(data.name)}", data.isDictionaryDef)).
|
||||
joinOpt (data.typeName) (": ") (typeNameNode).
|
||||
joinNoIndent (" ") (
|
||||
addBraces(data.constants.flatMap(annotateNode(defEnumConstant)))
|
||||
@ -320,7 +321,7 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
lines(s"struct ${ident(data.name)}").
|
||||
lines(prefixWithDictionary(s"struct ${ident(data.name)}", data.isDictionaryDef)).
|
||||
joinNoIndent (" ") (
|
||||
addBraces(data.members.flatMap(annotateNode(structTypeMember)))
|
||||
).
|
||||
@ -537,7 +538,7 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
val kind = data.kind.toString
|
||||
lines(s"locate ${kind}").
|
||||
lines(s"locate ${prefixWithDictionary(kind, data.isDictionaryDef)}").
|
||||
join (" ") (qualIdent(data.symbol.data)).
|
||||
join (" at ") (string(data.file.data))
|
||||
}
|
||||
@ -896,4 +897,9 @@ object FppWriter extends AstVisitor with LineUtils {
|
||||
|
||||
private def unop(op: Ast.Unop) = op.toString
|
||||
|
||||
private def prefixWithDictionary(s: String, isDictionaryDef: Boolean) =
|
||||
if isDictionaryDef then
|
||||
s"dictionary $s"
|
||||
else
|
||||
s
|
||||
}
|
||||
|
||||
@ -314,7 +314,7 @@ object AnalysisJsonEncoder extends JsonEncoder{
|
||||
Encoder.instance(_.toList.asJson)
|
||||
|
||||
private implicit val locationSpecifierMapEncoder:
|
||||
Encoder[Map[(Ast.SpecLoc.Kind, Name.Qualified), Ast.SpecLoc]] =
|
||||
Encoder[Map[(Ast.SpecLoc.Kind, Name.Qualified), AstNode[Ast.SpecLoc]]] =
|
||||
Encoder.instance(_.toList.asJson)
|
||||
|
||||
private implicit val portNumberMapEncoder: Encoder[Map[Connection, Int]] =
|
||||
@ -353,7 +353,8 @@ object AnalysisJsonEncoder extends JsonEncoder{
|
||||
"typeMap" -> a.typeMap.asJson,
|
||||
"useDefMap" -> a.useDefMap.asJson,
|
||||
"valueMap" -> a.valueMap.asJson,
|
||||
"stateMachineMap" -> a.stateMachineMap.asJson
|
||||
"stateMachineMap" -> a.stateMachineMap.asJson,
|
||||
"dictionarySymbolSet" -> a.dictionarySymbolSet.asJson
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node)
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node, data.isDictionaryDef)
|
||||
}
|
||||
|
||||
override def defArrayAnnotatedNode(
|
||||
@ -45,7 +45,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node)
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node, data.isDictionaryDef)
|
||||
}
|
||||
|
||||
override def defComponentAnnotatedNode(
|
||||
@ -92,7 +92,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
writeSpecLoc(s, Ast.SpecLoc.Constant, data.name, node)
|
||||
writeSpecLoc(s, Ast.SpecLoc.Constant, data.name, node, data.isDictionaryDef)
|
||||
}
|
||||
|
||||
override def defEnumAnnotatedNode(
|
||||
@ -101,7 +101,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node)
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node, data.isDictionaryDef)
|
||||
}
|
||||
|
||||
override def defModuleAnnotatedNode(
|
||||
@ -129,7 +129,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
) = {
|
||||
val (_, node, _) = aNode
|
||||
val data = node.data
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node)
|
||||
writeSpecLoc(s, Ast.SpecLoc.Type, data.name, node, data.isDictionaryDef)
|
||||
}
|
||||
|
||||
override def defTopologyAnnotatedNode(
|
||||
@ -148,7 +148,8 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
s: State,
|
||||
kind: Ast.SpecLoc.Kind,
|
||||
name: String,
|
||||
node: AstNode[T]
|
||||
node: AstNode[T],
|
||||
isDictionaryDef: Boolean = false
|
||||
): Out = {
|
||||
val loc = Locations.get(node.id).tuLocation
|
||||
loc.file match {
|
||||
@ -162,7 +163,7 @@ object LocateDefsFppWriter extends AstVisitor with LineUtils {
|
||||
val baseDirPath = java.nio.file.Paths.get(baseDir).toAbsolutePath
|
||||
val relativePath = baseDirPath.relativize(path)
|
||||
val fileNode = AstNode.create(relativePath.normalize.toString)
|
||||
val specLocNode = AstNode.create(Ast.SpecLoc(kind, qualIdentNode, fileNode))
|
||||
val specLocNode = AstNode.create(Ast.SpecLoc(kind, qualIdentNode, fileNode, isDictionaryDef))
|
||||
val specLocAnnotatedNode = (Nil, specLocNode, Nil)
|
||||
FppWriter.specLocAnnotatedNode((), specLocAnnotatedNode)
|
||||
}
|
||||
|
||||
@ -59,7 +59,8 @@ object ArrayXmlFppWriter extends LineUtils {
|
||||
AstNode.create(Ast.ExprLiteralInt(xmlSize.text)),
|
||||
AstNode.create(eltType),
|
||||
fppDefaultsOpt,
|
||||
fppFormatOpt.map(AstNode.create(_))
|
||||
fppFormatOpt.map(AstNode.create(_)),
|
||||
false
|
||||
)
|
||||
(note ++ comment, node, Nil)
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ object EnumXmlFppWriter extends LineUtils {
|
||||
yield {
|
||||
val repType = FppBuilder.repType(file)
|
||||
val default = FppBuilder.default(file)
|
||||
Ast.DefEnum(name, repType, constants, default)
|
||||
Ast.DefEnum(name, repType, constants, default, false)
|
||||
}
|
||||
|
||||
def defEnumConstant(
|
||||
|
||||
@ -99,7 +99,7 @@ object StructXmlFppWriter extends LineUtils {
|
||||
structName <- file.getAttribute(file.elem, "name")
|
||||
members <- structTypeMemberAnnotatedNodeList(file)
|
||||
}
|
||||
yield (comment, Ast.DefStruct(structName, members, None), Nil)
|
||||
yield (comment, Ast.DefStruct(structName, members, None, false), Nil)
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -370,7 +370,7 @@ object XmlFppWriter extends LineUtils {
|
||||
name <- file.getAttribute(node, "name")
|
||||
constants <- defEnumConstantNodeAnnotatedList(file)(node)
|
||||
}
|
||||
yield (Nil, Ast.DefEnum(name, None, constants, None), Nil)
|
||||
yield (Nil, Ast.DefEnum(name, None, constants, None, false), Nil)
|
||||
|
||||
/** Translates an enum if present in the node */
|
||||
def defEnumAnnotatedOpt(file: XmlFppWriter.File)(node: scala.xml.Node):
|
||||
|
||||
@ -47,6 +47,7 @@ object Lexer {
|
||||
("cpu", CPU),
|
||||
("default", DEFAULT),
|
||||
("diagnostic", DIAGNOSTIC),
|
||||
("dictionary", DICTIONARY),
|
||||
("do", DO),
|
||||
("drop", DROP),
|
||||
("else", ELSE),
|
||||
@ -239,6 +240,7 @@ object Lexer {
|
||||
case CPU => Token.CPU()
|
||||
case DEFAULT => Token.DEFAULT()
|
||||
case DIAGNOSTIC => Token.DIAGNOSTIC()
|
||||
case DICTIONARY => Token.DICTIONARY()
|
||||
case DO => Token.DO()
|
||||
case DOT => Token.DOT()
|
||||
case DROP => Token.DROP()
|
||||
|
||||
@ -74,9 +74,10 @@ object Parser extends Parsers {
|
||||
}
|
||||
}
|
||||
|
||||
private def defAliasType: Parser[Ast.DefAliasType] = {
|
||||
((typeToken ~> ident) ~ (equals ~> node(typeName))) ^^ {
|
||||
case ident ~ typeName => Ast.DefAliasType(ident, typeName)
|
||||
def defAliasType: Parser[Ast.DefAliasType] = {
|
||||
(opt(dictionary) ~ (typeToken ~> ident) ~ (equals ~> node(typeName))) ^^ {
|
||||
case dictionary ~ ident ~ typeName =>
|
||||
Ast.DefAliasType(ident, typeName, dictionary.isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
@ -91,12 +92,12 @@ object Parser extends Parsers {
|
||||
}
|
||||
|
||||
def defArray: Parser[Ast.DefArray] = {
|
||||
(array ~>! ident <~! equals) ~!
|
||||
opt(dictionary) ~ (array ~>! ident <~! equals) ~!
|
||||
index ~! node(typeName) ~!
|
||||
opt(default ~>! exprNode) ~!
|
||||
opt(format ~>! node(literalString)) ^^ {
|
||||
case name ~ size ~ eltType ~ default ~ format =>
|
||||
Ast.DefArray(name, size, eltType, default, format)
|
||||
case dictionary ~ name ~ size ~ eltType ~ default ~ format =>
|
||||
Ast.DefArray(name, size, eltType, default, format, dictionary.isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,8 +173,9 @@ object Parser extends Parsers {
|
||||
}
|
||||
|
||||
def defConstant: Parser[Ast.DefConstant] = {
|
||||
(constant ~>! ident) ~! (equals ~>! exprNode) ^^ { case id ~ e =>
|
||||
Ast.DefConstant(id, e)
|
||||
opt(dictionary) ~ (constant ~>! ident) ~! (equals ~>! exprNode) ^^ {
|
||||
case dictionary ~ id ~ e =>
|
||||
Ast.DefConstant(id, e, dictionary.isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,12 +184,12 @@ object Parser extends Parsers {
|
||||
|
||||
def constants = annotatedElementSequence(node(defEnumConstant), comma, id)
|
||||
|
||||
(enumeration ~>! ident) ~!
|
||||
opt(dictionary) ~ (enumeration ~>! ident) ~!
|
||||
opt(colon ~>! node(typeName)) ~!
|
||||
(lbrace ~>! constants <~! rbrace) ~!
|
||||
opt(default ~>! exprNode) ^^ {
|
||||
case name ~ typeName ~ constants ~ default =>
|
||||
Ast.DefEnum(name, typeName, constants, default)
|
||||
case dictionary ~ name ~ typeName ~ constants ~ default =>
|
||||
Ast.DefEnum(name, typeName, constants, default, dictionary.isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
@ -241,10 +243,10 @@ object Parser extends Parsers {
|
||||
|
||||
def members = annotatedElementSequence(node(structTypeMember), comma, id)
|
||||
|
||||
(struct ~>! ident) ~! (lbrace ~>! members <~! rbrace) ~! opt(
|
||||
opt(dictionary) ~ (struct ~>! ident) ~! (lbrace ~>! members <~! rbrace) ~! opt(
|
||||
default ~>! exprNode
|
||||
) ^^ { case name ~ members ~ default =>
|
||||
Ast.DefStruct(name, members, default)
|
||||
) ^^ { case dictionary ~ name ~ members ~ default =>
|
||||
Ast.DefStruct(name, members, default, dictionary.isDefined)
|
||||
}
|
||||
}
|
||||
|
||||
@ -668,24 +670,33 @@ object Parser extends Parsers {
|
||||
}
|
||||
}
|
||||
|
||||
def specLoc: Parser[Ast.SpecLoc] = {
|
||||
def kind = {
|
||||
def specLoc: Parser[Ast.SpecLoc] =
|
||||
def maybeDictKind =
|
||||
constant ^^ (_ => Ast.SpecLoc.Constant) |
|
||||
typeToken ^^ (_ => Ast.SpecLoc.Type)
|
||||
def nonDictKind =
|
||||
component ^^ (_ => Ast.SpecLoc.Component) |
|
||||
constant ^^ (_ => Ast.SpecLoc.Constant) |
|
||||
instance ^^ (_ => Ast.SpecLoc.ComponentInstance) |
|
||||
port ^^ (_ => Ast.SpecLoc.Port) |
|
||||
state ~! machine ^^ (_ => Ast.SpecLoc.StateMachine) |
|
||||
topology ^^ (_ => Ast.SpecLoc.Topology) |
|
||||
typeToken ^^ (_ => Ast.SpecLoc.Type) |
|
||||
interface ^^ (_ => Ast.SpecLoc.Interface) |
|
||||
failure("location kind expected")
|
||||
instance ^^ (_ => Ast.SpecLoc.ComponentInstance) |
|
||||
port ^^ (_ => Ast.SpecLoc.Port) |
|
||||
state ~! machine ^^ (_ => Ast.SpecLoc.StateMachine) |
|
||||
topology ^^ (_ => Ast.SpecLoc.Topology) |
|
||||
interface ^^ (_ => Ast.SpecLoc.Interface)
|
||||
def maybeDictPair =
|
||||
opt(dictionary) ~ maybeDictKind ^^ {
|
||||
case dictOpt ~ kind => (dictOpt.isDefined, kind)
|
||||
}
|
||||
def nonDictPair =
|
||||
nonDictKind ^^ { case kind => (false, kind) }
|
||||
def isDictAndKind =
|
||||
maybeDictPair |
|
||||
nonDictPair |
|
||||
failure("dictionary specifier or location kind expected")
|
||||
(locate ~>! isDictAndKind) ~! node(qualIdent) ~! (at ~>! node(literalString)) ^^ {
|
||||
case (isDict, kind) ~ symbol ~ file => {
|
||||
Ast.SpecLoc(kind, symbol, file, isDict)
|
||||
}
|
||||
}
|
||||
|
||||
(locate ~>! kind) ~! node(qualIdent) ~! (at ~>! node(literalString)) ^^ {
|
||||
case kind ~ symbol ~ file => Ast.SpecLoc(kind, symbol, file)
|
||||
}
|
||||
}
|
||||
|
||||
def specParam: Parser[Ast.SpecParam] = {
|
||||
opt(external) ~ (param ~>! ident) ~ (colon ~>! node(typeName)) ~!
|
||||
opt(default ~>! exprNode) ~!
|
||||
@ -1111,6 +1122,8 @@ object Parser extends Parsers {
|
||||
private def diagnostic =
|
||||
accept("diagnostic", { case t: Token.DIAGNOSTIC => t })
|
||||
|
||||
private def dictionary = accept("dictionary", { case t: Token.DICTIONARY => t })
|
||||
|
||||
private def doToken = accept("do", { case t: Token.DO => t })
|
||||
|
||||
private def dot = accept(".", { case t: Token.DOT => t })
|
||||
|
||||
@ -30,6 +30,7 @@ object Token {
|
||||
final case class CPU() extends Token
|
||||
final case class DEFAULT() extends Token
|
||||
final case class DIAGNOSTIC() extends Token
|
||||
final case class DICTIONARY() extends Token
|
||||
final case class DO() extends Token
|
||||
final case class DOT() extends Token
|
||||
final case class DROP() extends Token
|
||||
@ -180,6 +181,7 @@ enum TokenId {
|
||||
case CPU
|
||||
case DEFAULT
|
||||
case DIAGNOSTIC
|
||||
case DICTIONARY
|
||||
case DO
|
||||
case DROP
|
||||
case ELSE
|
||||
|
||||
@ -146,11 +146,20 @@ sealed trait Error {
|
||||
System.err.println(matchingLoc)
|
||||
System.err.println("conflicting connection is here:")
|
||||
System.err.println(prevLoc)
|
||||
case SemanticError.InconsistentSpecLoc(loc, path, prevLoc, prevPath) =>
|
||||
case SemanticError.InconsistentDictionarySpecifier(loc, prevLoc) =>
|
||||
Error.print (Some(loc)) (s"inconsistent location specifier")
|
||||
printPrevLoc(prevLoc)
|
||||
printNote("one specifies dictionary and one does not")
|
||||
case SemanticError.InconsistentLocationPath(loc, path, prevLoc, prevPath) =>
|
||||
Error.print (Some(loc)) (s"inconsistent location path ${path}")
|
||||
System.err.println(prevLoc)
|
||||
printPrevLoc(prevLoc)
|
||||
System.err.println(s"previous path is ${prevPath}")
|
||||
case SemanticError.IncorrectSpecLoc(loc, specifiedPath, actualLoc) =>
|
||||
case SemanticError.IncorrectDictionarySpecifier(loc, defLoc) =>
|
||||
Error.print (Some(loc)) (s"incorrect location specifier")
|
||||
System.err.println(s"actual definition is here:")
|
||||
System.err.println(defLoc)
|
||||
printNote("one specifies dictionary and one does not")
|
||||
case SemanticError.IncorrectLocationPath(loc, specifiedPath, actualLoc) =>
|
||||
Error.print (Some(loc)) (s"incorrect location path ${specifiedPath}")
|
||||
System.err.println(s"actual location is ${actualLoc}")
|
||||
case SemanticError.InvalidArraySize(loc, size) =>
|
||||
@ -514,15 +523,25 @@ object SemanticError {
|
||||
matchingLoc: Location,
|
||||
prevLoc: Location
|
||||
) extends Error
|
||||
/** Inconsistent dictionary specifiers in location specifiers */
|
||||
final case class InconsistentDictionarySpecifier(
|
||||
loc: Location,
|
||||
prevLoc: Location,
|
||||
) extends Error
|
||||
/** Inconsistent location specifiers */
|
||||
final case class InconsistentSpecLoc(
|
||||
final case class InconsistentLocationPath(
|
||||
loc: Location,
|
||||
path: String,
|
||||
prevLoc: Location,
|
||||
prevPath: String
|
||||
) extends Error
|
||||
/** Incorrect dictionary specifier in location specifier */
|
||||
final case class IncorrectDictionarySpecifier(
|
||||
loc: Location,
|
||||
defLoc: Location
|
||||
) extends Error
|
||||
/** Incorrect location specifiers */
|
||||
final case class IncorrectSpecLoc(
|
||||
final case class IncorrectLocationPath(
|
||||
loc: Location,
|
||||
specifiedPath: String,
|
||||
actualLoc: Location
|
||||
|
||||
@ -19,7 +19,7 @@ object Types {
|
||||
def aliasType(name: Ast.Ident, ty: Type, id: AstNode.Id = 0): AliasType = {
|
||||
val typeNameNode = AstNode.create(Ast.TypeNameInt(Ast.U32()), id)
|
||||
|
||||
val d = Ast.DefAliasType(name, typeNameNode)
|
||||
val d = Ast.DefAliasType(name, typeNameNode, false)
|
||||
val anode = annotatedNode(d, id)
|
||||
AliasType(anode, ty)
|
||||
}
|
||||
@ -27,19 +27,19 @@ object Types {
|
||||
def array(name: Ast.Ident, anonArray: AnonArray = AnonArray(None, U32), id: AstNode.Id = 0): Array = {
|
||||
val size = AstNode.create(Ast.ExprLiteralInt("1"))
|
||||
val eltType = AstNode.create(Ast.TypeNameInt(Ast.U32()))
|
||||
val d = Ast.DefArray(name, size, eltType, None, None)
|
||||
val d = Ast.DefArray(name, size, eltType, None, None, false)
|
||||
val anode = annotatedNode(d, id)
|
||||
Array(anode, anonArray)
|
||||
}
|
||||
|
||||
def enumeration(name: Ast.Ident, repType: Type.PrimitiveInt = I32, id: AstNode.Id = 0): Enum = {
|
||||
val d = Ast.DefEnum(name, None, List(), None)
|
||||
val d = Ast.DefEnum(name, None, List(), None, false)
|
||||
val anode = annotatedNode(d, id)
|
||||
Enum(anode, repType)
|
||||
}
|
||||
|
||||
def struct(name: Ast.Ident, anonStruct: AnonStruct = AnonStruct(Map()), id: AstNode.Id = 0): Struct = {
|
||||
val d = Ast.DefStruct(name, List(), None)
|
||||
val d = Ast.DefStruct(name, List(), None, false)
|
||||
val anode = annotatedNode(d, id)
|
||||
Struct(anode, anonStruct)
|
||||
}
|
||||
|
||||
@ -57,6 +57,17 @@ class ParserSpec extends AnyWordSpec {
|
||||
)
|
||||
}
|
||||
|
||||
"def alias type OK" should {
|
||||
parseAllOK(
|
||||
Parser.defAliasType,
|
||||
List(
|
||||
"type a = U32",
|
||||
"type a = F32",
|
||||
"dictionary type a = string"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
"def array OK" should {
|
||||
parseAllOK(
|
||||
Parser.defArray,
|
||||
@ -64,6 +75,7 @@ class ParserSpec extends AnyWordSpec {
|
||||
"array a = [10] U32",
|
||||
"array a = [10] U32 default 0",
|
||||
"array a = [10] U32 default 0 format \"{} counts\"",
|
||||
"dictionary array a = [10] U32"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -122,6 +134,7 @@ class ParserSpec extends AnyWordSpec {
|
||||
Parser.defConstant,
|
||||
List(
|
||||
"constant a = 0",
|
||||
"dictionary constant a = 0"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -138,6 +151,7 @@ class ParserSpec extends AnyWordSpec {
|
||||
@ Pre
|
||||
Y = 1 @< Post
|
||||
}""",
|
||||
"dictionary enum E { X = 0 }"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -206,6 +220,7 @@ class ParserSpec extends AnyWordSpec {
|
||||
@ Pre
|
||||
y: F32 @< Post
|
||||
}""",
|
||||
"dictionary struct S { x: [3] U32 }"
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -491,6 +506,8 @@ class ParserSpec extends AnyWordSpec {
|
||||
"locate port a.b at \"c.fpp\"",
|
||||
"locate topology a.b at \"c.fpp\"",
|
||||
"locate type a.b at \"c.fpp\"",
|
||||
"locate dictionary type a.b at \"c.fpp\"",
|
||||
"locate dictionary constant a.b at \"c.fpp\"",
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
type T
|
||||
dictionary array A = [3] T
|
||||
@ -0,0 +1,15 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/array/dictionary_not_displayable.fpp:2.1
|
||||
dictionary array A = [3] T
|
||||
^
|
||||
error: dictionary type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/array/dictionary_not_displayable.fpp:2.26
|
||||
dictionary array A = [3] T
|
||||
^
|
||||
because this type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/array/dictionary_not_displayable.fpp:1.1
|
||||
type T
|
||||
^
|
||||
Type is defined here
|
||||
1
compiler/tools/fpp-check/test/array/dictionary_ok.fpp
Normal file
1
compiler/tools/fpp-check/test/array/dictionary_ok.fpp
Normal file
@ -0,0 +1 @@
|
||||
dictionary array A = [3] U32
|
||||
@ -3,6 +3,8 @@ array_default_error
|
||||
array_default_ok
|
||||
array_no_default_ok
|
||||
default_ok
|
||||
dictionary_not_displayable
|
||||
dictionary_ok
|
||||
enum_default_error
|
||||
enum_default_ok
|
||||
enum_no_default_ok
|
||||
|
||||
@ -0,0 +1 @@
|
||||
dictionary constant c = { x = 0, y = 1 }
|
||||
@ -0,0 +1,5 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/constant/dictionary_error.fpp:1.1
|
||||
dictionary constant c = { x = 0, y = 1 }
|
||||
^
|
||||
error: dictionary constant must have a numeric, Boolean, string, or enum type
|
||||
1
compiler/tools/fpp-check/test/constant/dictionary_ok.fpp
Normal file
1
compiler/tools/fpp-check/test/constant/dictionary_ok.fpp
Normal file
@ -0,0 +1 @@
|
||||
dictionary constant c = 42
|
||||
@ -1,6 +1,8 @@
|
||||
tests="
|
||||
array_index_negative
|
||||
array_index_out_of_bounds
|
||||
dictionary_error
|
||||
dictionary_ok
|
||||
invalid_array_index_type
|
||||
invalid_array_type
|
||||
undef_1
|
||||
|
||||
1
compiler/tools/fpp-check/test/enum/dictionary_ok.fpp
Normal file
1
compiler/tools/fpp-check/test/enum/dictionary_ok.fpp
Normal file
@ -0,0 +1 @@
|
||||
dictionary enum E { A, B }
|
||||
@ -5,6 +5,7 @@ bad_constant
|
||||
bad_default
|
||||
bad_rep_type
|
||||
default_ok
|
||||
dictionary_ok
|
||||
duplicate_value
|
||||
explicit
|
||||
implied
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
locate dictionary type T at "abs_type_dictionary_error.fpp"
|
||||
type T
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_dictionary_error.fpp:1.1
|
||||
locate dictionary type T at "abs_type_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_dictionary_error.fpp:2.1
|
||||
type T
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_error.fpp:1.18
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_path_error.fpp:1.18
|
||||
locate type T at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_error.fpp:2.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/abs_type_path_error.fpp:2.1
|
||||
type T
|
||||
^
|
||||
@ -0,0 +1,2 @@
|
||||
locate type T at "alias_type_dictionary_error.fpp"
|
||||
dictionary type T = U32
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/alias_type_dictionary_error.fpp:1.1
|
||||
locate type T at "alias_type_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/alias_type_dictionary_error.fpp:2.1
|
||||
dictionary type T = U32
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
2
compiler/tools/fpp-check/test/spec_loc/alias_type_ok.fpp
Normal file
2
compiler/tools/fpp-check/test/spec_loc/alias_type_ok.fpp
Normal file
@ -0,0 +1,2 @@
|
||||
locate type T at "alias_type_ok.fpp"
|
||||
type T = U32
|
||||
@ -0,0 +1,2 @@
|
||||
locate type T at "incorrect.fpp"
|
||||
type T = U32
|
||||
@ -0,0 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/alias_type_path_error.fpp:1.18
|
||||
locate type T at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/alias_type_path_error.fpp:2.1
|
||||
type T = U32
|
||||
^
|
||||
@ -0,0 +1,2 @@
|
||||
locate dictionary type A at "array_dictionary_error.fpp"
|
||||
array A = [3] U32
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_dictionary_error.fpp:1.1
|
||||
locate dictionary type A at "array_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_dictionary_error.fpp:2.1
|
||||
array A = [3] U32
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_error.fpp:1.18
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_path_error.fpp:1.18
|
||||
locate type A at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_error.fpp:2.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/array_path_error.fpp:2.1
|
||||
array A = [3] U32
|
||||
^
|
||||
@ -0,0 +1,7 @@
|
||||
locate instance i at "component_instance_ok.fpp"
|
||||
|
||||
passive component C {
|
||||
|
||||
}
|
||||
|
||||
instance i: C base id 0x100
|
||||
@ -0,0 +1,7 @@
|
||||
locate instance i at "incorrect.fpp"
|
||||
|
||||
passive component C {
|
||||
|
||||
}
|
||||
|
||||
instance i: C base id 0x100
|
||||
@ -0,0 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/component_instance_path_error.fpp:1.22
|
||||
locate instance i at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/component_instance_path_error.fpp:7.1
|
||||
instance i: C base id 0x100
|
||||
^
|
||||
4
compiler/tools/fpp-check/test/spec_loc/component_ok.fpp
Normal file
4
compiler/tools/fpp-check/test/spec_loc/component_ok.fpp
Normal file
@ -0,0 +1,4 @@
|
||||
locate component C at "component_ok.fpp"
|
||||
passive component C {
|
||||
|
||||
}
|
||||
@ -0,0 +1,4 @@
|
||||
locate component C at "incorrect.fpp"
|
||||
passive component C {
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/component_path_error.fpp:1.23
|
||||
locate component C at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/component_path_error.fpp:2.1
|
||||
passive component C {
|
||||
^
|
||||
@ -0,0 +1,2 @@
|
||||
locate constant c at "constant_dictionary_error.fpp"
|
||||
dictionary constant c = 0
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_dictionary_error.fpp:1.1
|
||||
locate constant c at "constant_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_dictionary_error.fpp:2.1
|
||||
dictionary constant c = 0
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_error.fpp:1.22
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_path_error.fpp:1.22
|
||||
locate constant c at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_error.fpp:2.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/constant_path_error.fpp:2.1
|
||||
constant c = 0
|
||||
^
|
||||
@ -0,0 +1,2 @@
|
||||
locate dictionary type E at "enum_dictionary_error.fpp"
|
||||
enum E { X }
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_dictionary_error.fpp:1.1
|
||||
locate dictionary type E at "enum_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_dictionary_error.fpp:2.1
|
||||
enum E { X }
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_error.fpp:1.18
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_path_error.fpp:1.18
|
||||
locate type E at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_error.fpp:2.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/enum_path_error.fpp:2.1
|
||||
enum E { X }
|
||||
^
|
||||
5
compiler/tools/fpp-check/test/spec_loc/interface_ok.fpp
Normal file
5
compiler/tools/fpp-check/test/spec_loc/interface_ok.fpp
Normal file
@ -0,0 +1,5 @@
|
||||
locate interface I at "interface_ok.fpp"
|
||||
|
||||
interface I {
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
locate interface I at "incorrect.fpp"
|
||||
|
||||
interface I {
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/interface_path_error.fpp:1.23
|
||||
locate interface I at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/interface_path_error.fpp:3.1
|
||||
interface I {
|
||||
^
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/port_error.fpp:1.18
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/port_path_error.fpp:1.18
|
||||
locate port P at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/port_error.fpp:3.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/port_path_error.fpp:3.1
|
||||
port P
|
||||
^
|
||||
@ -0,0 +1,3 @@
|
||||
locate type S at "struct_dictionary_error.fpp"
|
||||
|
||||
dictionary struct S { x: U32 }
|
||||
@ -0,0 +1,10 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_dictionary_error.fpp:1.1
|
||||
locate type S at "struct_dictionary_error.fpp"
|
||||
^
|
||||
error: incorrect location specifier
|
||||
actual definition is here:
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_dictionary_error.fpp:3.1
|
||||
dictionary struct S { x: U32 }
|
||||
^
|
||||
note: one specifies dictionary and one does not
|
||||
@ -1,8 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_error.fpp:1.18
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_path_error.fpp:1.18
|
||||
locate type S at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_error.fpp:3.1
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/struct_path_error.fpp:3.1
|
||||
struct S { x: U32 }
|
||||
^
|
||||
@ -1,15 +1,31 @@
|
||||
tests="
|
||||
abs_type_error
|
||||
abs_type_dictionary_error
|
||||
abs_type_ok
|
||||
array_error
|
||||
abs_type_path_error
|
||||
alias_type_dictionary_error
|
||||
alias_type_ok
|
||||
alias_type_path_error
|
||||
array_dictionary_error
|
||||
array_ok
|
||||
constant_error
|
||||
array_path_error
|
||||
component_instance_ok
|
||||
component_instance_path_error
|
||||
component_ok
|
||||
component_path_error
|
||||
constant_dictionary_error
|
||||
constant_ok
|
||||
enum_error
|
||||
constant_path_error
|
||||
enum_dictionary_error
|
||||
enum_ok
|
||||
enum_path_error
|
||||
include_ok
|
||||
port_error
|
||||
interface_ok
|
||||
interface_path_error
|
||||
port_ok
|
||||
struct_error
|
||||
port_path_error
|
||||
struct_dictionary_error
|
||||
struct_ok
|
||||
struct_path_error
|
||||
topology_ok
|
||||
topology_path_error
|
||||
"
|
||||
|
||||
5
compiler/tools/fpp-check/test/spec_loc/topology_ok.fpp
Normal file
5
compiler/tools/fpp-check/test/spec_loc/topology_ok.fpp
Normal file
@ -0,0 +1,5 @@
|
||||
locate topology T at "topology_ok.fpp"
|
||||
|
||||
topology T {
|
||||
|
||||
}
|
||||
@ -0,0 +1,5 @@
|
||||
locate topology T at "incorrect.fpp"
|
||||
|
||||
topology T {
|
||||
|
||||
}
|
||||
@ -0,0 +1,8 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/topology_path_error.fpp:1.22
|
||||
locate topology T at "incorrect.fpp"
|
||||
^
|
||||
error: incorrect location path [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/incorrect.fpp
|
||||
actual location is [ local path prefix ]/compiler/tools/fpp-check/test/spec_loc/topology_path_error.fpp:3.1
|
||||
topology T {
|
||||
^
|
||||
@ -0,0 +1,2 @@
|
||||
type T
|
||||
dictionary struct S { x: T }
|
||||
@ -0,0 +1,15 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/struct/dictionary_not_displayable.fpp:2.1
|
||||
dictionary struct S { x: T }
|
||||
^
|
||||
error: dictionary type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/struct/dictionary_not_displayable.fpp:2.26
|
||||
dictionary struct S { x: T }
|
||||
^
|
||||
because this type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/struct/dictionary_not_displayable.fpp:1.1
|
||||
type T
|
||||
^
|
||||
Type is defined here
|
||||
1
compiler/tools/fpp-check/test/struct/dictionary_ok.fpp
Normal file
1
compiler/tools/fpp-check/test/struct/dictionary_ok.fpp
Normal file
@ -0,0 +1 @@
|
||||
dictionary struct S { x: U32 }
|
||||
@ -1,6 +1,8 @@
|
||||
tests="
|
||||
default_error
|
||||
default_ok
|
||||
dictionary_not_displayable
|
||||
dictionary_ok
|
||||
duplicate_names
|
||||
format_alias_not_numeric
|
||||
format_alias_numeric
|
||||
|
||||
@ -0,0 +1,2 @@
|
||||
type T1
|
||||
dictionary type T2 = T1
|
||||
@ -0,0 +1,15 @@
|
||||
fpp-check
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/type/alias_dictionary_not_displayable.fpp:2.1
|
||||
dictionary type T2 = T1
|
||||
^
|
||||
error: dictionary type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/type/alias_dictionary_not_displayable.fpp:2.22
|
||||
dictionary type T2 = T1
|
||||
^
|
||||
because this type is not displayable
|
||||
|
||||
[ local path prefix ]/compiler/tools/fpp-check/test/type/alias_dictionary_not_displayable.fpp:1.1
|
||||
type T1
|
||||
^
|
||||
Type is defined here
|
||||
@ -0,0 +1 @@
|
||||
dictionary type T = U32
|
||||
@ -1,4 +1,6 @@
|
||||
tests="
|
||||
alias_dictionary_not_displayable
|
||||
alias_dictionary_ok
|
||||
alias_type_ok
|
||||
string_size_negative
|
||||
string_size_not_numeric
|
||||
|
||||
@ -1,5 +1,8 @@
|
||||
locate type T at "T.fpp"
|
||||
locate type C.T at "C.fpp"
|
||||
locate dictionary type T2 at "T2.fpp"
|
||||
locate type T3 at "T3.fpp"
|
||||
|
||||
type A1 = T
|
||||
type A2 = C.T
|
||||
type A3 = T2
|
||||
|
||||
@ -1,2 +1,4 @@
|
||||
[ local path prefix ]/compiler/tools/fpp-depend/test/C.fpp
|
||||
[ local path prefix ]/compiler/tools/fpp-depend/test/T.fpp
|
||||
[ local path prefix ]/compiler/tools/fpp-depend/test/T2.fpp
|
||||
[ local path prefix ]/compiler/tools/fpp-depend/test/def_alias.fpp
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
locate constant a at "a.fpp"
|
||||
locate constant b at "b.fpp"
|
||||
locate constant c at "c.fpp"
|
||||
locate dictionary constant d at "d.fpp"
|
||||
|
||||
locate type T at "T.fpp"
|
||||
locate type C.T at "C.fpp"
|
||||
locate dictionary type T2 at "T2.fpp"
|
||||
|
||||
array A1 = [a] T default b
|
||||
array A2 = [a] C.T
|
||||
dictionary array A3 = [d] T2
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user