Skip to content

Commit f7bdd82

Browse files
authored
Merge pull request #933 from nasa/issue-926-framework-constants
Check framework constant values
2 parents d1bb5e6 + 9298462 commit f7bdd82

32 files changed

+724
-184
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package fpp.compiler.analysis
2+
3+
import fpp.compiler.ast._
4+
import fpp.compiler.util._
5+
6+
/** Check F Prime framework constant values */
7+
object CheckFrameworkConstantValues {
8+
9+
def check(a: Analysis) =
10+
Result.foldLeft (a.frameworkDefinitions.constantMap.toList) (a) (checkMapEntry)
11+
12+
private def checkMapEntry(a: Analysis, entry: (String, Symbol.Constant)) =
13+
val (name, s) = entry
14+
checkers.get(name).map(_(a, name, s)).getOrElse(Right(a))
15+
16+
private def requireNonnegativeIntegerConstant(a: Analysis, name: String, s: Symbol.Constant) =
17+
val v = a.getBigIntValue(s.getNodeId)
18+
if (v >= 0) then Right(a) else
19+
val valueId = s.node._2.data.value.id
20+
Left(
21+
SemanticError.InvalidIntValue(
22+
Locations.get(valueId),
23+
v,
24+
s"framework definition $name must be a nonnegative integer constant"
25+
)
26+
)
27+
28+
private def requirePositiveIntegerConstant(a: Analysis, name: String, s: Symbol.Constant) =
29+
val v = a.getBigIntValue(s.getNodeId)
30+
if (v > 0) then Right(a) else
31+
val valueId = s.node._2.data.value.id
32+
Left(
33+
SemanticError.InvalidIntValue(
34+
Locations.get(valueId),
35+
v,
36+
s"framework definition $name must be a positive integer constant"
37+
)
38+
)
39+
40+
private def requireStringSizeConstant(a: Analysis, name: String, s: Symbol.Constant) =
41+
val v = a.getBigIntValue(s.getNodeId)
42+
if (Type.String.isValidSize(v)) then Right(a) else
43+
val valueId = s.node._2.data.value.id
44+
val error = Left(
45+
SemanticError.InvalidStringSize(
46+
Locations.get(valueId),
47+
v
48+
)
49+
)
50+
val annotation = s"framework definition $name must be a string size constant"
51+
Result.annotateResult(error, annotation)
52+
53+
private val checkers = Map(
54+
"FW_ASSERT_COUNT_MAX" -> requireNonnegativeIntegerConstant,
55+
"FW_CMD_ARG_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
56+
"FW_CMD_STRING_MAX_SIZE" -> requireStringSizeConstant,
57+
"FW_COM_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
58+
"FW_FILE_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
59+
"FW_FIXED_LENGTH_STRING_SIZE" -> requireStringSizeConstant,
60+
"FW_INTERNAL_INTERFACE_STRING_MAX_SIZE" -> requireStringSizeConstant,
61+
"FW_LOG_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
62+
"FW_LOG_STRING_MAX_SIZE" -> requireStringSizeConstant,
63+
"FW_LOG_TEXT_BUFFER_SIZE" -> requirePositiveIntegerConstant,
64+
"FW_OBJ_SIMPLE_REG_BUFF_SIZE" -> requirePositiveIntegerConstant,
65+
"FW_OBJ_SIMPLE_REG_ENTRIES" -> requirePositiveIntegerConstant,
66+
"FW_PARAM_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
67+
"FW_PARAM_STRING_MAX_SIZE" -> requireStringSizeConstant,
68+
"FW_QUEUE_NAME_BUFFER_SIZE" -> requirePositiveIntegerConstant,
69+
"FW_QUEUE_SIMPLE_QUEUE_ENTRIES" -> requirePositiveIntegerConstant,
70+
"FW_SM_SIGNAL_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
71+
"FW_STATEMENT_ARG_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
72+
"FW_TASK_NAME_BUFFER_SIZE" -> requirePositiveIntegerConstant,
73+
"FW_TLM_BUFFER_MAX_SIZE" -> requirePositiveIntegerConstant,
74+
"FW_TLM_STRING_MAX_SIZE" -> requireStringSizeConstant,
75+
"Fw.DpCfg.CONTAINER_USER_DATA_SIZE" -> requirePositiveIntegerConstant
76+
)
77+
78+
}

compiler/lib/src/main/scala/analysis/CheckSemantics/CheckFrameworkDefs.scala

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ object CheckFrameworkDefs
2525
val id = aNode._2.id
2626
constants.get(name) match {
2727
case Some(checker) =>
28-
for a <- checker(a, name, id)
28+
for {
29+
_ <- checker(a, name, id)
30+
_ <- checkModuleQualifiers(a, s)
31+
}
2932
yield a.copy(frameworkDefinitions = a.frameworkDefinitions.addConstant(name, s))
3033
case None => Right(a)
3134
}
@@ -94,12 +97,39 @@ object CheckFrameworkDefs
9497
val id = s.getNodeId
9598
types.get(name) match {
9699
case Some(checker) =>
97-
for a <- checker(a, name, id)
100+
for {
101+
_ <- checker(a, name, id)
102+
_ <- checkModuleQualifiers(a, s)
103+
}
98104
yield a.copy(frameworkDefinitions = a.frameworkDefinitions.addType(name, s))
99105
case None => Right(a)
100106
}
101107
}
102108

