Revise dictionary analysis

This commit is contained in:
Rob Bocchino 2025-10-29 19:31:43 -07:00
parent e5171fabf6
commit ca61b2fdca
6 changed files with 51 additions and 67 deletions

View File

@ -10,36 +10,31 @@ object CheckDictionaryDefs
{
def checkConstantDef(a: Analysis, s: Symbol.Constant) =
if s.isDictionaryDef
then
if !s.isDictionaryDef
then Right(a)
else
val id = s.getNodeId
a.typeMap(id) match {
case Type.Integer | _: Type.Float | Type.Boolean | _: Type.String =>
Right(a.copy(dictionarySymbolSet = a.dictionarySymbolSet + s))
case Type.Enum(enumNode, _, _) =>
val enumSymbol = Symbol.Enum(enumNode)
Right(a.copy(dictionarySymbolSet = a.dictionarySymbolSet + s + enumSymbol))
case _ =>
val loc = Locations.get(id)
Left(
SemanticError.InvalidType(
loc, s"dictionary constant defintion must have a primitive, string, or enum type"
)
)
}
else Right(a)
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 defintion must have a primitive, 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 definition must be displayable"
)
} yield {
val ss = UsedSymbols.resolveUses(a, Set(s))
a.copy(dictionarySymbolSet = a.dictionarySymbolSet ++ ss)
}
if s.isDictionaryDef
then
for {
_ <- a.checkDisplayableType(
s.getNodeId,
"dictionary type definition must be displayable"
)
} yield a.copy(dictionarySymbolSet = a.dictionarySymbolSet + s)
else Right(a)
override def defAliasTypeAnnotatedNode(a: Analysis, aNode: Ast.Annotated[AstNode[Ast.DefAliasType]]) =

View File

@ -13,50 +13,43 @@ final case class DictionaryUsedSymbols(a: Analysis, t: Topology) {
val impliedUses = kinds.flatMap(
k => a.getImpliedUses(k, t.aNode._2.id).map(iu => a.useDefMap(iu.id))
)
Set.concat(
val ss = Set.concat(
t.instanceMap.keys.toSet.flatMap(getUsedSymbolsForInstance),
impliedUses,
impliedUses.flatMap(resolveUses),
a.dictionarySymbolSet
)
private def resolveUses(s: Symbol) =
s match
case _: Symbol.Constant =>
a.typeMap(s.getNodeId) match
case t: Type.Enum => Set(Symbol.Enum(t.node))
case _ => Set()
case _ => UsedSymbols.resolveUses(a, Set(s))
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,
@ -72,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
}
}
)
}

View File

@ -47,7 +47,7 @@ object UsedSymbols extends UseAnalyzer {
node: AstNode[Ast.TypeName],
use: Name.Qualified
) = addSymbol(a, node)
override def portUse(
a: Analysis,
node: AstNode[Ast.QualIdent],
@ -62,6 +62,12 @@ object UsedSymbols extends UseAnalyzer {
/** Resolves used symbols recursively */
def resolveUses(a: Analysis, ss: Set[Symbol]): Set[Symbol] = {
val a1: Analysis = a.copy(usedSymbolSet = Set())
def addEnumTypeForEnumConstant(s: Symbol) =
s match
case Symbol.EnumConstant(node) =>
val t @ Type.Enum(enumNode, _, _) = a.typeMap(node._2.id)
Set(s, Symbol.Enum(enumNode))
case _ => Set(s)
def helper(s: Symbol): Set[Symbol] = {
val Right(a2) = s match {
case Symbol.AbsType(node) => defAbsTypeAnnotatedNode(a1, node)
@ -81,7 +87,7 @@ object UsedSymbols extends UseAnalyzer {
}
a2.usedSymbolSet.flatMap(helper) + s
}
ss.flatMap(helper)
ss.flatMap(helper).flatMap(addEnumTypeForEnumConstant)
}
}

View File

@ -6225,12 +6225,6 @@
},
"dictionarySymbolSet" : [
{
"Array" : {
"nodeId" : 104,
"unqualifiedName" : "SignalPairSet"
}
},
{
"Constant" : {
"nodeId" : 1,
@ -6260,12 +6254,6 @@
"nodeId" : 108,
"unqualifiedName" : "SignalSet"
}
},
{
"Struct" : {
"nodeId" : 99,
"unqualifiedName" : "SignalPair"
}
}
]
}

View File

@ -4401,7 +4401,10 @@ expression appearing in <em>D</em> must have one of the following types:</p>
<div class="ulist">
<ul>
<li>
<p>A <a href="#Types_Primitive-Types">primitive type</a>.</p>
<p>A <a href="#Types_Internal-Types_Numeric-Types">numeric type</a>.</p>
</li>
<li>
<p>The <a href="#Types_The-Boolean-Type">Boolean type</a>.</p>
</li>
<li>
<p>A <a href="#Types_String-Types">string type</a>.</p>
@ -4426,8 +4429,7 @@ dictionary constant b = E.X
type T1
dictionary type T2 = T1 # Error: T2 is not displayable
# Error: c does not have primitive, string, or enum type
dictionary constant c = { x = U32 }</code></pre>
dictionary constant c = { x = U32 } # Error: struct type is not allowed</code></pre>
</div>
</div>
</div>
@ -12035,7 +12037,7 @@ equivalent.</p>
</div>
<div id="footer">
<div id="footer-text">
Last updated 2025-10-28 20:24:16 -0700
Last updated 2025-10-29 18:57:16 -0700
</div>
</div>
<script src="code-prettify/run_prettify.js"></script>

View File

@ -14,7 +14,8 @@ defined by _D_ must be a <<Types_Displayable-Types, displayable type>>.
If a constant definition _D_ is a dictionary definition, then the
expression appearing in _D_ must have one of the following types:
* A <<Types_Primitive-Types,primitive type>>.
* A <<Types_Internal-Types_Numeric-Types,numeric type>>.
* The <<Types_The-Boolean-Type,Boolean type>>.
* A <<Types_String-Types,string type>>.
* An <<Types_Enum-Types,enum type>>.
@ -32,6 +33,5 @@ dictionary constant b = E.X
type T1
dictionary type T2 = T1 # Error: T2 is not displayable
# Error: c does not have primitive, string, or enum type
dictionary constant c = { x = U32 }
dictionary constant c = { x = U32 } # Error: struct type is not allowed
----