109+
private def checkModuleQualifiers(a: Analysis, symbol: Symbol) = {
110+
def helper(symbolOpt: Option[Symbol]): Result.Result[Analysis] =
111+
symbolOpt match {
112+
case None => Right(a)
113+
case Some(s: Symbol.Module) =>
114+
helper(a.parentSymbolMap.get(s))
115+
case Some(s) =>
116+
val error = Left(
117+
SemanticError.InvalidQualifier(
118+
a.getQualifiedName(s).toString,
119+
Locations.get(symbol.getNodeId),
120+
"not a module symbol",
121+
Locations.get(s.getNodeId)
122+
)
123+
)
124+
val symbolName = a.getQualifiedName(symbol)
125+
Result.annotateResult(
126+
error,
127+
s"framework definition $symbolName must have module qualifiers"
128+
)
129+
}
130+
helper(a.parentSymbolMap.get(symbol))
131+
}
132+
103133
private def requireAliasType(a: Analysis, name: String, id: AstNode.Id) = {
104134
val t = a.typeMap(id)
105135
t match {

compiler/lib/src/main/scala/analysis/CheckSemantics/CheckSemantics.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ object CheckSemantics {
1919
a <- EvalImpliedEnumConsts.visitList(a, tul, EvalImpliedEnumConsts.transUnit)
2020
a <- EvalConstantExprs.visitList(a, tul, EvalConstantExprs.transUnit)
2121
a <- FinalizeTypeDefs.visitList(a, tul, FinalizeTypeDefs.transUnit)
22+
_ <- CheckFrameworkConstantValues.check(a)
2223
a <- CheckPortDefs.visitList(a, tul, CheckPortDefs.transUnit)
2324
a <- CheckInterfaceDefs.visitList(a, tul, CheckInterfaceDefs.transUnit)
2425
a <- CheckComponentDefs.visitList(a, tul, CheckComponentDefs.transUnit)

compiler/lib/src/main/scala/analysis/CheckSemantics/FinalizeTypeDefs.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ object FinalizeTypeDefs
219219
a.valueMap(id),
220220
Type.Integer
221221
)
222-
if (size > 0 && size <= Int.MaxValue) Right(t)
222+
if Type.String.isValidSize(size) then Right(t)
223223
else {
224224
val loc = Locations.get(id)
225225
Left(SemanticError.InvalidStringSize(loc, size))

compiler/lib/src/main/scala/analysis/Semantics/Type.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,12 @@ object Type {
169169
override def isDisplayable = true
170170
}
171171

172+
object String {
173+
174+
def isValidSize(size: BigInt) = size > 0 && size <= Int.MaxValue
175+
176+
}
177+
172178
/** The type of arbitrary-width integers */
173179
case object Integer extends Type with Int {
174180
override def getDefaultValue = Some(Value.Integer(0))

compiler/lib/src/main/scala/util/Error.scala

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,10 @@ sealed trait Error {
230230
Error.print (Some(loc)) (s"no member $memberName in anonymous struct value")
231231
System.err.println("symbol is defined here:")
232232
System.err.println(defLoc)
233+
case SemanticError.InvalidQualifier(name, loc, msg, defLoc) =>
234+
Error.print (Some(loc)) (s"invalid qualifier $name: $msg")
235+
System.err.println("symbol is defined here:")
236+
System.err.println(defLoc)
233237
case SemanticError.InvalidStructMember(memberName, loc, structTypeName, defLoc) =>
234238
Error.print (Some(loc)) (s"no member $memberName in struct type $structTypeName")
235239
System.err.println("symbol is defined here:")
@@ -565,6 +569,12 @@ object SemanticError {
565569
specifiedPath: String,
566570
actualLoc: Location
567571
) extends Error
572+
/** No member in anonymous struct type */
573+
final case class InvalidAnonStructMember(
574+
memberName: String,
575+
loc: Location,
576+
defLoc: Location
577+
) extends Error
568578
/** Invalid array size */
569579
final case class InvalidArraySize(loc: Location, size: BigInt) extends Error
570580
/** Invalid command */
@@ -651,17 +661,18 @@ object SemanticError {
651661
final case class InvalidSpecialPort(loc: Location, msg: String) extends Error
652662
/** Invalid string size */
653663
final case class InvalidStringSize(loc: Location, size: BigInt) extends Error
654-
/** No member in struct type */
655-
final case class InvalidStructMember(
656-
memberName: String,
664+
/** Invalid qualifier */
665+
final case class InvalidQualifier(
666+
name: String,
657667
loc: Location,
658-
structTypeName: String,
668+
msg: String,
659669
defLoc: Location
660670
) extends Error
661-
/** No member in anonymous struct type */
662-
final case class InvalidAnonStructMember(
671+
/** No member in struct type */
672+
final case class InvalidStructMember(
663673
memberName: String,
664674
loc: Location,
675+
structTypeName: String,
665676
defLoc: Location
666677
) extends Error
667678
/** No member in anonymous struct type */
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
constant FW_ASSERT_COUNT_MAX = -1
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fpp-check
2+
[ local path prefix ]/compiler/tools/fpp-check/test/framework_defs/invalid_positive_integer_constant.fpp:1.32
3+
constant FW_ASSERT_COUNT_MAX = -1
4+
^
5+
error: invalid integer value -1
6+
framework definition FW_ASSERT_COUNT_MAX must be a positive integer constant
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
fpp-check
2+
[ local path prefix ]/compiler/tools/fpp-check/test/framework_defs/invalid_nonnegative_integer_constant.fpp:1.32
3+
constant FW_ASSERT_COUNT_MAX = -1
4+
^
5+
error: invalid integer value -1
6+
framework definition FW_ASSERT_COUNT_MAX must be a nonnegative integer constant
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
constant FW_CMD_ARG_BUFFER_MAX_SIZE = 0

0 commit comments

Comments
 (0)